From c8d9c5705b35522151e5a7d927c27303de52fc69 Mon Sep 17 00:00:00 2001 From: monoid Date: Thu, 26 Jun 2025 19:41:23 +0900 Subject: [PATCH 1/3] rename initial.ts --- packages/server/migrations/2024-12-27.ts | 90 ++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 packages/server/migrations/2024-12-27.ts diff --git a/packages/server/migrations/2024-12-27.ts b/packages/server/migrations/2024-12-27.ts new file mode 100644 index 0000000..36f097e --- /dev/null +++ b/packages/server/migrations/2024-12-27.ts @@ -0,0 +1,90 @@ +import { Kysely, sql } from 'kysely'; + +export async function up(db: Kysely) { + await db.schema + .createTable('schema_migration') + .addColumn('version', 'char(16)') + .addColumn('dirty', 'boolean') + .execute(); + + await db.schema + .createTable('users') + .addColumn('username', 'varchar(256)', col => col.primaryKey()) + .addColumn('password_hash', 'varchar(64)', col => col.notNull()) + .addColumn('password_salt', 'varchar(64)', col => col.notNull()) + .execute(); + + await db.schema + .createTable('document') + .addColumn('id', 'serial', col => col.primaryKey()) + .addColumn('title', 'varchar(512)', col => col.notNull()) + .addColumn('content_type', 'varchar(16)', col => col.notNull()) + .addColumn('basepath', 'varchar(256)', col => col.notNull()) + .addColumn('filename', 'varchar(512)', col => col.notNull()) + .addColumn('content_hash', 'varchar') + .addColumn('additional', 'json') + .addColumn("pagenum", "integer", col => col.notNull()) + .addColumn('created_at', 'integer', col => col.notNull()) + .addColumn('modified_at', 'integer', col => col.notNull()) + .addColumn('deleted_at', 'integer') + .execute(); + + await db.schema + .createTable('tags') + .addColumn('name', 'varchar', col => col.primaryKey()) + .addColumn('description', 'text') + .execute(); + + await db.schema + .createTable('doc_tag_relation') + .addColumn('doc_id', 'integer', col => col.notNull()) + .addColumn('tag_name', 'varchar', col => col.notNull()) + .addForeignKeyConstraint('doc_id_fk', ['doc_id'], 'document', ['id']) + .addForeignKeyConstraint('tag_name_fk', ['tag_name'], 'tags', ['name']) + .addPrimaryKeyConstraint('doc_tag_relation_pk', ['doc_id', 'tag_name']) + .execute(); + + await db.schema + .createTable('permissions') + .addColumn('username', 'varchar', col => col.notNull()) + .addColumn('name', 'varchar', col => col.notNull()) + .addPrimaryKeyConstraint('permissions_pk', ['username', 'name']) + .addForeignKeyConstraint('username_fk', ['username'], 'users', ['username']) + .execute(); + + // create admin account. + await db + .insertInto('users') + .values({ + username: 'admin', + password_hash: 'unchecked', + password_salt: 'unchecked', + }) + .execute(); + + await db + .insertInto('schema_migration') + .values({ + version: '0.0.1', + dirty: false, + }) + .execute(); + + // create indexes + await db.schema.createIndex("index_document_basepath_filename") + .on("document") + .columns(["basepath", "filename"]) + .execute(); + await db.schema.createIndex("index_document_content_hash") + .on("document") + .columns(["content_hash"]) + .execute(); + await db.schema.createIndex("index_document_created_at") + .on("document") + .columns(["created_at"]) + .execute(); +} + +export async function down(db: Kysely) { + throw new Error('Downward migrations are not supported. Restore from backup.'); +} \ No newline at end of file -- 2.39.5 From 73fb3c94b3dce502308d8a5ae7adfb0ea0cf08ff Mon Sep 17 00:00:00 2001 From: monoid Date: Thu, 26 Jun 2025 20:08:20 +0900 Subject: [PATCH 2/3] =?UTF-8?q?migration=20code=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/server/gen_conf_schema.ts | 50 -- packages/server/migrations/2024-12-27.ts | 4 +- packages/server/migrations/2025-06-26.ts | 18 + packages/server/migrations/initial.ts | 90 --- packages/server/package.json | 24 +- packages/server/preload.ts | 7 - packages/server/src/database.ts | 70 +- packages/server/src/server.ts | 2 - packages/server/tools/migration.ts | 16 + pnpm-lock.yaml | 814 ++++++++++++----------- 10 files changed, 551 insertions(+), 544 deletions(-) delete mode 100644 packages/server/gen_conf_schema.ts create mode 100644 packages/server/migrations/2025-06-26.ts delete mode 100644 packages/server/migrations/initial.ts delete mode 100644 packages/server/preload.ts create mode 100644 packages/server/tools/migration.ts diff --git a/packages/server/gen_conf_schema.ts b/packages/server/gen_conf_schema.ts deleted file mode 100644 index f5a02b6..0000000 --- a/packages/server/gen_conf_schema.ts +++ /dev/null @@ -1,50 +0,0 @@ -// import { promises } from "fs"; -// const { readdir, writeFile } = promises; -// import { dirname, join } from "path"; -// import { createGenerator } from "ts-json-schema-generator"; - -// async function genSchema(path: string, typename: string) { -// const gen = createGenerator({ -// path: path, -// type: typename, -// tsconfig: "tsconfig.json", -// }); -// const schema = gen.createSchema(typename); -// if (schema.definitions != undefined) { -// const definitions = schema.definitions; -// const definition = definitions[typename]; -// if (typeof definition == "object") { -// let property = definition.properties; -// if (property) { -// property["$schema"] = { -// type: "string", -// }; -// } -// } -// } -// const text = JSON.stringify(schema); -// await writeFile(join(dirname(path), `${typename}.schema.json`), text); -// } -// function capitalize(s: string) { -// return s.charAt(0).toUpperCase() + s.slice(1); -// } -// async function setToALL(path: string) { -// console.log(`scan ${path}`); -// const direntry = await readdir(path, { withFileTypes: true }); -// const works = direntry -// .filter((x) => x.isFile() && x.name.endsWith("Config.ts")) -// .map((x) => { -// const name = x.name; -// const m = /(.+)\.ts/.exec(name); -// if (m !== null) { -// const typename = m[1]; -// return genSchema(join(path, typename), capitalize(typename)); -// } -// }); -// await Promise.all(works); -// const subdir = direntry.filter((x) => x.isDirectory()).map((x) => x.name); -// for (const x of subdir) { -// await setToALL(join(path, x)); -// } -// } -// setToALL("src"); diff --git a/packages/server/migrations/2024-12-27.ts b/packages/server/migrations/2024-12-27.ts index 36f097e..e62d503 100644 --- a/packages/server/migrations/2024-12-27.ts +++ b/packages/server/migrations/2024-12-27.ts @@ -65,8 +65,8 @@ export async function up(db: Kysely) { await db .insertInto('schema_migration') .values({ - version: '0.0.1', - dirty: false, + version: '2024-12-27', + dirty: 0, }) .execute(); diff --git a/packages/server/migrations/2025-06-26.ts b/packages/server/migrations/2025-06-26.ts new file mode 100644 index 0000000..08e8e77 --- /dev/null +++ b/packages/server/migrations/2025-06-26.ts @@ -0,0 +1,18 @@ +import { Kysely, sql } from 'kysely'; + +export async function up(db: Kysely) { + await db.schema + .createTable("user_settings") + .addColumn("username", "varchar(256)", col => col.notNull().primaryKey()) + .addColumn("settings", "jsonb", col => col.notNull()) + .addForeignKeyConstraint("user_settings_username_fk", ["username"], "users", ["username"]) + .execute(); + + await db.updateTable("schema_migration") + .set({ version: "2025-06-26", dirty: 0 }) + .execute(); +} + +export async function down(db: Kysely) { + throw new Error('Downward migrations are not supported. Restore from backup.'); +} \ No newline at end of file diff --git a/packages/server/migrations/initial.ts b/packages/server/migrations/initial.ts deleted file mode 100644 index 36f097e..0000000 --- a/packages/server/migrations/initial.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { Kysely, sql } from 'kysely'; - -export async function up(db: Kysely) { - await db.schema - .createTable('schema_migration') - .addColumn('version', 'char(16)') - .addColumn('dirty', 'boolean') - .execute(); - - await db.schema - .createTable('users') - .addColumn('username', 'varchar(256)', col => col.primaryKey()) - .addColumn('password_hash', 'varchar(64)', col => col.notNull()) - .addColumn('password_salt', 'varchar(64)', col => col.notNull()) - .execute(); - - await db.schema - .createTable('document') - .addColumn('id', 'serial', col => col.primaryKey()) - .addColumn('title', 'varchar(512)', col => col.notNull()) - .addColumn('content_type', 'varchar(16)', col => col.notNull()) - .addColumn('basepath', 'varchar(256)', col => col.notNull()) - .addColumn('filename', 'varchar(512)', col => col.notNull()) - .addColumn('content_hash', 'varchar') - .addColumn('additional', 'json') - .addColumn("pagenum", "integer", col => col.notNull()) - .addColumn('created_at', 'integer', col => col.notNull()) - .addColumn('modified_at', 'integer', col => col.notNull()) - .addColumn('deleted_at', 'integer') - .execute(); - - await db.schema - .createTable('tags') - .addColumn('name', 'varchar', col => col.primaryKey()) - .addColumn('description', 'text') - .execute(); - - await db.schema - .createTable('doc_tag_relation') - .addColumn('doc_id', 'integer', col => col.notNull()) - .addColumn('tag_name', 'varchar', col => col.notNull()) - .addForeignKeyConstraint('doc_id_fk', ['doc_id'], 'document', ['id']) - .addForeignKeyConstraint('tag_name_fk', ['tag_name'], 'tags', ['name']) - .addPrimaryKeyConstraint('doc_tag_relation_pk', ['doc_id', 'tag_name']) - .execute(); - - await db.schema - .createTable('permissions') - .addColumn('username', 'varchar', col => col.notNull()) - .addColumn('name', 'varchar', col => col.notNull()) - .addPrimaryKeyConstraint('permissions_pk', ['username', 'name']) - .addForeignKeyConstraint('username_fk', ['username'], 'users', ['username']) - .execute(); - - // create admin account. - await db - .insertInto('users') - .values({ - username: 'admin', - password_hash: 'unchecked', - password_salt: 'unchecked', - }) - .execute(); - - await db - .insertInto('schema_migration') - .values({ - version: '0.0.1', - dirty: false, - }) - .execute(); - - // create indexes - await db.schema.createIndex("index_document_basepath_filename") - .on("document") - .columns(["basepath", "filename"]) - .execute(); - await db.schema.createIndex("index_document_content_hash") - .on("document") - .columns(["content_hash"]) - .execute(); - await db.schema.createIndex("index_document_created_at") - .on("document") - .columns(["created_at"]) - .execute(); -} - -export async function down(db: Kysely) { - throw new Error('Downward migrations are not supported. Restore from backup.'); -} \ No newline at end of file diff --git a/packages/server/package.json b/packages/server/package.json index 978741a..1086e23 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -6,37 +6,37 @@ "type": "module", "scripts": { "dev": "tsx watch src/app.ts", - "start": "tsx src/app.ts" + "start": "tsx src/app.ts", + "migrate": "tsx tools/migration.ts" }, "author": "", "license": "ISC", "dependencies": { - "@std/async": "npm:@jsr/std__async@^1.0.12", - "@zip.js/zip.js": "^2.7.60", + "@std/async": "npm:@jsr/std__async@^1.0.13", + "@zip.js/zip.js": "^2.7.62", "better-sqlite3": "^9.6.0", "chokidar": "^3.6.0", "dbtype": "workspace:dbtype", - "dotenv": "^16.4.5", - "jose": "^5.9.3", - "koa": "^2.15.3", + "dotenv": "^16.5.0", + "jose": "^5.10.0", + "koa": "^2.16.1", "koa-bodyparser": "^4.4.1", "koa-compose": "^4.1.0", "koa-router": "^12.0.1", - "kysely": "^0.27.4", + "kysely": "^0.27.6", "natural-orderby": "^2.0.3", "tiny-async-pool": "^1.3.0" }, "devDependencies": { - "@types/better-sqlite3": "^7.6.11", + "@types/better-sqlite3": "^7.6.13", "@types/jsonwebtoken": "^8.5.9", "@types/koa": "^2.15.0", "@types/koa-bodyparser": "^4.3.12", "@types/koa-compose": "^3.2.8", "@types/koa-router": "^7.4.8", - "@types/node": "^22.15.3", + "@types/node": "^22.15.33", "@types/tiny-async-pool": "^1.0.5", - "nodemon": "^3.1.7", - "tsx": "^4.19.1", - "typescript": "^5.6.2" + "tsx": "^4.20.3", + "typescript": "^5.8.3" } } diff --git a/packages/server/preload.ts b/packages/server/preload.ts deleted file mode 100644 index 396815a..0000000 --- a/packages/server/preload.ts +++ /dev/null @@ -1,7 +0,0 @@ -// import { contextBridge, ipcRenderer } from "electron"; - -// contextBridge.exposeInMainWorld("electron", { -// passwordReset: async (username: string, toPw: string) => { -// return await ipcRenderer.invoke("reset_password", username, toPw); -// }, -// }); diff --git a/packages/server/src/database.ts b/packages/server/src/database.ts index 88a5063..1932dd0 100644 --- a/packages/server/src/database.ts +++ b/packages/server/src/database.ts @@ -1,14 +1,16 @@ import { Kysely } from "kysely"; import { getKysely } from "./db/kysely.ts"; +import fs from "node:fs/promises"; +import path from "path"; export async function connectDB() { const kysely = getKysely(); let tries = 0; - for (;;) { + for (; ;) { try { console.log("try to connect db"); - await kysely.selectNoFrom(eb=> eb.val(1).as("dummy")).execute(); + await kysely.selectNoFrom(eb => eb.val(1).as("dummy")).execute(); console.log("connect success"); } catch (err) { if (tries < 3) { @@ -25,20 +27,72 @@ export async function connectDB() { } async function checkTableExists(kysely: Kysely, table: string) { - const result = await kysely.selectFrom("sqlite_master").where("type", "=", "table").where("name", "=", table).executeTakeFirst(); + const result = await kysely.selectFrom("sqlite_master") + .selectAll() + .where("type", "=", "table") + .where("name", "=", table) + .executeTakeFirst(); return result !== undefined; -} +} export async function migrateDB() { const kysely = getKysely(); - let version_number = 0; // is schema_migration exists? const hasTable = await checkTableExists(kysely, "schema_migration"); if (!hasTable) { - // migrate from 0 - // create schema_migration + // 2. 마이그레이션 실행 (최초 마이그레이션) + const migration = await import("../migrations/2024-12-27.ts"); + await migration.up(kysely); + console.log("최초 마이그레이션 완료"); + return; } - const version = await kysely.selectFrom("schema_migration").executeTakeFirst(); + // 현재 버전 확인 + const row = await kysely.selectFrom("schema_migration").selectAll().executeTakeFirst(); + const currentVersion = row?.version ?? "0001-01-01"; // 기본값 설정 + // 마이그레이션 목록 정의 (버전순 정렬 필수) + const migrations = await readMigrations(); + + // 현재 버전보다 높은 migration만 실행 + let lastestVersion = currentVersion; + console.log(`현재 DB 버전: ${currentVersion}`); + for (const m of migrations) { + if (compareVersion(m.version, currentVersion) > 0) { + console.log(`마이그레이션 실행: ${m.version}`); + const migration = await import(m.file); + await migration.up(kysely); + await kysely.updateTable("schema_migration") + .set({ version: m.version, dirty: 0 }) + .execute(); + lastestVersion = m.version; + console.log(`마이그레이션 완료: ${m.version}`); + } + } + if (lastestVersion !== currentVersion) { + console.log(`마이그레이션 완료. ${currentVersion} -> ${lastestVersion}`); + } else { + console.log("마이그레이션 필요 없음"); + } + return; +} + +async function readMigrations(): Promise<{ version: string; file: string }[]> { + const migrationsDir = path.join(import.meta.dirname, "../migrations"); + const files = (await fs.readdir(migrationsDir)) + .filter(file => file.endsWith(".ts")) + .map(file => { + const version = file.match(/(\d{4}-\d{2}-\d{2})/)?.[0] || "0001-01-01"; + return { version, file: `../migrations/${file}` }; + }); + return files.sort((a, b) => compareVersion(a.version, b.version)); +} + +// Date 기반 버전 비교 함수. +function compareVersion(a: string, b: string): number { + const dateA = new Date(a); + const dateB = new Date(b); + if (dateA < dateB) return -1; + if (dateA > dateB) return 1; + return 0; // 같을 경우 } \ No newline at end of file diff --git a/packages/server/src/server.ts b/packages/server/src/server.ts index e9f2e49..6726d30 100644 --- a/packages/server/src/server.ts +++ b/packages/server/src/server.ts @@ -238,8 +238,6 @@ class ServerApplication { static async createServer() { const db = await connectDB(); - // todo : db migration - const app = new ServerApplication({ userController: createSqliteUserController(db), documentController: createSqliteDocumentAccessor(db), diff --git a/packages/server/tools/migration.ts b/packages/server/tools/migration.ts new file mode 100644 index 0000000..238ddde --- /dev/null +++ b/packages/server/tools/migration.ts @@ -0,0 +1,16 @@ +import { migrateDB } from "../src/database.ts"; +import { config } from "dotenv"; + +config(); // Load environment variables from .env file + +export async function runMigration() { + try { + await migrateDB(); + console.log("Database migration completed successfully."); + } catch (error) { + console.error("Database migration failed:", error); + process.exit(1); + } +} + +await runMigration(); \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b85f140..2b06c91 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -170,11 +170,11 @@ importers: packages/server: dependencies: '@std/async': - specifier: npm:@jsr/std__async@^1.0.12 - version: '@jsr/std__async@1.0.12' + specifier: npm:@jsr/std__async@^1.0.13 + version: '@jsr/std__async@1.0.13' '@zip.js/zip.js': - specifier: ^2.7.60 - version: 2.7.60 + specifier: ^2.7.62 + version: 2.7.62 better-sqlite3: specifier: ^9.6.0 version: 9.6.0 @@ -185,14 +185,14 @@ importers: specifier: workspace:dbtype version: link:../dbtype dotenv: - specifier: ^16.4.5 - version: 16.4.5 + specifier: ^16.5.0 + version: 16.5.0 jose: - specifier: ^5.9.3 - version: 5.9.3 + specifier: ^5.10.0 + version: 5.10.0 koa: - specifier: ^2.15.3 - version: 2.15.3 + specifier: ^2.16.1 + version: 2.16.1 koa-bodyparser: specifier: ^4.4.1 version: 4.4.1 @@ -203,8 +203,8 @@ importers: specifier: ^12.0.1 version: 12.0.1 kysely: - specifier: ^0.27.4 - version: 0.27.4 + specifier: ^0.27.6 + version: 0.27.6 natural-orderby: specifier: ^2.0.3 version: 2.0.3 @@ -213,8 +213,8 @@ importers: version: 1.3.0 devDependencies: '@types/better-sqlite3': - specifier: ^7.6.11 - version: 7.6.11 + specifier: ^7.6.13 + version: 7.6.13 '@types/jsonwebtoken': specifier: ^8.5.9 version: 8.5.9 @@ -231,20 +231,17 @@ importers: specifier: ^7.4.8 version: 7.4.8 '@types/node': - specifier: ^22.15.3 - version: 22.15.3 + specifier: ^22.15.33 + version: 22.15.33 '@types/tiny-async-pool': specifier: ^1.0.5 version: 1.0.5 - nodemon: - specifier: ^3.1.7 - version: 3.1.7 tsx: - specifier: ^4.19.1 - version: 4.19.1 + specifier: ^4.20.3 + version: 4.20.3 typescript: - specifier: ^5.6.2 - version: 5.6.2 + specifier: ^5.8.3 + version: 5.8.3 packages: @@ -430,8 +427,8 @@ packages: cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.23.1': - resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==} + '@esbuild/aix-ppc64@0.25.5': + resolution: {integrity: sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] @@ -442,8 +439,8 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.23.1': - resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==} + '@esbuild/android-arm64@0.25.5': + resolution: {integrity: sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==} engines: {node: '>=18'} cpu: [arm64] os: [android] @@ -454,8 +451,8 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-arm@0.23.1': - resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==} + '@esbuild/android-arm@0.25.5': + resolution: {integrity: sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==} engines: {node: '>=18'} cpu: [arm] os: [android] @@ -466,8 +463,8 @@ packages: cpu: [x64] os: [android] - '@esbuild/android-x64@0.23.1': - resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==} + '@esbuild/android-x64@0.25.5': + resolution: {integrity: sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==} engines: {node: '>=18'} cpu: [x64] os: [android] @@ -478,8 +475,8 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.23.1': - resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==} + '@esbuild/darwin-arm64@0.25.5': + resolution: {integrity: sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] @@ -490,8 +487,8 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.23.1': - resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==} + '@esbuild/darwin-x64@0.25.5': + resolution: {integrity: sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] @@ -502,8 +499,8 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.23.1': - resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==} + '@esbuild/freebsd-arm64@0.25.5': + resolution: {integrity: sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] @@ -514,8 +511,8 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.23.1': - resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==} + '@esbuild/freebsd-x64@0.25.5': + resolution: {integrity: sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] @@ -526,8 +523,8 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.23.1': - resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==} + '@esbuild/linux-arm64@0.25.5': + resolution: {integrity: sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==} engines: {node: '>=18'} cpu: [arm64] os: [linux] @@ -538,8 +535,8 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.23.1': - resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==} + '@esbuild/linux-arm@0.25.5': + resolution: {integrity: sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==} engines: {node: '>=18'} cpu: [arm] os: [linux] @@ -550,8 +547,8 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.23.1': - resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==} + '@esbuild/linux-ia32@0.25.5': + resolution: {integrity: sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==} engines: {node: '>=18'} cpu: [ia32] os: [linux] @@ -562,8 +559,8 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.23.1': - resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==} + '@esbuild/linux-loong64@0.25.5': + resolution: {integrity: sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==} engines: {node: '>=18'} cpu: [loong64] os: [linux] @@ -574,8 +571,8 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.23.1': - resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==} + '@esbuild/linux-mips64el@0.25.5': + resolution: {integrity: sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] @@ -586,8 +583,8 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.23.1': - resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==} + '@esbuild/linux-ppc64@0.25.5': + resolution: {integrity: sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] @@ -598,8 +595,8 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.23.1': - resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==} + '@esbuild/linux-riscv64@0.25.5': + resolution: {integrity: sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] @@ -610,8 +607,8 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.23.1': - resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==} + '@esbuild/linux-s390x@0.25.5': + resolution: {integrity: sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==} engines: {node: '>=18'} cpu: [s390x] os: [linux] @@ -622,26 +619,32 @@ packages: cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.23.1': - resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==} + '@esbuild/linux-x64@0.25.5': + resolution: {integrity: sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==} engines: {node: '>=18'} cpu: [x64] os: [linux] + '@esbuild/netbsd-arm64@0.25.5': + resolution: {integrity: sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@esbuild/netbsd-x64@0.21.5': resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.23.1': - resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==} + '@esbuild/netbsd-x64@0.25.5': + resolution: {integrity: sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.23.1': - resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==} + '@esbuild/openbsd-arm64@0.25.5': + resolution: {integrity: sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] @@ -652,8 +655,8 @@ packages: cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.23.1': - resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==} + '@esbuild/openbsd-x64@0.25.5': + resolution: {integrity: sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] @@ -664,8 +667,8 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.23.1': - resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==} + '@esbuild/sunos-x64@0.25.5': + resolution: {integrity: sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] @@ -676,8 +679,8 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.23.1': - resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==} + '@esbuild/win32-arm64@0.25.5': + resolution: {integrity: sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==} engines: {node: '>=18'} cpu: [arm64] os: [win32] @@ -688,8 +691,8 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.23.1': - resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==} + '@esbuild/win32-ia32@0.25.5': + resolution: {integrity: sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==} engines: {node: '>=18'} cpu: [ia32] os: [win32] @@ -700,8 +703,8 @@ packages: cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.23.1': - resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==} + '@esbuild/win32-x64@0.25.5': + resolution: {integrity: sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -777,8 +780,8 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - '@jsr/std__async@1.0.12': - resolution: {integrity: sha512-NUaSOcwMetVeVkIqet2Ammy2A5YxG8ViFxryBbTaC4h7l/cgAkU59U3zF58ek4Y8HZ0Nx5De7qBptPfp62kcgw==, tarball: https://npm.jsr.io/~/11/@jsr/std__async/1.0.12.tgz} + '@jsr/std__async@1.0.13': + resolution: {integrity: sha512-GEApyNtzauJ0kEZ/GxebSkdEN0t29qJtkw+WEvzYTwkL6fHX8cq3YWzRjCqHu+4jMl+rpHiwyr/lfitNInntzA==, tarball: https://npm.jsr.io/~/11/@jsr/std__async/1.0.13.tgz} '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -1402,23 +1405,23 @@ packages: '@types/accepts@1.3.7': resolution: {integrity: sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==} - '@types/better-sqlite3@7.6.11': - resolution: {integrity: sha512-i8KcD3PgGtGBLl3+mMYA8PdKkButvPyARxA7IQAd6qeslht13qxb1zzO8dRCtE7U3IoJS782zDBAeoKiM695kg==} + '@types/better-sqlite3@7.6.13': + resolution: {integrity: sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==} '@types/better-sqlite3@7.6.9': resolution: {integrity: sha512-FvktcujPDj9XKMJQWFcl2vVl7OdRIqsSRX9b0acWwTmwLK9CF2eqo/FRcmMLNpugKoX/avA6pb7TorDLmpgTnQ==} - '@types/body-parser@1.19.5': - resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} + '@types/body-parser@1.19.6': + resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==} '@types/connect@3.4.38': resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} - '@types/content-disposition@0.5.8': - resolution: {integrity: sha512-QVSSvno3dE0MgO76pJhmv4Qyi/j0Yk9pBp0Y7TJ2Tlj+KCgJWY6qX7nnxCOLkZ3VYRSIk1WTxCvwUSdx6CCLdg==} + '@types/content-disposition@0.5.9': + resolution: {integrity: sha512-8uYXI3Gw35MhiVYhG3s295oihrxRyytcRHjSjqnqZVDDy/xcGBRny7+Xj1Wgfhv5QzRtN2hB2dVRBUX9XW3UcQ==} - '@types/cookies@0.9.0': - resolution: {integrity: sha512-40Zk8qR147RABiQ7NQnBzWzDcjKzNrntB5BAmeGCb2p/MIyOE+4BVvc17wumsUqUw00bJYqoXFHYygQnEFh4/Q==} + '@types/cookies@0.9.1': + resolution: {integrity: sha512-E/DPgzifH4sM1UMadJMWd6mO2jOd4g1Ejwzx8/uRCDpJis1IrlyQEcGAYEomtAqRYmD5ORbNXMeI9U0RiVGZbg==} '@types/d3-array@3.2.1': resolution: {integrity: sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==} @@ -1453,17 +1456,17 @@ packages: '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - '@types/express-serve-static-core@5.0.0': - resolution: {integrity: sha512-AbXMTZGt40T+KON9/Fdxx0B2WK5hsgxcfXJLr5bFpZ7b4JCex2WyQPTEKdXqfHiY5nKKBScZ7yCoO6Pvgxfvnw==} + '@types/express-serve-static-core@5.0.6': + resolution: {integrity: sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==} - '@types/express@5.0.0': - resolution: {integrity: sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==} + '@types/express@5.0.3': + resolution: {integrity: sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==} - '@types/http-assert@1.5.5': - resolution: {integrity: sha512-4+tE/lwdAahgZT1g30Jkdm9PzFRde0xwxBNUyRsCitRvCQB90iuA2uJYdUnhnANRcqGXaWOGY4FEoxeElNAK2g==} + '@types/http-assert@1.5.6': + resolution: {integrity: sha512-TTEwmtjgVbYAzZYWyeHPrrtWnfVkm8tQkP8P21uQifPgMRgjrow3XDEYqucuC8SKZJT7pUnhU/JymvjggxO9vw==} - '@types/http-errors@2.0.4': - resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} + '@types/http-errors@2.0.5': + resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} '@types/jsonwebtoken@8.5.9': resolution: {integrity: sha512-272FMnFGzAVMGtu9tkr29hRL6bZj4Zs1KZNeHLnKqAvp06tAIcarTMwOh8/8bz4FmKRcMxZhZNeUAQsNLoiPhg==} @@ -1486,17 +1489,20 @@ packages: '@types/mime@1.3.5': resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} - '@types/node@22.15.3': - resolution: {integrity: sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==} - '@types/node@22.15.30': resolution: {integrity: sha512-6Q7lr06bEHdlfplU6YRbgG1SFBdlsfNC4/lX+SkhiTs0cpJkOElmWls8PxDFv4yY/xKb8Y6SO0OmSX4wgqTZbA==} + '@types/node@22.15.33': + resolution: {integrity: sha512-wzoocdnnpSxZ+6CjW4ADCK1jVmd1S/J3ArNWfn8FDDQtRm8dkDg7TA+mvek2wNrfCgwuZxqEOiB9B1XCJ6+dbw==} + + '@types/node@24.0.4': + resolution: {integrity: sha512-ulyqAkrhnuNq9pB76DRBTkcS6YsmDALy6Ua63V8OhrOBgbcYt6IOdzpw5P1+dyRIyMerzLkeYWBeOXPpA9GMAA==} + '@types/prop-types@15.7.14': resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==} - '@types/qs@6.9.16': - resolution: {integrity: sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==} + '@types/qs@6.14.0': + resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==} '@types/range-parser@1.2.7': resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} @@ -1509,11 +1515,11 @@ packages: '@types/react@18.3.23': resolution: {integrity: sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==} - '@types/send@0.17.4': - resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} + '@types/send@0.17.5': + resolution: {integrity: sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==} - '@types/serve-static@1.15.7': - resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} + '@types/serve-static@1.15.8': + resolution: {integrity: sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==} '@types/tiny-async-pool@1.0.5': resolution: {integrity: sha512-8hqr+s4rBthBtb+k02NXejl7BGVbj7CD/ZB2rMSvoSjXO52aXbtm9q/JEey5uDjzADs/zXEo7bU9iX+M6glAUA==} @@ -1613,8 +1619,8 @@ packages: '@vitest/utils@2.1.9': resolution: {integrity: sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==} - '@zip.js/zip.js@2.7.60': - resolution: {integrity: sha512-vA3rLyqdxBrVo1FWSsbyoecaqWTV+vgPRf0QKeM7kVDG0r+lHUqd7zQDv1TO9k4BcAoNzNDSNrrel24Mk6addA==} + '@zip.js/zip.js@2.7.62': + resolution: {integrity: sha512-OaLvZ8j4gCkLn048ypkZu29KX30r8/OfFF2w4Jo5WXFr+J04J+lzJ5TKZBVgFXhlvSkqNFQdfnY1Q8TMTCyBVA==} engines: {bun: '>=0.7.0', deno: '>=1.0.0', node: '>=16.5.0'} accepts@1.3.8: @@ -1752,8 +1758,12 @@ packages: resolution: {integrity: sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==} engines: {node: '>= 6.0.0'} - call-bind@1.0.7: - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} engines: {node: '>= 0.4'} callsites@3.1.0: @@ -1935,15 +1945,6 @@ packages: resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} engines: {node: '>= 12'} - debug@4.3.7: - resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - debug@4.4.1: resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} engines: {node: '>=6.0'} @@ -1977,10 +1978,6 @@ packages: defaults@1.0.4: resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} - define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} - delegates@1.0.0: resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} @@ -2004,6 +2001,10 @@ packages: resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} engines: {node: '>=8'} + detect-libc@2.0.4: + resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==} + engines: {node: '>=8'} + detect-node-es@1.1.0: resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} @@ -2036,10 +2037,14 @@ packages: resolution: {integrity: sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==} engines: {node: '>=12'} - dotenv@16.4.5: - resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} + dotenv@16.5.0: + resolution: {integrity: sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==} engines: {node: '>=12'} + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -2062,11 +2067,14 @@ packages: end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - es-define-property@1.0.0: - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} es-errors@1.3.0: @@ -2076,13 +2084,17 @@ packages: es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + esbuild@0.21.5: resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} engines: {node: '>=12'} hasBin: true - esbuild@0.23.1: - resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==} + esbuild@0.25.5: + resolution: {integrity: sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==} engines: {node: '>=18'} hasBin: true @@ -2252,20 +2264,24 @@ packages: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} - get-intrinsic@1.2.4: - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} get-nonce@1.0.1: resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} engines: {node: '>=6'} + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} - get-tsconfig@4.8.1: - resolution: {integrity: sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==} + get-tsconfig@4.10.1: + resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==} git-diff@2.0.6: resolution: {integrity: sha512-/Iu4prUrydE3Pb3lCBMbcSNIf81tgGt0W1ZwknnyF62t3tHmtiJTRj0f+1ZIhp3+Rh0ktz1pJVoa7ZXUCskivA==} @@ -2302,8 +2318,9 @@ packages: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} - gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -2319,15 +2336,8 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - - has-proto@1.0.3: - resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} - engines: {node: '>= 0.4'} - - has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} engines: {node: '>= 0.4'} has-tostringtag@1.0.2: @@ -2365,9 +2375,6 @@ packages: ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - ignore-by-default@1.0.1: - resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} - ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -2421,8 +2428,8 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-generator-function@1.0.10: - resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + is-generator-function@1.1.0: + resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} engines: {node: '>= 0.4'} is-glob@4.0.3: @@ -2441,6 +2448,10 @@ packages: resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} engines: {node: '>=8'} + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + is-stream@3.0.0: resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -2459,8 +2470,8 @@ packages: resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} hasBin: true - jose@5.9.3: - resolution: {integrity: sha512-egLIoYSpcd+QUF+UHgobt5YzI2Pkw/H39ou9suW687MY6PmCwPmkNV/4TNjn1p2tX5xO3j0d0sq5hiYE24bSlg==} + jose@5.10.0: + resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==} jotai@2.12.5: resolution: {integrity: sha512-G8m32HW3lSmcz/4mbqx0hgJIQ0ekndKWiYP7kWVKi0p6saLXdSoye+FZiOFyonnd7Q482LCzm8sMDl7Ar1NWDw==} @@ -2532,8 +2543,8 @@ packages: resolution: {integrity: sha512-gaDdj3GtzoLoeosacd50kBBTnnh3B9AYxDThQUo4sfUyXdOhY6ku1qyZKW88tQCRgc3Sw6ChXYXWZwwgjOxE0w==} engines: {node: '>= 12'} - koa@2.15.3: - resolution: {integrity: sha512-j/8tY9j5t+GVMLeioLaxweJiKUayFhlGqNTzf2ZGwL0ZCQijd2RLHK0SLW5Tsko8YyyqCZC2cojIb0/s62qTAg==} + koa@2.16.1: + resolution: {integrity: sha512-umfX9d3iuSxTQP4pnzLOz0HKnPg0FaUUIKcye2lOiz3KPu1Y3M3xlz76dISdFPQs37P9eJz1wUpcTS6KDPn9fA==} engines: {node: ^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4} kysely-codegen@0.14.1: @@ -2571,8 +2582,8 @@ packages: resolution: {integrity: sha512-lG03Ru+XyOJFsjH3OMY6R/9U38IjDPfnOfDgO3ynhbDr+Dz8fak+X6L62vqu3iybQnj+lG84OttBuU9KY3L9kA==} engines: {node: '>=14.0.0'} - kysely@0.27.4: - resolution: {integrity: sha512-dyNKv2KRvYOQPLCAOCjjQuCk4YFd33BvGdf/o5bC7FiW+BB6snA81Zt+2wT9QDFzKqxKa5rrOmvlK/anehCcgA==} + kysely@0.27.6: + resolution: {integrity: sha512-FIyV/64EkKhJmjgC0g2hygpBv5RNWVPyNCqSAD7eTCv6eFWNIi4PN1UvdSJGicN/o35bnevgis4Y0UDC0qi8jQ==} engines: {node: '>=14.0.0'} levn@0.4.1: @@ -2638,6 +2649,10 @@ packages: magic-string@0.30.17: resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} @@ -2724,6 +2739,9 @@ packages: napi-build-utils@1.0.2: resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} + napi-build-utils@2.0.0: + resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} + natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} @@ -2738,6 +2756,10 @@ packages: resolution: {integrity: sha512-7vbj10trelExNjFSBm5kTvZXXa7pZyKWx9RCKIyqe6I9Ev3IzGpQoqBP3a+cOdxY+pWj6VkP28n/2wWysBHD/A==} engines: {node: '>=10'} + node-abi@3.75.0: + resolution: {integrity: sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==} + engines: {node: '>=10'} + node-domexception@1.0.0: resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} engines: {node: '>=10.5.0'} @@ -2750,11 +2772,6 @@ packages: node-releases@2.0.19: resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} - nodemon@3.1.7: - resolution: {integrity: sha512-hLj7fuMow6f0lbB0cD14Lz2xNjwsyruH251Pk4t/yIitCFJbmY1myuLlHm/q06aST4jg6EgAh74PIBBrRqpVAQ==} - engines: {node: '>=10'} - hasBin: true - normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -2775,8 +2792,8 @@ packages: resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} engines: {node: '>= 6'} - object-inspect@1.13.2: - resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} engines: {node: '>= 0.4'} on-finished@2.4.1: @@ -2929,6 +2946,11 @@ packages: engines: {node: '>=10'} hasBin: true + prebuild-install@7.1.3: + resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==} + engines: {node: '>=10'} + hasBin: true + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -2940,18 +2962,18 @@ packages: prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} - pstree.remy@1.1.8: - resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==} - pump@3.0.2: resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} + pump@3.0.3: + resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - qs@6.13.0: - resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} + qs@6.14.0: + resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} engines: {node: '>=0.6'} queue-microtask@1.2.3: @@ -3097,6 +3119,10 @@ packages: safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -3111,20 +3137,11 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.6.3: - resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} - engines: {node: '>=10'} - hasBin: true - semver@7.7.2: resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} engines: {node: '>=10'} hasBin: true - set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} - setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} @@ -3149,8 +3166,20 @@ packages: engines: {node: '>=4'} hasBin: true - side-channel@1.0.6: - resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} engines: {node: '>= 0.4'} siginfo@2.0.0: @@ -3169,10 +3198,6 @@ packages: simple-get@4.0.1: resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} - simple-update-notifier@2.0.0: - resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} - engines: {node: '>=10'} - sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} @@ -3279,6 +3304,9 @@ packages: tar-fs@2.1.1: resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} + tar-fs@2.1.3: + resolution: {integrity: sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==} + tar-stream@2.2.0: resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} engines: {node: '>=6'} @@ -3325,10 +3353,6 @@ packages: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} - touch@3.1.1: - resolution: {integrity: sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==} - hasBin: true - ts-api-utils@1.4.3: resolution: {integrity: sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==} engines: {node: '>=16'} @@ -3352,8 +3376,8 @@ packages: resolution: {integrity: sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==} engines: {node: '>=0.6.x'} - tsx@4.19.1: - resolution: {integrity: sha512-0flMz1lh74BR4wOvBjuh9olbnwqCPc35OOlfyzHba0Dc+QNUeWX/Gq2YTbnwcWPO3BMd8fkzRVrHcsR+a7z7rA==} + tsx@4.20.3: + resolution: {integrity: sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ==} engines: {node: '>=18.0.0'} hasBin: true @@ -3377,22 +3401,17 @@ packages: engines: {node: '>=14.17'} hasBin: true - typescript@5.6.2: - resolution: {integrity: sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==} - engines: {node: '>=14.17'} - hasBin: true - typescript@5.8.3: resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} engines: {node: '>=14.17'} hasBin: true - undefsafe@2.0.5: - resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} - undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + undici-types@7.8.0: + resolution: {integrity: sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==} + universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} @@ -3782,142 +3801,145 @@ snapshots: '@esbuild/aix-ppc64@0.21.5': optional: true - '@esbuild/aix-ppc64@0.23.1': + '@esbuild/aix-ppc64@0.25.5': optional: true '@esbuild/android-arm64@0.21.5': optional: true - '@esbuild/android-arm64@0.23.1': + '@esbuild/android-arm64@0.25.5': optional: true '@esbuild/android-arm@0.21.5': optional: true - '@esbuild/android-arm@0.23.1': + '@esbuild/android-arm@0.25.5': optional: true '@esbuild/android-x64@0.21.5': optional: true - '@esbuild/android-x64@0.23.1': + '@esbuild/android-x64@0.25.5': optional: true '@esbuild/darwin-arm64@0.21.5': optional: true - '@esbuild/darwin-arm64@0.23.1': + '@esbuild/darwin-arm64@0.25.5': optional: true '@esbuild/darwin-x64@0.21.5': optional: true - '@esbuild/darwin-x64@0.23.1': + '@esbuild/darwin-x64@0.25.5': optional: true '@esbuild/freebsd-arm64@0.21.5': optional: true - '@esbuild/freebsd-arm64@0.23.1': + '@esbuild/freebsd-arm64@0.25.5': optional: true '@esbuild/freebsd-x64@0.21.5': optional: true - '@esbuild/freebsd-x64@0.23.1': + '@esbuild/freebsd-x64@0.25.5': optional: true '@esbuild/linux-arm64@0.21.5': optional: true - '@esbuild/linux-arm64@0.23.1': + '@esbuild/linux-arm64@0.25.5': optional: true '@esbuild/linux-arm@0.21.5': optional: true - '@esbuild/linux-arm@0.23.1': + '@esbuild/linux-arm@0.25.5': optional: true '@esbuild/linux-ia32@0.21.5': optional: true - '@esbuild/linux-ia32@0.23.1': + '@esbuild/linux-ia32@0.25.5': optional: true '@esbuild/linux-loong64@0.21.5': optional: true - '@esbuild/linux-loong64@0.23.1': + '@esbuild/linux-loong64@0.25.5': optional: true '@esbuild/linux-mips64el@0.21.5': optional: true - '@esbuild/linux-mips64el@0.23.1': + '@esbuild/linux-mips64el@0.25.5': optional: true '@esbuild/linux-ppc64@0.21.5': optional: true - '@esbuild/linux-ppc64@0.23.1': + '@esbuild/linux-ppc64@0.25.5': optional: true '@esbuild/linux-riscv64@0.21.5': optional: true - '@esbuild/linux-riscv64@0.23.1': + '@esbuild/linux-riscv64@0.25.5': optional: true '@esbuild/linux-s390x@0.21.5': optional: true - '@esbuild/linux-s390x@0.23.1': + '@esbuild/linux-s390x@0.25.5': optional: true '@esbuild/linux-x64@0.21.5': optional: true - '@esbuild/linux-x64@0.23.1': + '@esbuild/linux-x64@0.25.5': + optional: true + + '@esbuild/netbsd-arm64@0.25.5': optional: true '@esbuild/netbsd-x64@0.21.5': optional: true - '@esbuild/netbsd-x64@0.23.1': + '@esbuild/netbsd-x64@0.25.5': optional: true - '@esbuild/openbsd-arm64@0.23.1': + '@esbuild/openbsd-arm64@0.25.5': optional: true '@esbuild/openbsd-x64@0.21.5': optional: true - '@esbuild/openbsd-x64@0.23.1': + '@esbuild/openbsd-x64@0.25.5': optional: true '@esbuild/sunos-x64@0.21.5': optional: true - '@esbuild/sunos-x64@0.23.1': + '@esbuild/sunos-x64@0.25.5': optional: true '@esbuild/win32-arm64@0.21.5': optional: true - '@esbuild/win32-arm64@0.23.1': + '@esbuild/win32-arm64@0.25.5': optional: true '@esbuild/win32-ia32@0.21.5': optional: true - '@esbuild/win32-ia32@0.23.1': + '@esbuild/win32-ia32@0.25.5': optional: true '@esbuild/win32-x64@0.21.5': optional: true - '@esbuild/win32-x64@0.23.1': + '@esbuild/win32-x64@0.25.5': optional: true '@eslint-community/eslint-utils@4.7.0(eslint@8.57.1)': @@ -4000,7 +4022,7 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 - '@jsr/std__async@1.0.12': {} + '@jsr/std__async@1.0.13': {} '@nodelib/fs.scandir@2.1.5': dependencies: @@ -4560,33 +4582,33 @@ snapshots: '@types/accepts@1.3.7': dependencies: - '@types/node': 22.15.3 + '@types/node': 22.15.33 - '@types/better-sqlite3@7.6.11': + '@types/better-sqlite3@7.6.13': dependencies: - '@types/node': 22.15.3 + '@types/node': 22.15.33 '@types/better-sqlite3@7.6.9': dependencies: - '@types/node': 22.15.30 + '@types/node': 24.0.4 - '@types/body-parser@1.19.5': + '@types/body-parser@1.19.6': dependencies: '@types/connect': 3.4.38 - '@types/node': 22.15.3 + '@types/node': 22.15.33 '@types/connect@3.4.38': dependencies: - '@types/node': 22.15.3 + '@types/node': 22.15.33 - '@types/content-disposition@0.5.8': {} + '@types/content-disposition@0.5.9': {} - '@types/cookies@0.9.0': + '@types/cookies@0.9.1': dependencies: '@types/connect': 3.4.38 - '@types/express': 5.0.0 + '@types/express': 5.0.3 '@types/keygrip': 1.0.6 - '@types/node': 22.15.3 + '@types/node': 22.15.33 '@types/d3-array@3.2.1': {} @@ -4616,27 +4638,26 @@ snapshots: '@types/estree@1.0.8': {} - '@types/express-serve-static-core@5.0.0': + '@types/express-serve-static-core@5.0.6': dependencies: - '@types/node': 22.15.3 - '@types/qs': 6.9.16 + '@types/node': 22.15.33 + '@types/qs': 6.14.0 '@types/range-parser': 1.2.7 - '@types/send': 0.17.4 + '@types/send': 0.17.5 - '@types/express@5.0.0': + '@types/express@5.0.3': dependencies: - '@types/body-parser': 1.19.5 - '@types/express-serve-static-core': 5.0.0 - '@types/qs': 6.9.16 - '@types/serve-static': 1.15.7 + '@types/body-parser': 1.19.6 + '@types/express-serve-static-core': 5.0.6 + '@types/serve-static': 1.15.8 - '@types/http-assert@1.5.5': {} + '@types/http-assert@1.5.6': {} - '@types/http-errors@2.0.4': {} + '@types/http-errors@2.0.5': {} '@types/jsonwebtoken@8.5.9': dependencies: - '@types/node': 22.15.3 + '@types/node': 22.15.33 '@types/keygrip@1.0.6': {} @@ -4655,27 +4676,31 @@ snapshots: '@types/koa@2.15.0': dependencies: '@types/accepts': 1.3.7 - '@types/content-disposition': 0.5.8 - '@types/cookies': 0.9.0 - '@types/http-assert': 1.5.5 - '@types/http-errors': 2.0.4 + '@types/content-disposition': 0.5.9 + '@types/cookies': 0.9.1 + '@types/http-assert': 1.5.6 + '@types/http-errors': 2.0.5 '@types/keygrip': 1.0.6 '@types/koa-compose': 3.2.8 - '@types/node': 22.15.3 + '@types/node': 22.15.33 '@types/mime@1.3.5': {} - '@types/node@22.15.3': - dependencies: - undici-types: 6.21.0 - '@types/node@22.15.30': dependencies: undici-types: 6.21.0 + '@types/node@22.15.33': + dependencies: + undici-types: 6.21.0 + + '@types/node@24.0.4': + dependencies: + undici-types: 7.8.0 + '@types/prop-types@15.7.14': {} - '@types/qs@6.9.16': {} + '@types/qs@6.14.0': {} '@types/range-parser@1.2.7': {} @@ -4688,16 +4713,16 @@ snapshots: '@types/prop-types': 15.7.14 csstype: 3.1.3 - '@types/send@0.17.4': + '@types/send@0.17.5': dependencies: '@types/mime': 1.3.5 - '@types/node': 22.15.3 + '@types/node': 22.15.33 - '@types/serve-static@1.15.7': + '@types/serve-static@1.15.8': dependencies: - '@types/http-errors': 2.0.4 - '@types/node': 22.15.3 - '@types/send': 0.17.4 + '@types/http-errors': 2.0.5 + '@types/node': 22.15.33 + '@types/send': 0.17.5 '@types/tiny-async-pool@1.0.5': {} @@ -4832,7 +4857,7 @@ snapshots: loupe: 3.1.3 tinyrainbow: 1.2.0 - '@zip.js/zip.js@2.7.60': {} + '@zip.js/zip.js@2.7.62': {} accepts@1.3.8: dependencies: @@ -4913,7 +4938,7 @@ snapshots: better-sqlite3@9.6.0: dependencies: bindings: 1.5.0 - prebuild-install: 7.1.2 + prebuild-install: 7.1.3 binary-extensions@2.3.0: {} @@ -4972,13 +4997,15 @@ snapshots: mime-types: 2.1.35 ylru: 1.4.0 - call-bind@1.0.7: + call-bind-apply-helpers@1.0.2: dependencies: - es-define-property: 1.0.0 es-errors: 1.3.0 function-bind: 1.1.2 - get-intrinsic: 1.2.4 - set-function-length: 1.2.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 callsites@3.1.0: {} @@ -5041,7 +5068,7 @@ snapshots: dependencies: '@hapi/bourne': 3.0.0 inflation: 2.1.0 - qs: 6.13.0 + qs: 6.14.0 raw-body: 2.5.2 type-is: 1.6.18 @@ -5141,12 +5168,6 @@ snapshots: data-uri-to-buffer@4.0.1: {} - debug@4.3.7(supports-color@5.5.0): - dependencies: - ms: 2.1.3 - optionalDependencies: - supports-color: 5.5.0 - debug@4.4.1: dependencies: ms: 2.1.3 @@ -5169,12 +5190,6 @@ snapshots: dependencies: clone: 1.0.4 - define-data-property@1.1.4: - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - gopd: 1.0.1 - delegates@1.0.0: {} depd@1.1.2: {} @@ -5187,6 +5202,8 @@ snapshots: detect-libc@2.0.3: {} + detect-libc@2.0.4: {} + detect-node-es@1.1.0: {} didyoumean@1.2.2: {} @@ -5212,9 +5229,15 @@ snapshots: dotenv-expand@11.0.6: dependencies: - dotenv: 16.4.5 + dotenv: 16.5.0 - dotenv@16.4.5: {} + dotenv@16.5.0: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 eastasianwidth@0.2.0: {} @@ -5232,18 +5255,24 @@ snapshots: dependencies: once: 1.4.0 + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 - es-define-property@1.0.0: - dependencies: - get-intrinsic: 1.2.4 + es-define-property@1.0.1: {} es-errors@1.3.0: {} es-module-lexer@1.7.0: {} + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + esbuild@0.21.5: optionalDependencies: '@esbuild/aix-ppc64': 0.21.5 @@ -5270,32 +5299,33 @@ snapshots: '@esbuild/win32-ia32': 0.21.5 '@esbuild/win32-x64': 0.21.5 - esbuild@0.23.1: + esbuild@0.25.5: optionalDependencies: - '@esbuild/aix-ppc64': 0.23.1 - '@esbuild/android-arm': 0.23.1 - '@esbuild/android-arm64': 0.23.1 - '@esbuild/android-x64': 0.23.1 - '@esbuild/darwin-arm64': 0.23.1 - '@esbuild/darwin-x64': 0.23.1 - '@esbuild/freebsd-arm64': 0.23.1 - '@esbuild/freebsd-x64': 0.23.1 - '@esbuild/linux-arm': 0.23.1 - '@esbuild/linux-arm64': 0.23.1 - '@esbuild/linux-ia32': 0.23.1 - '@esbuild/linux-loong64': 0.23.1 - '@esbuild/linux-mips64el': 0.23.1 - '@esbuild/linux-ppc64': 0.23.1 - '@esbuild/linux-riscv64': 0.23.1 - '@esbuild/linux-s390x': 0.23.1 - '@esbuild/linux-x64': 0.23.1 - '@esbuild/netbsd-x64': 0.23.1 - '@esbuild/openbsd-arm64': 0.23.1 - '@esbuild/openbsd-x64': 0.23.1 - '@esbuild/sunos-x64': 0.23.1 - '@esbuild/win32-arm64': 0.23.1 - '@esbuild/win32-ia32': 0.23.1 - '@esbuild/win32-x64': 0.23.1 + '@esbuild/aix-ppc64': 0.25.5 + '@esbuild/android-arm': 0.25.5 + '@esbuild/android-arm64': 0.25.5 + '@esbuild/android-x64': 0.25.5 + '@esbuild/darwin-arm64': 0.25.5 + '@esbuild/darwin-x64': 0.25.5 + '@esbuild/freebsd-arm64': 0.25.5 + '@esbuild/freebsd-x64': 0.25.5 + '@esbuild/linux-arm': 0.25.5 + '@esbuild/linux-arm64': 0.25.5 + '@esbuild/linux-ia32': 0.25.5 + '@esbuild/linux-loong64': 0.25.5 + '@esbuild/linux-mips64el': 0.25.5 + '@esbuild/linux-ppc64': 0.25.5 + '@esbuild/linux-riscv64': 0.25.5 + '@esbuild/linux-s390x': 0.25.5 + '@esbuild/linux-x64': 0.25.5 + '@esbuild/netbsd-arm64': 0.25.5 + '@esbuild/netbsd-x64': 0.25.5 + '@esbuild/openbsd-arm64': 0.25.5 + '@esbuild/openbsd-x64': 0.25.5 + '@esbuild/sunos-x64': 0.25.5 + '@esbuild/win32-arm64': 0.25.5 + '@esbuild/win32-ia32': 0.25.5 + '@esbuild/win32-x64': 0.25.5 escalade@3.2.0: {} @@ -5483,19 +5513,29 @@ snapshots: gensync@1.0.0-beta.2: {} - get-intrinsic@1.2.4: + get-intrinsic@1.3.0: dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 es-errors: 1.3.0 + es-object-atoms: 1.1.1 function-bind: 1.1.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 hasown: 2.0.2 + math-intrinsics: 1.1.0 get-nonce@1.0.1: {} + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + get-stream@6.0.1: {} - get-tsconfig@4.8.1: + get-tsconfig@4.10.1: dependencies: resolve-pkg-maps: 1.0.0 @@ -5550,9 +5590,7 @@ snapshots: merge2: 1.4.1 slash: 3.0.0 - gopd@1.0.1: - dependencies: - get-intrinsic: 1.2.4 + gopd@1.2.0: {} graceful-fs@4.2.11: {} @@ -5562,17 +5600,11 @@ snapshots: has-flag@4.0.0: {} - has-property-descriptors@1.0.2: - dependencies: - es-define-property: 1.0.0 - - has-proto@1.0.3: {} - - has-symbols@1.0.3: {} + has-symbols@1.1.0: {} has-tostringtag@1.0.2: dependencies: - has-symbols: 1.0.3 + has-symbols: 1.1.0 hasown@2.0.2: dependencies: @@ -5614,8 +5646,6 @@ snapshots: ieee754@1.2.1: {} - ignore-by-default@1.0.1: {} - ignore@5.3.2: {} import-fresh@3.3.1: @@ -5654,9 +5684,12 @@ snapshots: is-fullwidth-code-point@3.0.0: {} - is-generator-function@1.0.10: + is-generator-function@1.1.0: dependencies: + call-bound: 1.0.4 + get-proto: 1.0.1 has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 is-glob@4.0.3: dependencies: @@ -5668,6 +5701,13 @@ snapshots: is-path-inside@3.0.3: {} + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + is-stream@3.0.0: {} is-unicode-supported@1.3.0: {} @@ -5682,7 +5722,7 @@ snapshots: jiti@1.21.7: {} - jose@5.9.3: {} + jose@5.10.0: {} jotai@2.12.5(@types/react@18.3.23)(react@18.3.1): optionalDependencies: @@ -5738,7 +5778,7 @@ snapshots: koa-router@12.0.1: dependencies: - debug: 4.3.7(supports-color@5.5.0) + debug: 4.4.1 http-errors: 2.0.0 koa-compose: 4.1.0 methods: 1.1.2 @@ -5746,14 +5786,14 @@ snapshots: transitivePeerDependencies: - supports-color - koa@2.15.3: + koa@2.16.1: dependencies: accepts: 1.3.8 cache-content-type: 1.0.1 content-disposition: 0.5.4 content-type: 1.0.5 cookies: 0.9.1 - debug: 4.3.7(supports-color@5.5.0) + debug: 4.4.1 delegates: 1.0.0 depd: 2.0.0 destroy: 1.2.0 @@ -5762,7 +5802,7 @@ snapshots: fresh: 0.5.2 http-assert: 1.5.0 http-errors: 1.8.1 - is-generator-function: 1.0.10 + is-generator-function: 1.1.0 koa-compose: 4.1.0 koa-convert: 2.0.0 on-finished: 2.4.1 @@ -5777,7 +5817,7 @@ snapshots: kysely-codegen@0.14.1(better-sqlite3@9.4.3)(kysely@0.27.3): dependencies: chalk: 4.1.2 - dotenv: 16.4.5 + dotenv: 16.5.0 dotenv-expand: 11.0.6 git-diff: 2.0.6 kysely: 0.27.3 @@ -5788,7 +5828,7 @@ snapshots: kysely@0.27.3: {} - kysely@0.27.4: {} + kysely@0.27.6: {} levn@0.4.1: dependencies: @@ -5847,6 +5887,8 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 + math-intrinsics@1.1.0: {} + media-typer@0.3.0: {} merge-stream@2.0.0: {} @@ -5911,6 +5953,8 @@ snapshots: napi-build-utils@1.0.2: {} + napi-build-utils@2.0.0: {} + natural-compare@1.4.0: {} natural-orderby@2.0.3: {} @@ -5921,6 +5965,10 @@ snapshots: dependencies: semver: 7.7.2 + node-abi@3.75.0: + dependencies: + semver: 7.7.2 + node-domexception@1.0.0: {} node-fetch@3.3.2: @@ -5931,19 +5979,6 @@ snapshots: node-releases@2.0.19: {} - nodemon@3.1.7: - dependencies: - chokidar: 3.6.0 - debug: 4.3.7(supports-color@5.5.0) - ignore-by-default: 1.0.1 - minimatch: 3.1.2 - pstree.remy: 1.1.8 - semver: 7.6.3 - simple-update-notifier: 2.0.0 - supports-color: 5.5.0 - touch: 3.1.1 - undefsafe: 2.0.5 - normalize-path@3.0.0: {} normalize-range@0.1.2: {} @@ -5956,7 +5991,7 @@ snapshots: object-hash@3.0.0: {} - object-inspect@1.13.2: {} + object-inspect@1.13.4: {} on-finished@2.4.1: dependencies: @@ -6105,6 +6140,21 @@ snapshots: tar-fs: 2.1.1 tunnel-agent: 0.6.0 + prebuild-install@7.1.3: + dependencies: + detect-libc: 2.0.4 + expand-template: 2.0.3 + github-from-package: 0.0.0 + minimist: 1.2.8 + mkdirp-classic: 0.5.3 + napi-build-utils: 2.0.0 + node-abi: 3.75.0 + pump: 3.0.3 + rc: 1.2.8 + simple-get: 4.0.1 + tar-fs: 2.1.3 + tunnel-agent: 0.6.0 + prelude-ls@1.2.1: {} prompts@2.4.2: @@ -6118,18 +6168,21 @@ snapshots: object-assign: 4.1.1 react-is: 16.13.1 - pstree.remy@1.1.8: {} - pump@3.0.2: dependencies: end-of-stream: 1.4.4 once: 1.4.0 + pump@3.0.3: + dependencies: + end-of-stream: 1.4.5 + once: 1.4.0 + punycode@2.3.1: {} - qs@6.13.0: + qs@6.14.0: dependencies: - side-channel: 1.0.6 + side-channel: 1.1.0 queue-microtask@1.2.3: {} @@ -6308,6 +6361,12 @@ snapshots: safe-buffer@5.2.1: {} + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + safer-buffer@2.1.2: {} scheduler@0.23.2: @@ -6318,19 +6377,8 @@ snapshots: semver@6.3.1: {} - semver@7.6.3: {} - semver@7.7.2: {} - set-function-length@1.2.2: - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - gopd: 1.0.1 - has-property-descriptors: 1.0.2 - setprototypeof@1.2.0: {} shadcn-ui@0.8.0(typescript@5.8.3): @@ -6373,12 +6421,33 @@ snapshots: interpret: 1.4.0 rechoir: 0.6.2 - side-channel@1.0.6: + side-channel-list@1.0.0: dependencies: - call-bind: 1.0.7 es-errors: 1.3.0 - get-intrinsic: 1.2.4 - object-inspect: 1.13.2 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 siginfo@2.0.0: {} @@ -6394,10 +6463,6 @@ snapshots: once: 1.4.0 simple-concat: 1.0.1 - simple-update-notifier@2.0.0: - dependencies: - semver: 7.6.3 - sisteransi@1.0.5: {} slash@3.0.0: {} @@ -6516,10 +6581,17 @@ snapshots: pump: 3.0.2 tar-stream: 2.2.0 + tar-fs@2.1.3: + dependencies: + chownr: 1.1.4 + mkdirp-classic: 0.5.3 + pump: 3.0.3 + tar-stream: 2.2.0 + tar-stream@2.2.0: dependencies: bl: 4.1.0 - end-of-stream: 1.4.4 + end-of-stream: 1.4.5 fs-constants: 1.0.0 inherits: 2.0.4 readable-stream: 3.6.2 @@ -6556,8 +6628,6 @@ snapshots: toidentifier@1.0.1: {} - touch@3.1.1: {} - ts-api-utils@1.4.3(typescript@5.8.3): dependencies: typescript: 5.8.3 @@ -6579,10 +6649,10 @@ snapshots: tsscmp@1.0.6: {} - tsx@4.19.1: + tsx@4.20.3: dependencies: - esbuild: 0.23.1 - get-tsconfig: 4.8.1 + esbuild: 0.25.5 + get-tsconfig: 4.10.1 optionalDependencies: fsevents: 2.3.3 @@ -6603,14 +6673,12 @@ snapshots: typescript@5.4.3: {} - typescript@5.6.2: {} - typescript@5.8.3: {} - undefsafe@2.0.5: {} - undici-types@6.21.0: {} + undici-types@7.8.0: {} + universalify@2.0.1: {} unpipe@1.0.0: {} -- 2.39.5 From d530dd8cb6dcb96cd745a866782fe2e3a7eb58c3 Mon Sep 17 00:00:00 2001 From: monoid Date: Thu, 26 Jun 2025 20:54:20 +0900 Subject: [PATCH 3/3] feat: add user settings management and update related handlers --- packages/dbtype/src/api.ts | 6 ++ packages/dbtype/src/types.ts | 6 ++ packages/server/migrations/2025-06-26.ts | 2 +- packages/server/src/db/user.ts | 20 ++++++- packages/server/src/login.ts | 58 +++++++++++++++++--- packages/server/src/model/user.ts | 15 +++++ packages/server/src/permission/permission.ts | 29 +++++----- packages/server/src/server.ts | 4 +- 8 files changed, 114 insertions(+), 26 deletions(-) diff --git a/packages/dbtype/src/api.ts b/packages/dbtype/src/api.ts index 1634c7e..6ee2075 100644 --- a/packages/dbtype/src/api.ts +++ b/packages/dbtype/src/api.ts @@ -53,6 +53,12 @@ export const UserSchema = z.object({ export type User = z.infer; +export const UserSettingSchema = z.object({ + fileDeepLinkRegex: z.string().optional(), +}); + +export type UserSetting = z.infer; + export const SchemaMigrationSchema = z.object({ version: z.string().nullable(), dirty: z.boolean(), diff --git a/packages/dbtype/src/types.ts b/packages/dbtype/src/types.ts index cbdb075..d7bd3d2 100644 --- a/packages/dbtype/src/types.ts +++ b/packages/dbtype/src/types.ts @@ -45,6 +45,11 @@ export interface Users { username: string | null; } +export interface UserSettings { + username: string; + settings: string | null; +} + export interface DB { doc_tag_relation: DocTagRelation; document: Document; @@ -52,4 +57,5 @@ export interface DB { schema_migration: SchemaMigration; tags: Tags; users: Users; + user_settings: UserSettings; } diff --git a/packages/server/migrations/2025-06-26.ts b/packages/server/migrations/2025-06-26.ts index 08e8e77..43688e4 100644 --- a/packages/server/migrations/2025-06-26.ts +++ b/packages/server/migrations/2025-06-26.ts @@ -4,7 +4,7 @@ export async function up(db: Kysely) { await db.schema .createTable("user_settings") .addColumn("username", "varchar(256)", col => col.notNull().primaryKey()) - .addColumn("settings", "jsonb", col => col.notNull()) + .addColumn("settings", "json", col => col.notNull()) .addForeignKeyConstraint("user_settings_username_fk", ["username"], "users", ["username"]) .execute(); diff --git a/packages/server/src/db/user.ts b/packages/server/src/db/user.ts index 84cdf5f..d73cf2e 100644 --- a/packages/server/src/db/user.ts +++ b/packages/server/src/db/user.ts @@ -1,5 +1,5 @@ import { getKysely } from "./kysely.ts"; -import { type IUser, Password, type UserAccessor, type UserCreateInput } from "../model/user.ts"; +import { type IUser, IUserSettings, Password, type UserAccessor, type UserCreateInput } from "../model/user.ts"; class SqliteUser implements IUser { readonly username: string; @@ -41,6 +41,24 @@ class SqliteUser implements IUser { .executeTakeFirst(); return (result.numDeletedRows ?? 0n) > 0; } + async get_settings(): Promise { + const settings = await this.kysely + .selectFrom("user_settings") + .select("settings") + .where("username", "=", this.username) + .executeTakeFirst(); + if (!settings) return undefined; + return settings.settings ? JSON.parse(settings.settings) as IUserSettings : undefined; + } + async set_settings(settings: IUserSettings) { + const settingsJson = JSON.stringify(settings); + const result = await this.kysely + .insertInto("user_settings") + .values({ username: this.username, settings: settingsJson }) + .onConflict((oc) => oc.doUpdateSet({ settings: settingsJson })) + .executeTakeFirst(); + return (result.numInsertedOrUpdatedRows ?? 0n) > 0; + } } export const createSqliteUserController = (kysely = getKysely()): UserAccessor => { diff --git a/packages/server/src/login.ts b/packages/server/src/login.ts index 7d347c9..d38c9b3 100644 --- a/packages/server/src/login.ts +++ b/packages/server/src/login.ts @@ -76,7 +76,7 @@ function setToken(ctx: Koa.Context, token_name: string, token_payload: string | }); } -export const createLoginMiddleware = (userController: UserAccessor) => async (ctx: Koa.Context, _next: Koa.Next) => { +export const createLoginHandler = (userController: UserAccessor) => async (ctx: Koa.Context, _next: Koa.Next) => { const setting = get_setting(); const secretKey = setting.jwt_secretkey; const body = ctx.request.body; @@ -115,7 +115,7 @@ export const createLoginMiddleware = (userController: UserAccessor) => async (ct return; }; -export const LogoutMiddleware = (ctx: Koa.Context, next: Koa.Next) => { +export const LogoutHandler = (ctx: Koa.Context, _next: Koa.Next) => { const setting = get_setting(); ctx.cookies.set(accessTokenName, null); ctx.cookies.set(refreshTokenName, null); @@ -127,9 +127,9 @@ export const LogoutMiddleware = (ctx: Koa.Context, next: Koa.Next) => { return; }; -export const createUserMiddleWare = +export const createUserHandler = (userController: UserAccessor) => async (ctx: Koa.ParameterizedContext, next: Koa.Next) => { - const refreshToken = refreshTokenHandler(userController); + const refreshToken = makeRefreshToken(userController); const setting = get_setting(); const setGuest = async () => { setToken(ctx, accessTokenName, null, 0); @@ -140,7 +140,7 @@ export const createUserMiddleWare = return await refreshToken(ctx, setGuest, next); }; -const refreshTokenHandler = (cntr: UserAccessor) => async (ctx: Koa.Context, fail: Koa.Next, next: Koa.Next) => { +const makeRefreshToken = (cntr: UserAccessor) => async (ctx: Koa.Context, fail: Koa.Next, next: Koa.Next) => { const accessPayload = ctx.cookies.get(accessTokenName); const setting = get_setting(); const secretKey = setting.jwt_secretkey; @@ -200,7 +200,7 @@ const refreshTokenHandler = (cntr: UserAccessor) => async (ctx: Koa.Context, fai } }; export const createRefreshTokenMiddleware = (cntr: UserAccessor) => async (ctx: Koa.Context, next: Koa.Next) => { - const handler = refreshTokenHandler(cntr); + const handler = makeRefreshToken(cntr); await handler(ctx, fail, success); async function fail() { const user = ctx.state.user as PayloadInfo; @@ -242,12 +242,54 @@ export const resetPasswordMiddleware = (cntr: UserAccessor) => async (ctx: Koa.C ctx.type = "json"; }; +export function getUserSettingHandler(userController: UserAccessor) { + return async (ctx: Koa.ParameterizedContext, next: Koa.Next) => { + const username = ctx.state.user.username; + if (!username) { + return sendError(403, "not authorized"); + } + const user = await userController.findUser(username); + if (user === undefined) { + return sendError(403, "not authorized"); + } + const settings = await user.get_settings(); + if (settings === undefined) { + ctx.body = {}; + ctx.type = "json"; + return; + } + ctx.body = settings; + ctx.type = "json"; + await next(); + }; +} +export function setUserSettingHandler(userController: UserAccessor) { + return async (ctx: Koa.ParameterizedContext, next: Koa.Next) => { + const username = ctx.state.user.username; + if (!username) { + return sendError(403, "not authorized"); + } + const user = await userController.findUser(username); + if (user === undefined) { + return sendError(403, "not authorized"); + } + const body = ctx.request.body; + const settings = body as Record; + await user.set_settings(settings); + ctx.body = { ok: true }; + ctx.type = "json"; + await next(); + }; +} + export function createLoginRouter(userController: UserAccessor) { const router = new Router(); - router.post("/login", createLoginMiddleware(userController)); - router.post("/logout", LogoutMiddleware); + router.post("/login", createLoginHandler(userController)); + router.post("/logout", LogoutHandler); router.post("/refresh", createRefreshTokenMiddleware(userController)); router.post("/reset", resetPasswordMiddleware(userController)); + router.get("/settings", getUserSettingHandler(userController)); + router.post("/settings", setUserSettingHandler(userController)); return router; } diff --git a/packages/server/src/model/user.ts b/packages/server/src/model/user.ts index fdfff72..b0adc1f 100644 --- a/packages/server/src/model/user.ts +++ b/packages/server/src/model/user.ts @@ -1,3 +1,4 @@ +import { UserSetting } from "dbtype"; import { createHmac, randomBytes } from "node:crypto"; function hashForPassword(salt: string, password: string) { @@ -41,6 +42,8 @@ export interface UserCreateInput { password: string; } +export type IUserSettings = UserSetting; + export interface IUser { readonly username: string; readonly password: Password; @@ -65,6 +68,18 @@ export interface IUser { * @param password password to set */ reset_password(password: string): Promise; + + /** + * get user settings + * @returns user settings, or undefined if not set + */ + get_settings(): Promise; + /** + * set user settings + * @param settings user settings to set + * @returns if settings updated, return true + */ + set_settings(settings: IUserSettings): Promise; } export interface UserAccessor { diff --git a/packages/server/src/permission/permission.ts b/packages/server/src/permission/permission.ts index 4632ef6..04f96c7 100644 --- a/packages/server/src/permission/permission.ts +++ b/packages/server/src/permission/permission.ts @@ -36,20 +36,21 @@ export enum Permission { export const createPermissionCheckMiddleware = (...permissions: string[]) => - async (ctx: Koa.ParameterizedContext, next: Koa.Next) => { - const user = ctx.state.user; - if (user.username === "admin") { - return await next(); - } - const user_permission = user.permission; - // if permissions is not subset of user permission - if (!permissions.map((p) => user_permission.includes(p)).every((x) => x)) { - if (user.username === "") { - return sendError(401, "you are guest. login needed."); - }return sendError(403, "do not have permission"); - } - await next(); - }; + async (ctx: Koa.ParameterizedContext, next: Koa.Next) => { + const user = ctx.state.user; + if (user.username === "admin") { + return await next(); + } + const user_permission = user.permission; + // if permissions is not subset of user permission + if (!permissions.map((p) => user_permission.includes(p)).every((x) => x)) { + if (user.username === "") { + return sendError(401, "you are guest. login needed."); + } return sendError(403, "do not have permission"); + } + await next(); + }; + export const AdminOnlyMiddleware = async (ctx: Koa.ParameterizedContext, next: Koa.Next) => { const user = ctx.state.user; if (user.username !== "admin") { diff --git a/packages/server/src/server.ts b/packages/server/src/server.ts index 6726d30..6ba4037 100644 --- a/packages/server/src/server.ts +++ b/packages/server/src/server.ts @@ -8,7 +8,7 @@ import { get_setting, SettingConfig } from "./SettingConfig.ts"; import { createReadStream, readFileSync } from "node:fs"; import bodyparser from "koa-bodyparser"; import { createSqliteDocumentAccessor, createSqliteTagController, createSqliteUserController } from "./db/mod.ts"; -import { createLoginRouter, createUserMiddleWare, getAdmin, isAdminFirst } from "./login.ts"; +import { createLoginRouter, createUserHandler, getAdmin, isAdminFirst } from "./login.ts"; import getContentRouter from "./route/contents.ts"; import { error_handler } from "./route/error_handler.ts"; @@ -63,7 +63,7 @@ class ServerApplication { } app.use(bodyparser()); app.use(error_handler); - app.use(createUserMiddleWare(this.userController)); + app.use(createUserHandler(this.userController)); const diff_router = createDiffRouter(this.diffManger); this.diffManger.register("comic", createComicWatcher()); -- 2.39.5