diff --git a/packages/backend/package.json b/packages/backend/package.json index 3aa1028fd8..433de36891 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -16,15 +16,11 @@ "@bull-board/api": "5.2.0", "@bull-board/koa": "5.2.0", "@bull-board/ui": "5.2.0", - "@elastic/elasticsearch": "7.17.0", "@koa/cors": "3.4.3", "@koa/multer": "3.0.2", "@koa/router": "9.0.1", "@msgpack/msgpack": "3.0.0-beta2", "@peertube/http-signature": "1.7.0", - "@redocly/openapi-core": "1.0.0-beta.120", - "@sinonjs/fake-timers": "9.1.2", - "@syuilo/aiscript": "0.11.1", "adm-zip": "^0.5.16", "ajv": "8.12.0", "archiver": "5.3.1", @@ -58,7 +54,6 @@ "is-svg": "4.3.2", "js-yaml": "4.1.0", "jsdom": "20.0.3", - "jsonld": "8.2.0", "jsrsasign": "10.6.1", "koa": "2.13.4", "koa-body": "^6.0.1", @@ -71,7 +66,6 @@ "koa-send": "5.0.1", "koa-slow": "2.1.0", "koa-views": "7.0.2", - "meilisearch": "0.33.0", "mfm-js": "0.23.3", "mime-types": "2.1.35", "multer": "1.4.4-lts.1", @@ -98,11 +92,10 @@ "rename": "1.0.4", "rndstr": "1.0.0", "rss-parser": "3.13.0", - "sanitize-html": "2.10.0", + "sanitize-html": "2.12.1", "semver": "7.5.1", "sharp": "0.32.6", "smart-buffer": "^4.2.0", - "sonic-channel": "^1.3.1", "stringz": "2.1.0", "syslog-pro": "1.0.0", "systeminformation": "5.17.17", @@ -123,7 +116,6 @@ "@types/adm-zip": "^0.5.5", "@types/bcryptjs": "2.4.2", "@types/bull": "3.15.9", - "@types/cbor": "6.0.0", "@types/escape-regexp": "0.0.1", "@types/fluent-ffmpeg": "2.1.20", "@types/js-yaml": "4.0.5", @@ -137,12 +129,10 @@ "@types/koa-logger": "3.1.2", "@types/koa-mount": "4.0.2", "@types/koa-send": "4.1.3", - "@types/koa-views": "7.0.0", "@types/koa__cors": "3.3.0", "@types/koa__multer": "2.0.4", "@types/koa__router": "8.0.11", "@types/node": "18.11.18", - "@types/node-fetch": "3.0.3", "@types/nodemailer": "6.4.8", "@types/oauth": "0.9.1", "@types/probe-image-size": "^7.2.5", @@ -151,7 +141,6 @@ "@types/qs": "6.9.7", "@types/random-seed": "0.3.3", "@types/ratelimiter": "3.4.4", - "@types/redis": "4.0.11", "@types/rename": "1.0.4", "@types/sanitize-html": "2.9.0", "@types/semver": "7.5.0", diff --git a/packages/backend/src/config/types.ts b/packages/backend/src/config/types.ts index aa6245129c..b0acffd487 100644 --- a/packages/backend/src/config/types.ts +++ b/packages/backend/src/config/types.ts @@ -25,27 +25,6 @@ export type Source = { db?: number; prefix?: string; }; - elasticsearch: { - host: string; - port: number; - ssl?: boolean; - user?: string; - pass?: string; - index?: string; - }; - sonic: { - host: string; - port: number; - auth?: string; - collection?: string; - bucket?: string; - }; - meilisearch: { - host: string; - port: number; - apiKey?: string; - ssl: boolean; - }; proxy?: string; proxySmtp?: string; diff --git a/packages/backend/src/daemons/server-stats.ts b/packages/backend/src/daemons/server-stats.ts index c936d619ab..492b34b8e9 100644 --- a/packages/backend/src/daemons/server-stats.ts +++ b/packages/backend/src/daemons/server-stats.ts @@ -1,7 +1,6 @@ import si from "systeminformation"; import Xev from "xev"; import * as osUtils from "os-utils"; -import meilisearch from "../db/meilisearch.js"; const ev = new Xev(); @@ -25,7 +24,6 @@ export default function () { const memStats = await mem(); const netStats = await net(); const fsStats = await fs(); - const meilisearchStats = await meilisearchStatus(); const stats = { cpu: roundCpu(cpu), @@ -40,8 +38,7 @@ export default function () { fs: { r: round(Math.max(0, fsStats.rIO_sec ?? 0)), w: round(Math.max(0, fsStats.wIO_sec ?? 0)), - }, - meilisearch: meilisearchStats, + } }; ev.emit("serverStats", stats); log.unshift(stats); @@ -80,16 +77,3 @@ async function fs() { const data = await si.disksIO().catch(() => ({ rIO_sec: 0, wIO_sec: 0 })); return data || { rIO_sec: 0, wIO_sec: 0 }; } - -// MEILI STAT -async function meilisearchStatus() { - if (meilisearch) { - return meilisearch.serverStats(); - } else { - return { - health: "unconfigured", - size: 0, - indexed_count: 0, - }; - } -} diff --git a/packages/backend/src/db/elasticsearch.ts b/packages/backend/src/db/elasticsearch.ts deleted file mode 100644 index 2640e7f918..0000000000 --- a/packages/backend/src/db/elasticsearch.ts +++ /dev/null @@ -1,65 +0,0 @@ -import * as elasticsearch from "@elastic/elasticsearch"; -import config from "@/config/index.js"; - -const index = { - settings: { - analysis: { - analyzer: { - ngram: { - tokenizer: "ngram", - }, - }, - }, - }, - mappings: { - properties: { - text: { - type: "text", - index: true, - analyzer: "ngram", - }, - userId: { - type: "keyword", - index: true, - }, - userHost: { - type: "keyword", - index: true, - }, - }, - }, -}; - -// Init ElasticSearch connection -const client = config.elasticsearch - ? new elasticsearch.Client({ - node: `${config.elasticsearch.ssl ? "https://" : "http://"}${ - config.elasticsearch.host - }:${config.elasticsearch.port}`, - auth: - config.elasticsearch.user && config.elasticsearch.pass - ? { - username: config.elasticsearch.user, - password: config.elasticsearch.pass, - } - : undefined, - pingTimeout: 30000, - }) - : null; - -if (client) { - client.indices - .exists({ - index: config.elasticsearch.index || "misskey_note", - }) - .then((exist) => { - if (!exist.body) { - client.indices.create({ - index: config.elasticsearch.index || "misskey_note", - body: index, - }); - } - }); -} - -export default client; diff --git a/packages/backend/src/db/meilisearch.ts b/packages/backend/src/db/meilisearch.ts deleted file mode 100644 index 6a82c38b90..0000000000 --- a/packages/backend/src/db/meilisearch.ts +++ /dev/null @@ -1,409 +0,0 @@ -import {Health, Index, MeiliSearch, Stats} from "meilisearch"; -import {dbLogger} from "./logger.js"; - -import config from "@/config/index.js"; -import {Note} from "@/models/entities/note.js"; -import * as url from "url"; -import {ILocalUser} from "@/models/entities/user.js"; -import {Followings, Users} from "@/models/index.js"; - -const logger = dbLogger.createSubLogger("meilisearch", "gray", false); - -let posts: Index; -let client: MeiliSearch; - -const hasConfig = - config.meilisearch && - (config.meilisearch.host || - config.meilisearch.port || - config.meilisearch.apiKey); - -if (hasConfig) { - const host = hasConfig ? config.meilisearch.host ?? "localhost" : ""; - const port = hasConfig ? config.meilisearch.port ?? 7700 : 0; - const auth = hasConfig ? config.meilisearch.apiKey ?? "" : ""; - const ssl = hasConfig ? config.meilisearch.ssl ?? false : false; - - logger.info("Connecting to MeiliSearch"); - - client = new MeiliSearch({ - host: `${ssl ? "https" : "http"}://${host}:${port}`, - apiKey: auth, - }); - - posts = client.index("posts"); - - posts - .updateSearchableAttributes(["text"]) - .catch((e) => - logger.error(`Setting searchable attr failed, searches won't work: ${e}`), - ); - - posts - .updateFilterableAttributes([ - "userName", - "userHost", - "mediaAttachment", - "createdAt", - "userId", - ]) - .catch((e) => - logger.error( - `Setting filterable attr failed, advanced searches won't work: ${e}`, - ), - ); - - posts - .updateSortableAttributes(["createdAt"]) - .catch((e) => - logger.error( - `Setting sortable attr failed, placeholder searches won't sort properly: ${e}`, - ), - ); - - posts - .updateStopWords([ - "the", - "a", - "as", - "be", - "of", - "they", - "these", - "これ", - "それ", - "あれ", - "この", - "その", - "あの", - "ここ", - "そこ", - "あそこ", - "こちら", - "どこ", - "だれ", - "なに", - "なん", - "何", - "私", - "貴方", - "貴方方", - "我々", - "私達", - "あの人", - "あのか", - "彼女", - "彼", - "です", - "ありま", - "おりま", - "います", - "は", - "が", - "の", - "に", - "を", - "で", - "え", - "から", - "まで", - "より", - "も", - "どの", - "と", - "し", - "それで", - "しかし", - ]) - .catch((e) => - logger.error( - `Failed to set Meilisearch stop words, database size will be larger: ${e}`, - ), - ); - - logger.info("Connected to MeiliSearch"); -} - -export type MeilisearchNote = { - id: string; - text: string; - userId: string; - userHost: string; - userName: string; - mediaAttachment: string; - createdAt: number; -}; - -function timestampToUnix(timestamp: string) { - let unix = 0; - - // Only contains numbers => UNIX timestamp - if (/^\d+$/.test(timestamp)) { - unix = Number.parseInt(timestamp); - } - - if (unix === 0) { - // Try to parse the timestamp as JavaScript Date - const date = Date.parse(timestamp); - if (isNaN(date)) return 0; - unix = date / 1000; - } - - return unix; -} - -export default hasConfig - ? { - search: async ( - query: string, - limit: number, - offset: number, - userCtx: ILocalUser | null, - ) => { - /// Advanced search syntax - /// from:user => filter by user + optional domain - /// has:image/video/audio/text/file => filter by attachment types - /// domain:domain.com => filter by domain - /// before:Date => show posts made before Date - /// after: Date => show posts made after Date - /// "text" => get posts with exact text between quotes - /// filter:following => show results only from users you follow - /// filter:followers => show results only from followers - - const constructedFilters: string[] = []; - - const splitSearch = query.split(" "); - - // Detect search operators and remove them from the actual query - const filteredSearchTerms = ( - await Promise.all( - splitSearch.map(async (term) => { - if (term.startsWith("has:")) { - const fileType = term.slice(4); - constructedFilters.push(`mediaAttachment = "${fileType}"`); - return null; - } else if (term.startsWith("from:")) { - let user = term.slice(5); - - if (user.length === 0) return null; - - // Cut off leading @, those aren't saved in the DB - if (user.charAt(0) === "@") { - user = user.slice(1); - } - - // Determine if we got a webfinger address or a single username - if (user.split("@").length > 1) { - let splitUser = user.split("@"); - - let domain = splitUser.pop(); - user = splitUser.join("@"); - - constructedFilters.push( - `userName = ${user} AND userHost = ${domain}`, - ); - } else { - constructedFilters.push(`userName = ${user}`); - } - - return null; - } else if (term.startsWith("domain:")) { - const domain = term.slice(7); - constructedFilters.push(`userHost = ${domain}`); - return null; - } else if (term.startsWith("after:")) { - const timestamp = term.slice(6); - - let unix = timestampToUnix(timestamp); - - if (unix !== 0) constructedFilters.push(`createdAt > ${unix}`); - - return null; - } else if (term.startsWith("before:")) { - const timestamp = term.slice(7); - - let unix = timestampToUnix(timestamp); - if (unix !== 0) constructedFilters.push(`createdAt < ${unix}`); - - return null; - } else if (term.startsWith("filter:following")) { - // Check if we got a context user - if (userCtx) { - // Fetch user follows from DB - const followedUsers = await Followings.find({ - where: { - followerId: userCtx.id, - }, - select: { - followeeId: true, - }, - }); - const followIDs = followedUsers.map( - (user) => user.followeeId, - ); - - if (followIDs.length === 0) return null; - - constructedFilters.push(`userId IN [${followIDs.join(",")}]`); - } else { - logger.warn( - "search filtered to follows called without user context", - ); - } - - return null; - } else if (term.startsWith("filter:followers")) { - // Check if we got a context user - if (userCtx) { - // Fetch users follows from DB - const followedUsers = await Followings.find({ - where: { - followeeId: userCtx.id, - }, - select: { - followerId: true, - }, - }); - const followIDs = followedUsers.map( - (user) => user.followerId, - ); - - if (followIDs.length === 0) return null; - - constructedFilters.push(`userId IN [${followIDs.join(",")}]`); - } else { - logger.warn( - "search filtered to followers called without user context", - ); - } - - return null; - } - - return term; - }), - ) - ).filter((term) => term !== null); - - const sortRules = []; - - // An empty search term with defined filters means we have a placeholder search => https://www.meilisearch.com/docs/reference/api/search#placeholder-search - // These have to be ordered manually, otherwise the *oldest* posts are returned first, which we don't want - if (filteredSearchTerms.length === 0 && constructedFilters.length > 0) { - sortRules.push("createdAt:desc"); - } - - logger.info(`Searching for ${filteredSearchTerms.join(" ")}`); - logger.info(`Limit: ${limit}`); - logger.info(`Offset: ${offset}`); - logger.info(`Filters: ${constructedFilters}`); - logger.info(`Ordering: ${sortRules}`); - - return posts.search(filteredSearchTerms.join(" "), { - limit: limit, - offset: offset, - filter: constructedFilters, - sort: sortRules, - }); - }, - ingestNote: async (ingestNotes: Note | Note[]) => { - if (ingestNotes instanceof Note) { - ingestNotes = [ingestNotes]; - } - - const indexingBatch: MeilisearchNote[] = []; - - for (const note of ingestNotes) { - if (note.user === undefined) { - note.user = await Users.findOne({ - where: { - id: note.userId, - }, - }); - } - - let attachmentType = ""; - if (note.attachedFileTypes.length > 0) { - attachmentType = note.attachedFileTypes[0].split("/")[0]; - switch (attachmentType) { - case "image": - case "video": - case "audio": - case "text": - break; - default: - attachmentType = "file"; - break; - } - } - - indexingBatch.push({ - id: note.id.toString(), - text: note.text ? note.text : "", - userId: note.userId, - userHost: - note.userHost !== "" - ? note.userHost - : url.parse(config.host).host, - mediaAttachment: attachmentType, - userName: note.user?.username ?? "UNKNOWN", - createdAt: note.createdAt.getTime() / 1000, // division by 1000 is necessary because Node returns in ms-accuracy - }); - } - - return posts - .addDocuments(indexingBatch, { - primaryKey: "id", - }) - .then(() => - logger.info(`sent ${indexingBatch.length} posts for indexing`), - ); - }, - serverStats: async () => { - const health: Health = await client.health(); - const stats: Stats = await client.getStats(); - - return { - health: health.status, - size: stats.databaseSize, - indexed_count: stats.indexes["posts"].numberOfDocuments, - }; - }, - deleteNotes: async (note: Note | Note[] | string | string[]) => { - if (note instanceof Note) { - note = [note]; - } - if (typeof note === "string") { - note = [note]; - } - - const deletionBatch = note - .map((n) => { - if (n instanceof Note) { - return n.id; - } - - if (n.length > 0) return n; - - logger.error( - `Failed to delete note from Meilisearch, invalid post ID: ${JSON.stringify( - n, - )}`, - ); - - throw new Error( - `Invalid note ID passed to meilisearch deleteNote: ${JSON.stringify( - n, - )}`, - ); - }) - .filter((el) => el !== null); - - await posts.deleteDocuments(deletionBatch as string[]).then(() => { - logger.info( - `submitted ${deletionBatch.length} large batch for deletion`, - ); - }); - }, - } - : null; diff --git a/packages/backend/src/db/sonic.ts b/packages/backend/src/db/sonic.ts deleted file mode 100644 index 032982f083..0000000000 --- a/packages/backend/src/db/sonic.ts +++ /dev/null @@ -1,51 +0,0 @@ -import * as SonicChannel from "sonic-channel"; -import { dbLogger } from "./logger.js"; - -import config from "@/config/index.js"; - -const logger = dbLogger.createSubLogger("sonic", "gray", false); - -const handlers = (type: string): SonicChannel.Handlers => ({ - connected: () => { - logger.succ(`Connected to Sonic ${type}`); - }, - disconnected: (error) => { - logger.warn(`Disconnected from Sonic ${type}, error: ${error}`); - }, - error: (error) => { - logger.warn(`Sonic ${type} error: ${error}`); - }, - retrying: () => { - logger.info(`Sonic ${type} retrying`); - }, - timeout: () => { - logger.warn(`Sonic ${type} timeout`); - }, -}); - -const hasConfig = - config.sonic && (config.sonic.host || config.sonic.port || config.sonic.auth); - -if (hasConfig) { - logger.info("Connecting to Sonic"); -} - -const host = hasConfig ? config.sonic.host ?? "localhost" : ""; -const port = hasConfig ? config.sonic.port ?? 1491 : 0; -const auth = hasConfig ? config.sonic.auth ?? "SecretPassword" : ""; -const collection = hasConfig ? config.sonic.collection ?? "main" : ""; -const bucket = hasConfig ? config.sonic.bucket ?? "default" : ""; - -export default hasConfig - ? { - search: new SonicChannel.Search({ host, port, auth }).connect( - handlers("search"), - ), - ingest: new SonicChannel.Ingest({ host, port, auth }).connect( - handlers("ingest"), - ), - - collection, - bucket, - } - : null; diff --git a/packages/backend/src/misc/get-file-info.ts b/packages/backend/src/misc/get-file-info.ts index 4cde4e09c2..053f0013c3 100644 --- a/packages/backend/src/misc/get-file-info.ts +++ b/packages/backend/src/misc/get-file-info.ts @@ -1,17 +1,12 @@ import * as fs from "node:fs"; import * as crypto from "node:crypto"; -import { join } from "node:path"; import * as stream from "node:stream"; import * as util from "node:util"; -import { FSWatcher } from "chokidar"; -import { fileTypeFromFile } from "file-type"; +import {fileTypeFromFile} from "file-type"; import probeImageSize from "probe-image-size"; -import FFmpeg from "fluent-ffmpeg"; import isSvg from "is-svg"; -import { type predictionType } from "nsfwjs"; import sharp from "sharp"; -import { encode } from "blurhash"; -import { createTempDir } from "./create-temp.js"; +import {encode} from "blurhash"; const pipeline = util.promisify(stream.pipeline); diff --git a/packages/backend/src/queue/processors/background/index-all-notes.ts b/packages/backend/src/queue/processors/background/index-all-notes.ts index 10c332aa3b..cfa8d58bf5 100644 --- a/packages/backend/src/queue/processors/background/index-all-notes.ts +++ b/packages/backend/src/queue/processors/background/index-all-notes.ts @@ -1,11 +1,10 @@ import type Bull from "bull"; -import { queueLogger } from "../../logger.js"; -import { Notes } from "@/models/index.js"; -import { MoreThan } from "typeorm"; -import { index } from "@/services/note/create.js"; -import { Note } from "@/models/entities/note.js"; -import meilisearch from "../../../db/meilisearch.js"; +import {queueLogger} from "../../logger.js"; +import {Notes} from "@/models/index.js"; +import {MoreThan} from "typeorm"; +import {index} from "@/services/note/create.js"; +import {Note} from "@/models/entities/note.js"; const logger = queueLogger.createSubLogger("index-all-notes"); @@ -61,10 +60,6 @@ export default async function indexAllNotes( for (let i = 0; i < notes.length; i += batch) { const chunk = notes.slice(i, i + batch); - if (meilisearch) { - await meilisearch.ingestNote(chunk); - } - await Promise.all(chunk.map((note) => index(note, true))); indexedCount += chunk.length; diff --git a/packages/backend/src/queue/processors/db/delete-account.ts b/packages/backend/src/queue/processors/db/delete-account.ts index 1cd7642ba5..b725c5ae2a 100644 --- a/packages/backend/src/queue/processors/db/delete-account.ts +++ b/packages/backend/src/queue/processors/db/delete-account.ts @@ -1,13 +1,12 @@ import type Bull from "bull"; -import { queueLogger } from "../../logger.js"; -import { DriveFiles, Notes, UserProfiles, Users } from "@/models/index.js"; -import type { DbUserDeleteJobData } from "@/queue/types.js"; -import type { Note } from "@/models/entities/note.js"; -import type { DriveFile } from "@/models/entities/drive-file.js"; -import { MoreThan } from "typeorm"; -import { deleteFileSync } from "@/services/drive/delete-file.js"; -import { sendEmail } from "@/services/send-email.js"; -import meilisearch from "@/db/meilisearch.js"; +import {queueLogger} from "../../logger.js"; +import {DriveFiles, Notes, UserProfiles, Users} from "@/models/index.js"; +import type {DbUserDeleteJobData} from "@/queue/types.js"; +import type {Note} from "@/models/entities/note.js"; +import type {DriveFile} from "@/models/entities/drive-file.js"; +import {MoreThan} from "typeorm"; +import {deleteFileSync} from "@/services/drive/delete-file.js"; +import {sendEmail} from "@/services/send-email.js"; const logger = queueLogger.createSubLogger("delete-account"); @@ -42,9 +41,6 @@ export async function deleteAccount( cursor = notes[notes.length - 1].id; await Notes.delete(notes.map((note) => note.id)); - if (meilisearch) { - await meilisearch.deleteNotes(notes); - } } logger.succ("All of notes deleted"); diff --git a/packages/backend/src/remote/activitypub/resolver.ts b/packages/backend/src/remote/activitypub/resolver.ts index a4a4e23293..7f92db2009 100644 --- a/packages/backend/src/remote/activitypub/resolver.ts +++ b/packages/backend/src/remote/activitypub/resolver.ts @@ -121,31 +121,31 @@ export default class Resolver { switch (parsed.object.type) { case "NoteActivity": - return Notes.findOneByOrFail({ id: parsed.object.id }).then((note) => - renderActivity(renderCreate(renderNote(note, false), note)) + return Notes.findOneByOrFail({ id: parsed.object.id }).then(async (note) => + renderActivity(renderCreate(await renderNote(note, false), note)) ); case "Note": - return Notes.findOneByOrFail({ id: parsed.object.id }).then((note) => - renderActivity(renderNote(note)) + return Notes.findOneByOrFail({ id: parsed.object.id }).then(async(note) => + renderActivity(await renderNote(note)) ); case "User": - return Users.findOneByOrFail({ id: parsed.object.id }).then((user) => - renderActivity(renderPerson(user as ILocalUser)) + return Users.findOneByOrFail({ id: parsed.object.id }).then(async (user) => + renderActivity(await renderPerson(user as ILocalUser)) ); case "Question": // Polls are indexed by the note they are attached to. return Promise.all([ Notes.findOneByOrFail({ id: parsed.object.id }), Polls.findOneByOrFail({ noteId: parsed.object.id }), - ]).then(([note, poll]) => - renderActivity(renderQuestion({id: note.userId}, note, poll)), + ]).then(async ([note, poll]) => + renderActivity(await renderQuestion({id: note.userId}, note, poll)), ); case "Like": return Promise.all([ Notes.findOneByOrFail({ id: parsed.object.id }), NoteReactions.findOneByOrFail({ id: parsed.object.id }) ]).then( - ([note, reaction]) => renderActivity(renderLike(reaction, note)), + async ([note, reaction]) => renderActivity(await renderLike(reaction, note)), ); case "Follow": return Promise.all( diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index 924ce0385e..eb3fe3e274 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -487,7 +487,6 @@ export default define(meta, paramDef, async (ps, me) => { recommendedTimeline: !instance.disableRecommendedTimeline, globalTimeLine: !instance.disableGlobalTimeline, emailRequiredForSignup: instance.emailRequiredForSignup, - searchFilters: config.meilisearch ? true : false, hcaptcha: instance.enableHcaptcha, recaptcha: instance.enableRecaptcha, objectStorage: instance.useObjectStorage, diff --git a/packages/backend/src/server/api/endpoints/notes/search.ts b/packages/backend/src/server/api/endpoints/notes/search.ts index 5a4c709b31..da1e53a1a3 100644 --- a/packages/backend/src/server/api/endpoints/notes/search.ts +++ b/packages/backend/src/server/api/endpoints/notes/search.ts @@ -1,10 +1,5 @@ -import {In} from "typeorm"; import {Notes} from "@/models/index.js"; import {Note} from "@/models/entities/note.js"; -import config from "@/config/index.js"; -import es from "@/db/elasticsearch.js"; -import sonic from "@/db/sonic.js"; -import meilisearch, {MeilisearchNote} from "@/db/meilisearch.js"; import define from "../../define.js"; import {makePaginationQuery} from "../../common/make-pagination-query.js"; import {generateVisibilityQuery} from "../../common/generate-visibility-query.js"; @@ -63,244 +58,28 @@ export const paramDef = { } as const; export default define(meta, paramDef, async (ps, me) => { - if (es == null && sonic == null && meilisearch == null) { - const query = makePaginationQuery( - Notes.createQueryBuilder("note"), - ps.sinceId, - ps.untilId, - ); + const query = makePaginationQuery( + Notes.createQueryBuilder("note"), + ps.sinceId, + ps.untilId, + ); - if (ps.userId) { - query.andWhere("note.userId = :userId", { userId: ps.userId }); - } else if (ps.channelId) { - query.andWhere("note.channelId = :channelId", { - channelId: ps.channelId, - }); - } + if (ps.userId) { + query.andWhere("note.userId = :userId", { userId: ps.userId }); + } else if (ps.channelId) { + query.andWhere("note.channelId = :channelId", { + channelId: ps.channelId, + }); + } - query - .andWhere("note.text ILIKE :q", { q: `%${sqlLikeEscape(ps.query)}%` }); + query + .andWhere("note.text ILIKE :q", { q: `%${sqlLikeEscape(ps.query)}%` }); - generateVisibilityQuery(query, me); - if (me) generateMutedUserQuery(query, me); - if (me) generateBlockedUserQuery(query, me); + generateVisibilityQuery(query, me); + if (me) generateMutedUserQuery(query, me); + if (me) generateBlockedUserQuery(query, me); - const notes: Note[] = await query.take(ps.limit).getMany(); + const notes: Note[] = await query.take(ps.limit).getMany(); - return notes; - } else if (sonic) { - let start = 0; - const chunkSize = 100; - - // Use sonic to fetch and step through all search results that could match the requirements - const ids = []; - while (true) { - const results = await sonic.search.query( - sonic.collection, - sonic.bucket, - ps.query, - { - limit: chunkSize, - offset: start, - }, - ); - - start += chunkSize; - - if (results.length === 0) { - break; - } - - const res = results - .map((k) => JSON.parse(k)) - .filter((key) => { - if (ps.userId && key.userId !== ps.userId) { - return false; - } - if (ps.channelId && key.channelId !== ps.channelId) { - return false; - } - if (ps.sinceId && key.id <= ps.sinceId) { - return false; - } - if (ps.untilId && key.id >= ps.untilId) { - return false; - } - return true; - }) - .map((key) => key.id); - - ids.push(...res); - } - - // Sort all the results by note id DESC (newest first) - ids.sort((a, b) => b - a); - - // Fetch the notes from the database until we have enough to satisfy the limit - start = 0; - const found = []; - while (found.length < ps.limit && start < ids.length) { - const chunk = ids.slice(start, start + chunkSize); - const notes: Note[] = await Notes.find({ - where: { - id: In(chunk), - }, - order: { - id: "DESC", - }, - }); - - // The notes are checked for visibility and muted/blocked users when packed - found.push(...notes); - start += chunkSize; - } - - // If we have more results than the limit, trim them - if (found.length > ps.limit) { - found.length = ps.limit; - } - - return found; - } else if (meilisearch) { - let start = 0; - const chunkSize = 100; - - // Use meilisearch to fetch and step through all search results that could match the requirements - const ids = []; - while (true) { - const results = await meilisearch.search(ps.query, chunkSize, start, me); - - start += chunkSize; - - if (results.hits.length === 0) { - break; - } - - const res = results.hits - .filter((key: MeilisearchNote) => { - if (ps.userId && key.userId !== ps.userId) { - return false; - } - if (ps.sinceId && key.id <= ps.sinceId) { - return false; - } - if (ps.untilId && key.id >= ps.untilId) { - return false; - } - return true; - }) - .map((key) => key.id); - - ids.push(...res); - } - - // Sort all the results by note id DESC (newest first) - ids.sort((a, b) => b - a); - - // Fetch the notes from the database until we have enough to satisfy the limit - start = 0; - const found = []; - while (found.length < ps.limit && start < ids.length) { - const chunk = ids.slice(start, start + chunkSize); - const notes: Note[] = await Notes.find({ - where: { - id: In(chunk), - }, - order: { - id: "DESC", - }, - }); - - // The notes are checked for visibility and muted/blocked users when packed - found.push(...notes); - start += chunkSize; - } - - // If we have more results than the limit, trim them - if (found.length > ps.limit) { - found.length = ps.limit; - } - - return found; - } else { - const userQuery = - ps.userId != null - ? [ - { - term: { - userId: ps.userId, - }, - }, - ] - : []; - - const hostQuery = - ps.userId == null - ? ps.host === null - ? [ - { - bool: { - must_not: { - exists: { - field: "userHost", - }, - }, - }, - }, - ] - : ps.host !== undefined - ? [ - { - term: { - userHost: ps.host, - }, - }, - ] - : [] - : []; - - const result = await es.search({ - index: config.elasticsearch.index || "misskey_note", - body: { - size: ps.limit, - from: ps.offset, - query: { - bool: { - must: [ - { - simple_query_string: { - fields: ["text"], - query: ps.query.toLowerCase(), - default_operator: "and", - }, - }, - ...hostQuery, - ...userQuery, - ], - }, - }, - sort: [ - { - _doc: "desc", - }, - ], - }, - }); - - const hits = result.body.hits.hits.map((hit: any) => hit._id); - - if (hits.length === 0) return []; - - // Fetch found notes - const notes = await Notes.find({ - where: { - id: In(hits), - }, - order: { - id: -1, - }, - }); - - return notes; - } + return notes; }); diff --git a/packages/backend/src/server/api/endpoints/server-info.ts b/packages/backend/src/server/api/endpoints/server-info.ts index 81bb053db4..0a01917049 100644 --- a/packages/backend/src/server/api/endpoints/server-info.ts +++ b/packages/backend/src/server/api/endpoints/server-info.ts @@ -1,7 +1,6 @@ import * as os from "node:os"; import si from "systeminformation"; import define from "../define.js"; -import meilisearch from "@/db/meilisearch.js"; export const meta = { requireCredential: false, @@ -45,14 +44,3 @@ export default define(meta, paramDef, async () => { }; }); -async function meilisearchStatus() { - if (meilisearch) { - return meilisearch.serverStats(); - } else { - return { - health: "unconfigured", - size: 0, - indexed_count: 0, - }; - } -} diff --git a/packages/backend/src/services/note/create.ts b/packages/backend/src/services/note/create.ts index 4ea51bed26..edd4022219 100644 --- a/packages/backend/src/services/note/create.ts +++ b/packages/backend/src/services/note/create.ts @@ -1,6 +1,4 @@ import * as mfm from "mfm-js"; -import es from "../../db/elasticsearch.js"; -import sonic from "../../db/sonic.js"; import {publishMainStream, publishNotesStream, publishNoteStream,} from "@/services/stream.js"; import DeliverManager from "@/remote/activitypub/deliver-manager.js"; import renderNote from "@/remote/activitypub/renderer/note.js"; @@ -51,7 +49,6 @@ import type {UserProfile} from "@/models/entities/user-profile.js"; import {db} from "@/db/postgre.js"; import {getActiveWebhooks} from "@/misc/webhook-cache.js"; import {shouldSilenceInstance} from "@/misc/should-block-instance.js"; -import meilisearch from "../../db/meilisearch.js"; import {redisClient} from "@/db/redis.js"; import {getNote} from "@/server/api/common/getters.js"; @@ -716,34 +713,7 @@ async function insertNote( export async function index(note: Note, reindexing: boolean): Promise { if (!note.text) return; - if (config.elasticsearch && es) { - es.index({ - index: config.elasticsearch.index || "misskey_note", - id: note.id.toString(), - body: { - text: normalizeForSearch(note.text), - userId: note.userId, - userHost: note.userHost, - }, - }); - } - - if (sonic) { - await sonic.ingest.push( - sonic.collection, - sonic.bucket, - JSON.stringify({ - id: note.id, - userId: note.userId, - userHost: note.userHost - }), - note.text, - ); - } - - if (meilisearch && !reindexing) { - await meilisearch.ingestNote(note); - } + // TODO } async function notifyToWatchersOfRenotee( diff --git a/packages/backend/src/services/note/delete.ts b/packages/backend/src/services/note/delete.ts index 7db43cefd3..36deaa0d5e 100644 --- a/packages/backend/src/services/note/delete.ts +++ b/packages/backend/src/services/note/delete.ts @@ -13,7 +13,6 @@ import {instanceChart, notesChart, perUserNotesChart,} from "@/services/chart/in import {deliverToFollowers, deliverToUser,} from "@/remote/activitypub/deliver-manager.js"; import {countSameRenotes} from "@/misc/count-same-renotes.js"; import {registerOrFetchInstanceDoc} from "../register-or-fetch-instance-doc.js"; -import meilisearch from "@/db/meilisearch.js"; /** * 投稿を削除します。 @@ -112,10 +111,6 @@ export default async function ( id: note.id, userId: user.id, }); - - if (meilisearch) { - await meilisearch.deleteNotes(note.id); - } } async function findCascadingNotes(note: Note) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f36a3878a7..29146878fa 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -51,9 +51,6 @@ importers: '@bull-board/ui': specifier: 5.2.0 version: 5.2.0 - '@elastic/elasticsearch': - specifier: 7.17.0 - version: 7.17.0 '@koa/cors': specifier: 3.4.3 version: 3.4.3 @@ -177,9 +174,6 @@ importers: jsdom: specifier: 20.0.3 version: 20.0.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) - jsonld: - specifier: 8.2.0 - version: 8.2.0(web-streams-polyfill@3.3.3) jsrsasign: specifier: 10.6.1 version: 10.6.1 @@ -216,9 +210,6 @@ importers: koa-views: specifier: 7.0.2 version: 7.0.2(@types/koa@2.13.5)(ejs@3.1.10)(lodash@4.17.21) - meilisearch: - specifier: 0.33.0 - version: 0.33.0(encoding@0.1.13) mfm-js: specifier: 0.23.3 version: 0.23.3 @@ -298,8 +289,8 @@ importers: specifier: 3.13.0 version: 3.13.0 sanitize-html: - specifier: 2.10.0 - version: 2.10.0 + specifier: 2.12.1 + version: 2.12.1 semver: specifier: 7.5.1 version: 7.5.1 @@ -309,9 +300,6 @@ importers: smart-buffer: specifier: ^4.2.0 version: 4.2.0 - sonic-channel: - specifier: ^1.3.1 - version: 1.3.1 stringz: specifier: 2.1.0 version: 2.1.0 @@ -371,9 +359,6 @@ importers: '@types/bull': specifier: 3.15.9 version: 3.15.9 - '@types/cbor': - specifier: 6.0.0 - version: 6.0.0 '@types/escape-regexp': specifier: 0.0.1 version: 0.0.1 @@ -413,9 +398,6 @@ importers: '@types/koa-send': specifier: 4.1.3 version: 4.1.3 - '@types/koa-views': - specifier: 7.0.0 - version: 7.0.0(@types/koa@2.13.5)(ejs@3.1.10)(lodash@4.17.21) '@types/koa__cors': specifier: 3.3.0 version: 3.3.0 @@ -428,9 +410,6 @@ importers: '@types/node': specifier: 18.11.18 version: 18.11.18 - '@types/node-fetch': - specifier: 3.0.3 - version: 3.0.3 '@types/nodemailer': specifier: 6.4.8 version: 6.4.8 @@ -455,9 +434,6 @@ importers: '@types/ratelimiter': specifier: 3.4.4 version: 3.4.4 - '@types/redis': - specifier: 4.0.11 - version: 4.0.11 '@types/rename': specifier: 1.0.4 version: 1.0.4 @@ -645,14 +621,6 @@ packages: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} - '@digitalbazaar/http-client@3.4.1': - resolution: {integrity: sha512-Ahk1N+s7urkgj7WvvUND5f8GiWEPfUw0D41hdElaqLgu8wZScI8gdI0q+qWw5N1d35x7GCRH2uk9mi+Uzo9M3g==} - engines: {node: '>=14.0'} - - '@elastic/elasticsearch@7.17.0': - resolution: {integrity: sha512-5QLPCjd0uLmLj1lSuKSThjNpq39f6NmlTy9ROLFwG5gjyTgpwSqufDeYG/Fm43Xs05uF7WcscoO7eguI3HuuYA==} - engines: {node: '>=12'} - '@eslint-community/eslint-utils@4.4.1': resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -671,10 +639,6 @@ packages: resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@fastify/busboy@2.1.1': - resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} - engines: {node: '>=14'} - '@hapi/bourne@3.0.0': resolution: {integrity: sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==} @@ -1029,10 +993,6 @@ packages: '@types/cacheable-request@6.0.3': resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} - '@types/cbor@6.0.0': - resolution: {integrity: sha512-mGQ1lbYOwVti5Xlarn1bTeBZqgY0kstsdjnkoEovgohYKdBjGejHyNGXHdMBeqyQazIv32Jjp33+5pBEaSRy2w==} - deprecated: This is a stub types definition. cbor provides its own type definitions, so you do not need this installed. - '@types/co-body@6.1.3': resolution: {integrity: sha512-UhuhrQ5hclX6UJctv5m4Rfp52AfG9o9+d9/HwjxhVB5NjXxr5t9oKgJxN8xRHgr35oo8meUEHUPFWiKg6y71aA==} @@ -1121,10 +1081,6 @@ packages: '@types/koa-send@4.1.3': resolution: {integrity: sha512-daaTqPZlgjIJycSTNjKpHYuKhXYP30atFc1pBcy6HHqB9+vcymDgYTguPdx9tO4HMOqNyz6bz/zqpxt5eLR+VA==} - '@types/koa-views@7.0.0': - resolution: {integrity: sha512-AB/NB+oFHcLOZJYFv3bG5Af8YbwYCD9/zK0WcKALsbjI/FRKrcXTUTC64RebDrkyOkBm3bpCgpGndhAH/3YQ2Q==} - deprecated: This is a stub types definition. koa-views provides its own type definitions, so you do not need this installed. - '@types/koa@2.13.5': resolution: {integrity: sha512-HSUOdzKz3by4fnqagwthW/1w/yJspTgppyyalPVbgZf8jQWvdIXcVW5h2DGtw4zYntOaeRGx49r1hxoPWrD4aA==} @@ -1143,10 +1099,6 @@ packages: '@types/needle@3.3.0': resolution: {integrity: sha512-UFIuc1gdyzAqeVUYpSL+cliw2MmU/ZUhVZKE7Zo4wPbgc8hbljeKSnn6ls6iG8r5jpegPXLUIhJ+Wb2kLVs8cg==} - '@types/node-fetch@3.0.3': - resolution: {integrity: sha512-HhggYPH5N+AQe/OmN6fmhKmRRt2XuNJow+R3pQwJxOOF9GuwM7O2mheyGeIrs5MOIeNjDEdgdoyHBOrFeJBR3g==} - deprecated: This is a stub types definition. node-fetch provides its own type definitions, so you do not need this installed. - '@types/node@14.18.63': resolution: {integrity: sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==} @@ -1183,10 +1135,6 @@ packages: '@types/redis@2.8.32': resolution: {integrity: sha512-7jkMKxcGq9p242exlbsVzuJb57KqHRhNl4dHoQu2Y5v9bCAbtIXXH0R3HleSQW4CTOqpHIYUW3t6tpUj4BVQ+w==} - '@types/redis@4.0.11': - resolution: {integrity: sha512-bI+gth8La8Wg/QCR1+V1fhrL9+LZUSWfcqpOj2Kc80ZQ4ffbdL173vQd5wovmoV9i071FU9oP2g6etLuEwb6Rg==} - deprecated: This is a stub types definition. redis provides its own type definitions, so you do not need this installed. - '@types/rename@1.0.4': resolution: {integrity: sha512-eV81+6bVv2mdCBahkMefjEUwAjKDAP3AuyhqWCWRxcRaeVdUeHUBaoq2zSz+5HNHF2jzTajMcfLvJsy4K3cbwA==} @@ -1297,10 +1245,6 @@ packages: resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - abort-controller@3.0.0: - resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} - engines: {node: '>=6.5'} - accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} engines: {node: '>= 0.6'} @@ -1633,9 +1577,6 @@ packages: caniuse-lite@1.0.30001680: resolution: {integrity: sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==} - canonicalize@1.0.8: - resolution: {integrity: sha512-0CNTVCLZggSh7bc5VkX5WWPWO+cyZbNd07IHIsSXLia/eAq+r836hgk+8BKoEh7949Mda87VUOitx5OddVj64A==} - cbor@8.1.0: resolution: {integrity: sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==} engines: {node: '>=12.19'} @@ -1994,9 +1935,6 @@ packages: engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} hasBin: true - cross-fetch@3.1.8: - resolution: {integrity: sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==} - cross-spawn@5.1.0: resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} @@ -2004,6 +1942,10 @@ packages: resolution: {integrity: sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug==} engines: {node: '>= 8'} + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + cssom@0.3.8: resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} @@ -2311,6 +2253,7 @@ packages: eslint@8.57.0: resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true esniff@2.0.1: @@ -2352,10 +2295,6 @@ packages: event-stream@3.3.4: resolution: {integrity: sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==} - event-target-shim@5.0.1: - resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} - engines: {node: '>=6'} - events@1.1.1: resolution: {integrity: sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==} engines: {node: '>=0.4.x'} @@ -3039,10 +2978,6 @@ packages: engines: {node: '>=6'} hasBin: true - jsonld@8.2.0: - resolution: {integrity: sha512-qHUa9pn3/cdAZw26HY1Jmy9+sHOxaLrveTRWUcrSDx5apTa20bBTe+X4nzI7dlqc+M5GkwQW6RgRdqO6LF5nkw==} - engines: {node: '>=14'} - jsprim@1.4.2: resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==} engines: {node: '>=0.6.0'} @@ -3129,20 +3064,6 @@ packages: resolution: {integrity: sha512-43zkIKubNbnrULWlHdN5h1g3SEKXOEzoAlRsHOTFpnlDu8JlAOZSMJBLULusuXRequboiwJcj5vtYXKB3k7+2g==} engines: {node: ^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4} - ky-universal@0.11.0: - resolution: {integrity: sha512-65KyweaWvk+uKKkCrfAf+xqN2/epw1IJDtlyCPxYffFCMR8u1sp2U65NtWpnozYfZxQ6IUzIlvUcw+hQ82U2Xw==} - engines: {node: '>=14.16'} - peerDependencies: - ky: '>=0.31.4' - web-streams-polyfill: '>=3.2.1' - peerDependenciesMeta: - web-streams-polyfill: - optional: true - - ky@0.33.3: - resolution: {integrity: sha512-CasD9OCEQSFIam2U8efFK81Yeg8vNMTBUqtMOHlrcWQHqUX3HeCl9Dr31u4toV7emlH8Mymk5+9p0lL6mKb/Xw==} - engines: {node: '>=14.16'} - layerr@2.1.0: resolution: {integrity: sha512-xDD9suWxfBYeXgqffRVH/Wqh+mqZrQcqPRn0I0ijl7iJQ7vu8gMGPt1Qop59pEW/jaIDNUN7+PX1Qk40+vuflg==} @@ -3250,9 +3171,6 @@ packages: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} - meilisearch@0.33.0: - resolution: {integrity: sha512-bYPb9WyITnJfzf92e7QFK8Rc50DmshFWxypXCs3ILlpNh8pT15A7KSu9Xgnnk/K3G/4vb3wkxxtFS4sxNkWB8w==} - merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -3846,6 +3764,10 @@ packages: q@1.4.1: resolution: {integrity: sha512-/CdEdaw49VZVmyIDGUQKDDT53c7qBkO6g5CefWz91Ae+l4+cRtcDYwMTXh6me4O8TMldeGHG3N2Bl84V78Ywbg==} engines: {node: '>=0.6.0', teleport: '>=0.2.0'} + deprecated: |- + You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other. + + (For a CapTP with native promises, see @endo/eventual-send and @endo/captp) qrcode@1.5.3: resolution: {integrity: sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==} @@ -3895,10 +3817,6 @@ packages: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true - rdf-canonize@3.4.0: - resolution: {integrity: sha512-fUeWjrkOO0t1rg7B2fdyDTvngj+9RlUyL92vOdiB7c0FPguWVsniIMjEtHH+meLBO9rzkUlUzBVXgWrjI8P9LA==} - engines: {node: '>=12'} - re2@1.20.9: resolution: {integrity: sha512-ZYcPTFr5ha2xq3WQjBDTF9CWPSDK1z28MLh5UFRxc//7X8BNQ3A7yR7ITnP0jO346661ertdKVFqw1qoL3FMEQ==} @@ -4024,8 +3942,8 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - sanitize-html@2.10.0: - resolution: {integrity: sha512-JqdovUd81dG4k87vZt6uA6YhDfWkUGruUu/aPmXLxXi45gZExnt9Bnw/qeQU8oGf82vPyaE0vO4aH0PbobB9JQ==} + sanitize-html@2.12.1: + resolution: {integrity: sha512-Plh+JAn0UVDpBRP/xEjsk+xDCoOvMBwQUf/K+/cBAVuTbtX8bj2VB7S1sL1dssVpykqp0/KPSesHrqXtokVBpA==} sax@1.2.1: resolution: {integrity: sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==} @@ -4041,9 +3959,6 @@ packages: resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} engines: {node: '>= 10.13.0'} - secure-json-parse@2.7.0: - resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} - seedrandom@2.4.2: resolution: {integrity: sha512-uQ72txMoObtuJooiBLSVs5Yu2e9d/lHQz0boaqHjW8runXB9vR8nFtaZV54wYii613N0C8ZqTBLsfwDhAdpvqQ==} @@ -4082,9 +3997,6 @@ packages: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} - setimmediate@1.0.5: - resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} - setprototypeof@1.1.0: resolution: {integrity: sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==} @@ -4151,10 +4063,6 @@ packages: resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==} engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} - sonic-channel@1.3.1: - resolution: {integrity: sha512-+K4IZVFE7Tf2DB4EFZ23xo7a/+gJaiOHhFzXVZpzkX6Rs/rvf4YbSxnEGdYw8mrTcjtpG+jLVQEhP8sNTtN5VA==} - engines: {node: '>= 6.0.0'} - sort-keys-length@1.0.1: resolution: {integrity: sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==} engines: {node: '>=0.10.0'} @@ -4563,10 +4471,6 @@ packages: resolution: {integrity: sha512-DU9F5t1tihdafuNyW3fIrXUFHHiHxmwuQSGVGIbSpqkc93IH4P0dU8nPhk0gOW7ARxaFu4+P/9cxVwn6PdnIaQ==} engines: {node: '>=16'} - undici@5.28.4: - resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} - engines: {node: '>=14.0'} - unique-filename@3.0.0: resolution: {integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -5084,23 +4988,6 @@ snapshots: dependencies: '@jridgewell/trace-mapping': 0.3.9 - '@digitalbazaar/http-client@3.4.1(web-streams-polyfill@3.3.3)': - dependencies: - ky: 0.33.3 - ky-universal: 0.11.0(ky@0.33.3)(web-streams-polyfill@3.3.3) - undici: 5.28.4 - transitivePeerDependencies: - - web-streams-polyfill - - '@elastic/elasticsearch@7.17.0': - dependencies: - debug: 4.3.7 - hpagent: 0.1.2 - ms: 2.1.3 - secure-json-parse: 2.7.0 - transitivePeerDependencies: - - supports-color - '@eslint-community/eslint-utils@4.4.1(eslint@8.57.0)': dependencies: eslint: 8.57.0 @@ -5124,8 +5011,6 @@ snapshots: '@eslint/js@8.57.0': {} - '@fastify/busboy@2.1.1': {} - '@hapi/bourne@3.0.0': {} '@hapi/hoek@9.3.0': {} @@ -5295,28 +5180,34 @@ snapshots: '@redis/bloom@1.2.0(@redis/client@1.6.0)': dependencies: '@redis/client': 1.6.0 + optional: true '@redis/client@1.6.0': dependencies: cluster-key-slot: 1.1.2 generic-pool: 3.9.0 yallist: 4.0.0 + optional: true '@redis/graph@1.1.1(@redis/client@1.6.0)': dependencies: '@redis/client': 1.6.0 + optional: true '@redis/json@1.0.7(@redis/client@1.6.0)': dependencies: '@redis/client': 1.6.0 + optional: true '@redis/search@1.2.0(@redis/client@1.6.0)': dependencies: '@redis/client': 1.6.0 + optional: true '@redis/time-series@1.1.0(@redis/client@1.6.0)': dependencies: '@redis/client': 1.6.0 + optional: true '@redocly/ajv@8.11.2': dependencies: @@ -5492,10 +5383,6 @@ snapshots: '@types/node': 18.11.18 '@types/responselike': 1.0.3 - '@types/cbor@6.0.0': - dependencies: - cbor: 8.1.0 - '@types/co-body@6.1.3': dependencies: '@types/node': 18.11.18 @@ -5602,66 +5489,6 @@ snapshots: dependencies: '@types/koa': 2.13.5 - '@types/koa-views@7.0.0(@types/koa@2.13.5)(ejs@3.1.10)(lodash@4.17.21)': - dependencies: - koa-views: 7.0.2(@types/koa@2.13.5)(ejs@3.1.10)(lodash@4.17.21) - transitivePeerDependencies: - - '@types/koa' - - arc-templates - - atpl - - babel-core - - bracket-template - - coffee-script - - dot - - dust - - dustjs-helpers - - dustjs-linkedin - - eco - - ect - - ejs - - haml-coffee - - hamlet - - hamljs - - handlebars - - hogan.js - - htmling - - jade - - jazz - - jqtpl - - just - - liquid-node - - liquor - - lodash - - marko - - mote - - mustache - - nunjucks - - plates - - pug - - qejs - - ractive - - razor-tmpl - - react - - react-dom - - slm - - squirrelly - - supports-color - - swig - - swig-templates - - teacup - - templayed - - then-jade - - then-pug - - tinyliquid - - toffee - - twig - - twing - - underscore - - vash - - velocityjs - - walrus - - whiskers - '@types/koa@2.13.5': dependencies: '@types/accepts': 1.3.7 @@ -5691,10 +5518,6 @@ snapshots: dependencies: '@types/node': 18.11.18 - '@types/node-fetch@3.0.3': - dependencies: - node-fetch: 3.3.1 - '@types/node@14.18.63': {} '@types/node@18.11.18': {} @@ -5730,10 +5553,6 @@ snapshots: dependencies: '@types/node': 18.11.18 - '@types/redis@4.0.11': - dependencies: - redis: 4.7.0 - '@types/rename@1.0.4': {} '@types/responselike@1.0.3': @@ -5871,10 +5690,6 @@ snapshots: abbrev@2.0.0: {} - abort-controller@3.0.0: - dependencies: - event-target-shim: 5.0.1 - accepts@1.3.8: dependencies: mime-types: 2.1.35 @@ -6289,8 +6104,6 @@ snapshots: caniuse-lite@1.0.30001680: {} - canonicalize@1.0.8: {} - cbor@8.1.0: dependencies: nofilter: 3.1.0 @@ -6497,13 +6310,7 @@ snapshots: cross-env@7.0.3: dependencies: - cross-spawn: 7.0.5 - - cross-fetch@3.1.8(encoding@0.1.13): - dependencies: - node-fetch: 2.7.0(encoding@0.1.13) - transitivePeerDependencies: - - encoding + cross-spawn: 7.0.6 cross-spawn@5.1.0: dependencies: @@ -6517,6 +6324,12 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + cssom@0.3.8: {} cssom@0.5.0: {} @@ -6857,8 +6670,6 @@ snapshots: stream-combiner: 0.0.4 through: 2.3.8 - event-target-shim@5.0.1: {} - events@1.1.1: {} events@3.3.0: {} @@ -6875,7 +6686,7 @@ snapshots: execa@5.1.1: dependencies: - cross-spawn: 7.0.5 + cross-spawn: 7.0.6 get-stream: 6.0.1 human-signals: 2.1.0 is-stream: 2.0.1 @@ -7034,7 +6845,7 @@ snapshots: foreground-child@3.3.0: dependencies: - cross-spawn: 7.0.5 + cross-spawn: 7.0.6 signal-exit: 4.1.0 form-data-encoder@2.1.4: {} @@ -7091,7 +6902,8 @@ snapshots: strip-ansi: 6.0.1 wide-align: 1.1.5 - generic-pool@3.9.0: {} + generic-pool@3.9.0: + optional: true gensync@1.0.0-beta.2: {} @@ -7578,15 +7390,6 @@ snapshots: json5@2.2.3: {} - jsonld@8.2.0(web-streams-polyfill@3.3.3): - dependencies: - '@digitalbazaar/http-client': 3.4.1(web-streams-polyfill@3.3.3) - canonicalize: 1.0.8 - lru-cache: 6.0.0 - rdf-canonize: 3.4.0 - transitivePeerDependencies: - - web-streams-polyfill - jsprim@1.4.2: dependencies: assert-plus: 1.0.0 @@ -7789,16 +7592,6 @@ snapshots: transitivePeerDependencies: - supports-color - ky-universal@0.11.0(ky@0.33.3)(web-streams-polyfill@3.3.3): - dependencies: - abort-controller: 3.0.0 - ky: 0.33.3 - node-fetch: 3.3.1 - optionalDependencies: - web-streams-polyfill: 3.3.3 - - ky@0.33.3: {} - layerr@2.1.0: {} lazy-ass@1.6.0: {} @@ -7898,12 +7691,6 @@ snapshots: media-typer@0.3.0: {} - meilisearch@0.33.0(encoding@0.1.13): - dependencies: - cross-fetch: 3.1.8(encoding@0.1.13) - transitivePeerDependencies: - - encoding - merge-stream@2.0.0: {} merge2@1.4.1: {} @@ -8483,10 +8270,6 @@ snapshots: minimist: 1.2.8 strip-json-comments: 2.0.1 - rdf-canonize@3.4.0: - dependencies: - setimmediate: 1.0.5 - re2@1.20.9: dependencies: install-artifact-from-github: 1.3.5 @@ -8543,6 +8326,7 @@ snapshots: '@redis/json': 1.0.7(@redis/client@1.6.0) '@redis/search': 1.2.0(@redis/client@1.6.0) '@redis/time-series': 1.1.0(@redis/client@1.6.0) + optional: true reflect-metadata@0.1.13: {} @@ -8621,7 +8405,7 @@ snapshots: safer-buffer@2.1.2: {} - sanitize-html@2.10.0: + sanitize-html@2.12.1: dependencies: deepmerge: 4.3.1 escape-string-regexp: 4.0.0 @@ -8644,8 +8428,6 @@ snapshots: ajv: 6.12.6 ajv-keywords: 3.5.2(ajv@6.12.6) - secure-json-parse@2.7.0: {} - seedrandom@2.4.2: {} seedrandom@3.0.5: {} @@ -8679,8 +8461,6 @@ snapshots: gopd: 1.0.1 has-property-descriptors: 1.0.2 - setimmediate@1.0.5: {} - setprototypeof@1.1.0: {} setprototypeof@1.2.0: {} @@ -8753,8 +8533,6 @@ snapshots: ip-address: 9.0.5 smart-buffer: 4.2.0 - sonic-channel@1.3.1: {} - sort-keys-length@1.0.1: dependencies: sort-keys: 1.1.2 @@ -9154,10 +8932,6 @@ snapshots: dependencies: layerr: 2.1.0 - undici@5.28.4: - dependencies: - '@fastify/busboy': 2.1.1 - unique-filename@3.0.0: dependencies: unique-slug: 4.0.0