From 31a9f8469c55a295557d3b3283671055ae728730 Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Thu, 22 Feb 2024 14:50:44 -0500 Subject: [PATCH] Introduce the db integration (prerelease) (#10201) * Initial DB migration code * chore: update package.json * chore: update lockfile * feat: add db as top-level config value * Small package change * Add a very basic test * deps: remove unused * chore: astro/db scripts, exports, deps * chore: set tsconfig to monorepo defaults * feat: MVP to use libsql in dev * fix: test fixture paths * fix: test file paths * chore: remove CLI tests * fix: add astro-scripts to db * fix: package.json merge * fix: load seed file separately for build * feat: create db on filesystem for build * fix: ul test. It passes now! * Squashed commit of the following: commit acdddd728c56f25e42975db7f367ab8a998e8c41 Author: Princesseuh <3019731+Princesseuh@users.noreply.github.com> Date: Wed Jan 10 14:06:16 2024 -0500 fix: proper type augment for the config commit b41ca9aacf291d1e5f0a27b6d6339ce4fc608ec3 Author: Nate Moore Date: Tue Jan 9 14:33:42 2024 -0600 wip: type augmentation * feat: data() fn with basic type safety * wip: update from seed file to data() * fix: bad collectionSchema data type * refactor: move dev to use filesystem to run seed at right time * chore: remove seed file logic * docs: add basic README * CLI sync command * Runtime checking of writable * docs: add join example * Implement defineWritableCollection * feat: use studio connection for studio builds * fix: add defineWritableCollection export * refactor: use getTableName() util * feat(db): add support for pass-through `astro db` command * chore: add error map * fix: add drizzle import * refactor: studio -> db cli * feat: add ticketing example * fix: bad types in astro config * fix: remove invalid `data()` on writable collection * fix: vite warning on load-astro-config * wip: add seeding for readable collections (nonstable ids!) * merge migration work into branch * cleanup migration commands * migrate seed data to new db push command * add migrations table to db * fix remote db bugs * fix: warn writable collections when studio false * chore: delete README contents (now on Notion) * chore: remove blank README * chore: add dev dependency on db * Removed unused deps * 0.1.0 * Add config-augment.d.ts to published artifacts" * Fixes merge issues with main * fix: support promise response from data() * feat: basic glob fixture * Add a main field * Give a help message when no db command is provided * feat: `db push --token` for GitHub CI secrets * fix getPackage for db package * 0.1.2 * wip: build a table type * chore: update lockfile * chore: temporarily remove `Table` type * feat: better Table object for type inference * format * add primaryKey support * improve snapshot parsing support * cleanup primary key support, db push * add simple db shell * cleanup old copy paste code * feat: scrappy global data() prototype * feat(test): recipes example * fix: use Extract to narrow keyof to strings * 0.1.3 * Create a runtime version of createRemoteDatabaseClient * 0.1.4 * Grab the dbUrl from the environment * 0.1.5 * Expose the database to the build output * 0.1.6 * 0.1.7 * 0.1.15 * wip: data() -> set() concept * fix: just infer insert keys for now * refactor: rewrite to injected set() function * deps: chokidar, drizzle * feat: glob support with { db, table } signature * chore: move basics to new data set * refactor: set -> seed * feat: expose Model.table * refactor: clean up types * feat: migrations now working! * upgrade @libsql/client * format * expose relevant types * 0.1.16 * feat: config design * feat: add indexes from collectionToTable * feat: add indexes to setupDbTables * fix: remove unique constraint on recipeId * Use an import statement to grab the database file * 0.1.17 * Remove unused import * Rename to ?fileurl * 0.1.18 * feat: index migrations * move migration logic to turso, add back sync support * feat: add queries unit tests and fix related bugs * refactor: move field queries to field-queries.test * feat: index query tests * refactor: reorganize the rats nest of files * Make the DB_URL be root relative * Upgrade to latest libsql * 0.1.19 * 0.1.20 * Make work in webcontainer * 0.1.22 * Remove content database from the static build * 0.1.23 * chore: remove `optional: true` from pk * chore: disable console linting for CLI * fix: remove `id` column from Table type * chore: remove `AstroId` type * fix(ex): add `id` col to ticketing * 0.2.0 * 0.2.1 * add keywords * 0.2.2 * feat: API shape * feat: FINALLY collection and name attached * refactor: move to arrow function signature * fix: foreignKeys references signature * chore: unused imports * feat: add foreignkeys to create table * chore: lint * chore: enable foreign keys in local mode only * refactor: objShallowEqual -> deep diff * fix: correct `hasDefault` inference * fix: correct type Config reference * fix: respect primaryKey from hasDefault * fix: mark data keys as optional until we have type inference * improve conflict and dataloss handling - moved prompts to db push - moved prompt logic out of lower-level functions - improved logic overall - improved user-facing prompt messages * improve error messaging around studio config missing * make it more clear when remove vs. local db is in use * fix bug in prompt logic * feat: better field.x() types * feat: better seed() types * chore: remove `as any` on seed values * feat: good enough return type on seed :) * feat: defineData() * fix: add back promptResponse injection * fix: use schema.parse to resolve dates * fix: correctly respect primary key on INSERT INTO * add short-lived db tokens * add help output * add better token error logging * fix studio tests * add shortcut link command from studio web ui * Add support for SQL defaults You can now use sql`CURRENT_TIMESTAMP`, `NOW`, and a couple of other helpers, to set defaults. * chore: todo * feat: ignore `optional` and `default` when pk is present * refactor: type `false` instead of type `never` * feat: prevent `optional` on text pk * fix db URL import for windows * fix: add back textField multiline * fix: remove explicit AUTOINCREMENT on int pk * feat(db-cli): clean up CLI logging, support --json flag for `astro db verify`, extract shared logic to a utility * prepare to run seed on all db push commands * chore: expose setMeta for unit testing * feat(test): reference add and remove tests * feat: add references checks to migratiosn * feat: remove useForeignKey checks * feat: add pragma when pushing migrations * feat(test): foreignKeys * fix: transform collection config to be JSON serializable * refactor: _setMeta -> preprocess for `table` * refactor: reference tests * chore: remove console log * fix: handle serialized SQL object correctly * refactor: store raw sql instead * seed on every push * Move field schema only a `schema` object * Fix references test * 0.3.0 * add default URLs to db package * 0.3.1 * Fix input types * fix: primaryKey type check * 0.3.2 * fix: respect default in table types * fix: avoid dropping tables on production seed * fix: escape name on drop table * feat: allow verify to mock migration file * Handle unauthorized linking * Fix verbiage of unauthorized link warning * Add some color to the unauthorized message * 0.3.3 * Improve the unauthorized error output * 0.3.4 * fix: better error message * Seed the Themes in build too * Push skipped test * chore: remove dead isJsonSerializable check * fix: use `dateType` for dates (oops) * refactor: clarify date coerce comment * refactor: remove unused coerce * chore: unskip date test * feat: seed -> seedReturning * refactor: throw when seeding writable in prod * Add unsafeWritable option * refactor: use FieldsConfig for Table generic * chore: lint * fix: use z.input for AstroConfigWithDB type * fix: add defaults for boolean config options * Support new CLI command structure * Allow writable in the tests * fix: handle defaults for safe type changes * refactor: avoid selecting ['schema'] on input types * 0.3.5 * Rename field->column, collection->table * Rename collections->tables * rename to defineReadableTable * deps: upgrade ticketing-example * fix: stray console.log * deps: bump preact again * chore: preact->react * fix: parse params.event as number * fix: correct event references * Allow integrations to define schema * fix: file-url plugin failure on repeated generateBundle() runs * update url * Cleanup * Linting * fix windows file permission issue When runnng `astro dev`, the watcher would close trying to delete the `content.db` file due to a file permission error. This change makes the local DB client a disposable to allow cleanup after usage. * Formatting * "fix" Symbol.dispose usage --------- Co-authored-by: Nate Moore Co-authored-by: bholmesdev Co-authored-by: Fred K. Schott Co-authored-by: itsMapleLeaf <19603573+itsMapleLeaf@users.noreply.github.com> --- .eslintrc.cjs | 6 + .prettierignore | 3 + packages/astro/src/cli/db/index.ts | 1 - packages/astro/src/cli/index.ts | 11 +- packages/astro/src/cli/install-package.ts | 24 +- packages/astro/src/core/config/merge.ts | 10 +- packages/db/CHANGELOG.md | 0 packages/db/config-augment.d.ts | 4 + packages/db/index.d.ts | 3 + packages/db/package.json | 81 + .../db/src/core/cli/commands/gen/index.ts | 43 + .../db/src/core/cli/commands/link/index.ts | 79 + .../db/src/core/cli/commands/login/index.ts | 52 + .../db/src/core/cli/commands/logout/index.ts | 9 + .../db/src/core/cli/commands/push/index.ts | 264 + .../db/src/core/cli/commands/shell/index.ts | 16 + .../db/src/core/cli/commands/verify/index.ts | 43 + packages/db/src/core/cli/index.ts | 73 + packages/db/src/core/cli/migration-queries.ts | 554 ++ packages/db/src/core/cli/migrations.ts | 140 + packages/db/src/core/consts.ts | 14 + packages/db/src/core/errors.ts | 43 + packages/db/src/core/integration/error-map.ts | 104 + packages/db/src/core/integration/file-url.ts | 95 + packages/db/src/core/integration/index.ts | 139 + .../src/core/integration/load-astro-config.ts | 92 + packages/db/src/core/integration/typegen.ts | 46 + .../db/src/core/integration/vite-plugin-db.ts | 98 + .../integration/vite-plugin-inject-env-ts.ts | 65 + packages/db/src/core/queries.ts | 271 + packages/db/src/core/tokens.ts | 143 + packages/db/src/core/types.ts | 386 ++ packages/db/src/core/utils.ts | 19 + packages/db/src/index.ts | 5 + packages/db/src/runtime/db-client.ts | 111 + packages/db/src/runtime/drizzle.ts | 25 + packages/db/src/runtime/index.ts | 139 + packages/db/src/runtime/types.ts | 109 + packages/db/test/basics.test.js | 104 + .../db/test/fixtures/basics/astro.config.ts | 28 + packages/db/test/fixtures/basics/package.json | 9 + .../fixtures/basics/src/pages/index.astro | 26 + .../src/pages/insert-into-readonly.astro | 14 + .../src/pages/insert-into-writable.astro | 12 + .../fixtures/basics/themes-integration.ts | 36 + .../db/test/fixtures/glob/astro.config.ts | 25 + packages/db/test/fixtures/glob/package.json | 21 + .../db/test/fixtures/glob/quotes/erika.json | 4 + .../db/test/fixtures/glob/quotes/tony.json | 4 + .../test/fixtures/glob/src/pages/index.astro | 25 + packages/db/test/fixtures/glob/utils.ts | 60 + .../db/test/fixtures/recipes/astro.config.ts | 82 + .../db/test/fixtures/recipes/package.json | 16 + .../fixtures/recipes/src/pages/index.astro | 25 + .../fixtures/ticketing-example/.gitignore | 24 + .../test/fixtures/ticketing-example/README.md | 54 + .../ticketing-example/astro.config.ts | 56 + .../fixtures/ticketing-example/package.json | 27 + .../fixtures/ticketing-example/pnpm-lock.yaml | 5266 +++++++++++++++++ .../ticketing-example/public/favicon.svg | 9 + .../ticketing-example/src/components/Form.tsx | 119 + .../src/layouts/Layout.astro | 80 + .../src/pages/[event]/_Ticket.tsx | 40 + .../src/pages/[event]/index.astro | 50 + .../ticketing-example/src/pages/index.astro | 17 + .../fixtures/ticketing-example/tsconfig.json | 7 + packages/db/test/unit/field-queries.test.js | 449 ++ packages/db/test/unit/index-queries.test.js | 97 + .../db/test/unit/reference-queries.test.js | 178 + packages/db/tsconfig.json | 7 + pnpm-lock.yaml | 1229 +++- 71 files changed, 11439 insertions(+), 81 deletions(-) create mode 100644 packages/db/CHANGELOG.md create mode 100644 packages/db/config-augment.d.ts create mode 100644 packages/db/index.d.ts create mode 100644 packages/db/package.json create mode 100644 packages/db/src/core/cli/commands/gen/index.ts create mode 100644 packages/db/src/core/cli/commands/link/index.ts create mode 100644 packages/db/src/core/cli/commands/login/index.ts create mode 100644 packages/db/src/core/cli/commands/logout/index.ts create mode 100644 packages/db/src/core/cli/commands/push/index.ts create mode 100644 packages/db/src/core/cli/commands/shell/index.ts create mode 100644 packages/db/src/core/cli/commands/verify/index.ts create mode 100644 packages/db/src/core/cli/index.ts create mode 100644 packages/db/src/core/cli/migration-queries.ts create mode 100644 packages/db/src/core/cli/migrations.ts create mode 100644 packages/db/src/core/consts.ts create mode 100644 packages/db/src/core/errors.ts create mode 100644 packages/db/src/core/integration/error-map.ts create mode 100644 packages/db/src/core/integration/file-url.ts create mode 100644 packages/db/src/core/integration/index.ts create mode 100644 packages/db/src/core/integration/load-astro-config.ts create mode 100644 packages/db/src/core/integration/typegen.ts create mode 100644 packages/db/src/core/integration/vite-plugin-db.ts create mode 100644 packages/db/src/core/integration/vite-plugin-inject-env-ts.ts create mode 100644 packages/db/src/core/queries.ts create mode 100644 packages/db/src/core/tokens.ts create mode 100644 packages/db/src/core/types.ts create mode 100644 packages/db/src/core/utils.ts create mode 100644 packages/db/src/index.ts create mode 100644 packages/db/src/runtime/db-client.ts create mode 100644 packages/db/src/runtime/drizzle.ts create mode 100644 packages/db/src/runtime/index.ts create mode 100644 packages/db/src/runtime/types.ts create mode 100644 packages/db/test/basics.test.js create mode 100644 packages/db/test/fixtures/basics/astro.config.ts create mode 100644 packages/db/test/fixtures/basics/package.json create mode 100644 packages/db/test/fixtures/basics/src/pages/index.astro create mode 100644 packages/db/test/fixtures/basics/src/pages/insert-into-readonly.astro create mode 100644 packages/db/test/fixtures/basics/src/pages/insert-into-writable.astro create mode 100644 packages/db/test/fixtures/basics/themes-integration.ts create mode 100644 packages/db/test/fixtures/glob/astro.config.ts create mode 100644 packages/db/test/fixtures/glob/package.json create mode 100644 packages/db/test/fixtures/glob/quotes/erika.json create mode 100644 packages/db/test/fixtures/glob/quotes/tony.json create mode 100644 packages/db/test/fixtures/glob/src/pages/index.astro create mode 100644 packages/db/test/fixtures/glob/utils.ts create mode 100644 packages/db/test/fixtures/recipes/astro.config.ts create mode 100644 packages/db/test/fixtures/recipes/package.json create mode 100644 packages/db/test/fixtures/recipes/src/pages/index.astro create mode 100644 packages/db/test/fixtures/ticketing-example/.gitignore create mode 100644 packages/db/test/fixtures/ticketing-example/README.md create mode 100644 packages/db/test/fixtures/ticketing-example/astro.config.ts create mode 100644 packages/db/test/fixtures/ticketing-example/package.json create mode 100644 packages/db/test/fixtures/ticketing-example/pnpm-lock.yaml create mode 100644 packages/db/test/fixtures/ticketing-example/public/favicon.svg create mode 100644 packages/db/test/fixtures/ticketing-example/src/components/Form.tsx create mode 100644 packages/db/test/fixtures/ticketing-example/src/layouts/Layout.astro create mode 100644 packages/db/test/fixtures/ticketing-example/src/pages/[event]/_Ticket.tsx create mode 100644 packages/db/test/fixtures/ticketing-example/src/pages/[event]/index.astro create mode 100644 packages/db/test/fixtures/ticketing-example/src/pages/index.astro create mode 100644 packages/db/test/fixtures/ticketing-example/tsconfig.json create mode 100644 packages/db/test/unit/field-queries.test.js create mode 100644 packages/db/test/unit/index-queries.test.js create mode 100644 packages/db/test/unit/reference-queries.test.js create mode 100644 packages/db/tsconfig.json diff --git a/.eslintrc.cjs b/.eslintrc.cjs index a5e9f80d80..552033711b 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -122,6 +122,12 @@ module.exports = { 'no-console': 'off', }, }, + { + files: ['packages/db/**/cli/**/*.ts'], + rules: { + 'no-console': 'off', + }, + }, { files: ['packages/astro/src/core/errors/errors-data.ts'], rules: { diff --git a/.prettierignore b/.prettierignore index af84e34338..0703752ee5 100644 --- a/.prettierignore +++ b/.prettierignore @@ -10,6 +10,9 @@ benchmark/results/ **/vendor **/.vercel +# Short-term need to format +!packages/db/test/fixtures + # Directories .github .changeset diff --git a/packages/astro/src/cli/db/index.ts b/packages/astro/src/cli/db/index.ts index 95d6f40453..086a61026b 100644 --- a/packages/astro/src/cli/db/index.ts +++ b/packages/astro/src/cli/db/index.ts @@ -24,7 +24,6 @@ export async function db({ flags }: { flags: Arguments }) { } const { cli } = dbPackage; - const inlineConfig = flagsToAstroInlineConfig(flags); const { astroConfig } = await resolveConfig(inlineConfig, 'build'); diff --git a/packages/astro/src/cli/index.ts b/packages/astro/src/cli/index.ts index a6ca88400d..3978d9feac 100644 --- a/packages/astro/src/cli/index.ts +++ b/packages/astro/src/cli/index.ts @@ -30,6 +30,7 @@ async function printAstroHelp() { ['add', 'Add an integration.'], ['build', 'Build your project and write it to disk.'], ['check', 'Check your project for errors.'], + ['db', 'Manage your Astro database.'], ['dev', 'Start the development server.'], ['docs', 'Open documentation in your web browser.'], ['info', 'List info about your current Astro setup.'], @@ -75,6 +76,10 @@ function resolveCommand(flags: yargs.Arguments): CLICommand { 'docs', 'db', 'info', + 'login', + 'loutout', + 'link', + 'init', ]); if (supportedCommands.has(cmd)) { return cmd as CLICommand; @@ -145,7 +150,11 @@ async function runCommand(cmd: string, flags: yargs.Arguments) { await add(packages, { flags }); return; } - case 'db': { + case 'db': + case 'login': + case 'logout': + case 'link': + case 'init': { const { db } = await import('./db/index.js'); await db({ flags }); return; diff --git a/packages/astro/src/cli/install-package.ts b/packages/astro/src/cli/install-package.ts index 667037a0cb..b68e65d773 100644 --- a/packages/astro/src/cli/install-package.ts +++ b/packages/astro/src/cli/install-package.ts @@ -6,6 +6,9 @@ import prompts from 'prompts'; import resolvePackage from 'resolve'; import whichPm from 'which-pm'; import { type Logger } from '../core/logger/core.js'; +import { createRequire } from 'node:module'; +import { sep } from 'node:path'; +const require = createRequire(import.meta.url); type GetPackageOptions = { skipAsk?: boolean; @@ -18,12 +21,20 @@ export async function getPackage( options: GetPackageOptions, otherDeps: string[] = [] ): Promise { - let packageImport; try { + // Custom resolution logic for @astrojs/db. Since it lives in our monorepo, + // the generic tryResolve() method doesn't work. + if (packageName === '@astrojs/db') { + const packageJsonLoc = require.resolve(packageName + '/package.json', { + paths: [options.cwd ?? process.cwd()], + }); + const packageLoc = packageJsonLoc.replace(`package.json`, 'dist/index.js'); + const packageImport = await import(packageLoc); + return packageImport as T; + } await tryResolve(packageName, options.cwd ?? process.cwd()); - - // The `require.resolve` is required as to avoid Node caching the failed `import` - packageImport = await import(packageName); + const packageImport = await import(packageName); + return packageImport as T; } catch (e) { logger.info( null, @@ -32,13 +43,12 @@ export async function getPackage( const result = await installPackage([packageName, ...otherDeps], options, logger); if (result) { - packageImport = await import(packageName); + const packageImport = await import(packageName); + return packageImport; } else { return undefined; } } - - return packageImport as T; } function tryResolve(packageName: string, cwd: string) { diff --git a/packages/astro/src/core/config/merge.ts b/packages/astro/src/core/config/merge.ts index 93c386ecad..81b3b70f37 100644 --- a/packages/astro/src/core/config/merge.ts +++ b/packages/astro/src/core/config/merge.ts @@ -13,7 +13,7 @@ function mergeConfigRecursively( continue; } - const existing = merged[key]; + let existing = merged[key]; if (existing == null) { merged[key] = value; @@ -38,6 +38,14 @@ function mergeConfigRecursively( } } + if (key === 'data' && rootPath === 'db') { + // db.data can be a function or an array of functions. When + // merging, make sure they become an array + if (!Array.isArray(existing) && !Array.isArray(value)) { + existing = [existing]; + } + } + if (Array.isArray(existing) || Array.isArray(value)) { merged[key] = [...arraify(existing ?? []), ...arraify(value ?? [])]; continue; diff --git a/packages/db/CHANGELOG.md b/packages/db/CHANGELOG.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/db/config-augment.d.ts b/packages/db/config-augment.d.ts new file mode 100644 index 0000000000..3278e6c2ab --- /dev/null +++ b/packages/db/config-augment.d.ts @@ -0,0 +1,4 @@ +declare namespace Config { + type DBUserConfig = import('./dist/core/types.js').DBUserConfig; + export interface Database extends DBUserConfig {} +} diff --git a/packages/db/index.d.ts b/packages/db/index.d.ts new file mode 100644 index 0000000000..3a2134b9fc --- /dev/null +++ b/packages/db/index.d.ts @@ -0,0 +1,3 @@ +/// +export * from './dist/index.js'; +export { default } from './dist/index.js'; diff --git a/packages/db/package.json b/packages/db/package.json new file mode 100644 index 0000000000..7d3a0fb1bc --- /dev/null +++ b/packages/db/package.json @@ -0,0 +1,81 @@ +{ + "name": "@astrojs/db", + "version": "0.3.5", + "description": "", + "license": "MIT", + "type": "module", + "types": "./index.d.ts", + "author": "withastro", + "main": "./dist/index.js", + "exports": { + ".": { + "types": "./index.d.ts", + "import": "./dist/index.js" + }, + "./runtime": { + "types": "./dist/runtime/index.d.ts", + "import": "./dist/runtime/index.js" + }, + "./runtime/drizzle": { + "types": "./dist/runtime/drizzle.d.ts", + "import": "./dist/runtime/drizzle.js" + }, + "./package.json": "./package.json" + }, + "typesVersions": { + "*": { + ".": [ + "./index.d.ts" + ], + "runtime": [ + "./dist/runtime/index.d.ts" + ], + "runtime/drizzle": [ + "./dist/runtime/drizzle.d.ts" + ] + } + }, + "files": [ + "index.d.ts", + "config-augment.d.ts", + "dist" + ], + "keywords": [ + "withastro", + "astro-integration" + ], + "scripts": { + "build": "astro-scripts build \"src/**/*.ts\" && tsc", + "build:ci": "astro-scripts build \"src/**/*.ts\"", + "dev": "astro-scripts dev \"src/**/*.ts\"", + "test": "mocha --exit --timeout 20000 \"test/*.js\" \"test/unit/**/*.js\"", + "test:match": "mocha --timeout 20000 \"test/*.js\" \"test/unit/*.js\" -g" + }, + "dependencies": { + "@libsql/client": "^0.4.3", + "deep-diff": "^1.0.2", + "drizzle-orm": "^0.28.6", + "kleur": "^4.1.5", + "nanoid": "^5.0.1", + "open": "^10.0.3", + "ora": "^7.0.1", + "prompts": "^2.4.2", + "yargs-parser": "^21.1.1", + "zod": "^3.22.4" + }, + "devDependencies": { + "@types/chai": "^4.3.6", + "@types/deep-diff": "^1.0.5", + "@types/diff": "^5.0.8", + "@types/mocha": "^10.0.2", + "@types/prompts": "^2.4.8", + "@types/yargs-parser": "^21.0.3", + "astro": "workspace:*", + "astro-scripts": "workspace:*", + "chai": "^4.3.10", + "cheerio": "1.0.0-rc.12", + "mocha": "^10.2.0", + "typescript": "^5.2.2", + "vite": "^4.4.11" + } +} diff --git a/packages/db/src/core/cli/commands/gen/index.ts b/packages/db/src/core/cli/commands/gen/index.ts new file mode 100644 index 0000000000..551350306c --- /dev/null +++ b/packages/db/src/core/cli/commands/gen/index.ts @@ -0,0 +1,43 @@ +import type { AstroConfig } from 'astro'; +import type { Arguments } from 'yargs-parser'; +import { writeFile } from 'node:fs/promises'; +import { + MIGRATIONS_CREATED, + MIGRATIONS_UP_TO_DATE, + getMigrationStatus, + initializeMigrationsDirectory, +} from '../../migrations.js'; +import { getMigrationQueries } from '../../migration-queries.js'; +import { bgRed, red, reset } from 'kleur/colors'; + +export async function cmd({ config }: { config: AstroConfig; flags: Arguments }) { + const migration = await getMigrationStatus(config); + + if (migration.state === 'no-migrations-found') { + await initializeMigrationsDirectory(migration.currentSnapshot); + console.log(MIGRATIONS_CREATED); + return; + } else if (migration.state === 'up-to-date') { + console.log(MIGRATIONS_UP_TO_DATE); + return; + } + + const { oldSnapshot, newSnapshot, newFilename, diff } = migration; + const { queries: migrationQueries, confirmations } = await getMigrationQueries({ + oldSnapshot, + newSnapshot, + }); + // Warn the user about any changes that lead to data-loss. + // When the user runs `db push`, they will be prompted to confirm these changes. + confirmations.map((message) => console.log(bgRed(' !!! ') + ' ' + red(message))); + const migrationFileContent = { + diff, + db: migrationQueries, + // TODO(fks): Encode the relevant data, instead of the raw message. + // This will give `db push` more control over the formatting of the message. + confirm: confirmations.map((c) => reset(c)), + }; + const migrationFileName = `./migrations/${newFilename}`; + await writeFile(migrationFileName, JSON.stringify(migrationFileContent, undefined, 2)); + console.log(migrationFileName + ' created!'); +} diff --git a/packages/db/src/core/cli/commands/link/index.ts b/packages/db/src/core/cli/commands/link/index.ts new file mode 100644 index 0000000000..ef32341e69 --- /dev/null +++ b/packages/db/src/core/cli/commands/link/index.ts @@ -0,0 +1,79 @@ +import type { AstroConfig } from 'astro'; +import { mkdir, writeFile } from 'node:fs/promises'; +import { bgRed, cyan } from 'kleur/colors'; +import prompts from 'prompts'; +import type { Arguments } from 'yargs-parser'; +import { PROJECT_ID_FILE, getSessionIdFromFile } from '../../../tokens.js'; +import { getAstroStudioUrl } from '../../../utils.js'; +import { MISSING_SESSION_ID_ERROR } from '../../../errors.js'; + +export async function cmd({ flags }: { config: AstroConfig; flags: Arguments }) { + const linkUrl = new URL(getAstroStudioUrl() + '/auth/cli/link'); + const sessionToken = await getSessionIdFromFile(); + if (!sessionToken) { + console.error(MISSING_SESSION_ID_ERROR); + process.exit(1); + } + let body = { id: flags._[4] } as { + id?: string; + projectIdName?: string; + workspaceIdName?: string; + }; + if (!body.id) { + const workspaceIdName = await promptWorkspaceName(); + const projectIdName = await promptProjectName(); + body = { projectIdName, workspaceIdName }; + } + const response = await fetch(linkUrl, { + method: 'POST', + headers: { + Authorization: `Bearer ${await getSessionIdFromFile()}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify(body), + }); + if (!response.ok) { + // Unauthorized + if (response.status === 401) { + console.error( + `${bgRed('Unauthorized')}\n\n Are you logged in?\n Run ${cyan( + 'astro db login' + )} to authenticate and then try linking again.\n\n` + ); + process.exit(1); + } + + console.error(`Failed to link project: ${response.status} ${response.statusText}`); + process.exit(1); + } + const { data } = await response.json(); + await mkdir(new URL('.', PROJECT_ID_FILE), { recursive: true }); + await writeFile(PROJECT_ID_FILE, `${data.id}`); + console.info('Project linked.'); +} + +export async function promptProjectName(defaultName?: string): Promise { + const { projectName } = await prompts({ + type: 'text', + name: 'projectName', + message: 'Project ID', + initial: defaultName, + }); + if (typeof projectName !== 'string') { + process.exit(0); + } + return projectName; +} + +export async function promptWorkspaceName(defaultName?: string): Promise { + const { workspaceName } = await prompts({ + type: 'text', + name: 'workspaceName', + message: 'Workspace ID', + initial: defaultName, + }); + if (typeof workspaceName !== 'string') { + process.exit(0); + } + return workspaceName; +} diff --git a/packages/db/src/core/cli/commands/login/index.ts b/packages/db/src/core/cli/commands/login/index.ts new file mode 100644 index 0000000000..e9548772ae --- /dev/null +++ b/packages/db/src/core/cli/commands/login/index.ts @@ -0,0 +1,52 @@ +import type { AstroConfig } from 'astro'; +import { cyan } from 'kleur/colors'; +import { mkdir, writeFile } from 'node:fs/promises'; +import { createServer } from 'node:http'; +import ora from 'ora'; +import type { Arguments } from 'yargs-parser'; +import { getAstroStudioUrl } from '../../../utils.js'; +import open from 'open'; +import { SESSION_LOGIN_FILE } from '../../../tokens.js'; + +function serveAndResolveSession(): Promise { + let resolve: (value: string | PromiseLike) => void, + reject: (value?: string | PromiseLike) => void; + const sessionPromise = new Promise((_resolve, _reject) => { + resolve = _resolve; + reject = _reject; + }); + + const server = createServer((req, res) => { + res.writeHead(200); + res.end(); + const url = new URL(req.url ?? '/', `http://${req.headers.host}`); + const session = url.searchParams.get('session'); + if (!session) { + reject(); + } else { + resolve(session); + } + }).listen(5710, 'localhost'); + + return sessionPromise.finally(() => { + server.closeAllConnections(); + server.close(); + }); +} + +export async function cmd({ flags }: { config: AstroConfig; flags: Arguments }) { + let session = flags.session; + const loginUrl = getAstroStudioUrl() + '/auth/cli'; + + if (!session) { + console.log(`Opening ${cyan(loginUrl)} in your browser...`); + console.log(`If something goes wrong, copy-and-paste the URL into your browser.`); + open(loginUrl); + const spinner = ora('Waiting for confirmation...'); + session = await serveAndResolveSession(); + spinner.succeed('Successfully logged in!'); + } + + await mkdir(new URL('.', SESSION_LOGIN_FILE), { recursive: true }); + await writeFile(SESSION_LOGIN_FILE, `${session}`); +} diff --git a/packages/db/src/core/cli/commands/logout/index.ts b/packages/db/src/core/cli/commands/logout/index.ts new file mode 100644 index 0000000000..feae880cca --- /dev/null +++ b/packages/db/src/core/cli/commands/logout/index.ts @@ -0,0 +1,9 @@ +import type { AstroConfig } from 'astro'; +import { unlink } from 'node:fs/promises'; +import type { Arguments } from 'yargs-parser'; +import { SESSION_LOGIN_FILE } from '../../../tokens.js'; + +export async function cmd({}: { config: AstroConfig; flags: Arguments }) { + await unlink(SESSION_LOGIN_FILE); + console.log('Successfully logged out of Astro Studio.'); +} diff --git a/packages/db/src/core/cli/commands/push/index.ts b/packages/db/src/core/cli/commands/push/index.ts new file mode 100644 index 0000000000..e0d6b9306e --- /dev/null +++ b/packages/db/src/core/cli/commands/push/index.ts @@ -0,0 +1,264 @@ +import { createClient, type InStatement } from '@libsql/client'; +import type { AstroConfig } from 'astro'; +import { drizzle as drizzleProxy } from 'drizzle-orm/sqlite-proxy'; +import { drizzle as drizzleLibsql } from 'drizzle-orm/libsql'; +import { SQLiteAsyncDialect } from 'drizzle-orm/sqlite-core'; +import { red } from 'kleur/colors'; +import prompts from 'prompts'; +import type { Arguments } from 'yargs-parser'; +import { recreateTables, seedData } from '../../../queries.js'; +import { getManagedAppTokenOrExit } from '../../../tokens.js'; +import { tablesSchema, type AstroConfigWithDB, type DBSnapshot } from '../../../types.js'; +import { getRemoteDatabaseUrl } from '../../../utils.js'; +import { getMigrationQueries } from '../../migration-queries.js'; +import { + createEmptySnapshot, + getMigrations, + getMigrationStatus, + loadInitialSnapshot, + loadMigration, + MIGRATION_NEEDED, + MIGRATIONS_NOT_INITIALIZED, + MIGRATIONS_UP_TO_DATE, +} from '../../migrations.js'; +import { MISSING_SESSION_ID_ERROR } from '../../../errors.js'; + +export async function cmd({ config, flags }: { config: AstroConfig; flags: Arguments }) { + const isDryRun = flags.dryRun; + const appToken = await getManagedAppTokenOrExit(flags.token); + const migration = await getMigrationStatus(config); + if (migration.state === 'no-migrations-found') { + console.log(MIGRATIONS_NOT_INITIALIZED); + process.exit(1); + } else if (migration.state === 'ahead') { + console.log(MIGRATION_NEEDED); + process.exit(1); + } + + // get all migrations from the filesystem + const allLocalMigrations = await getMigrations(); + let missingMigrations: string[] = []; + try { + const { data } = await prepareMigrateQuery({ + migrations: allLocalMigrations, + appToken: appToken.token, + }); + missingMigrations = data; + } catch (error) { + if (error instanceof Error) { + if (error.message.startsWith('{')) { + const { error: { code } = { code: '' } } = JSON.parse(error.message); + if (code === 'TOKEN_UNAUTHORIZED') { + console.error(MISSING_SESSION_ID_ERROR); + } + } + } + console.error(error); + process.exit(1); + } + // push the database schema + if (missingMigrations.length === 0) { + console.log(MIGRATIONS_UP_TO_DATE); + } else { + console.log(`Pushing ${missingMigrations.length} migrations...`); + await pushSchema({ + migrations: missingMigrations, + appToken: appToken.token, + isDryRun, + currentSnapshot: migration.currentSnapshot, + }); + } + // push the database seed data + console.info('Pushing data...'); + await pushData({ config, appToken: appToken.token, isDryRun }); + // cleanup and exit + await appToken.destroy(); + console.info('Push complete!'); +} + +async function pushSchema({ + migrations, + appToken, + isDryRun, + currentSnapshot, +}: { + migrations: string[]; + appToken: string; + isDryRun: boolean; + currentSnapshot: DBSnapshot; +}) { + // load all missing migrations + const initialSnapshot = migrations.find((m) => m === '0000_snapshot.json'); + const filteredMigrations = migrations.filter((m) => m !== '0000_snapshot.json'); + const missingMigrationContents = await Promise.all(filteredMigrations.map(loadMigration)); + // create a migration for the initial snapshot, if needed + const initialMigrationBatch = initialSnapshot + ? ( + await getMigrationQueries({ + oldSnapshot: createEmptySnapshot(), + newSnapshot: await loadInitialSnapshot(), + }) + ).queries + : []; + + // combine all missing migrations into a single batch + const confirmations = missingMigrationContents.reduce((acc, curr) => { + return [...acc, ...(curr.confirm || [])]; + }, [] as string[]); + if (confirmations.length > 0) { + const response = await prompts([ + ...confirmations.map((message, index) => ({ + type: 'confirm' as const, + name: String(index), + message: red('Warning: ') + message + '\nContinue?', + initial: true, + })), + ]); + if ( + Object.values(response).length === 0 || + Object.values(response).some((value) => value === false) + ) { + process.exit(1); + } + } + + // combine all missing migrations into a single batch + const queries = missingMigrationContents.reduce((acc, curr) => { + return [...acc, ...curr.db]; + }, initialMigrationBatch); + // apply the batch to the DB + await runMigrateQuery({ queries, migrations, snapshot: currentSnapshot, appToken, isDryRun }); +} + +const sqlite = new SQLiteAsyncDialect(); + +async function pushData({ + config, + appToken, + isDryRun, +}: { + config: AstroConfigWithDB; + appToken: string; + isDryRun?: boolean; +}) { + const queries: InStatement[] = []; + if (config.db?.data) { + const libsqlClient = createClient({ url: ':memory:' }); + // Stand up tables locally to mirror inserts. + // Needed to generate return values. + await recreateTables({ + db: drizzleLibsql(libsqlClient), + tables: tablesSchema.parse(config.db.tables ?? {}), + }); + + for (const [collectionName, { writable }] of Object.entries(config.db.tables ?? {})) { + if (!writable) { + queries.push({ + sql: `DELETE FROM ${sqlite.escapeName(collectionName)}`, + args: [], + }); + } + } + + // Use proxy to trace all queries to queue up in a batch. + const db = await drizzleProxy(async (sqlQuery, params, method) => { + const stmt: InStatement = { sql: sqlQuery, args: params }; + queries.push(stmt); + // Use in-memory database to generate results for `returning()`. + const { rows } = await libsqlClient.execute(stmt); + const rowValues: unknown[][] = []; + for (const row of rows) { + if (row != null && typeof row === 'object') { + rowValues.push(Object.values(row)); + } + } + if (method === 'get') { + return { rows: rowValues[0] }; + } + return { rows: rowValues }; + }); + await seedData({ + db, + mode: 'build', + data: config.db.data, + }); + } + + const url = new URL('/db/query', getRemoteDatabaseUrl()); + + if (isDryRun) { + console.info('[DRY RUN] Batch data seed:', JSON.stringify(queries, null, 2)); + return new Response(null, { status: 200 }); + } + + return await fetch(url, { + method: 'POST', + headers: new Headers({ + Authorization: `Bearer ${appToken}`, + }), + body: JSON.stringify(queries), + }); +} + +async function runMigrateQuery({ + queries: baseQueries, + migrations, + snapshot, + appToken, + isDryRun, +}: { + queries: string[]; + migrations: string[]; + snapshot: DBSnapshot; + appToken: string; + isDryRun?: boolean; +}) { + const queries = ['pragma defer_foreign_keys=true;', ...baseQueries]; + + const requestBody = { + snapshot, + migrations, + sql: queries, + experimentalVersion: 1, + }; + + if (isDryRun) { + console.info('[DRY RUN] Batch query:', JSON.stringify(requestBody, null, 2)); + return new Response(null, { status: 200 }); + } + + const url = new URL('/migrations/run', getRemoteDatabaseUrl()); + + return await fetch(url, { + method: 'POST', + headers: new Headers({ + Authorization: `Bearer ${appToken}`, + }), + body: JSON.stringify(requestBody), + }); +} + +async function prepareMigrateQuery({ + migrations, + appToken, +}: { + migrations: string[]; + appToken: string; +}) { + const url = new URL('/migrations/prepare', getRemoteDatabaseUrl()); + const requestBody = { + migrations, + experimentalVersion: 1, + }; + const result = await fetch(url, { + method: 'POST', + headers: new Headers({ + Authorization: `Bearer ${appToken}`, + }), + body: JSON.stringify(requestBody), + }); + if (result.status >= 400) { + throw new Error(await result.text()); + } + return await result.json(); +} diff --git a/packages/db/src/core/cli/commands/shell/index.ts b/packages/db/src/core/cli/commands/shell/index.ts new file mode 100644 index 0000000000..13450bf311 --- /dev/null +++ b/packages/db/src/core/cli/commands/shell/index.ts @@ -0,0 +1,16 @@ +import type { AstroConfig } from 'astro'; +import { sql } from 'drizzle-orm'; +import type { Arguments } from 'yargs-parser'; +import { createRemoteDatabaseClient } from '../../../../runtime/db-client.js'; +import { getManagedAppTokenOrExit } from '../../../tokens.js'; +import { getRemoteDatabaseUrl } from '../../../utils.js'; + +export async function cmd({ flags }: { config: AstroConfig; flags: Arguments }) { + const query = flags.query; + const appToken = await getManagedAppTokenOrExit(flags.token); + const db = createRemoteDatabaseClient(appToken.token, getRemoteDatabaseUrl()); + // Temporary: create the migration table just in case it doesn't exist + const result = await db.run(sql.raw(query)); + await appToken.destroy(); + console.log(result); +} diff --git a/packages/db/src/core/cli/commands/verify/index.ts b/packages/db/src/core/cli/commands/verify/index.ts new file mode 100644 index 0000000000..96b4b6576f --- /dev/null +++ b/packages/db/src/core/cli/commands/verify/index.ts @@ -0,0 +1,43 @@ +import type { AstroConfig } from 'astro'; +import type { Arguments } from 'yargs-parser'; +import { + getMigrationStatus, + MIGRATION_NEEDED, + MIGRATIONS_NOT_INITIALIZED, + MIGRATIONS_UP_TO_DATE, +} from '../../migrations.js'; +import { getMigrationQueries } from '../../migration-queries.js'; + +export async function cmd({ config, flags }: { config: AstroConfig; flags: Arguments }) { + const status = await getMigrationStatus(config); + const { state } = status; + if (flags.json) { + if (state === 'ahead') { + const { queries: migrationQueries } = await getMigrationQueries({ + oldSnapshot: status.oldSnapshot, + newSnapshot: status.newSnapshot, + }); + const newFileContent = { + diff: status.diff, + db: migrationQueries, + }; + status.newFileContent = JSON.stringify(newFileContent, null, 2); + } + console.log(JSON.stringify(status)); + process.exit(state === 'up-to-date' ? 0 : 1); + } + switch (state) { + case 'no-migrations-found': { + console.log(MIGRATIONS_NOT_INITIALIZED); + process.exit(1); + } + case 'ahead': { + console.log(MIGRATION_NEEDED); + process.exit(1); + } + case 'up-to-date': { + console.log(MIGRATIONS_UP_TO_DATE); + return; + } + } +} diff --git a/packages/db/src/core/cli/index.ts b/packages/db/src/core/cli/index.ts new file mode 100644 index 0000000000..56a5667a67 --- /dev/null +++ b/packages/db/src/core/cli/index.ts @@ -0,0 +1,73 @@ +import type { AstroConfig } from 'astro'; +import type { Arguments } from 'yargs-parser'; +import { STUDIO_CONFIG_MISSING_CLI_ERROR } from '../errors.js'; + +export async function cli({ flags, config }: { flags: Arguments; config: AstroConfig }) { + const args = flags._ as string[]; + // Most commands are `astro db foo`, but for now login/logout + // are also handled by this package, so first check if this is a db command. + const command = args[2] === 'db' ? args[3] : args[2]; + + if (!config.db?.studio) { + console.log(STUDIO_CONFIG_MISSING_CLI_ERROR); + process.exit(1); + } + + switch (command) { + case 'shell': { + const { cmd } = await import('./commands/shell/index.js'); + return await cmd({ config, flags }); + } + case 'gen': + case 'sync': { + const { cmd } = await import('./commands/gen/index.js'); + return await cmd({ config, flags }); + } + case 'push': { + const { cmd } = await import('./commands/push/index.js'); + return await cmd({ config, flags }); + } + case 'verify': { + const { cmd } = await import('./commands/verify/index.js'); + return await cmd({ config, flags }); + } + case 'login': { + const { cmd } = await import('./commands/login/index.js'); + return await cmd({ config, flags }); + } + case 'logout': { + const { cmd } = await import('./commands/logout/index.js'); + return await cmd({ config, flags }); + } + case 'link': { + const { cmd } = await import('./commands/link/index.js'); + return await cmd({ config, flags }); + } + default: { + if (command == null) { + console.error(`No command provided. + +${showHelp()}`); + } else { + console.error(`Unknown command: ${command} + +${showHelp()}`); + } + return; + } + } + + function showHelp() { + return `astro db + +Usage: + +astro login Authenticate your machine with Astro Studio +astro logout End your authenticated session with Astro Studio +astro link Link this directory to an Astro Studio project + +astro db gen Creates snapshot based on your schema +astro db push Pushes migrations to Astro Studio +astro db verify Verifies migrations have been pushed and errors if not`; + } +} diff --git a/packages/db/src/core/cli/migration-queries.ts b/packages/db/src/core/cli/migration-queries.ts new file mode 100644 index 0000000000..7acd1dad3f --- /dev/null +++ b/packages/db/src/core/cli/migration-queries.ts @@ -0,0 +1,554 @@ +import * as color from 'kleur/colors'; +import deepDiff from 'deep-diff'; +import { + columnSchema, + type BooleanColumn, + type DBTable, + type DBTables, + type DBColumn, + type DBColumns, + type DBSnapshot, + type DateColumn, + type ColumnType, + type Indexes, + type JsonColumn, + type NumberColumn, + type TextColumn, +} from '../types.js'; +import { SQLiteAsyncDialect } from 'drizzle-orm/sqlite-core'; +import { customAlphabet } from 'nanoid'; +import prompts from 'prompts'; +import { + getCreateIndexQueries, + getCreateTableQuery, + getModifiers, + getReferencesConfig, + hasDefault, + schemaTypeToSqlType, +} from '../queries.js'; +import { hasPrimaryKey } from '../../runtime/index.js'; +import { isSerializedSQL } from '../../runtime/types.js'; + +const sqlite = new SQLiteAsyncDialect(); +const genTempTableName = customAlphabet('abcdefghijklmnopqrstuvwxyz', 10); + +/** Dependency injected for unit testing */ +type AmbiguityResponses = { + collectionRenames: Record; + columnRenames: { + [collectionName: string]: Record; + }; +}; + +export async function getMigrationQueries({ + oldSnapshot, + newSnapshot, + ambiguityResponses, +}: { + oldSnapshot: DBSnapshot; + newSnapshot: DBSnapshot; + ambiguityResponses?: AmbiguityResponses; +}): Promise<{ queries: string[]; confirmations: string[] }> { + const queries: string[] = []; + const confirmations: string[] = []; + let added = getAddedCollections(oldSnapshot, newSnapshot); + let dropped = getDroppedCollections(oldSnapshot, newSnapshot); + if (!isEmpty(added) && !isEmpty(dropped)) { + const resolved = await resolveCollectionRenames(added, dropped, ambiguityResponses); + added = resolved.added; + dropped = resolved.dropped; + for (const { from, to } of resolved.renamed) { + const renameQuery = `ALTER TABLE ${sqlite.escapeName(from)} RENAME TO ${sqlite.escapeName( + to + )}`; + queries.push(renameQuery); + } + } + + for (const [collectionName, collection] of Object.entries(added)) { + queries.push(getCreateTableQuery(collectionName, collection)); + queries.push(...getCreateIndexQueries(collectionName, collection)); + } + + for (const [collectionName] of Object.entries(dropped)) { + const dropQuery = `DROP TABLE ${sqlite.escapeName(collectionName)}`; + queries.push(dropQuery); + } + + for (const [collectionName, newCollection] of Object.entries(newSnapshot.schema)) { + const oldCollection = oldSnapshot.schema[collectionName]; + if (!oldCollection) continue; + const result = await getCollectionChangeQueries({ + collectionName, + oldCollection, + newCollection, + }); + queries.push(...result.queries); + confirmations.push(...result.confirmations); + } + return { queries, confirmations }; +} + +export async function getCollectionChangeQueries({ + collectionName, + oldCollection, + newCollection, + ambiguityResponses, +}: { + collectionName: string; + oldCollection: DBTable; + newCollection: DBTable; + ambiguityResponses?: AmbiguityResponses; +}): Promise<{ queries: string[]; confirmations: string[] }> { + const queries: string[] = []; + const confirmations: string[] = []; + const updated = getUpdatedColumns(oldCollection.columns, newCollection.columns); + let added = getAdded(oldCollection.columns, newCollection.columns); + let dropped = getDropped(oldCollection.columns, newCollection.columns); + /** Any foreign key changes require a full table recreate */ + const hasForeignKeyChanges = Boolean( + deepDiff(oldCollection.foreignKeys, newCollection.foreignKeys) + ); + + if (!hasForeignKeyChanges && isEmpty(updated) && isEmpty(added) && isEmpty(dropped)) { + return { + queries: getChangeIndexQueries({ + collectionName, + oldIndexes: oldCollection.indexes, + newIndexes: newCollection.indexes, + }), + confirmations, + }; + } + if (!hasForeignKeyChanges && !isEmpty(added) && !isEmpty(dropped)) { + const resolved = await resolveColumnRenames(collectionName, added, dropped, ambiguityResponses); + added = resolved.added; + dropped = resolved.dropped; + queries.push(...getColumnRenameQueries(collectionName, resolved.renamed)); + } + if ( + !hasForeignKeyChanges && + isEmpty(updated) && + Object.values(dropped).every(canAlterTableDropColumn) && + Object.values(added).every(canAlterTableAddColumn) + ) { + queries.push( + ...getAlterTableQueries(collectionName, added, dropped), + ...getChangeIndexQueries({ + collectionName, + oldIndexes: oldCollection.indexes, + newIndexes: newCollection.indexes, + }) + ); + return { queries, confirmations }; + } + + const dataLossCheck = canRecreateTableWithoutDataLoss(added, updated); + if (dataLossCheck.dataLoss) { + const { reason, columnName } = dataLossCheck; + const reasonMsgs: Record = { + 'added-required': `New column ${color.bold( + collectionName + '.' + columnName + )} is required with no default value.\nThis requires deleting existing data in the ${color.bold( + collectionName + )} collection.`, + 'added-unique': `New column ${color.bold( + collectionName + '.' + columnName + )} is marked as unique.\nThis requires deleting existing data in the ${color.bold( + collectionName + )} collection.`, + 'updated-type': `Updated column ${color.bold( + collectionName + '.' + columnName + )} cannot convert data to new column data type.\nThis requires deleting existing data in the ${color.bold( + collectionName + )} collection.`, + }; + confirmations.push(reasonMsgs[reason]); + } + + const primaryKeyExists = Object.entries(newCollection.columns).find(([, column]) => + hasPrimaryKey(column) + ); + const droppedPrimaryKey = Object.entries(dropped).find(([, column]) => hasPrimaryKey(column)); + + const recreateTableQueries = getRecreateTableQueries({ + collectionName, + newCollection, + added, + hasDataLoss: dataLossCheck.dataLoss, + migrateHiddenPrimaryKey: !primaryKeyExists && !droppedPrimaryKey, + }); + queries.push(...recreateTableQueries, ...getCreateIndexQueries(collectionName, newCollection)); + return { queries, confirmations }; +} + +function getChangeIndexQueries({ + collectionName, + oldIndexes = {}, + newIndexes = {}, +}: { + collectionName: string; + oldIndexes?: Indexes; + newIndexes?: Indexes; +}) { + const added = getAdded(oldIndexes, newIndexes); + const dropped = getDropped(oldIndexes, newIndexes); + const updated = getUpdated(oldIndexes, newIndexes); + + Object.assign(dropped, updated); + Object.assign(added, updated); + + const queries: string[] = []; + for (const indexName of Object.keys(dropped)) { + const dropQuery = `DROP INDEX ${sqlite.escapeName(indexName)}`; + queries.push(dropQuery); + } + queries.push(...getCreateIndexQueries(collectionName, { indexes: added })); + return queries; +} + +type Renamed = Array<{ from: string; to: string }>; + +async function resolveColumnRenames( + collectionName: string, + mightAdd: DBColumns, + mightDrop: DBColumns, + ambiguityResponses?: AmbiguityResponses +): Promise<{ added: DBColumns; dropped: DBColumns; renamed: Renamed }> { + const added: DBColumns = {}; + const dropped: DBColumns = {}; + const renamed: Renamed = []; + + for (const [columnName, column] of Object.entries(mightAdd)) { + let oldColumnName = ambiguityResponses + ? ambiguityResponses.columnRenames[collectionName]?.[columnName] ?? '__NEW__' + : undefined; + if (!oldColumnName) { + const res = await prompts( + { + type: 'select', + name: 'columnName', + message: + 'New column ' + + color.blue(color.bold(`${collectionName}.${columnName}`)) + + ' detected. Was this renamed from an existing column?', + choices: [ + { title: 'New column (not renamed from existing)', value: '__NEW__' }, + ...Object.keys(mightDrop) + .filter((key) => !(key in renamed)) + .map((key) => ({ title: key, value: key })), + ], + }, + { + onCancel: () => { + process.exit(1); + }, + } + ); + oldColumnName = res.columnName as string; + } + + if (oldColumnName === '__NEW__') { + added[columnName] = column; + } else { + renamed.push({ from: oldColumnName, to: columnName }); + } + } + for (const [droppedColumnName, droppedColumn] of Object.entries(mightDrop)) { + if (!renamed.find((r) => r.from === droppedColumnName)) { + dropped[droppedColumnName] = droppedColumn; + } + } + + return { added, dropped, renamed }; +} + +async function resolveCollectionRenames( + mightAdd: DBTables, + mightDrop: DBTables, + ambiguityResponses?: AmbiguityResponses +): Promise<{ added: DBTables; dropped: DBTables; renamed: Renamed }> { + const added: DBTables = {}; + const dropped: DBTables = {}; + const renamed: Renamed = []; + + for (const [collectionName, collection] of Object.entries(mightAdd)) { + let oldCollectionName = ambiguityResponses + ? ambiguityResponses.collectionRenames[collectionName] ?? '__NEW__' + : undefined; + if (!oldCollectionName) { + const res = await prompts( + { + type: 'select', + name: 'collectionName', + message: + 'New collection ' + + color.blue(color.bold(collectionName)) + + ' detected. Was this renamed from an existing collection?', + choices: [ + { title: 'New collection (not renamed from existing)', value: '__NEW__' }, + ...Object.keys(mightDrop) + .filter((key) => !(key in renamed)) + .map((key) => ({ title: key, value: key })), + ], + }, + { + onCancel: () => { + process.exit(1); + }, + } + ); + oldCollectionName = res.collectionName as string; + } + + if (oldCollectionName === '__NEW__') { + added[collectionName] = collection; + } else { + renamed.push({ from: oldCollectionName, to: collectionName }); + } + } + + for (const [droppedCollectionName, droppedCollection] of Object.entries(mightDrop)) { + if (!renamed.find((r) => r.from === droppedCollectionName)) { + dropped[droppedCollectionName] = droppedCollection; + } + } + + return { added, dropped, renamed }; +} + +function getAddedCollections(oldCollections: DBSnapshot, newCollections: DBSnapshot): DBTables { + const added: DBTables = {}; + for (const [key, newCollection] of Object.entries(newCollections.schema)) { + if (!(key in oldCollections.schema)) added[key] = newCollection; + } + return added; +} + +function getDroppedCollections(oldCollections: DBSnapshot, newCollections: DBSnapshot): DBTables { + const dropped: DBTables = {}; + for (const [key, oldCollection] of Object.entries(oldCollections.schema)) { + if (!(key in newCollections.schema)) dropped[key] = oldCollection; + } + return dropped; +} + +function getColumnRenameQueries(unescapedCollectionName: string, renamed: Renamed): string[] { + const queries: string[] = []; + const collectionName = sqlite.escapeName(unescapedCollectionName); + + for (const { from, to } of renamed) { + const q = `ALTER TABLE ${collectionName} RENAME COLUMN ${sqlite.escapeName( + from + )} TO ${sqlite.escapeName(to)}`; + queries.push(q); + } + + return queries; +} + +/** + * Get ALTER TABLE queries to update the table schema. Assumes all added and dropped columns pass + * `canUseAlterTableAddColumn` and `canAlterTableDropColumn` checks! + */ +function getAlterTableQueries( + unescapedCollectionName: string, + added: DBColumns, + dropped: DBColumns +): string[] { + const queries: string[] = []; + const collectionName = sqlite.escapeName(unescapedCollectionName); + + for (const [unescColumnName, column] of Object.entries(added)) { + const columnName = sqlite.escapeName(unescColumnName); + const type = schemaTypeToSqlType(column.type); + const q = `ALTER TABLE ${collectionName} ADD COLUMN ${columnName} ${type}${getModifiers( + columnName, + column + )}`; + queries.push(q); + } + + for (const unescColumnName of Object.keys(dropped)) { + const columnName = sqlite.escapeName(unescColumnName); + const q = `ALTER TABLE ${collectionName} DROP COLUMN ${columnName}`; + queries.push(q); + } + + return queries; +} + +function getRecreateTableQueries({ + collectionName: unescCollectionName, + newCollection, + added, + hasDataLoss, + migrateHiddenPrimaryKey, +}: { + collectionName: string; + newCollection: DBTable; + added: Record; + hasDataLoss: boolean; + migrateHiddenPrimaryKey: boolean; +}): string[] { + const unescTempName = `${unescCollectionName}_${genTempTableName()}`; + const tempName = sqlite.escapeName(unescTempName); + const collectionName = sqlite.escapeName(unescCollectionName); + + if (hasDataLoss) { + return [ + `DROP TABLE ${collectionName}`, + getCreateTableQuery(unescCollectionName, newCollection), + ]; + } + const newColumns = [...Object.keys(newCollection.columns)]; + if (migrateHiddenPrimaryKey) { + newColumns.unshift('_id'); + } + const escapedColumns = newColumns + .filter((i) => !(i in added)) + .map((c) => sqlite.escapeName(c)) + .join(', '); + + return [ + getCreateTableQuery(unescTempName, newCollection), + `INSERT INTO ${tempName} (${escapedColumns}) SELECT ${escapedColumns} FROM ${collectionName}`, + `DROP TABLE ${collectionName}`, + `ALTER TABLE ${tempName} RENAME TO ${collectionName}`, + ]; +} + +function isEmpty(obj: Record) { + return Object.keys(obj).length === 0; +} + +/** + * ADD COLUMN is preferred for O(1) table updates, but is only supported for _some_ column + * definitions. + * + * @see https://www.sqlite.org/lang_altertable.html#alter_table_add_column + */ +function canAlterTableAddColumn(column: DBColumn) { + if (column.schema.unique) return false; + if (hasRuntimeDefault(column)) return false; + if (!column.schema.optional && !hasDefault(column)) return false; + if (hasPrimaryKey(column)) return false; + if (getReferencesConfig(column)) return false; + return true; +} + +function canAlterTableDropColumn(column: DBColumn) { + if (column.schema.unique) return false; + if (hasPrimaryKey(column)) return false; + return true; +} + +type DataLossReason = 'added-required' | 'added-unique' | 'updated-type'; +type DataLossResponse = + | { dataLoss: false } + | { dataLoss: true; columnName: string; reason: DataLossReason }; + +function canRecreateTableWithoutDataLoss( + added: DBColumns, + updated: UpdatedColumns +): DataLossResponse { + for (const [columnName, a] of Object.entries(added)) { + if (hasPrimaryKey(a) && a.type !== 'number' && !hasDefault(a)) { + return { dataLoss: true, columnName, reason: 'added-required' }; + } + if (!a.schema.optional && !hasDefault(a)) { + return { dataLoss: true, columnName, reason: 'added-required' }; + } + if (!a.schema.optional && a.schema.unique) { + return { dataLoss: true, columnName, reason: 'added-unique' }; + } + } + for (const [columnName, u] of Object.entries(updated)) { + if (u.old.type !== u.new.type && !canChangeTypeWithoutQuery(u.old, u.new)) { + return { dataLoss: true, columnName, reason: 'updated-type' }; + } + } + return { dataLoss: false }; +} + +function getAdded(oldObj: Record, newObj: Record) { + const added: Record = {}; + for (const [key, value] of Object.entries(newObj)) { + if (!(key in oldObj)) added[key] = value; + } + return added; +} + +function getDropped(oldObj: Record, newObj: Record) { + const dropped: Record = {}; + for (const [key, value] of Object.entries(oldObj)) { + if (!(key in newObj)) dropped[key] = value; + } + return dropped; +} + +function getUpdated(oldObj: Record, newObj: Record) { + const updated: Record = {}; + for (const [key, value] of Object.entries(newObj)) { + const oldValue = oldObj[key]; + if (!oldValue) continue; + if (deepDiff(oldValue, value)) updated[key] = value; + } + return updated; +} + +type UpdatedColumns = Record; + +function getUpdatedColumns(oldColumns: DBColumns, newColumns: DBColumns): UpdatedColumns { + const updated: UpdatedColumns = {}; + for (const [key, newColumn] of Object.entries(newColumns)) { + let oldColumn = oldColumns[key]; + if (!oldColumn) continue; + + if (oldColumn.type !== newColumn.type && canChangeTypeWithoutQuery(oldColumn, newColumn)) { + // If we can safely change the type without a query, + // try parsing the old schema as the new schema. + // This lets us diff the columns as if they were the same type. + const asNewColumn = columnSchema.safeParse({ + type: newColumn.type, + schema: oldColumn.schema, + }); + if (asNewColumn.success) { + oldColumn = asNewColumn.data; + } + // If parsing fails, move on to the standard diff. + } + + const diff = deepDiff(oldColumn, newColumn); + + if (diff) { + updated[key] = { old: oldColumn, new: newColumn }; + } + } + return updated; +} +const typeChangesWithoutQuery: Array<{ from: ColumnType; to: ColumnType }> = [ + { from: 'boolean', to: 'number' }, + { from: 'date', to: 'text' }, + { from: 'json', to: 'text' }, +]; + +function canChangeTypeWithoutQuery(oldColumn: DBColumn, newColumn: DBColumn) { + return typeChangesWithoutQuery.some( + ({ from, to }) => oldColumn.type === from && newColumn.type === to + ); +} + +// Using `DBColumn` will not narrow `default` based on the column `type` +// Handle each column separately +type WithDefaultDefined = T & Required>; +type DBColumnWithDefault = + | WithDefaultDefined + | WithDefaultDefined + | WithDefaultDefined + | WithDefaultDefined + | WithDefaultDefined; + +function hasRuntimeDefault(column: DBColumn): column is DBColumnWithDefault { + return !!(column.schema.default && isSerializedSQL(column.schema.default)); +} diff --git a/packages/db/src/core/cli/migrations.ts b/packages/db/src/core/cli/migrations.ts new file mode 100644 index 0000000000..8b57d4b63f --- /dev/null +++ b/packages/db/src/core/cli/migrations.ts @@ -0,0 +1,140 @@ +import deepDiff from 'deep-diff'; +import { mkdir, readFile, readdir, writeFile } from 'fs/promises'; +import { tablesSchema, type DBSnapshot } from '../types.js'; +import type { AstroConfig } from 'astro'; +import { cyan, green, yellow } from 'kleur/colors'; +const { applyChange, diff: generateDiff } = deepDiff; + +export type MigrationStatus = + | { + state: 'no-migrations-found'; + currentSnapshot: DBSnapshot; + } + | { + state: 'ahead'; + oldSnapshot: DBSnapshot; + newSnapshot: DBSnapshot; + diff: deepDiff.Diff[]; + newFilename: string; + summary: string; + newFileContent?: string; + } + | { + state: 'up-to-date'; + currentSnapshot: DBSnapshot; + }; + +export async function getMigrationStatus(config: AstroConfig): Promise { + const currentSnapshot = createCurrentSnapshot(config); + const allMigrationFiles = await getMigrations(); + + if (allMigrationFiles.length === 0) { + return { + state: 'no-migrations-found', + currentSnapshot, + }; + } + + const previousSnapshot = await initializeFromMigrations(allMigrationFiles); + const diff = generateDiff(previousSnapshot, currentSnapshot); + + if (diff) { + const n = getNewMigrationNumber(allMigrationFiles); + const newFilename = `${String(n + 1).padStart(4, '0')}_migration.json`; + return { + state: 'ahead', + oldSnapshot: previousSnapshot, + newSnapshot: currentSnapshot, + diff, + newFilename, + summary: generateDiffSummary(diff), + }; + } + + return { + state: 'up-to-date', + currentSnapshot, + }; +} + +export const MIGRATIONS_CREATED = `${green( + '■ Migrations initialized!' +)}\n\n To execute your migrations, run\n ${cyan('astro db push')}`; +export const MIGRATIONS_UP_TO_DATE = `${green( + '■ No migrations needed!' +)}\n\n Your database is up to date.\n`; +export const MIGRATIONS_NOT_INITIALIZED = `${yellow( + '▶ No migrations found!' +)}\n\n To scaffold your migrations folder, run\n ${cyan('astro db sync')}\n`; +export const MIGRATION_NEEDED = `${yellow( + '▶ Changes detected!' +)}\n\n To create the necessary migration file, run\n ${cyan('astro db sync')}\n`; + +function generateDiffSummary(diff: deepDiff.Diff[]) { + // TODO: human readable summary + return JSON.stringify(diff, null, 2); +} + +function getNewMigrationNumber(allMigrationFiles: string[]): number { + const len = allMigrationFiles.length - 1; + return allMigrationFiles.reduce((acc, curr) => { + const num = Number.parseInt(curr.split('_')[0] ?? len, 10); + return num > acc ? num : acc; + }, 0); +} + +export async function getMigrations(): Promise { + const migrationFiles = await readdir('./migrations').catch((err) => { + if (err.code === 'ENOENT') { + return []; + } + throw err; + }); + return migrationFiles; +} + +export async function loadMigration( + migration: string +): Promise<{ diff: any[]; db: string[]; confirm?: string[] }> { + return JSON.parse(await readFile(`./migrations/${migration}`, 'utf-8')); +} + +export async function loadInitialSnapshot(): Promise { + const snapshot = JSON.parse(await readFile('./migrations/0000_snapshot.json', 'utf-8')); + // `experimentalVersion: 1` -- added the version column + if (snapshot.experimentalVersion === 1) { + return snapshot; + } + // `experimentalVersion: 0` -- initial format + if (!snapshot.schema) { + return { experimentalVersion: 1, schema: snapshot }; + } + throw new Error('Invalid snapshot format'); +} + +export async function initializeMigrationsDirectory(currentSnapshot: DBSnapshot) { + await mkdir('./migrations', { recursive: true }); + await writeFile('./migrations/0000_snapshot.json', JSON.stringify(currentSnapshot, undefined, 2)); +} + +export async function initializeFromMigrations(allMigrationFiles: string[]): Promise { + const prevSnapshot = await loadInitialSnapshot(); + for (const migration of allMigrationFiles) { + if (migration === '0000_snapshot.json') continue; + const migrationContent = await loadMigration(migration); + migrationContent.diff.forEach((change: any) => { + applyChange(prevSnapshot, {}, change); + }); + } + return prevSnapshot; +} + +export function createCurrentSnapshot(config: AstroConfig): DBSnapshot { + // Parse to resolve non-serializable types like () => references + const tablesConfig = tablesSchema.parse(config.db?.tables ?? {}); + const schema = JSON.parse(JSON.stringify(tablesConfig)); + return { experimentalVersion: 1, schema }; +} +export function createEmptySnapshot(): DBSnapshot { + return { experimentalVersion: 1, schema: {} }; +} diff --git a/packages/db/src/core/consts.ts b/packages/db/src/core/consts.ts new file mode 100644 index 0000000000..1f6771b04f --- /dev/null +++ b/packages/db/src/core/consts.ts @@ -0,0 +1,14 @@ +import { readFileSync } from 'node:fs'; + +export const PACKAGE_NAME = JSON.parse( + readFileSync(new URL('../../package.json', import.meta.url), 'utf8') +).name; + +export const RUNTIME_IMPORT = JSON.stringify(`${PACKAGE_NAME}/runtime`); +export const RUNTIME_DRIZZLE_IMPORT = JSON.stringify(`${PACKAGE_NAME}/runtime/drizzle`); + +export const DB_TYPES_FILE = 'db-types.d.ts'; + +export const VIRTUAL_MODULE_ID = 'astro:db'; + +export const DB_PATH = '.astro/content.db'; diff --git a/packages/db/src/core/errors.ts b/packages/db/src/core/errors.ts new file mode 100644 index 0000000000..4346f23557 --- /dev/null +++ b/packages/db/src/core/errors.ts @@ -0,0 +1,43 @@ +import { cyan, bold, red, green, yellow } from 'kleur/colors'; + +export const MISSING_SESSION_ID_ERROR = `${red('▶ Login required!')} + + To authenticate with Astro Studio, run + ${cyan('astro db login')}\n`; + +export const MISSING_PROJECT_ID_ERROR = `${red('▶ Directory not linked.')} + + To link this directory to an Astro Studio project, run + ${cyan('astro db link')}\n`; + +export const STUDIO_CONFIG_MISSING_WRITABLE_COLLECTIONS_ERROR = (collectionName: string) => `${red( + `▶ Writable collection ${bold(collectionName)} requires Astro Studio or the ${yellow( + 'unsafeWritable' + )} option.` +)} + + Visit ${cyan('https://astro.build/studio')} to create your account + and set ${green('studio: true')} in your astro.config.mjs file to enable Studio.\n`; + +export const UNSAFE_WRITABLE_WARNING = `${yellow( + 'unsafeWritable' +)} option is enabled and you are using writable tables. + Redeploying your app may result in wiping away your database. + I hope you know what you are doing.\n`; + +export const STUDIO_CONFIG_MISSING_CLI_ERROR = `${red('▶ This command requires Astro Studio.')} + + Visit ${cyan('https://astro.build/studio')} to create your account + and set ${green('studio: true')} in your astro.config.mjs file to enable Studio.\n`; + +export const MIGRATIONS_NOT_INITIALIZED = `${yellow( + '▶ No migrations found!' +)}\n\n To scaffold your migrations folder, run\n ${cyan('astro db sync')}\n`; + +export const SEED_WRITABLE_IN_PROD_ERROR = (collectionName: string) => { + return `${red( + `Writable tables should not be seeded in production with data().` + )} You can seed ${bold( + collectionName + )} in development mode only using the "mode" flag. See the docs for more: https://www.notion.so/astroinc/astrojs-db-README-dcf6fa10de9a4f528be56cee96e8c054?pvs=4#278aed3fc37e4cec80240d1552ff6ac5`; +}; diff --git a/packages/db/src/core/integration/error-map.ts b/packages/db/src/core/integration/error-map.ts new file mode 100644 index 0000000000..e471fead5d --- /dev/null +++ b/packages/db/src/core/integration/error-map.ts @@ -0,0 +1,104 @@ +/** + * This is a modified version of Astro's error map. source: + * https://github.com/withastro/astro/blob/main/packages/astro/src/content/error-map.ts + */ +import type { z } from 'astro/zod'; + +interface TypeOrLiteralErrByPathEntry { + code: 'invalid_type' | 'invalid_literal'; + received: unknown; + expected: unknown[]; +} + +export const errorMap: z.ZodErrorMap = (baseError, ctx) => { + const baseErrorPath = flattenErrorPath(baseError.path); + if (baseError.code === 'invalid_union') { + // Optimization: Combine type and literal errors for keys that are common across ALL union types + // Ex. a union between `{ key: z.literal('tutorial') }` and `{ key: z.literal('blog') }` will + // raise a single error when `key` does not match: + // > Did not match union. + // > key: Expected `'tutorial' | 'blog'`, received 'foo' + const typeOrLiteralErrByPath = new Map(); + for (const unionError of baseError.unionErrors.flatMap((e) => e.errors)) { + if (unionError.code === 'invalid_type' || unionError.code === 'invalid_literal') { + const flattenedErrorPath = flattenErrorPath(unionError.path); + const typeOrLiteralErr = typeOrLiteralErrByPath.get(flattenedErrorPath); + if (typeOrLiteralErr) { + typeOrLiteralErr.expected.push(unionError.expected); + } else { + typeOrLiteralErrByPath.set(flattenedErrorPath, { + code: unionError.code, + received: (unionError as any).received, + expected: [unionError.expected], + }); + } + } + } + const messages: string[] = [ + prefix( + baseErrorPath, + typeOrLiteralErrByPath.size ? 'Did not match union:' : 'Did not match union.' + ), + ]; + return { + message: messages + .concat( + [...typeOrLiteralErrByPath.entries()] + // If type or literal error isn't common to ALL union types, + // filter it out. Can lead to confusing noise. + .filter(([, error]) => error.expected.length === baseError.unionErrors.length) + .map(([key, error]) => + // Avoid printing the key again if it's a base error + key === baseErrorPath + ? `> ${getTypeOrLiteralMsg(error)}` + : `> ${prefix(key, getTypeOrLiteralMsg(error))}` + ) + ) + .join('\n'), + }; + } + if (baseError.code === 'invalid_literal' || baseError.code === 'invalid_type') { + return { + message: prefix( + baseErrorPath, + getTypeOrLiteralMsg({ + code: baseError.code, + received: (baseError as any).received, + expected: [baseError.expected], + }) + ), + }; + } else if (baseError.message) { + return { message: prefix(baseErrorPath, baseError.message) }; + } else { + return { message: prefix(baseErrorPath, ctx.defaultError) }; + } +}; + +const getTypeOrLiteralMsg = (error: TypeOrLiteralErrByPathEntry): string => { + if (error.received === 'undefined') return 'Required'; + const expectedDeduped = new Set(error.expected); + switch (error.code) { + case 'invalid_type': + return `Expected type \`${unionExpectedVals(expectedDeduped)}\`, received ${JSON.stringify( + error.received + )}`; + case 'invalid_literal': + return `Expected \`${unionExpectedVals(expectedDeduped)}\`, received ${JSON.stringify( + error.received + )}`; + } +}; + +const prefix = (key: string, msg: string) => (key.length ? `**${key}**: ${msg}` : msg); + +const unionExpectedVals = (expectedVals: Set) => + [...expectedVals] + .map((expectedVal, idx) => { + if (idx === 0) return JSON.stringify(expectedVal); + const sep = ' | '; + return `${sep}${JSON.stringify(expectedVal)}`; + }) + .join(''); + +const flattenErrorPath = (errorPath: Array) => errorPath.join('.'); diff --git a/packages/db/src/core/integration/file-url.ts b/packages/db/src/core/integration/file-url.ts new file mode 100644 index 0000000000..7dc4b916e9 --- /dev/null +++ b/packages/db/src/core/integration/file-url.ts @@ -0,0 +1,95 @@ +import type { AstroConfig, AstroIntegration } from 'astro'; +import type { VitePlugin } from '../utils.js'; +import fs from 'node:fs'; +import { pathToFileURL } from 'node:url'; +import path from 'node:path'; + +async function copyFile(toDir: URL, fromUrl: URL, toUrl: URL) { + await fs.promises.mkdir(toDir, { recursive: true }); + await fs.promises.rename(fromUrl, toUrl); +} + +export function fileURLIntegration(): AstroIntegration { + const fileNames: string[] = []; + + function createVitePlugin(command: 'build' | 'preview' | 'dev'): VitePlugin { + let referenceIds: string[] = []; + return { + name: '@astrojs/db/file-url', + enforce: 'pre', + async load(id) { + if (id.endsWith('?fileurl')) { + const filePath = id.slice(0, id.indexOf('?')); + if (command === 'build') { + const data = await fs.promises.readFile(filePath); + const name = path.basename(filePath); + const referenceId = this.emitFile({ + name, + source: data, + type: 'asset', + }); + referenceIds.push(referenceId); + return `export default import.meta.ROLLUP_FILE_URL_${referenceId};`; + } + // dev mode + else { + return `export default new URL(${JSON.stringify(pathToFileURL(filePath).toString())})`; + } + } + }, + generateBundle() { + // Save file names so we can copy them back over. + for (const referenceId of referenceIds) { + fileNames.push(this.getFileName(referenceId)); + } + // Reset `referenceIds` for later generateBundle() runs. + // Prevents lookup for ids that have already been copied. + referenceIds = []; + }, + }; + } + + let config: AstroConfig; + return { + name: '@astrojs/db/file-url', + hooks: { + 'astro:config:setup'({ updateConfig, command }) { + updateConfig({ + vite: { + plugins: [createVitePlugin(command)], + }, + }); + }, + 'astro:config:done': ({ config: _config }) => { + config = _config; + }, + async 'astro:build:done'() { + if (config.output === 'static') { + // Delete the files since they are only used for the build process. + const unlinks: Promise[] = []; + for (const fileName of fileNames) { + const url = new URL(fileName, config.outDir); + unlinks.push(fs.promises.unlink(url)); + } + await Promise.all(unlinks); + const assetDir = new URL(config.build.assets, config.outDir); + const assetFiles = await fs.promises.readdir(assetDir); + if (!assetFiles.length) { + // Directory is empty, delete it. + await fs.promises.rmdir(assetDir); + } + } else { + // Move files back over to the dist output path + const moves: Promise[] = []; + for (const fileName of fileNames) { + const fromUrl = new URL(fileName, config.build.client); + const toUrl = new URL(fileName, config.build.server); + const toDir = new URL('./', toUrl); + moves.push(copyFile(toDir, fromUrl, toUrl)); + } + await Promise.all(moves); + } + }, + }, + }; +} diff --git a/packages/db/src/core/integration/index.ts b/packages/db/src/core/integration/index.ts new file mode 100644 index 0000000000..c9b7aefe79 --- /dev/null +++ b/packages/db/src/core/integration/index.ts @@ -0,0 +1,139 @@ +import type { AstroIntegration } from 'astro'; +import { vitePluginDb } from './vite-plugin-db.js'; +import { vitePluginInjectEnvTs } from './vite-plugin-inject-env-ts.js'; +import { typegen } from './typegen.js'; +import { existsSync } from 'fs'; +import { mkdir, rm, writeFile } from 'fs/promises'; +import { DB_PATH } from '../consts.js'; +import { createLocalDatabaseClient } from '../../runtime/db-client.js'; +import { astroConfigWithDbSchema, type DBTables } from '../types.js'; +import { type VitePlugin } from '../utils.js'; +import { + STUDIO_CONFIG_MISSING_WRITABLE_COLLECTIONS_ERROR, + UNSAFE_WRITABLE_WARNING, +} from '../errors.js'; +import { errorMap } from './error-map.js'; +import { dirname } from 'path'; +import { fileURLToPath } from 'url'; +import { blue, yellow } from 'kleur/colors'; +import { fileURLIntegration } from './file-url.js'; +import { recreateTables, seedData } from '../queries.js'; +import { getManagedAppTokenOrExit, type ManagedAppToken } from '../tokens.js'; + +function astroDBIntegration(): AstroIntegration { + let connectedToRemote = false; + let appToken: ManagedAppToken | undefined; + let schemas = { + tables(): DBTables { + throw new Error('tables not found'); + }, + }; + let command: 'dev' | 'build' | 'preview'; + return { + name: 'astro:db', + hooks: { + 'astro:config:setup': async ({ updateConfig, config, command: _command, logger }) => { + command = _command; + if (_command === 'preview') return; + + let dbPlugin: VitePlugin | undefined = undefined; + const studio = config.db?.studio ?? false; + + if (studio && command === 'build' && process.env.ASTRO_DB_TEST_ENV !== '1') { + appToken = await getManagedAppTokenOrExit(); + connectedToRemote = true; + dbPlugin = vitePluginDb({ + connectToStudio: true, + appToken: appToken.token, + schemas, + root: config.root, + }); + } else { + dbPlugin = vitePluginDb({ + connectToStudio: false, + schemas, + root: config.root, + }); + } + + updateConfig({ + vite: { + assetsInclude: [DB_PATH], + plugins: [dbPlugin, vitePluginInjectEnvTs(config, logger)], + }, + }); + }, + 'astro:config:done': async ({ config, logger }) => { + // TODO: refine where we load tables + // @matthewp: may want to load tables by path at runtime + const configWithDb = astroConfigWithDbSchema.parse(config, { errorMap }); + const tables = configWithDb.db?.tables ?? {}; + // Redefine getTables so our integration can grab them + schemas.tables = () => tables; + + const studio = configWithDb.db?.studio ?? false; + const unsafeWritable = Boolean(configWithDb.db?.unsafeWritable); + const foundWritableCollection = Object.entries(tables).find(([, c]) => c.writable); + const writableAllowed = studio || unsafeWritable; + if (!writableAllowed && foundWritableCollection) { + logger.error( + STUDIO_CONFIG_MISSING_WRITABLE_COLLECTIONS_ERROR(foundWritableCollection[0]) + ); + process.exit(1); + } + // Using writable tables with the opt-in flag. Warn them to let them + // know the risk. + else if (unsafeWritable && foundWritableCollection) { + logger.warn(UNSAFE_WRITABLE_WARNING); + } + + if (!connectedToRemote) { + const dbUrl = new URL(DB_PATH, config.root); + if (existsSync(dbUrl)) { + await rm(dbUrl); + } + await mkdir(dirname(fileURLToPath(dbUrl)), { recursive: true }); + await writeFile(dbUrl, ''); + + using db = await createLocalDatabaseClient({ + tables, + dbUrl: dbUrl.toString(), + seeding: true, + }); + await recreateTables({ db, tables }); + if (configWithDb.db?.data) { + await seedData({ + db, + data: configWithDb.db.data, + logger, + mode: command === 'dev' ? 'dev' : 'build', + }); + } + logger.debug('Database setup complete.'); + } + + await typegen({ tables, root: config.root }); + }, + 'astro:server:start': async ({ logger }) => { + // Wait for the server startup to log, so that this can come afterwards. + setTimeout(() => { + logger.info( + connectedToRemote ? 'Connected to remote database.' : 'New local database created.' + ); + }, 100); + }, + 'astro:build:start': async ({ logger }) => { + logger.info( + 'database: ' + (connectedToRemote ? yellow('remote') : blue('local database.')) + ); + }, + 'astro:build:done': async ({}) => { + await appToken?.destroy(); + }, + }, + }; +} + +export function integration(): AstroIntegration[] { + return [astroDBIntegration(), fileURLIntegration()]; +} diff --git a/packages/db/src/core/integration/load-astro-config.ts b/packages/db/src/core/integration/load-astro-config.ts new file mode 100644 index 0000000000..b1a8cf01b4 --- /dev/null +++ b/packages/db/src/core/integration/load-astro-config.ts @@ -0,0 +1,92 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { pathToFileURL } from 'node:url'; +import { bold, red } from 'kleur/colors'; +import { type ViteDevServer, createServer } from 'vite'; + +/** + * Pulled from the mothership, Astro core ❤️ + * + * @see https://github.com/withastro/astro/blob/main/packages/astro/src/core/config/config.ts#L121 + */ +export async function loadAstroConfig(root: string): Promise> { + const configPath = search(root); + if (!configPath) return {}; + + // Create a vite server to load the config + try { + return await loadConfigWithVite(configPath); + } catch (e) { + // Config errors should bypass log level as it breaks startup + + // eslint-disable-next-line no-console + console.error(`${bold(red('[astro]'))} Unable to load Astro config.\n`); + throw e; + } +} + +function search(root: string) { + const paths = [ + 'astro.config.mjs', + 'astro.config.js', + 'astro.config.ts', + 'astro.config.mts', + 'astro.config.cjs', + 'astro.config.cts', + ].map((p) => path.join(root, p)); + + for (const file of paths) { + if (fs.existsSync(file)) { + return file; + } + } +} + +async function loadConfigWithVite(configPath: string): Promise> { + if (/\.[cm]?js$/.test(configPath)) { + try { + const config = await import( + /* @vite-ignore */ pathToFileURL(configPath).toString() + '?t=' + Date.now() + ); + return config.default ?? {}; + } catch (e) { + // We do not need to throw the error here as we have a Vite fallback below + } + } + + // Try Loading with Vite + let server: ViteDevServer | undefined; + try { + server = await createViteServer(); + const mod = await server.ssrLoadModule(configPath, { fixStacktrace: true }); + return mod.default ?? {}; + } finally { + if (server) { + await server.close(); + } + } +} + +async function createViteServer(): Promise { + const viteServer = await createServer({ + server: { middlewareMode: true, hmr: false, watch: { ignored: ['**'] } }, + optimizeDeps: { disabled: true }, + clearScreen: false, + appType: 'custom', + ssr: { + // NOTE: Vite doesn't externalize linked packages by default. During testing locally, + // these dependencies trip up Vite's dev SSR transform. Awaiting upstream feature: + // https://github.com/vitejs/vite/pull/10939 + external: [ + '@astrojs/tailwind', + '@astrojs/mdx', + '@astrojs/react', + '@astrojs/preact', + '@astrojs/sitemap', + '@astrojs/markdoc', + ], + }, + }); + + return viteServer; +} diff --git a/packages/db/src/core/integration/typegen.ts b/packages/db/src/core/integration/typegen.ts new file mode 100644 index 0000000000..ce53aa6673 --- /dev/null +++ b/packages/db/src/core/integration/typegen.ts @@ -0,0 +1,46 @@ +import { existsSync } from 'node:fs'; +import { mkdir, writeFile } from 'node:fs/promises'; +import type { DBTable, DBTables } from '../types.js'; +import { DB_TYPES_FILE, RUNTIME_DRIZZLE_IMPORT, RUNTIME_IMPORT } from '../consts.js'; + +export async function typegen({ tables, root }: { tables: DBTables; root: URL }) { + const content = `// This file is generated by \`studio sync\` +declare module 'astro:db' { + export const db: import(${RUNTIME_IMPORT}).SqliteDB; + export const dbUrl: string; + export * from ${RUNTIME_DRIZZLE_IMPORT}; + +${Object.entries(tables) + .map(([name, collection]) => generateTableType(name, collection)) + .join('\n')} +} +`; + + const dotAstroDir = new URL('.astro/', root); + + if (!existsSync(dotAstroDir)) { + await mkdir(dotAstroDir); + } + + await writeFile(new URL(DB_TYPES_FILE, dotAstroDir), content); +} + +function generateTableType(name: string, collection: DBTable): string { + let tableType = ` export const ${name}: import(${RUNTIME_IMPORT}).Table< + ${JSON.stringify(name)}, + ${JSON.stringify( + Object.fromEntries( + Object.entries(collection.columns).map(([columnName, column]) => [ + columnName, + { + // Only select columns Drizzle needs for inference + type: column.type, + optional: column.schema.optional, + default: column.schema.default, + }, + ]) + ) + )} + >;`; + return tableType; +} diff --git a/packages/db/src/core/integration/vite-plugin-db.ts b/packages/db/src/core/integration/vite-plugin-db.ts new file mode 100644 index 0000000000..1aefe84b7b --- /dev/null +++ b/packages/db/src/core/integration/vite-plugin-db.ts @@ -0,0 +1,98 @@ +import { DB_PATH, RUNTIME_DRIZZLE_IMPORT, RUNTIME_IMPORT, VIRTUAL_MODULE_ID } from '../consts.js'; +import type { DBTables } from '../types.js'; +import type { VitePlugin } from '../utils.js'; + +const resolvedVirtualModuleId = '\0' + VIRTUAL_MODULE_ID; + +type LateSchema = { + tables: () => DBTables; +}; + +type VitePluginDBParams = + | { + connectToStudio: false; + schemas: LateSchema; + root: URL; + } + | { + connectToStudio: true; + schemas: LateSchema; + appToken: string; + root: URL; + }; + +export function vitePluginDb(params: VitePluginDBParams): VitePlugin { + return { + name: 'astro:db', + enforce: 'pre', + resolveId(id) { + if (id === VIRTUAL_MODULE_ID) { + return resolvedVirtualModuleId; + } + }, + load(id) { + if (id !== resolvedVirtualModuleId) return; + + if (params.connectToStudio) { + return getStudioVirtualModContents({ + appToken: params.appToken, + tables: params.schemas.tables(), + }); + } + return getVirtualModContents({ + root: params.root, + tables: params.schemas.tables(), + }); + }, + }; +} + +export function getVirtualModContents({ tables, root }: { tables: DBTables; root: URL }) { + const dbUrl = new URL(DB_PATH, root); + return ` +import { collectionToTable, createLocalDatabaseClient } from ${RUNTIME_IMPORT}; +import dbUrl from ${JSON.stringify(`${dbUrl}?fileurl`)}; + +const params = ${JSON.stringify({ + tables, + seeding: false, + })}; +params.dbUrl = dbUrl; + +export const db = await createLocalDatabaseClient(params); + +export * from ${RUNTIME_DRIZZLE_IMPORT}; + +${getStringifiedCollectionExports(tables)} +`; +} + +export function getStudioVirtualModContents({ + tables, + appToken, +}: { + tables: DBTables; + appToken: string; +}) { + return ` +import {collectionToTable, createRemoteDatabaseClient} from ${RUNTIME_IMPORT}; + +export const db = await createRemoteDatabaseClient(${JSON.stringify( + appToken + )}, import.meta.env.ASTRO_STUDIO_REMOTE_DB_URL); +export * from ${RUNTIME_DRIZZLE_IMPORT}; + +${getStringifiedCollectionExports(tables)} + `; +} + +function getStringifiedCollectionExports(tables: DBTables) { + return Object.entries(tables) + .map( + ([name, collection]) => + `export const ${name} = collectionToTable(${JSON.stringify(name)}, ${JSON.stringify( + collection + )}, false)` + ) + .join('\n'); +} diff --git a/packages/db/src/core/integration/vite-plugin-inject-env-ts.ts b/packages/db/src/core/integration/vite-plugin-inject-env-ts.ts new file mode 100644 index 0000000000..91fa1228f1 --- /dev/null +++ b/packages/db/src/core/integration/vite-plugin-inject-env-ts.ts @@ -0,0 +1,65 @@ +import { existsSync } from 'node:fs'; +import { readFile, writeFile } from 'node:fs/promises'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { bold, cyan } from 'kleur/colors'; +import { normalizePath } from 'vite'; +import { DB_TYPES_FILE } from '../consts.js'; +import type { VitePlugin } from '../utils.js'; +import type { AstroIntegrationLogger } from 'astro'; + +export function vitePluginInjectEnvTs( + { srcDir, root }: { srcDir: URL; root: URL }, + logger: AstroIntegrationLogger +): VitePlugin { + return { + name: 'db-inject-env-ts', + enforce: 'post', + async config() { + await setUpEnvTs({ srcDir, root, logger }); + }, + }; +} + +export async function setUpEnvTs({ + srcDir, + root, + logger, +}: { + srcDir: URL; + root: URL; + logger: AstroIntegrationLogger; +}) { + const envTsPath = getEnvTsPath({ srcDir }); + const envTsPathRelativetoRoot = normalizePath( + path.relative(fileURLToPath(root), fileURLToPath(envTsPath)) + ); + + if (existsSync(envTsPath)) { + let typesEnvContents = await readFile(envTsPath, 'utf-8'); + const dotAstroDir = new URL('.astro/', root); + + if (!existsSync(dotAstroDir)) return; + + const dbTypeReference = getDBTypeReference({ srcDir, dotAstroDir }); + + if (!typesEnvContents.includes(dbTypeReference)) { + typesEnvContents = `${dbTypeReference}\n${typesEnvContents}`; + await writeFile(envTsPath, typesEnvContents, 'utf-8'); + logger.info(`${cyan(bold('[astro:db]'))} Added ${bold(envTsPathRelativetoRoot)} types`); + } + } +} + +function getDBTypeReference({ srcDir, dotAstroDir }: { srcDir: URL; dotAstroDir: URL }) { + const dbTypesFile = new URL(DB_TYPES_FILE, dotAstroDir); + const contentTypesRelativeToSrcDir = normalizePath( + path.relative(fileURLToPath(srcDir), fileURLToPath(dbTypesFile)) + ); + + return `/// `; +} + +function getEnvTsPath({ srcDir }: { srcDir: URL }) { + return new URL('env.d.ts', srcDir); +} diff --git a/packages/db/src/core/queries.ts b/packages/db/src/core/queries.ts new file mode 100644 index 0000000000..82c0fe3f85 --- /dev/null +++ b/packages/db/src/core/queries.ts @@ -0,0 +1,271 @@ +import type { SqliteRemoteDatabase } from 'drizzle-orm/sqlite-proxy'; +import { + type BooleanColumn, + type DBTable, + type DBTables, + type DBColumn, + type DateColumn, + type ColumnType, + type JsonColumn, + type NumberColumn, + type TextColumn, +} from '../core/types.js'; +import { bold } from 'kleur/colors'; +import { type SQL, sql, getTableName } from 'drizzle-orm'; +import { SQLiteAsyncDialect, type SQLiteInsert } from 'drizzle-orm/sqlite-core'; +import type { AstroIntegrationLogger } from 'astro'; +import type { DBUserConfig } from '../core/types.js'; +import { hasPrimaryKey } from '../runtime/index.js'; +import { isSerializedSQL } from '../runtime/types.js'; +import { SEED_WRITABLE_IN_PROD_ERROR } from './errors.js'; + +const sqlite = new SQLiteAsyncDialect(); + +export async function recreateTables({ + db, + tables, +}: { + db: SqliteRemoteDatabase; + tables: DBTables; +}) { + const setupQueries: SQL[] = []; + for (const [name, collection] of Object.entries(tables)) { + const dropQuery = sql.raw(`DROP TABLE IF EXISTS ${sqlite.escapeName(name)}`); + const createQuery = sql.raw(getCreateTableQuery(name, collection)); + const indexQueries = getCreateIndexQueries(name, collection); + setupQueries.push(dropQuery, createQuery, ...indexQueries.map((s) => sql.raw(s))); + } + for (const q of setupQueries) { + await db.run(q); + } +} + +export async function seedData({ + db, + data, + logger, + mode, +}: { + db: SqliteRemoteDatabase; + data: DBUserConfig['data']; + logger?: AstroIntegrationLogger; + mode: 'dev' | 'build'; +}) { + try { + const dataFns = Array.isArray(data) ? data : [data]; + for (const dataFn of dataFns) { + await dataFn({ + seed: async ({ table, writable }, values) => { + if (writable && mode === 'build' && process.env.ASTRO_DB_TEST_ENV !== '1') { + (logger ?? console).error(SEED_WRITABLE_IN_PROD_ERROR(getTableName(table))); + process.exit(1); + } + await db.insert(table).values(values as any); + }, + seedReturning: async ({ table, writable }, values) => { + if (writable && mode === 'build' && process.env.ASTRO_DB_TEST_ENV !== '1') { + (logger ?? console).error(SEED_WRITABLE_IN_PROD_ERROR(getTableName(table))); + process.exit(1); + } + let result: SQLiteInsert = db + .insert(table) + .values(values as any) + .returning(); + if (!Array.isArray(values)) { + result = result.get(); + } + return result; + }, + db, + mode, + }); + } + } catch (error) { + (logger ?? console).error( + `Failed to seed data. Did you update to match recent schema changes?` + ); + (logger ?? console).error(error as string); + } +} + +export function getCreateTableQuery(collectionName: string, collection: DBTable) { + let query = `CREATE TABLE ${sqlite.escapeName(collectionName)} (`; + + const colQueries = []; + const colHasPrimaryKey = Object.entries(collection.columns).find(([, column]) => + hasPrimaryKey(column) + ); + if (!colHasPrimaryKey) { + colQueries.push('_id INTEGER PRIMARY KEY'); + } + for (const [columnName, column] of Object.entries(collection.columns)) { + const colQuery = `${sqlite.escapeName(columnName)} ${schemaTypeToSqlType( + column.type + )}${getModifiers(columnName, column)}`; + colQueries.push(colQuery); + } + + colQueries.push(...getCreateForeignKeyQueries(collectionName, collection)); + + query += colQueries.join(', ') + ')'; + return query; +} + +export function getCreateIndexQueries( + collectionName: string, + collection: Pick +) { + let queries: string[] = []; + for (const [indexName, indexProps] of Object.entries(collection.indexes ?? {})) { + const onColNames = asArray(indexProps.on); + const onCols = onColNames.map((colName) => sqlite.escapeName(colName)); + + const unique = indexProps.unique ? 'UNIQUE ' : ''; + const indexQuery = `CREATE ${unique}INDEX ${sqlite.escapeName( + indexName + )} ON ${sqlite.escapeName(collectionName)} (${onCols.join(', ')})`; + queries.push(indexQuery); + } + return queries; +} + +export function getCreateForeignKeyQueries(collectionName: string, collection: DBTable) { + let queries: string[] = []; + for (const foreignKey of collection.foreignKeys ?? []) { + const columns = asArray(foreignKey.columns); + const references = asArray(foreignKey.references); + + if (columns.length !== references.length) { + throw new Error( + `Foreign key on ${collectionName} is misconfigured. \`columns\` and \`references\` must be the same length.` + ); + } + const referencedCollection = references[0]?.schema.collection; + if (!referencedCollection) { + throw new Error( + `Foreign key on ${collectionName} is misconfigured. \`references\` cannot be empty.` + ); + } + const query = `FOREIGN KEY (${columns + .map((f) => sqlite.escapeName(f)) + .join(', ')}) REFERENCES ${sqlite.escapeName(referencedCollection)}(${references + .map((r) => sqlite.escapeName(r.schema.name!)) + .join(', ')})`; + queries.push(query); + } + return queries; +} + +function asArray(value: T | T[]) { + return Array.isArray(value) ? value : [value]; +} + +export function schemaTypeToSqlType(type: ColumnType): 'text' | 'integer' { + switch (type) { + case 'date': + case 'text': + case 'json': + return 'text'; + case 'number': + case 'boolean': + return 'integer'; + } +} + +export function getModifiers(columnName: string, column: DBColumn) { + let modifiers = ''; + if (hasPrimaryKey(column)) { + return ' PRIMARY KEY'; + } + if (!column.schema.optional) { + modifiers += ' NOT NULL'; + } + if (column.schema.unique) { + modifiers += ' UNIQUE'; + } + if (hasDefault(column)) { + modifiers += ` DEFAULT ${getDefaultValueSql(columnName, column)}`; + } + const references = getReferencesConfig(column); + if (references) { + const { collection, name } = references.schema; + if (!collection || !name) { + throw new Error( + `Column ${collection}.${name} references a collection that does not exist. Did you apply the referenced collection to the \`tables\` object in your Astro config?` + ); + } + + modifiers += ` REFERENCES ${sqlite.escapeName(collection)} (${sqlite.escapeName(name)})`; + } + return modifiers; +} + +export function getReferencesConfig(column: DBColumn) { + const canHaveReferences = column.type === 'number' || column.type === 'text'; + if (!canHaveReferences) return undefined; + return column.schema.references; +} + +// Using `DBColumn` will not narrow `default` based on the column `type` +// Handle each column separately +type WithDefaultDefined = T & { + schema: Required>; +}; +type DBColumnWithDefault = + | WithDefaultDefined + | WithDefaultDefined + | WithDefaultDefined + | WithDefaultDefined + | WithDefaultDefined; + +// Type narrowing the default fails on union types, so use a type guard +export function hasDefault(column: DBColumn): column is DBColumnWithDefault { + if (column.schema.default !== undefined) { + return true; + } + if (hasPrimaryKey(column) && column.type === 'number') { + return true; + } + return false; +} + +function toDefault(def: T | SQL): string { + const type = typeof def; + if (type === 'string') { + return sqlite.escapeString(def as string); + } else if (type === 'boolean') { + return def ? 'TRUE' : 'FALSE'; + } else { + return def + ''; + } +} + +function getDefaultValueSql(columnName: string, column: DBColumnWithDefault): string { + if (isSerializedSQL(column.schema.default)) { + return column.schema.default.sql; + } + + switch (column.type) { + case 'boolean': + case 'number': + case 'text': + case 'date': + return toDefault(column.schema.default); + case 'json': { + let stringified = ''; + try { + stringified = JSON.stringify(column.schema.default); + } catch (e) { + // eslint-disable-next-line no-console + console.log( + `Invalid default value for column ${bold( + columnName + )}. Defaults must be valid JSON when using the \`json()\` type.` + ); + process.exit(0); + } + + return sqlite.escapeString(stringified); + } + } +} diff --git a/packages/db/src/core/tokens.ts b/packages/db/src/core/tokens.ts new file mode 100644 index 0000000000..6b15723095 --- /dev/null +++ b/packages/db/src/core/tokens.ts @@ -0,0 +1,143 @@ +import { readFile } from 'node:fs/promises'; +import { homedir } from 'node:os'; +import { join } from 'node:path'; +import { pathToFileURL } from 'node:url'; +import { getAstroStudioEnv, getAstroStudioUrl } from './utils.js'; +import { MISSING_PROJECT_ID_ERROR, MISSING_SESSION_ID_ERROR } from './errors.js'; + +export const SESSION_LOGIN_FILE = pathToFileURL(join(homedir(), '.astro', 'session-token')); +export const PROJECT_ID_FILE = pathToFileURL(join(process.cwd(), '.astro', 'link')); + +export interface ManagedAppToken { + token: string; + renew(): Promise; + destroy(): Promise; +} + +class ManagedLocalAppToken implements ManagedAppToken { + token: string; + constructor(token: string) { + this.token = token; + } + async renew() {} + async destroy() {} +} + +class ManagedRemoteAppToken implements ManagedAppToken { + token: string; + session: string; + projectId: string; + ttl: number; + renewTimer: NodeJS.Timeout | undefined; + + static async create(sessionToken: string, projectId: string) { + const response = await fetch(new URL(`${getAstroStudioUrl()}/auth/cli/token-create`), { + method: 'POST', + headers: new Headers({ + Authorization: `Bearer ${sessionToken}`, + }), + body: JSON.stringify({ projectId }), + }); + const { token: shortLivedAppToken, ttl } = await response.json(); + return new ManagedRemoteAppToken({ + token: shortLivedAppToken, + session: sessionToken, + projectId, + ttl, + }); + } + + constructor(options: { token: string; session: string; projectId: string; ttl: number }) { + this.token = options.token; + this.session = options.session; + this.projectId = options.projectId; + this.ttl = options.ttl; + this.renewTimer = setTimeout(() => this.renew(), (1000 * 60 * 5) / 2); + } + + private async fetch(url: string, body: unknown) { + return fetch(`${getAstroStudioUrl()}${url}`, { + method: 'POST', + headers: { + Authorization: `Bearer ${this.session}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify(body), + }); + } + + async renew() { + clearTimeout(this.renewTimer); + delete this.renewTimer; + try { + const response = await this.fetch('/auth/cli/token-renew', { + token: this.token, + projectId: this.projectId, + }); + if (response.status === 200) { + this.renewTimer = setTimeout(() => this.renew(), (1000 * 60 * this.ttl) / 2); + } else { + throw new Error(`Unexpected response: ${response.status} ${response.statusText}`); + } + } catch (error: any) { + const retryIn = (60 * this.ttl) / 10; + // eslint-disable-next-line no-console + console.error(`Failed to renew token. Retrying in ${retryIn} seconds.`, error?.message); + this.renewTimer = setTimeout(() => this.renew(), retryIn * 1000); + } + } + + async destroy() { + try { + const response = await this.fetch('/auth/cli/token-delete', { + token: this.token, + projectId: this.projectId, + }); + if (response.status !== 200) { + throw new Error(`Unexpected response: ${response.status} ${response.statusText}`); + } + } catch (error: any) { + // eslint-disable-next-line no-console + console.error('Failed to delete token.', error?.message); + } + } +} + +export async function getProjectIdFromFile() { + try { + return await readFile(PROJECT_ID_FILE, 'utf-8'); + } catch (error) { + return undefined; + } +} + +export async function getSessionIdFromFile() { + try { + return await readFile(SESSION_LOGIN_FILE, 'utf-8'); + } catch (error) { + return undefined; + } +} + +export async function getManagedAppTokenOrExit(token?: string): Promise { + if (token) { + return new ManagedLocalAppToken(token); + } + const { ASTRO_STUDIO_APP_TOKEN } = getAstroStudioEnv(); + if (ASTRO_STUDIO_APP_TOKEN) { + return new ManagedLocalAppToken(ASTRO_STUDIO_APP_TOKEN); + } + const sessionToken = await getSessionIdFromFile(); + if (!sessionToken) { + // eslint-disable-next-line no-console + console.error(MISSING_SESSION_ID_ERROR); + process.exit(1); + } + const projectId = await getProjectIdFromFile(); + if (!sessionToken || !projectId) { + // eslint-disable-next-line no-console + console.error(MISSING_PROJECT_ID_ERROR); + process.exit(1); + } + return ManagedRemoteAppToken.create(sessionToken, projectId); +} diff --git a/packages/db/src/core/types.ts b/packages/db/src/core/types.ts new file mode 100644 index 0000000000..ec2322ed5c --- /dev/null +++ b/packages/db/src/core/types.ts @@ -0,0 +1,386 @@ +import { SQLiteAsyncDialect, type SQLiteInsertValue } from 'drizzle-orm/sqlite-core'; +import type { InferSelectModel } from 'drizzle-orm'; +import { collectionToTable, type SqliteDB, type Table } from '../runtime/index.js'; +import { z, type ZodTypeDef } from 'zod'; +import { SQL } from 'drizzle-orm'; +import { errorMap } from './integration/error-map.js'; +import { SERIALIZED_SQL_KEY, type SerializedSQL } from '../runtime/types.js'; + +export type MaybePromise = T | Promise; +export type MaybeArray = T | T[]; + +// Transform to serializable object for migration files +const sqlite = new SQLiteAsyncDialect(); + +const sqlSchema = z.instanceof(SQL).transform( + (sqlObj): SerializedSQL => ({ + [SERIALIZED_SQL_KEY]: true, + sql: sqlite.sqlToQuery(sqlObj).sql, + }) +); + +const baseColumnSchema = z.object({ + label: z.string().optional(), + optional: z.boolean().optional().default(false), + unique: z.boolean().optional().default(false), + + // Defined when `defineReadableTable()` is called + name: z.string().optional(), + collection: z.string().optional(), +}); + +const booleanColumnSchema = z.object({ + type: z.literal('boolean'), + schema: baseColumnSchema.extend({ + default: z.union([z.boolean(), sqlSchema]).optional(), + }), +}); + +const numberColumnBaseSchema = baseColumnSchema.omit({ optional: true }).and( + z.union([ + z.object({ + primaryKey: z.literal(false).optional().default(false), + optional: baseColumnSchema.shape.optional, + default: z.union([z.number(), sqlSchema]).optional(), + }), + z.object({ + // `integer primary key` uses ROWID as the default value. + // `optional` and `default` do not have an effect, + // so disable these config options for primary keys. + primaryKey: z.literal(true), + optional: z.literal(false).optional(), + default: z.literal(undefined).optional(), + }), + ]) +); + +const numberColumnOptsSchema: z.ZodType< + z.infer & { + // ReferenceableColumn creates a circular type. Define ZodType to resolve. + references?: NumberColumn; + }, + ZodTypeDef, + z.input & { + references?: () => z.input; + } +> = numberColumnBaseSchema.and( + z.object({ + references: z + .function() + .returns(z.lazy(() => numberColumnSchema)) + .optional() + .transform((fn) => fn?.()), + }) +); + +const numberColumnSchema = z.object({ + type: z.literal('number'), + schema: numberColumnOptsSchema, +}); + +const textColumnBaseSchema = baseColumnSchema + .omit({ optional: true }) + .extend({ + default: z.union([z.string(), sqlSchema]).optional(), + multiline: z.boolean().optional(), + }) + .and( + z.union([ + z.object({ + primaryKey: z.literal(false).optional().default(false), + optional: baseColumnSchema.shape.optional, + }), + z.object({ + // text primary key allows NULL values. + // NULL values bypass unique checks, which could + // lead to duplicate URLs per record in Astro Studio. + // disable `optional` for primary keys. + primaryKey: z.literal(true), + optional: z.literal(false).optional(), + }), + ]) + ); + +const textColumnOptsSchema: z.ZodType< + z.infer & { + // ReferenceableColumn creates a circular type. Define ZodType to resolve. + references?: TextColumn; + }, + ZodTypeDef, + z.input & { + references?: () => z.input; + } +> = textColumnBaseSchema.and( + z.object({ + references: z + .function() + .returns(z.lazy(() => textColumnSchema)) + .optional() + .transform((fn) => fn?.()), + }) +); + +const textColumnSchema = z.object({ + type: z.literal('text'), + schema: textColumnOptsSchema, +}); + +const dateColumnSchema = z.object({ + type: z.literal('date'), + schema: baseColumnSchema.extend({ + default: z + .union([ + sqlSchema, + // transform to ISO string for serialization + z.date().transform((d) => d.toISOString()), + ]) + .optional(), + }), +}); + +const jsonColumnSchema = z.object({ + type: z.literal('json'), + schema: baseColumnSchema.extend({ + default: z.unknown().optional(), + }), +}); + +export const columnSchema = z.union([ + booleanColumnSchema, + numberColumnSchema, + textColumnSchema, + dateColumnSchema, + jsonColumnSchema, +]); +export const referenceableColumnSchema = z.union([textColumnSchema, numberColumnSchema]); + +const columnsSchema = z.record(columnSchema); + +export const indexSchema = z.object({ + on: z.string().or(z.array(z.string())), + unique: z.boolean().optional(), +}); + +type ForeignKeysInput = { + columns: MaybeArray; + references: () => MaybeArray, 'references'>>; +}; + +type ForeignKeysOutput = Omit & { + // reference fn called in `transform`. Ensures output is JSON serializable. + references: MaybeArray, 'references'>>; +}; + +const foreignKeysSchema: z.ZodType = z.object({ + columns: z.string().or(z.array(z.string())), + references: z + .function() + .returns(z.lazy(() => referenceableColumnSchema.or(z.array(referenceableColumnSchema)))) + .transform((fn) => fn()), +}); + +export type Indexes = Record>; + +const baseCollectionSchema = z.object({ + columns: columnsSchema, + indexes: z.record(indexSchema).optional(), + foreignKeys: z.array(foreignKeysSchema).optional(), +}); + +export const readableCollectionSchema = baseCollectionSchema.extend({ + writable: z.literal(false), +}); + +export const writableCollectionSchema = baseCollectionSchema.extend({ + writable: z.literal(true), +}); + +export const collectionSchema = z.union([readableCollectionSchema, writableCollectionSchema]); +export const tablesSchema = z.preprocess((rawCollections) => { + // Use `z.any()` to avoid breaking object references + const tables = z.record(z.any()).parse(rawCollections, { errorMap }); + for (const [collectionName, collection] of Object.entries(tables)) { + // Append `table` object for data seeding. + // Must append at runtime so table name exists. + collection.table = collectionToTable( + collectionName, + collectionSchema.parse(collection, { errorMap }) + ); + // Append collection and column names to columns. + // Used to track collection info for references. + const { columns } = z.object({ columns: z.record(z.any()) }).parse(collection, { errorMap }); + for (const [columnName, column] of Object.entries(columns)) { + column.schema.name = columnName; + column.schema.collection = collectionName; + } + } + return rawCollections; +}, z.record(collectionSchema)); + +export type BooleanColumn = z.infer; +export type BooleanColumnInput = z.input; +export type NumberColumn = z.infer; +export type NumberColumnInput = z.input; +export type TextColumn = z.infer; +export type TextColumnInput = z.input; +export type DateColumn = z.infer; +export type DateColumnInput = z.input; +export type JsonColumn = z.infer; +export type JsonColumnInput = z.input; + +export type ColumnType = + | BooleanColumn['type'] + | NumberColumn['type'] + | TextColumn['type'] + | DateColumn['type'] + | JsonColumn['type']; + +export type DBColumn = z.infer; +export type DBColumnInput = + | DateColumnInput + | BooleanColumnInput + | NumberColumnInput + | TextColumnInput + | JsonColumnInput; +export type DBColumns = z.infer; +export type DBTable = z.infer; +export type DBTables = Record; +export type DBSnapshot = { + schema: Record; + /** + * Snapshot version. Breaking changes to the snapshot format increment this number. + * @todo Rename to "version" once closer to release. + */ + experimentalVersion: number; +}; +export type ReadableDBTable = z.infer; +export type WritableDBTable = z.infer; + +export type DBDataContext = { + db: SqliteDB; + seed: ( + collection: ResolvedCollectionConfig, + data: MaybeArray>> + ) => Promise; + seedReturning: < + TColumns extends ColumnsConfig, + TData extends MaybeArray>>, + >( + collection: ResolvedCollectionConfig, + data: TData + ) => Promise< + TData extends Array>> + ? InferSelectModel>[] + : InferSelectModel> + >; + mode: 'dev' | 'build'; +}; + +export function defineData(fn: (ctx: DBDataContext) => MaybePromise) { + return fn; +} + +const dbDataFn = z.function().returns(z.union([z.void(), z.promise(z.void())])); + +export const dbConfigSchema = z.object({ + studio: z.boolean().optional(), + tables: tablesSchema.optional(), + data: z.union([dbDataFn, z.array(dbDataFn)]).optional(), + unsafeWritable: z.boolean().optional().default(false), +}); + +type DataFunction = (params: DBDataContext) => MaybePromise; + +export type DBUserConfig = Omit, 'data'> & { + data: DataFunction | DataFunction[]; +}; + +export const astroConfigWithDbSchema = z.object({ + db: dbConfigSchema.optional(), +}); + +export type ColumnsConfig = z.input['columns']; + +interface CollectionConfig + // use `extends` to ensure types line up with zod, + // only adding generics for type completions. + extends Pick, 'columns' | 'indexes' | 'foreignKeys'> { + columns: TColumns; + foreignKeys?: Array<{ + columns: MaybeArray>; + // TODO: runtime error if parent collection doesn't match for all columns. Can't put a generic here... + references: () => MaybeArray>; + }>; + indexes?: Record>; +} + +interface IndexConfig extends z.input { + on: MaybeArray>; +} + +export type ResolvedCollectionConfig< + TColumns extends ColumnsConfig = ColumnsConfig, + Writable extends boolean = boolean, +> = CollectionConfig & { + writable: Writable; + table: Table; +}; + +function baseDefineCollection( + userConfig: CollectionConfig, + writable: TWritable +): ResolvedCollectionConfig { + return { + ...userConfig, + writable, + // set at runtime to get the table name + table: null!, + }; +} + +export function defineReadableTable( + userConfig: CollectionConfig +): ResolvedCollectionConfig { + return baseDefineCollection(userConfig, false); +} + +export function defineWritableTable( + userConfig: CollectionConfig +): ResolvedCollectionConfig { + return baseDefineCollection(userConfig, true); +} + +export type AstroConfigWithDB = z.input; + +// We cannot use `Omit`, +// since Omit collapses our union type on primary key. +type NumberColumnOpts = z.input; +type TextColumnOpts = z.input; + +function createColumn>(type: S, schema: T) { + return { + type, + /** + * @internal + */ + schema, + }; +} + +export const column = { + number: (opts: T = {} as T) => { + return createColumn('number', opts) satisfies { type: 'number' }; + }, + boolean: (opts: T = {} as T) => { + return createColumn('boolean', opts) satisfies { type: 'boolean' }; + }, + text: (opts: T = {} as T) => { + return createColumn('text', opts) satisfies { type: 'text' }; + }, + date(opts: T = {} as T) { + return createColumn('date', opts) satisfies { type: 'date' }; + }, + json(opts: T = {} as T) { + return createColumn('json', opts) satisfies { type: 'json' }; + }, +}; diff --git a/packages/db/src/core/utils.ts b/packages/db/src/core/utils.ts new file mode 100644 index 0000000000..b579770400 --- /dev/null +++ b/packages/db/src/core/utils.ts @@ -0,0 +1,19 @@ +import type { AstroConfig } from 'astro'; +import { loadEnv } from 'vite'; + +export type VitePlugin = Required['plugins'][number]; + +export function getAstroStudioEnv(envMode = ''): Record<`ASTRO_STUDIO_${string}`, string> { + const env = loadEnv(envMode, process.cwd(), 'ASTRO_STUDIO_'); + return env; +} + +export function getRemoteDatabaseUrl(): string { + const env = getAstroStudioEnv(); + return env.ASTRO_STUDIO_REMOTE_DB_URL || 'https://db.services.astro.build'; +} + +export function getAstroStudioUrl(): string { + const env = getAstroStudioEnv(); + return env.ASTRO_STUDIO_URL || 'https://stardate.astro.build'; +} diff --git a/packages/db/src/index.ts b/packages/db/src/index.ts new file mode 100644 index 0000000000..f280f35587 --- /dev/null +++ b/packages/db/src/index.ts @@ -0,0 +1,5 @@ +export { defineReadableTable, defineWritableTable, defineData, column } from './core/types.js'; +export type { ResolvedCollectionConfig, DBDataContext } from './core/types.js'; +export { cli } from './core/cli/index.js'; +export { integration as default } from './core/integration/index.js'; +export { sql, NOW, TRUE, FALSE } from './runtime/index.js'; diff --git a/packages/db/src/runtime/db-client.ts b/packages/db/src/runtime/db-client.ts new file mode 100644 index 0000000000..28db1138fb --- /dev/null +++ b/packages/db/src/runtime/db-client.ts @@ -0,0 +1,111 @@ +import type { InStatement } from '@libsql/client'; +import { createClient } from '@libsql/client'; +import { type DBTables } from '../core/types.js'; +import type { LibSQLDatabase } from 'drizzle-orm/libsql'; +import { drizzle as drizzleLibsql } from 'drizzle-orm/libsql'; +import { drizzle as drizzleProxy } from 'drizzle-orm/sqlite-proxy'; +import { type SQLiteTable } from 'drizzle-orm/sqlite-core'; +import { z } from 'zod'; +import { getTableName } from 'drizzle-orm'; + +const isWebContainer = !!process.versions?.webcontainer; + +interface LocalDatabaseClient extends LibSQLDatabase, Disposable {} + +export async function createLocalDatabaseClient({ + tables, + dbUrl, + seeding, +}: { + dbUrl: string; + tables: DBTables; + seeding: boolean; +}): Promise { + const url = isWebContainer ? 'file:content.db' : dbUrl; + const client = createClient({ url }); + const db = Object.assign(drizzleLibsql(client), { + [Symbol.dispose || Symbol.for('Symbol.dispose')]() { + client.close(); + }, + }); + + if (seeding) return db; + + const { insert: drizzleInsert, update: drizzleUpdate, delete: drizzleDelete } = db; + return Object.assign(db, { + insert(Table: SQLiteTable) { + checkIfModificationIsAllowed(tables, Table); + return drizzleInsert.call(this, Table); + }, + update(Table: SQLiteTable) { + checkIfModificationIsAllowed(tables, Table); + return drizzleUpdate.call(this, Table); + }, + delete(Table: SQLiteTable) { + checkIfModificationIsAllowed(tables, Table); + return drizzleDelete.call(this, Table); + }, + }); +} + +function checkIfModificationIsAllowed(tables: DBTables, Table: SQLiteTable) { + const tableName = getTableName(Table); + const collection = tables[tableName]; + if (!collection.writable) { + throw new Error(`The [${tableName}] collection is read-only.`); + } +} + +export function createRemoteDatabaseClient(appToken: string, remoteDbURL: string) { + const url = new URL('/db/query', remoteDbURL); + + const db = drizzleProxy(async (sql, parameters, method) => { + const requestBody: InStatement = { sql, args: parameters }; + // eslint-disable-next-line no-console + console.info(JSON.stringify(requestBody)); + const res = await fetch(url, { + method: 'POST', + headers: { + Authorization: `Bearer ${appToken}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify(requestBody), + }); + if (!res.ok) { + throw new Error( + `Failed to execute query.\nQuery: ${sql}\nFull error: ${res.status} ${await res.text()}}` + ); + } + + const queryResultSchema = z.object({ + rows: z.array(z.unknown()), + }); + let rows: unknown[]; + try { + const json = await res.json(); + rows = queryResultSchema.parse(json).rows; + } catch (e) { + throw new Error( + `Failed to execute query.\nQuery: ${sql}\nFull error: Unexpected JSON response. ${ + e instanceof Error ? e.message : String(e) + }` + ); + } + + // Drizzle expects each row as an array of its values + const rowValues: unknown[][] = []; + + for (const row of rows) { + if (row != null && typeof row === 'object') { + rowValues.push(Object.values(row)); + } + } + + if (method === 'get') { + return { rows: rowValues[0] }; + } + + return { rows: rowValues }; + }); + return db; +} diff --git a/packages/db/src/runtime/drizzle.ts b/packages/db/src/runtime/drizzle.ts new file mode 100644 index 0000000000..d2dfa9e325 --- /dev/null +++ b/packages/db/src/runtime/drizzle.ts @@ -0,0 +1,25 @@ +// Drizzle utilities we expose directly from `astro:db` +export { + sql, + eq, + gt, + gte, + lt, + lte, + ne, + isNull, + isNotNull, + inArray, + notInArray, + exists, + notExists, + between, + notBetween, + like, + notIlike, + not, + asc, + desc, + and, + or, +} from 'drizzle-orm'; diff --git a/packages/db/src/runtime/index.ts b/packages/db/src/runtime/index.ts new file mode 100644 index 0000000000..99d2cf31ee --- /dev/null +++ b/packages/db/src/runtime/index.ts @@ -0,0 +1,139 @@ +import type { SqliteRemoteDatabase } from 'drizzle-orm/sqlite-proxy'; +import { type DBTable, type DBColumn } from '../core/types.js'; +import { type ColumnBuilderBaseConfig, type ColumnDataType, sql } from 'drizzle-orm'; +import { + customType, + integer, + sqliteTable, + text, + index, + type SQLiteColumnBuilderBase, + type IndexBuilder, +} from 'drizzle-orm/sqlite-core'; +import { isSerializedSQL, type SerializedSQL } from './types.js'; + +export { sql }; +export type SqliteDB = SqliteRemoteDatabase; +export type { Table } from './types.js'; +export { createRemoteDatabaseClient, createLocalDatabaseClient } from './db-client.js'; + +export function hasPrimaryKey(column: DBColumn) { + return 'primaryKey' in column.schema && !!column.schema.primaryKey; +} + +// Exports a few common expressions +export const NOW = sql`CURRENT_TIMESTAMP`; +export const TRUE = sql`TRUE`; +export const FALSE = sql`FALSE`; + +const dateType = customType<{ data: Date; driverData: string }>({ + dataType() { + return 'text'; + }, + toDriver(value) { + return value.toISOString(); + }, + fromDriver(value) { + return new Date(value); + }, +}); + +const jsonType = customType<{ data: unknown; driverData: string }>({ + dataType() { + return 'text'; + }, + toDriver(value) { + return JSON.stringify(value); + }, + fromDriver(value) { + return JSON.parse(value); + }, +}); + +type D1ColumnBuilder = SQLiteColumnBuilderBase< + ColumnBuilderBaseConfig & { data: unknown } +>; + +export function collectionToTable(name: string, collection: DBTable) { + const columns: Record = {}; + if (!Object.entries(collection.columns).some(([, column]) => hasPrimaryKey(column))) { + columns['_id'] = integer('_id').primaryKey(); + } + for (const [columnName, column] of Object.entries(collection.columns)) { + columns[columnName] = columnMapper(columnName, column); + } + const table = sqliteTable(name, columns, (ormTable) => { + const indexes: Record = {}; + for (const [indexName, indexProps] of Object.entries(collection.indexes ?? {})) { + const onColNames = Array.isArray(indexProps.on) ? indexProps.on : [indexProps.on]; + const onCols = onColNames.map((colName) => ormTable[colName]); + if (!atLeastOne(onCols)) continue; + + indexes[indexName] = index(indexName).on(...onCols); + } + return indexes; + }); + return table; +} + +function atLeastOne(arr: T[]): arr is [T, ...T[]] { + return arr.length > 0; +} + +function columnMapper(columnName: string, column: DBColumn) { + let c: ReturnType< + | typeof text + | typeof integer + | typeof jsonType + | typeof dateType + | typeof integer + >; + + switch (column.type) { + case 'text': { + c = text(columnName); + // Duplicate default logic across cases to preserve type inference. + // No clean generic for every column builder. + if (column.schema.default !== undefined) + c = c.default(handleSerializedSQL(column.schema.default)); + if (column.schema.primaryKey === true) c = c.primaryKey(); + break; + } + case 'number': { + c = integer(columnName); + if (column.schema.default !== undefined) + c = c.default(handleSerializedSQL(column.schema.default)); + if (column.schema.primaryKey === true) c = c.primaryKey(); + break; + } + case 'boolean': { + c = integer(columnName, { mode: 'boolean' }); + if (column.schema.default !== undefined) + c = c.default(handleSerializedSQL(column.schema.default)); + break; + } + case 'json': + c = jsonType(columnName); + if (column.schema.default !== undefined) c = c.default(column.schema.default); + break; + case 'date': { + c = dateType(columnName); + if (column.schema.default !== undefined) { + const def = handleSerializedSQL(column.schema.default); + c = c.default(typeof def === 'string' ? new Date(def) : def); + } + break; + } + } + + if (!column.schema.optional) c = c.notNull(); + if (column.schema.unique) c = c.unique(); + return c; +} + +function handleSerializedSQL(def: T | SerializedSQL) { + if (isSerializedSQL(def)) { + return sql.raw(def.sql); + } + return def; +} diff --git a/packages/db/src/runtime/types.ts b/packages/db/src/runtime/types.ts new file mode 100644 index 0000000000..32ee6153b8 --- /dev/null +++ b/packages/db/src/runtime/types.ts @@ -0,0 +1,109 @@ +import type { ColumnDataType, ColumnBaseConfig } from 'drizzle-orm'; +import type { SQLiteColumn, SQLiteTableWithColumns } from 'drizzle-orm/sqlite-core'; +import type { DBColumn, ColumnsConfig } from '../core/types.js'; + +type GeneratedConfig = Pick< + ColumnBaseConfig, + 'name' | 'tableName' | 'notNull' | 'hasDefault' +>; + +export type AstroText> = SQLiteColumn< + T & { + data: string; + dataType: 'string'; + columnType: 'SQLiteText'; + driverParam: string; + enumValues: never; + baseColumn: never; + } +>; + +export type AstroDate> = SQLiteColumn< + T & { + data: Date; + dataType: 'custom'; + columnType: 'SQLiteCustomColumn'; + driverParam: string; + enumValues: never; + baseColumn: never; + } +>; + +export type AstroBoolean> = SQLiteColumn< + T & { + data: boolean; + dataType: 'boolean'; + columnType: 'SQLiteBoolean'; + driverParam: number; + enumValues: never; + baseColumn: never; + } +>; + +export type AstroNumber> = SQLiteColumn< + T & { + data: number; + dataType: 'number'; + columnType: 'SQLiteInteger'; + driverParam: number; + enumValues: never; + baseColumn: never; + } +>; + +export type AstroJson> = SQLiteColumn< + T & { + data: unknown; + dataType: 'custom'; + columnType: 'SQLiteCustomColumn'; + driverParam: string; + enumValues: never; + baseColumn: never; + } +>; + +export type Column = T extends 'boolean' + ? AstroBoolean + : T extends 'number' + ? AstroNumber + : T extends 'text' + ? AstroText + : T extends 'date' + ? AstroDate + : T extends 'json' + ? AstroJson + : never; + +export type Table< + TTableName extends string, + TColumns extends ColumnsConfig, +> = SQLiteTableWithColumns<{ + name: TTableName; + schema: undefined; + dialect: 'sqlite'; + columns: { + [K in Extract]: Column< + TColumns[K]['type'], + { + tableName: TTableName; + name: K; + hasDefault: TColumns[K]['schema'] extends { default: NonNullable } + ? true + : TColumns[K]['schema'] extends { primaryKey: true } + ? true + : false; + notNull: TColumns[K]['schema']['optional'] extends true ? false : true; + } + >; + }; +}>; + +export const SERIALIZED_SQL_KEY = '__serializedSQL'; +export type SerializedSQL = { + [SERIALIZED_SQL_KEY]: true; + sql: string; +}; + +export function isSerializedSQL(value: any): value is SerializedSQL { + return typeof value === 'object' && value !== null && SERIALIZED_SQL_KEY in value; +} diff --git a/packages/db/test/basics.test.js b/packages/db/test/basics.test.js new file mode 100644 index 0000000000..8a8d9caea2 --- /dev/null +++ b/packages/db/test/basics.test.js @@ -0,0 +1,104 @@ +import { expect } from 'chai'; +import { load as cheerioLoad } from 'cheerio'; +import testAdapter from '../../astro/test/test-adapter.js'; +import { loadFixture } from '../../astro/test/test-utils.js'; + +// TODO(fks): Rename this to something more generic/generally useful +// like `ASTRO_MONOREPO_TEST_ENV` if @astrojs/db is merged into astro. +process.env.ASTRO_DB_TEST_ENV = '1'; + +describe('astro:db', () => { + let fixture; + before(async () => { + fixture = await loadFixture({ + root: new URL('./fixtures/basics/', import.meta.url), + output: 'server', + adapter: testAdapter(), + }); + }); + + describe('production', () => { + before(async () => { + await fixture.build(); + }); + + it('Prints the list of authors', async () => { + const app = await fixture.loadTestAdapterApp(); + const request = new Request('http://example.com/'); + const res = await app.render(request); + const html = await res.text(); + const $ = cheerioLoad(html); + + const ul = $('.authors-list'); + expect(ul.children()).to.have.a.lengthOf(5); + expect(ul.children().eq(0).text()).to.equal('Ben'); + }); + + it('Errors when inserting to a readonly collection', async () => { + const app = await fixture.loadTestAdapterApp(); + const request = new Request('http://example.com/insert-into-readonly'); + const res = await app.render(request); + const html = await res.text(); + const $ = cheerioLoad(html); + + expect($('#error').text()).to.equal('The [Author] collection is read-only.'); + }); + + it('Does not error when inserting into writable collection', async () => { + const app = await fixture.loadTestAdapterApp(); + const request = new Request('http://example.com/insert-into-writable'); + const res = await app.render(request); + const html = await res.text(); + const $ = cheerioLoad(html); + + expect($('#error').text()).to.equal(''); + }); + + describe('Expression defaults', () => { + let app; + before(async () => { + app = await fixture.loadTestAdapterApp(); + }); + + it('Allows expression defaults for date columns', async () => { + const request = new Request('http://example.com/'); + const res = await app.render(request); + const html = await res.text(); + const $ = cheerioLoad(html); + + const themeAdded = $($('.themes-list .theme-added')[0]).text(); + expect(new Date(themeAdded).getTime()).to.not.be.NaN; + }); + + it('Defaults can be overridden for dates', async () => { + const request = new Request('http://example.com/'); + const res = await app.render(request); + const html = await res.text(); + const $ = cheerioLoad(html); + + const themeAdded = $($('.themes-list .theme-added')[1]).text(); + expect(new Date(themeAdded).getTime()).to.not.be.NaN; + }); + + it('Allows expression defaults for text columns', async () => { + const request = new Request('http://example.com/'); + const res = await app.render(request); + const html = await res.text(); + const $ = cheerioLoad(html); + + const themeOwner = $($('.themes-list .theme-owner')[0]).text(); + expect(themeOwner).to.equal(''); + }); + + it('Allows expression defaults for boolean columns', async () => { + const request = new Request('http://example.com/'); + const res = await app.render(request); + const html = await res.text(); + const $ = cheerioLoad(html); + + const themeDark = $($('.themes-list .theme-dark')[0]).text(); + expect(themeDark).to.equal('dark mode'); + }); + }); + }); +}); diff --git a/packages/db/test/fixtures/basics/astro.config.ts b/packages/db/test/fixtures/basics/astro.config.ts new file mode 100644 index 0000000000..665568a821 --- /dev/null +++ b/packages/db/test/fixtures/basics/astro.config.ts @@ -0,0 +1,28 @@ +import db, { defineReadableTable, column } from '@astrojs/db'; +import { defineConfig } from 'astro/config'; +import { themes } from './themes-integration'; + +const Author = defineReadableTable({ + columns: { + name: column.text(), + }, +}); + +// https://astro.build/config +export default defineConfig({ + integrations: [db(), themes()], + db: { + studio: false, + unsafeWritable: true, + tables: { Author }, + async data({ seed }) { + await seed(Author, [ + { name: 'Ben' }, + { name: 'Nate' }, + { name: 'Erika' }, + { name: 'Bjorn' }, + { name: 'Sarah' }, + ]); + }, + }, +}); diff --git a/packages/db/test/fixtures/basics/package.json b/packages/db/test/fixtures/basics/package.json new file mode 100644 index 0000000000..f537f998df --- /dev/null +++ b/packages/db/test/fixtures/basics/package.json @@ -0,0 +1,9 @@ +{ + "name": "@test/db-aliases", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/db": "workspace:*", + "astro": "workspace:*" + } +} diff --git a/packages/db/test/fixtures/basics/src/pages/index.astro b/packages/db/test/fixtures/basics/src/pages/index.astro new file mode 100644 index 0000000000..4e8882d57e --- /dev/null +++ b/packages/db/test/fixtures/basics/src/pages/index.astro @@ -0,0 +1,26 @@ +--- +import { Author, db, Themes } from 'astro:db'; + +const authors = await db.select().from(Author); +const themes = await db.select().from(Themes); +--- + +

Authors

+
    + {authors.map((author) =>
  • {author.name}
  • )} +
+ +

Themes

+
    + { + themes.map((theme) => ( +
  • +
    {theme.name}
    +
    {theme.added}
    +
    {theme.updated}
    +
    {theme.isDark ? 'dark' : 'light'} mode
    +
    {theme.owner}
    +
  • + )) + } +
diff --git a/packages/db/test/fixtures/basics/src/pages/insert-into-readonly.astro b/packages/db/test/fixtures/basics/src/pages/insert-into-readonly.astro new file mode 100644 index 0000000000..7a6bb37bc3 --- /dev/null +++ b/packages/db/test/fixtures/basics/src/pages/insert-into-readonly.astro @@ -0,0 +1,14 @@ +--- +import { Author, db } from 'astro:db'; + +const authors = await db.select().from(Author); + +let error: any = {}; +try { + db.insert(Author).values({ name: 'Person A' }); +} catch (err) { + error = err; +} +--- + +
{error.message}
diff --git a/packages/db/test/fixtures/basics/src/pages/insert-into-writable.astro b/packages/db/test/fixtures/basics/src/pages/insert-into-writable.astro new file mode 100644 index 0000000000..3e3ad2f31a --- /dev/null +++ b/packages/db/test/fixtures/basics/src/pages/insert-into-writable.astro @@ -0,0 +1,12 @@ +--- +import { Themes, db } from 'astro:db'; + +let error: any = {}; +try { + db.insert(Themes).values({ name: 'Person A' }); +} catch (err) { + error = err; +} +--- + +
{error.message}
diff --git a/packages/db/test/fixtures/basics/themes-integration.ts b/packages/db/test/fixtures/basics/themes-integration.ts new file mode 100644 index 0000000000..d034d840f8 --- /dev/null +++ b/packages/db/test/fixtures/basics/themes-integration.ts @@ -0,0 +1,36 @@ +import { NOW, column, defineWritableTable, sql } from '@astrojs/db'; +import type { AstroIntegration } from 'astro'; + +const Themes = defineWritableTable({ + columns: { + name: column.text(), + added: column.date({ + default: sql`CURRENT_TIMESTAMP`, + }), + updated: column.date({ + default: NOW, + }), + isDark: column.boolean({ default: sql`TRUE` }), + owner: column.text({ optional: true, default: sql`NULL` }), + }, +}); + +export function themes(): AstroIntegration { + return { + name: 'themes-integration', + hooks: { + 'astro:config:setup': ({ updateConfig }) => { + updateConfig({ + db: { + tables: { Themes }, + async data({ seed }) { + // Seed writable tables in dev mode, only + // but in this case we do it for both, due to tests + await seed(Themes, [{ name: 'dracula' }, { name: 'monokai', added: new Date() }]); + }, + }, + }); + }, + }, + }; +} diff --git a/packages/db/test/fixtures/glob/astro.config.ts b/packages/db/test/fixtures/glob/astro.config.ts new file mode 100644 index 0000000000..d84117f4e6 --- /dev/null +++ b/packages/db/test/fixtures/glob/astro.config.ts @@ -0,0 +1,25 @@ +import db, { defineReadableTable, column } from '@astrojs/db'; +import { defineConfig } from 'astro/config'; +import { asJson, createGlob } from './utils'; + +const Quote = defineReadableTable({ + columns: { + author: column.text(), + body: column.text(), + file: column.text({ unique: true }), + }, +}); + +export default defineConfig({ + db: { + tables: { Quote }, + data({ seed, ...ctx }) { + const glob = createGlob(ctx); + glob('quotes/*.json', { + into: Quote, + parse: asJson, + }); + }, + }, + integrations: [db()], +}); diff --git a/packages/db/test/fixtures/glob/package.json b/packages/db/test/fixtures/glob/package.json new file mode 100644 index 0000000000..d7db0815c9 --- /dev/null +++ b/packages/db/test/fixtures/glob/package.json @@ -0,0 +1,21 @@ +{ + "name": "glob", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "dev": "astro dev", + "build": "astro build", + "preview": "astro preview" + }, + "dependencies": { + "@astrojs/db": "workspace:*", + "astro": "workspace:*", + "chokidar": "^3.5.3", + "drizzle-orm": "^0.28.6", + "fast-glob": "^3.3.2" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/packages/db/test/fixtures/glob/quotes/erika.json b/packages/db/test/fixtures/glob/quotes/erika.json new file mode 100644 index 0000000000..c7ece9ca6e --- /dev/null +++ b/packages/db/test/fixtures/glob/quotes/erika.json @@ -0,0 +1,4 @@ +{ + "author": "Erika", + "body": "Put the quote in the database." +} diff --git a/packages/db/test/fixtures/glob/quotes/tony.json b/packages/db/test/fixtures/glob/quotes/tony.json new file mode 100644 index 0000000000..3aaed7746b --- /dev/null +++ b/packages/db/test/fixtures/glob/quotes/tony.json @@ -0,0 +1,4 @@ +{ + "author": "Tony Sull", + "body": "All content is data, but not all data is content." +} diff --git a/packages/db/test/fixtures/glob/src/pages/index.astro b/packages/db/test/fixtures/glob/src/pages/index.astro new file mode 100644 index 0000000000..6d2fdf22c0 --- /dev/null +++ b/packages/db/test/fixtures/glob/src/pages/index.astro @@ -0,0 +1,25 @@ +--- +/// +import { Quote, db } from 'astro:db'; + +const quotes = await db.select().from(Quote); +--- + + + + + + + Document + + + { + quotes.map((q) => ( +
+
{q.body}
+
{q.author}
+
+ )) + } + + diff --git a/packages/db/test/fixtures/glob/utils.ts b/packages/db/test/fixtures/glob/utils.ts new file mode 100644 index 0000000000..5602c61080 --- /dev/null +++ b/packages/db/test/fixtures/glob/utils.ts @@ -0,0 +1,60 @@ +import { type DBDataContext, type ResolvedCollectionConfig } from '@astrojs/db'; +import chokidar from 'chokidar'; +import { eq } from 'drizzle-orm'; +import fastGlob from 'fast-glob'; +import { readFile } from 'fs/promises'; + +export function createGlob({ db, mode }: Pick) { + return async function glob( + pattern: string, + opts: { + into: ResolvedCollectionConfig; + parse: (params: { file: string; content: string }) => Record; + } + ) { + // TODO: expose `table` + const { table } = opts.into as any; + const fileColumn = table.file; + if (!fileColumn) { + throw new Error('`file` column is required for glob tables.'); + } + if (mode === 'dev') { + chokidar + .watch(pattern) + .on('add', async (file) => { + const content = await readFile(file, 'utf-8'); + const parsed = opts.parse({ file, content }); + await db.insert(table).values({ ...parsed, file }); + }) + .on('change', async (file) => { + const content = await readFile(file, 'utf-8'); + const parsed = opts.parse({ file, content }); + await db + .insert(table) + .values({ ...parsed, file }) + .onConflictDoUpdate({ + target: fileColumn, + set: parsed, + }); + }) + .on('unlink', async (file) => { + await db.delete(table).where(eq(fileColumn, file)); + }); + } else { + const files = await fastGlob(pattern); + for (const file of files) { + const content = await readFile(file, 'utf-8'); + const parsed = opts.parse({ file, content }); + await db.insert(table).values({ ...parsed, file }); + } + } + }; +} + +export function asJson(params: { file: string; content: string }) { + try { + return JSON.parse(params.content); + } catch (e) { + throw new Error(`Error parsing ${params.file}: ${e.message}`); + } +} diff --git a/packages/db/test/fixtures/recipes/astro.config.ts b/packages/db/test/fixtures/recipes/astro.config.ts new file mode 100644 index 0000000000..bb7ad225e4 --- /dev/null +++ b/packages/db/test/fixtures/recipes/astro.config.ts @@ -0,0 +1,82 @@ +import astroDb, { defineReadableTable, column } from '@astrojs/db'; +import { defineConfig } from 'astro/config'; + +const Recipe = defineReadableTable({ + columns: { + id: column.number({ primaryKey: true }), + title: column.text(), + description: column.text(), + }, +}); + +const Ingredient = defineReadableTable({ + columns: { + id: column.number({ primaryKey: true }), + name: column.text(), + quantity: column.number(), + recipeId: column.number(), + }, + indexes: { + recipeIdx: { on: 'recipeId' }, + }, + foreignKeys: [{ columns: 'recipeId', references: () => [Recipe.columns.id] }], +}); + +export default defineConfig({ + integrations: [astroDb()], + db: { + tables: { Recipe, Ingredient }, + async data({ seed, seedReturning }) { + const pancakes = await seedReturning(Recipe, { + title: 'Pancakes', + description: 'A delicious breakfast', + }); + + await seed(Ingredient, [ + { + name: 'Flour', + quantity: 1, + recipeId: pancakes.id, + }, + { + name: 'Eggs', + quantity: 2, + recipeId: pancakes.id, + }, + { + name: 'Milk', + quantity: 1, + recipeId: pancakes.id, + }, + ]); + + const pizza = await seedReturning(Recipe, { + title: 'Pizza', + description: 'A delicious dinner', + }); + + await seed(Ingredient, [ + { + name: 'Flour', + quantity: 1, + recipeId: pizza.id, + }, + { + name: 'Eggs', + quantity: 2, + recipeId: pizza.id, + }, + { + name: 'Milk', + quantity: 1, + recipeId: pizza.id, + }, + { + name: 'Tomato Sauce', + quantity: 1, + recipeId: pizza.id, + }, + ]); + }, + }, +}); diff --git a/packages/db/test/fixtures/recipes/package.json b/packages/db/test/fixtures/recipes/package.json new file mode 100644 index 0000000000..cd1e83c02d --- /dev/null +++ b/packages/db/test/fixtures/recipes/package.json @@ -0,0 +1,16 @@ +{ + "name": "@test/recipes", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "@astrojs/db": "workspace:*", + "astro": "workspace:*" + } +} diff --git a/packages/db/test/fixtures/recipes/src/pages/index.astro b/packages/db/test/fixtures/recipes/src/pages/index.astro new file mode 100644 index 0000000000..f1856c12ed --- /dev/null +++ b/packages/db/test/fixtures/recipes/src/pages/index.astro @@ -0,0 +1,25 @@ +--- +/// +import { Recipe, Ingredient, db, eq } from 'astro:db'; + +const ingredientsByRecipe = await db + .select({ + name: Ingredient.name, + recipeName: Recipe.title, + }) + .from(Ingredient) + .innerJoin(Recipe, eq(Ingredient.recipeId, Recipe.id)); + +console.log(ingredientsByRecipe); +--- + +

Shopping list

+
    + { + ingredientsByRecipe.map(({ name, recipeName }) => ( +
  • + {name} ({recipeName}) +
  • + )) + } +
diff --git a/packages/db/test/fixtures/ticketing-example/.gitignore b/packages/db/test/fixtures/ticketing-example/.gitignore new file mode 100644 index 0000000000..ce6405d096 --- /dev/null +++ b/packages/db/test/fixtures/ticketing-example/.gitignore @@ -0,0 +1,24 @@ +# build output +dist/ + +# generated types +.astro/ + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# environment variables +.env +.env.production + +# macOS-specific files +.DS_Store + +# Cloudflare +.wrangler/ diff --git a/packages/db/test/fixtures/ticketing-example/README.md b/packages/db/test/fixtures/ticketing-example/README.md new file mode 100644 index 0000000000..1db3fb3991 --- /dev/null +++ b/packages/db/test/fixtures/ticketing-example/README.md @@ -0,0 +1,54 @@ +# Astro Starter Kit: Basics + +```sh +npm create astro@latest -- --template basics +``` + +[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/astro/tree/latest/examples/basics) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/astro/tree/latest/examples/basics) +[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/withastro/astro?devcontainer_path=.devcontainer/basics/devcontainer.json) + +> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun! + +![just-the-basics](https://github.com/withastro/astro/assets/2244813/a0a5533c-a856-4198-8470-2d67b1d7c554) + +## 🚀 Project Structure + +Inside of your Astro project, you'll see the following folders and files: + +```text +/ +├── public/ +│ └── favicon.svg +├── src/ +│ ├── components/ +│ │ └── Card.astro +│ ├── layouts/ +│ │ └── Layout.astro +│ └── pages/ +│ └── index.astro +└── package.json +``` + +Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name. + +There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components. + +Any static assets, like images, can be placed in the `public/` directory. + +## 🧞 Commands + +All commands are run from the root of the project, from a terminal: + +| Command | Action | +| :------------------------ | :----------------------------------------------- | +| `npm install` | Installs dependencies | +| `npm run dev` | Starts local dev server at `localhost:4321` | +| `npm run build` | Build your production site to `./dist/` | +| `npm run preview` | Preview your build locally, before deploying | +| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` | +| `npm run astro -- --help` | Get help using the Astro CLI | + +## 👀 Want to learn more? + +Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat). diff --git a/packages/db/test/fixtures/ticketing-example/astro.config.ts b/packages/db/test/fixtures/ticketing-example/astro.config.ts new file mode 100644 index 0000000000..1f34f6f0d7 --- /dev/null +++ b/packages/db/test/fixtures/ticketing-example/astro.config.ts @@ -0,0 +1,56 @@ +import db, { defineReadableTable, defineWritableTable, column } from '@astrojs/db'; +import node from '@astrojs/node'; +import react from '@astrojs/react'; +import { defineConfig } from 'astro/config'; +import simpleStackForm from 'simple-stack-form'; + +const Event = defineReadableTable({ + columns: { + id: column.number({ + primaryKey: true, + }), + name: column.text(), + description: column.text(), + ticketPrice: column.number(), + date: column.date(), + location: column.text(), + }, +}); +const Ticket = defineWritableTable({ + columns: { + eventId: column.number({ references: () => Event.columns.id }), + email: column.text(), + quantity: column.number(), + newsletter: column.boolean({ + default: false, + }), + }, +}); + +// https://astro.build/config +export default defineConfig({ + integrations: [simpleStackForm(), db(), react()], + output: 'server', + adapter: node({ + mode: 'standalone', + }), + db: { + studio: true, + tables: { + Event, + Ticket, + }, + data({ seed }) { + seed(Event, [ + { + name: 'Sampha LIVE in Brooklyn', + description: + 'Sampha is on tour with his new, flawless album Lahai. Come see the live performance outdoors in Prospect Park. Yes, there will be a grand piano 🎹', + date: new Date('2024-01-01'), + ticketPrice: 10000, + location: 'Brooklyn, NY', + }, + ]); + }, + }, +}); diff --git a/packages/db/test/fixtures/ticketing-example/package.json b/packages/db/test/fixtures/ticketing-example/package.json new file mode 100644 index 0000000000..6a31011097 --- /dev/null +++ b/packages/db/test/fixtures/ticketing-example/package.json @@ -0,0 +1,27 @@ +{ + "name": "eventbrite-from-scratch", + "type": "module", + "version": "0.0.1", + "scripts": { + "dev": "pnpm astro dev", + "start": "astro dev", + "build": "astro check && astro build", + "preview": "astro preview", + "astro": "astro" + }, + "dependencies": { + "@astrojs/check": "^0.5.5", + "@astrojs/db": "workspace:*", + "@astrojs/node": "workspace:*", + "@astrojs/react": "^3.0.10", + "@types/react": "^18.2.57", + "@types/react-dom": "^18.2.19", + "astro": "workspace:*", + "open-props": "^1.6.17", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "simple-stack-form": "^0.1.10", + "typescript": "^5.3.2", + "zod": "^3.22.4" + } +} diff --git a/packages/db/test/fixtures/ticketing-example/pnpm-lock.yaml b/packages/db/test/fixtures/ticketing-example/pnpm-lock.yaml new file mode 100644 index 0000000000..a56a3f54b1 --- /dev/null +++ b/packages/db/test/fixtures/ticketing-example/pnpm-lock.yaml @@ -0,0 +1,5266 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + '@astrojs/check': + specifier: ^0.3.1 + version: 0.3.1(typescript@5.3.2) + '@astrojs/db': + specifier: file:./astrojs-db-0.1.3.tgz + version: file:astrojs-db-0.1.3.tgz(@cloudflare/workers-types@4.20231121.0)(typescript@5.3.2) + '@astrojs/node': + specifier: ^8.0.0 + version: 8.0.0(astro@4.2.0) + '@astrojs/preact': + specifier: ^3.0.1 + version: 3.0.1(@babel/core@7.23.7)(preact@10.19.2)(vite@5.0.11) + astro: + specifier: ^4.2.0 + version: 4.2.0(typescript@5.3.2) + open-props: + specifier: ^1.6.17 + version: 1.6.17 + preact: + specifier: ^10.6.5 + version: 10.19.2 + simple-stack-form: + specifier: ^0.1.10 + version: 0.1.10(astro@4.2.0)(zod@3.22.4) + typescript: + specifier: ^5.3.2 + version: 5.3.2 + zod: + specifier: ^3.22.4 + version: 3.22.4 + +devDependencies: + '@cloudflare/workers-types': + specifier: ^4.20231121.0 + version: 4.20231121.0 + +packages: + + /@ampproject/remapping@2.2.1: + resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.20 + dev: false + + /@astrojs/check@0.3.1(typescript@5.3.2): + resolution: {integrity: sha512-3LjEUvh7Z4v9NPokaqKMXQ0DwnSXfmtcyAuWVTjNt9yzjv54SxykobV5CTOB3TIko+Rqg59ejamJBxaJN6fvkw==} + hasBin: true + peerDependencies: + typescript: ^5.0.0 + dependencies: + '@astrojs/language-server': 2.5.2(typescript@5.3.2) + chokidar: 3.5.3 + fast-glob: 3.3.2 + kleur: 4.1.5 + typescript: 5.3.2 + yargs: 17.7.2 + transitivePeerDependencies: + - prettier + - prettier-plugin-astro + dev: false + + /@astrojs/compiler@2.3.2: + resolution: {integrity: sha512-jkY7bCVxl27KeZsSxIZ+pqACe+g8VQUdTiSJRj/sXYdIaZlW3ZMq4qF2M17P/oDt3LBq0zLNwQr4Cb7fSpRGxQ==} + dev: false + + /@astrojs/compiler@2.4.2: + resolution: {integrity: sha512-aPdo8rtdN1eBmyERfP5TnYZOnImLYZ8VPHl0eKhFaWIcEIRYhT5NHSohCwtiKcv1M+BprZWRQymojJ3uuk+x7Q==} + dev: false + + /@astrojs/internal-helpers@0.2.1: + resolution: {integrity: sha512-06DD2ZnItMwUnH81LBLco3tWjcZ1lGU9rLCCBaeUCGYe9cI0wKyY2W3kDyoW1I6GmcWgt1fu+D1CTvz+FIKf8A==} + dev: false + + /@astrojs/language-server@2.5.2(typescript@5.3.2): + resolution: {integrity: sha512-O5SMzoQ65wSxA1KygreI9UJYmHpgt15bSYBxceHwqX7OCDM4Ek8mr6mZn45LGDtwM3dp1uup7kp8exfRPwIFbA==} + hasBin: true + peerDependencies: + prettier: ^3.0.0 + prettier-plugin-astro: '>=0.11.0' + peerDependenciesMeta: + prettier: + optional: true + prettier-plugin-astro: + optional: true + dependencies: + '@astrojs/compiler': 2.3.2 + '@jridgewell/sourcemap-codec': 1.4.15 + '@volar/kit': 1.10.10(typescript@5.3.2) + '@volar/language-core': 1.10.10 + '@volar/language-server': 1.10.10 + '@volar/language-service': 1.10.10 + '@volar/source-map': 1.10.10 + '@volar/typescript': 1.10.10 + fast-glob: 3.3.2 + muggle-string: 0.3.1 + volar-service-css: 0.0.16(@volar/language-service@1.10.10) + volar-service-emmet: 0.0.16(@volar/language-service@1.10.10) + volar-service-html: 0.0.16(@volar/language-service@1.10.10) + volar-service-prettier: 0.0.16(@volar/language-service@1.10.10) + volar-service-typescript: 0.0.16(@volar/language-service@1.10.10)(@volar/typescript@1.10.10) + volar-service-typescript-twoslash-queries: 0.0.16(@volar/language-service@1.10.10) + vscode-html-languageservice: 5.1.1 + vscode-uri: 3.0.8 + transitivePeerDependencies: + - typescript + dev: false + + /@astrojs/markdoc@0.8.2(astro@4.1.1): + resolution: {integrity: sha512-HN4N0fcWNTuQk2XN1VaShbjq+osNtsA5ML4VdBMlHF0SafgFigpao5P+tG8Xq2EEYhXynZDHHWS+F4/HODyfwQ==} + engines: {node: '>=18.14.1'} + peerDependencies: + astro: ^3.0.0 || ^4.0.0 + dependencies: + '@astrojs/internal-helpers': 0.2.1 + '@astrojs/prism': 3.0.0 + '@markdoc/markdoc': 0.3.5 + astro: 4.1.1(typescript@5.3.2) + esbuild: 0.19.11 + github-slugger: 2.0.0 + gray-matter: 4.0.3 + htmlparser2: 9.1.0 + kleur: 4.1.5 + shikiji: 0.6.13 + zod: 3.22.4 + transitivePeerDependencies: + - '@types/react' + - react + dev: false + + /@astrojs/markdown-remark@4.0.1: + resolution: {integrity: sha512-RU4ESnqvyLpj8WZs0n5elS6idaDdtIIm7mIpMaRNPCebpxMjfcfdwcmBwz83ktAj5d2eO5bC3z92TcGdli+lRw==} + dependencies: + '@astrojs/prism': 3.0.0 + github-slugger: 2.0.0 + import-meta-resolve: 4.0.0 + mdast-util-definitions: 6.0.0 + rehype-raw: 7.0.0 + rehype-stringify: 10.0.0 + remark-gfm: 4.0.0 + remark-parse: 11.0.0 + remark-rehype: 11.1.0 + remark-smartypants: 2.0.0 + shikiji: 0.6.13 + unified: 11.0.4 + unist-util-visit: 5.0.0 + vfile: 6.0.1 + transitivePeerDependencies: + - supports-color + dev: false + + /@astrojs/markdown-remark@4.1.0: + resolution: {integrity: sha512-JnIy6zk+6f/SgSVMZecZFxQt0faT1uBckwYCuBxKH1hYYJsal8OOe+tx6JxfnyaV+xViyjUvQ28mmn+p/F5LkQ==} + dependencies: + '@astrojs/prism': 3.0.0 + github-slugger: 2.0.0 + import-meta-resolve: 4.0.0 + mdast-util-definitions: 6.0.0 + rehype-raw: 7.0.0 + rehype-stringify: 10.0.0 + remark-gfm: 4.0.0 + remark-parse: 11.0.0 + remark-rehype: 11.1.0 + remark-smartypants: 2.0.0 + shikiji: 0.9.19 + unified: 11.0.4 + unist-util-visit: 5.0.0 + vfile: 6.0.1 + transitivePeerDependencies: + - supports-color + dev: false + + /@astrojs/node@8.0.0(astro@4.2.0): + resolution: {integrity: sha512-qgLN2k0/GPHRNRYyXNMxx7bGR2DBNsVMWBv/S4w/q5LtsHNc+y2lhGsuk0Cz4xxvuORqXkJARjloDvtlpYwYzQ==} + peerDependencies: + astro: ^4.2.0 + dependencies: + astro: 4.2.0(typescript@5.3.2) + send: 0.18.0 + server-destroy: 1.0.1 + transitivePeerDependencies: + - supports-color + dev: false + + /@astrojs/preact@3.0.1(@babel/core@7.23.7)(preact@10.19.2)(vite@5.0.11): + resolution: {integrity: sha512-pAfN+U7J4hw7qijqkBx1ZBpPO+ooa+MkKIgshCozfqsHTp18uPflxQUviz0TEzB5nn7hSndzncWuc3pz/HbtJw==} + engines: {node: '>=18.14.1'} + peerDependencies: + preact: ^10.6.5 + dependencies: + '@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.23.7) + '@babel/plugin-transform-react-jsx-development': 7.22.5(@babel/core@7.23.7) + '@preact/preset-vite': 2.7.0(@babel/core@7.23.7)(preact@10.19.2)(vite@5.0.11) + '@preact/signals': 1.2.2(preact@10.19.2) + babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.23.7) + preact: 10.19.2 + preact-render-to-string: 6.3.1(preact@10.19.2) + transitivePeerDependencies: + - '@babel/core' + - supports-color + - vite + dev: false + + /@astrojs/prism@3.0.0: + resolution: {integrity: sha512-g61lZupWq1bYbcBnYZqdjndShr/J3l/oFobBKPA3+qMat146zce3nz2kdO4giGbhYDt4gYdhmoBz0vZJ4sIurQ==} + engines: {node: '>=18.14.1'} + dependencies: + prismjs: 1.29.0 + dev: false + + /@astrojs/telemetry@3.0.4: + resolution: {integrity: sha512-A+0c7k/Xy293xx6odsYZuXiaHO0PL+bnDoXOc47sGDF5ffIKdKQGRPFl2NMlCF4L0NqN4Ynbgnaip+pPF0s7pQ==} + engines: {node: '>=18.14.1'} + dependencies: + ci-info: 3.9.0 + debug: 4.3.4 + dlv: 1.1.3 + dset: 3.1.3 + is-docker: 3.0.0 + is-wsl: 3.1.0 + which-pm-runs: 1.1.0 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/code-frame@7.23.4: + resolution: {integrity: sha512-r1IONyb6Ia+jYR2vvIDhdWdlTGhqbBoFqLTQidzZ4kepUFH15ejXvFHxCVbtl7BOXIudsIubf4E81xeA3h3IXA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.23.4 + chalk: 2.4.2 + dev: false + + /@babel/code-frame@7.23.5: + resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.23.4 + chalk: 2.4.2 + dev: false + + /@babel/compat-data@7.23.3: + resolution: {integrity: sha512-BmR4bWbDIoFJmJ9z2cZ8Gmm2MXgEDgjdWgpKmKWUt54UGFJdlj31ECtbaDvCG/qVdG3AQ1SfpZEs01lUFbzLOQ==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/compat-data@7.23.5: + resolution: {integrity: sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/core@7.23.3: + resolution: {integrity: sha512-Jg+msLuNuCJDyBvFv5+OKOUjWMZgd85bKjbICd3zWrKAo+bJ49HJufi7CQE0q0uR8NGyO6xkCACScNqyjHSZew==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.1 + '@babel/code-frame': 7.23.4 + '@babel/generator': 7.23.4 + '@babel/helper-compilation-targets': 7.22.15 + '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.3) + '@babel/helpers': 7.23.4 + '@babel/parser': 7.23.4 + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.4 + '@babel/types': 7.23.4 + convert-source-map: 2.0.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/core@7.23.7: + resolution: {integrity: sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.1 + '@babel/code-frame': 7.23.5 + '@babel/generator': 7.23.6 + '@babel/helper-compilation-targets': 7.23.6 + '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.7) + '@babel/helpers': 7.23.8 + '@babel/parser': 7.23.6 + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.7 + '@babel/types': 7.23.6 + convert-source-map: 2.0.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/generator@7.23.4: + resolution: {integrity: sha512-esuS49Cga3HcThFNebGhlgsrVLkvhqvYDTzgjfFFlHJcIfLe5jFmRRfCQ1KuBfc4Jrtn3ndLgKWAKjBE+IraYQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.4 + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.20 + jsesc: 2.5.2 + dev: false + + /@babel/generator@7.23.6: + resolution: {integrity: sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.21 + jsesc: 2.5.2 + dev: false + + /@babel/helper-annotate-as-pure@7.22.5: + resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.4 + dev: false + + /@babel/helper-compilation-targets@7.22.15: + resolution: {integrity: sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/compat-data': 7.23.3 + '@babel/helper-validator-option': 7.22.15 + browserslist: 4.22.1 + lru-cache: 5.1.1 + semver: 6.3.1 + dev: false + + /@babel/helper-compilation-targets@7.23.6: + resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/compat-data': 7.23.5 + '@babel/helper-validator-option': 7.23.5 + browserslist: 4.22.2 + lru-cache: 5.1.1 + semver: 6.3.1 + dev: false + + /@babel/helper-environment-visitor@7.22.20: + resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/helper-function-name@7.23.0: + resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.22.15 + '@babel/types': 7.23.4 + dev: false + + /@babel/helper-hoist-variables@7.22.5: + resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.4 + dev: false + + /@babel/helper-module-imports@7.22.15: + resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.4 + dev: false + + /@babel/helper-module-transforms@7.23.3(@babel/core@7.23.3): + resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.3 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-module-imports': 7.22.15 + '@babel/helper-simple-access': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/helper-validator-identifier': 7.22.20 + dev: false + + /@babel/helper-module-transforms@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-module-imports': 7.22.15 + '@babel/helper-simple-access': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/helper-validator-identifier': 7.22.20 + dev: false + + /@babel/helper-plugin-utils@7.22.5: + resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/helper-simple-access@7.22.5: + resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.4 + dev: false + + /@babel/helper-split-export-declaration@7.22.6: + resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.4 + dev: false + + /@babel/helper-string-parser@7.23.4: + resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/helper-validator-identifier@7.22.20: + resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/helper-validator-option@7.22.15: + resolution: {integrity: sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/helper-validator-option@7.23.5: + resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} + engines: {node: '>=6.9.0'} + dev: false + + /@babel/helpers@7.23.4: + resolution: {integrity: sha512-HfcMizYz10cr3h29VqyfGL6ZWIjTwWfvYBMsBVGwpcbhNGe3wQ1ZXZRPzZoAHhd9OqHadHqjQ89iVKINXnbzuw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.4 + '@babel/types': 7.23.4 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/helpers@7.23.8: + resolution: {integrity: sha512-KDqYz4PiOWvDFrdHLPhKtCThtIcKVy6avWD2oG4GEvyQ+XDZwHD4YQd+H2vNMnq2rkdxsDkU82T+Vk8U/WXHRQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.7 + '@babel/types': 7.23.6 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/highlight@7.23.4: + resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.22.20 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: false + + /@babel/parser@7.23.4: + resolution: {integrity: sha512-vf3Xna6UEprW+7t6EtOmFpHNAuxw3xqPZghy+brsnusscJRW5BMUzzHZc5ICjULee81WeUV2jjakG09MDglJXQ==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.23.4 + dev: false + + /@babel/parser@7.23.6: + resolution: {integrity: sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.23.6 + dev: false + + /@babel/plugin-syntax-jsx@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: false + + /@babel/plugin-transform-react-jsx-development@7.22.5(@babel/core@7.23.7): + resolution: {integrity: sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.23.7) + dev: false + + /@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.23.7): + resolution: {integrity: sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-module-imports': 7.22.15 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.23.7) + '@babel/types': 7.23.4 + dev: false + + /@babel/template@7.22.15: + resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.23.4 + '@babel/parser': 7.23.4 + '@babel/types': 7.23.4 + dev: false + + /@babel/traverse@7.23.4: + resolution: {integrity: sha512-IYM8wSUwunWTB6tFC2dkKZhxbIjHoWemdK+3f8/wq8aKhbUscxD5MX72ubd90fxvFknaLPeGw5ycU84V1obHJg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.23.4 + '@babel/generator': 7.23.4 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/parser': 7.23.4 + '@babel/types': 7.23.4 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/traverse@7.23.7: + resolution: {integrity: sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.23.5 + '@babel/generator': 7.23.6 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/parser': 7.23.6 + '@babel/types': 7.23.6 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: false + + /@babel/types@7.23.4: + resolution: {integrity: sha512-7uIFwVYpoplT5jp/kVv6EF93VaJ8H+Yn5IczYiaAi98ajzjfoZfslet/e0sLh+wVBjb2qqIut1b0S26VSafsSQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.23.4 + '@babel/helper-validator-identifier': 7.22.20 + to-fast-properties: 2.0.0 + dev: false + + /@babel/types@7.23.6: + resolution: {integrity: sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.23.4 + '@babel/helper-validator-identifier': 7.22.20 + to-fast-properties: 2.0.0 + dev: false + + /@clack/core@0.3.3: + resolution: {integrity: sha512-5ZGyb75BUBjlll6eOa1m/IZBxwk91dooBWhPSL67sWcLS0zt9SnswRL0l26TVdBhb0wnWORRxUn//uH6n4z7+A==} + dependencies: + picocolors: 1.0.0 + sisteransi: 1.0.5 + dev: false + + /@clack/prompts@0.7.0: + resolution: {integrity: sha512-0MhX9/B4iL6Re04jPrttDm+BsP8y6mS7byuv0BvXgdXhbV5PdlsHt55dvNsuBCPZ7xq1oTAOOuotR9NFbQyMSA==} + dependencies: + '@clack/core': 0.3.3 + picocolors: 1.0.0 + sisteransi: 1.0.5 + dev: false + bundledDependencies: + - is-unicode-supported + + /@cloudflare/workers-types@4.20231121.0: + resolution: {integrity: sha512-+kWfpCkqiepwAKXyHoE0gnkPgkLhz0/9HOBIGhHRsUvUKvhUtm3mbqqoGRWgF1qcjzrDUBbrrOq4MYHfFtc2RA==} + + /@emmetio/abbreviation@2.3.3: + resolution: {integrity: sha512-mgv58UrU3rh4YgbE/TzgLQwJ3pFsHHhCLqY20aJq+9comytTXUDNGG/SMtSeMJdkpxgXSXunBGLD8Boka3JyVA==} + dependencies: + '@emmetio/scanner': 1.0.4 + dev: false + + /@emmetio/css-abbreviation@2.1.8: + resolution: {integrity: sha512-s9yjhJ6saOO/uk1V74eifykk2CBYi01STTK3WlXWGOepyKa23ymJ053+DNQjpFcy1ingpaO7AxCcwLvHFY9tuw==} + dependencies: + '@emmetio/scanner': 1.0.4 + dev: false + + /@emmetio/scanner@1.0.4: + resolution: {integrity: sha512-IqRuJtQff7YHHBk4G8YZ45uB9BaAGcwQeVzgj/zj8/UdOhtQpEIupUhSk8dys6spFIWVZVeK20CzGEnqR5SbqA==} + dev: false + + /@emnapi/runtime@0.45.0: + resolution: {integrity: sha512-Txumi3td7J4A/xTTwlssKieHKTGl3j4A1tglBx72auZ49YK7ePY6XZricgIg9mnZT4xPfA+UPCUdnhRuEFDL+w==} + requiresBuild: true + dependencies: + tslib: 2.6.2 + dev: false + optional: true + + /@esbuild/aix-ppc64@0.19.11: + resolution: {integrity: sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + requiresBuild: true + dev: false + optional: true + + /@esbuild/android-arm64@0.19.11: + resolution: {integrity: sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@esbuild/android-arm@0.19.11: + resolution: {integrity: sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@esbuild/android-x64@0.19.11: + resolution: {integrity: sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@esbuild/darwin-arm64@0.19.11: + resolution: {integrity: sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@esbuild/darwin-x64@0.19.11: + resolution: {integrity: sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@esbuild/freebsd-arm64@0.19.11: + resolution: {integrity: sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/freebsd-x64@0.19.11: + resolution: {integrity: sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-arm64@0.19.11: + resolution: {integrity: sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-arm@0.19.11: + resolution: {integrity: sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-ia32@0.19.11: + resolution: {integrity: sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-loong64@0.19.11: + resolution: {integrity: sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-mips64el@0.19.11: + resolution: {integrity: sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-ppc64@0.19.11: + resolution: {integrity: sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-riscv64@0.19.11: + resolution: {integrity: sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-s390x@0.19.11: + resolution: {integrity: sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/linux-x64@0.19.11: + resolution: {integrity: sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@esbuild/netbsd-x64@0.19.11: + resolution: {integrity: sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/openbsd-x64@0.19.11: + resolution: {integrity: sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: false + optional: true + + /@esbuild/sunos-x64@0.19.11: + resolution: {integrity: sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: false + optional: true + + /@esbuild/win32-arm64@0.19.11: + resolution: {integrity: sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@esbuild/win32-ia32@0.19.11: + resolution: {integrity: sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@esbuild/win32-x64@0.19.11: + resolution: {integrity: sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-darwin-arm64@0.33.2: + resolution: {integrity: sha512-itHBs1rPmsmGF9p4qRe++CzCgd+kFYktnsoR1sbIAfsRMrJZau0Tt1AH9KVnufc2/tU02Gf6Ibujx+15qRE03w==} + engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.0.1 + dev: false + optional: true + + /@img/sharp-darwin-x64@0.33.2: + resolution: {integrity: sha512-/rK/69Rrp9x5kaWBjVN07KixZanRr+W1OiyKdXcbjQD6KbW+obaTeBBtLUAtbBsnlTTmWthw99xqoOS7SsySDg==} + engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [darwin] + requiresBuild: true + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.0.1 + dev: false + optional: true + + /@img/sharp-libvips-darwin-arm64@1.0.1: + resolution: {integrity: sha512-kQyrSNd6lmBV7O0BUiyu/OEw9yeNGFbQhbxswS1i6rMDwBBSX+e+rPzu3S+MwAiGU3HdLze3PanQ4Xkfemgzcw==} + engines: {macos: '>=11', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-libvips-darwin-x64@1.0.1: + resolution: {integrity: sha512-eVU/JYLPVjhhrd8Tk6gosl5pVlvsqiFlt50wotCvdkFGf+mDNBJxMh+bvav+Wt3EBnNZWq8Sp2I7XfSjm8siog==} + engines: {macos: '>=10.13', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-libvips-linux-arm64@1.0.1: + resolution: {integrity: sha512-bnGG+MJjdX70mAQcSLxgeJco11G+MxTz+ebxlz8Y3dxyeb3Nkl7LgLI0mXupoO+u1wRNx/iRj5yHtzA4sde1yA==} + engines: {glibc: '>=2.26', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-libvips-linux-arm@1.0.1: + resolution: {integrity: sha512-FtdMvR4R99FTsD53IA3LxYGghQ82t3yt0ZQ93WMZ2xV3dqrb0E8zq4VHaTOuLEAuA83oDawHV3fd+BsAPadHIQ==} + engines: {glibc: '>=2.28', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-libvips-linux-s390x@1.0.1: + resolution: {integrity: sha512-3+rzfAR1YpMOeA2zZNp+aYEzGNWK4zF3+sdMxuCS3ey9HhDbJ66w6hDSHDMoap32DueFwhhs3vwooAB2MaK4XQ==} + engines: {glibc: '>=2.28', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-libvips-linux-x64@1.0.1: + resolution: {integrity: sha512-3NR1mxFsaSgMMzz1bAnnKbSAI+lHXVTqAHgc1bgzjHuXjo4hlscpUxc0vFSAPKI3yuzdzcZOkq7nDPrP2F8Jgw==} + engines: {glibc: '>=2.26', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-libvips-linuxmusl-arm64@1.0.1: + resolution: {integrity: sha512-5aBRcjHDG/T6jwC3Edl3lP8nl9U2Yo8+oTl5drd1dh9Z1EBfzUKAJFUDTDisDjUwc7N4AjnPGfCA3jl3hY8uDg==} + engines: {musl: '>=1.2.2', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-libvips-linuxmusl-x64@1.0.1: + resolution: {integrity: sha512-dcT7inI9DBFK6ovfeWRe3hG30h51cBAP5JXlZfx6pzc/Mnf9HFCQDLtYf4MCBjxaaTfjCCjkBxcy3XzOAo5txw==} + engines: {musl: '>=1.2.2', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-linux-arm64@0.33.2: + resolution: {integrity: sha512-pz0NNo882vVfqJ0yNInuG9YH71smP4gRSdeL09ukC2YLE6ZyZePAlWKEHgAzJGTiOh8Qkaov6mMIMlEhmLdKew==} + engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [linux] + requiresBuild: true + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.0.1 + dev: false + optional: true + + /@img/sharp-linux-arm@0.33.2: + resolution: {integrity: sha512-Fndk/4Zq3vAc4G/qyfXASbS3HBZbKrlnKZLEJzPLrXoJuipFNNwTes71+Ki1hwYW5lch26niRYoZFAtZVf3EGA==} + engines: {glibc: '>=2.28', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm] + os: [linux] + requiresBuild: true + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.0.1 + dev: false + optional: true + + /@img/sharp-linux-s390x@0.33.2: + resolution: {integrity: sha512-MBoInDXDppMfhSzbMmOQtGfloVAflS2rP1qPcUIiITMi36Mm5YR7r0ASND99razjQUpHTzjrU1flO76hKvP5RA==} + engines: {glibc: '>=2.28', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [s390x] + os: [linux] + requiresBuild: true + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.0.1 + dev: false + optional: true + + /@img/sharp-linux-x64@0.33.2: + resolution: {integrity: sha512-xUT82H5IbXewKkeF5aiooajoO1tQV4PnKfS/OZtb5DDdxS/FCI/uXTVZ35GQ97RZXsycojz/AJ0asoz6p2/H/A==} + engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [linux] + requiresBuild: true + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.0.1 + dev: false + optional: true + + /@img/sharp-linuxmusl-arm64@0.33.2: + resolution: {integrity: sha512-F+0z8JCu/UnMzg8IYW1TMeiViIWBVg7IWP6nE0p5S5EPQxlLd76c8jYemG21X99UzFwgkRo5yz2DS+zbrnxZeA==} + engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [linux] + requiresBuild: true + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.0.1 + dev: false + optional: true + + /@img/sharp-linuxmusl-x64@0.33.2: + resolution: {integrity: sha512-+ZLE3SQmSL+Fn1gmSaM8uFusW5Y3J9VOf+wMGNnTtJUMUxFhv+P4UPaYEYT8tqnyYVaOVGgMN/zsOxn9pSsO2A==} + engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [linux] + requiresBuild: true + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.0.1 + dev: false + optional: true + + /@img/sharp-wasm32@0.33.2: + resolution: {integrity: sha512-fLbTaESVKuQcpm8ffgBD7jLb/CQLcATju/jxtTXR1XCLwbOQt+OL5zPHSDMmp2JZIeq82e18yE0Vv7zh6+6BfQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [wasm32] + requiresBuild: true + dependencies: + '@emnapi/runtime': 0.45.0 + dev: false + optional: true + + /@img/sharp-win32-ia32@0.33.2: + resolution: {integrity: sha512-okBpql96hIGuZ4lN3+nsAjGeggxKm7hIRu9zyec0lnfB8E7Z6p95BuRZzDDXZOl2e8UmR4RhYt631i7mfmKU8g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-win32-x64@0.33.2: + resolution: {integrity: sha512-E4magOks77DK47FwHUIGH0RYWSgRBfGdK56kIHSVeB9uIS4pPFr4N2kIVsXdQQo4LzOsENKV5KAhRlRL7eMAdg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@jridgewell/gen-mapping@0.3.3: + resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.20 + dev: false + + /@jridgewell/resolve-uri@3.1.1: + resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} + engines: {node: '>=6.0.0'} + dev: false + + /@jridgewell/set-array@1.1.2: + resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} + engines: {node: '>=6.0.0'} + dev: false + + /@jridgewell/sourcemap-codec@1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + dev: false + + /@jridgewell/trace-mapping@0.3.20: + resolution: {integrity: sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==} + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + dev: false + + /@jridgewell/trace-mapping@0.3.21: + resolution: {integrity: sha512-SRfKmRe1KvYnxjEMtxEr+J4HIeMX5YBg/qhRHpxEIGjhX1rshcHlnFUE9K0GazhVKWM7B+nARSkV8LuvJdJ5/g==} + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + dev: false + + /@libsql/client@0.4.0-pre.5: + resolution: {integrity: sha512-GyKigCBslE5uztwT7mpvp9Zn0z3iWjnufcfeTeDSFPMyXCPjSAHUOiwSLAaHii909w6EQacA692CXmYYFo/eig==} + dependencies: + '@libsql/hrana-client': 0.5.5 + js-base64: 3.7.5 + libsql: 0.2.0-pre.7 + transitivePeerDependencies: + - bufferutil + - encoding + - utf-8-validate + dev: false + + /@libsql/darwin-arm64@0.2.0-pre.7: + resolution: {integrity: sha512-rtNYnXF0W3kKwZ5MxrhjzE8uWq2YI20zIeKLDFX8JzT6zfgR3qym9AUrDV8tPYGr4bF/mgdH/CZxr49zddy4ig==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@libsql/darwin-x64@0.2.0-pre.7: + resolution: {integrity: sha512-14cb9xJCHwOIl71TPpzeZhKZ4pvwEeRTkP2XmmMBvkNaDPK27lE4ibMATL+IZ/JL0S7aQNcBLwTpwu2Zt0IMuQ==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@libsql/hrana-client@0.5.5: + resolution: {integrity: sha512-i+hDBpiV719poqEiHupUUZYKJ9YSbCRFe5Q2PQ0v3mHIftePH6gayLjp2u6TXbqbO/Dv6y8yyvYlBXf/kFfRZA==} + dependencies: + '@libsql/isomorphic-fetch': 0.1.10 + '@libsql/isomorphic-ws': 0.1.5 + js-base64: 3.7.5 + node-fetch: 3.3.2 + transitivePeerDependencies: + - bufferutil + - encoding + - utf-8-validate + dev: false + + /@libsql/isomorphic-fetch@0.1.10: + resolution: {integrity: sha512-dH0lMk50gKSvEKD78xWMu60SY1sjp1sY//iFLO0XMmBwfVfG136P9KOk06R4maBdlb8KMXOzJ1D28FR5ZKnHTA==} + dependencies: + '@types/node-fetch': 2.6.11 + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + dev: false + + /@libsql/isomorphic-ws@0.1.5: + resolution: {integrity: sha512-DtLWIH29onUYR00i0GlQ3UdcTRC6EP4u9w/h9LxpUZJWRMARk6dQwZ6Jkd+QdwVpuAOrdxt18v0K2uIYR3fwFg==} + dependencies: + '@types/ws': 8.5.10 + ws: 8.14.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: false + + /@libsql/linux-arm64-gnu@0.2.0-pre.7: + resolution: {integrity: sha512-fiygBotFaYmWnK0or0yEQQQ+3V2m886aaIXDuYtSMpoeykbY3JuRu/CSvriI6/ovnufoMoERo82YZUBR6EDPKA==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@libsql/linux-arm64-musl@0.2.0-pre.7: + resolution: {integrity: sha512-5m2OnItWBwyhGiB4kpOvGaOGwHemEY5cz/dc0gK/L6OjEP1lTPZwhXongp3EtI/cApGpHyLctkSWkgM+y2zp9w==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@libsql/linux-x64-gnu@0.2.0-pre.7: + resolution: {integrity: sha512-i72WtvZqsuoM5rnMslS2LGsOo3zvlH0nc5gAwUz45UnsXQBSiLP7ELktVW0n8soMaeQE47ayT6jsB61CMC0KSA==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@libsql/linux-x64-musl@0.2.0-pre.7: + resolution: {integrity: sha512-9QO7xg6mExrQVQES9gW1OsExsUEJ6cBRdmt6nYfeDGShh/eoV3kiPSUeMXckNNbl77F5+m86WZqIDpi2UskgDw==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@libsql/win32-x64-msvc@0.2.0-pre.7: + resolution: {integrity: sha512-vNKWGHIws3qoqMV4hX0kRt54IiFaA0FuSzQnclqlygGTXetHragnuimZANIOYVWagU35wk5s23+Ir/eO158+Sg==} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@markdoc/markdoc@0.3.5: + resolution: {integrity: sha512-Z3agu2wnodoOYd5kzKbtwZduSfX19Kbsg/FlK0TeMn29cTTEEVPJtjfgKSMTN/Wq+kUQXnPtOEhHRgke5d/Xiw==} + engines: {node: '>=14.7.0'} + peerDependencies: + '@types/react': '*' + react: '*' + peerDependenciesMeta: + '@types/react': + optional: true + react: + optional: true + optionalDependencies: + '@types/markdown-it': 12.2.3 + dev: false + + /@neon-rs/load@0.0.4: + resolution: {integrity: sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw==} + dev: false + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: false + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: false + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.15.0 + dev: false + + /@preact/preset-vite@2.7.0(@babel/core@7.23.7)(preact@10.19.2)(vite@5.0.11): + resolution: {integrity: sha512-m5N0FVtxbCCDxNk55NGhsRpKJChYcupcuQHzMJc/Bll07IKZKn8amwYciyKFS9haU6AgzDAJ/ewvApr6Qg1DHw==} + peerDependencies: + '@babel/core': 7.x + vite: 2.x || 3.x || 4.x || 5.x + dependencies: + '@babel/core': 7.23.7 + '@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.23.7) + '@babel/plugin-transform-react-jsx-development': 7.22.5(@babel/core@7.23.7) + '@prefresh/vite': 2.4.4(preact@10.19.2)(vite@5.0.11) + '@rollup/pluginutils': 4.2.1 + babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.23.7) + debug: 4.3.4 + kolorist: 1.8.0 + resolve: 1.22.8 + vite: 5.0.11 + transitivePeerDependencies: + - preact + - supports-color + dev: false + + /@preact/signals-core@1.5.0: + resolution: {integrity: sha512-U2diO1Z4i1n2IoFgMYmRdHWGObNrcuTRxyNEn7deSq2cru0vj0583HYQZHsAqcs7FE+hQyX3mjIV7LAfHCvy8w==} + dev: false + + /@preact/signals@1.2.2(preact@10.19.2): + resolution: {integrity: sha512-ColCqdo4cRP18bAuIR4Oik5rDpiyFtPIJIygaYPMEAwTnl4buWkBOflGBSzhYyPyJfKpkwlekrvK+1pzQ2ldWw==} + peerDependencies: + preact: 10.x + dependencies: + '@preact/signals-core': 1.5.0 + preact: 10.19.2 + dev: false + + /@prefresh/babel-plugin@0.5.1: + resolution: {integrity: sha512-uG3jGEAysxWoyG3XkYfjYHgaySFrSsaEb4GagLzYaxlydbuREtaX+FTxuIidp241RaLl85XoHg9Ej6E4+V1pcg==} + dev: false + + /@prefresh/core@1.5.2(preact@10.19.2): + resolution: {integrity: sha512-A/08vkaM1FogrCII5PZKCrygxSsc11obExBScm3JF1CryK2uDS3ZXeni7FeKCx1nYdUkj4UcJxzPzc1WliMzZA==} + peerDependencies: + preact: ^10.0.0 + dependencies: + preact: 10.19.2 + dev: false + + /@prefresh/utils@1.2.0: + resolution: {integrity: sha512-KtC/fZw+oqtwOLUFM9UtiitB0JsVX0zLKNyRTA332sqREqSALIIQQxdUCS1P3xR/jT1e2e8/5rwH6gdcMLEmsQ==} + dev: false + + /@prefresh/vite@2.4.4(preact@10.19.2)(vite@5.0.11): + resolution: {integrity: sha512-7jcz3j5pXufOWTjl31n0Lc3BcU8oGoacoaWx/Ur1QJ+fd4Xu0G7g/ER1xV02x7DCiVoFi7xtSgaophOXoJvpmA==} + peerDependencies: + preact: ^10.4.0 + vite: '>=2.0.0' + dependencies: + '@babel/core': 7.23.3 + '@prefresh/babel-plugin': 0.5.1 + '@prefresh/core': 1.5.2(preact@10.19.2) + '@prefresh/utils': 1.2.0 + '@rollup/pluginutils': 4.2.1 + preact: 10.19.2 + vite: 5.0.11 + transitivePeerDependencies: + - supports-color + dev: false + + /@rollup/pluginutils@4.2.1: + resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} + engines: {node: '>= 8.0.0'} + dependencies: + estree-walker: 2.0.2 + picomatch: 2.3.1 + dev: false + + /@rollup/rollup-android-arm-eabi@4.9.5: + resolution: {integrity: sha512-idWaG8xeSRCfRq9KpRysDHJ/rEHBEXcHuJ82XY0yYFIWnLMjZv9vF/7DOq8djQ2n3Lk6+3qfSH8AqlmHlmi1MA==} + cpu: [arm] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-android-arm64@4.9.5: + resolution: {integrity: sha512-f14d7uhAMtsCGjAYwZGv6TwuS3IFaM4ZnGMUn3aCBgkcHAYErhV1Ad97WzBvS2o0aaDv4mVz+syiN0ElMyfBPg==} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-darwin-arm64@4.9.5: + resolution: {integrity: sha512-ndoXeLx455FffL68OIUrVr89Xu1WLzAG4n65R8roDlCoYiQcGGg6MALvs2Ap9zs7AHg8mpHtMpwC8jBBjZrT/w==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-darwin-x64@4.9.5: + resolution: {integrity: sha512-UmElV1OY2m/1KEEqTlIjieKfVwRg0Zwg4PLgNf0s3glAHXBN99KLpw5A5lrSYCa1Kp63czTpVll2MAqbZYIHoA==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-linux-arm-gnueabihf@4.9.5: + resolution: {integrity: sha512-Q0LcU61v92tQB6ae+udZvOyZ0wfpGojtAKrrpAaIqmJ7+psq4cMIhT/9lfV6UQIpeItnq/2QDROhNLo00lOD1g==} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-linux-arm64-gnu@4.9.5: + resolution: {integrity: sha512-dkRscpM+RrR2Ee3eOQmRWFjmV/payHEOrjyq1VZegRUa5OrZJ2MAxBNs05bZuY0YCtpqETDy1Ix4i/hRqX98cA==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-linux-arm64-musl@4.9.5: + resolution: {integrity: sha512-QaKFVOzzST2xzY4MAmiDmURagWLFh+zZtttuEnuNn19AiZ0T3fhPyjPPGwLNdiDT82ZE91hnfJsUiDwF9DClIQ==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-linux-riscv64-gnu@4.9.5: + resolution: {integrity: sha512-HeGqmRJuyVg6/X6MpE2ur7GbymBPS8Np0S/vQFHDmocfORT+Zt76qu+69NUoxXzGqVP1pzaY6QIi0FJWLC3OPA==} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-linux-x64-gnu@4.9.5: + resolution: {integrity: sha512-Dq1bqBdLaZ1Gb/l2e5/+o3B18+8TI9ANlA1SkejZqDgdU/jK/ThYaMPMJpVMMXy2uRHvGKbkz9vheVGdq3cJfA==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-linux-x64-musl@4.9.5: + resolution: {integrity: sha512-ezyFUOwldYpj7AbkwyW9AJ203peub81CaAIVvckdkyH8EvhEIoKzaMFJj0G4qYJ5sw3BpqhFrsCc30t54HV8vg==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-win32-arm64-msvc@4.9.5: + resolution: {integrity: sha512-aHSsMnUw+0UETB0Hlv7B/ZHOGY5bQdwMKJSzGfDfvyhnpmVxLMGnQPGNE9wgqkLUs3+gbG1Qx02S2LLfJ5GaRQ==} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-win32-ia32-msvc@4.9.5: + resolution: {integrity: sha512-AiqiLkb9KSf7Lj/o1U3SEP9Zn+5NuVKgFdRIZkvd4N0+bYrTOovVd0+LmYCPQGbocT4kvFyK+LXCDiXPBF3fyA==} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@rollup/rollup-win32-x64-msvc@4.9.5: + resolution: {integrity: sha512-1q+mykKE3Vot1kaFJIDoUFv5TuW+QQVaf2FmTT9krg86pQrGStOSJJ0Zil7CFagyxDuouTepzt5Y5TVzyajOdQ==} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@types/babel__core@7.20.5: + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + dependencies: + '@babel/parser': 7.23.6 + '@babel/types': 7.23.6 + '@types/babel__generator': 7.6.7 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.4 + dev: false + + /@types/babel__generator@7.6.7: + resolution: {integrity: sha512-6Sfsq+EaaLrw4RmdFWE9Onp63TOUue71AWb4Gpa6JxzgTYtimbM086WnYTy2U67AofR++QKCo08ZP6pwx8YFHQ==} + dependencies: + '@babel/types': 7.23.6 + dev: false + + /@types/babel__template@7.4.4: + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + dependencies: + '@babel/parser': 7.23.6 + '@babel/types': 7.23.6 + dev: false + + /@types/babel__traverse@7.20.4: + resolution: {integrity: sha512-mSM/iKUk5fDDrEV/e83qY+Cr3I1+Q3qqTuEn++HAWYjEa1+NxZr6CNrcJGf2ZTnq4HoFGC3zaTPZTobCzCFukA==} + dependencies: + '@babel/types': 7.23.6 + dev: false + + /@types/debug@4.1.12: + resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + dependencies: + '@types/ms': 0.7.34 + dev: false + + /@types/estree@1.0.5: + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + dev: false + + /@types/hast@3.0.3: + resolution: {integrity: sha512-2fYGlaDy/qyLlhidX42wAH0KBi2TCjKMH8CHmBXgRlJ3Y+OXTiqsPQ6IWarZKwF1JoUcAJdPogv1d4b0COTpmQ==} + dependencies: + '@types/unist': 3.0.2 + dev: false + + /@types/linkify-it@3.0.5: + resolution: {integrity: sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw==} + requiresBuild: true + dev: false + optional: true + + /@types/markdown-it@12.2.3: + resolution: {integrity: sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==} + requiresBuild: true + dependencies: + '@types/linkify-it': 3.0.5 + '@types/mdurl': 1.0.5 + dev: false + optional: true + + /@types/mdast@4.0.3: + resolution: {integrity: sha512-LsjtqsyF+d2/yFOYaN22dHZI1Cpwkrj+g06G8+qtUKlhovPW89YhqSnfKtMbkgmEtYpH2gydRNULd6y8mciAFg==} + dependencies: + '@types/unist': 3.0.2 + dev: false + + /@types/mdurl@1.0.5: + resolution: {integrity: sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA==} + requiresBuild: true + dev: false + optional: true + + /@types/ms@0.7.34: + resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} + dev: false + + /@types/nlcst@1.0.4: + resolution: {integrity: sha512-ABoYdNQ/kBSsLvZAekMhIPMQ3YUZvavStpKYs7BjLLuKVmIMA0LUgZ7b54zzuWJRbHF80v1cNf4r90Vd6eMQDg==} + dependencies: + '@types/unist': 2.0.10 + dev: false + + /@types/node-fetch@2.6.11: + resolution: {integrity: sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==} + dependencies: + '@types/node': 20.11.5 + form-data: 4.0.0 + dev: false + + /@types/node@20.11.5: + resolution: {integrity: sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==} + dependencies: + undici-types: 5.26.5 + dev: false + + /@types/unist@2.0.10: + resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==} + dev: false + + /@types/unist@3.0.2: + resolution: {integrity: sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==} + dev: false + + /@types/ws@8.5.10: + resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} + dependencies: + '@types/node': 20.11.5 + dev: false + + /@types/yargs-parser@21.0.3: + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + dev: false + + /@ungap/structured-clone@1.2.0: + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + dev: false + + /@volar/kit@1.10.10(typescript@5.3.2): + resolution: {integrity: sha512-V2SyUPCPUhueqH8j5t48LJ0QsjExGSXzTv/XOdkUHV7hJ/ekyRGFqKxcfBtMq/nK6Tgu2G1ba+6u0d7e6wKcQw==} + peerDependencies: + typescript: '*' + dependencies: + '@volar/language-service': 1.10.10 + typesafe-path: 0.2.2 + typescript: 5.3.2 + vscode-languageserver-textdocument: 1.0.11 + vscode-uri: 3.0.8 + dev: false + + /@volar/language-core@1.10.10: + resolution: {integrity: sha512-nsV1o3AZ5n5jaEAObrS3MWLBWaGwUj/vAsc15FVNIv+DbpizQRISg9wzygsHBr56ELRH8r4K75vkYNMtsSNNWw==} + dependencies: + '@volar/source-map': 1.10.10 + dev: false + + /@volar/language-server@1.10.10: + resolution: {integrity: sha512-F2PRBU+CRjT7L9qe8bjof/uz/LbAXVmgwNU2gOSX2y1bUl3E8DHmD0dB6pwIVublvkx+Ivg/0r3Z6oyxfPPruQ==} + dependencies: + '@volar/language-core': 1.10.10 + '@volar/language-service': 1.10.10 + '@volar/typescript': 1.10.10 + '@vscode/l10n': 0.0.16 + path-browserify: 1.0.1 + request-light: 0.7.0 + vscode-languageserver: 9.0.1 + vscode-languageserver-protocol: 3.17.5 + vscode-languageserver-textdocument: 1.0.11 + vscode-uri: 3.0.8 + dev: false + + /@volar/language-service@1.10.10: + resolution: {integrity: sha512-P4fiPWDI6fLGO6BghlksCVHs1nr9gvWAMDyma3Bca4aowxXusxjUVTsnJq0EVorIN5uIr1Xel4B/tNdXt/IKyw==} + dependencies: + '@volar/language-core': 1.10.10 + '@volar/source-map': 1.10.10 + vscode-languageserver-protocol: 3.17.5 + vscode-languageserver-textdocument: 1.0.11 + vscode-uri: 3.0.8 + dev: false + + /@volar/source-map@1.10.10: + resolution: {integrity: sha512-GVKjLnifV4voJ9F0vhP56p4+F3WGf+gXlRtjFZsv6v3WxBTWU3ZVeaRaEHJmWrcv5LXmoYYpk/SC25BKemPRkg==} + dependencies: + muggle-string: 0.3.1 + dev: false + + /@volar/typescript@1.10.10: + resolution: {integrity: sha512-4a2r5bdUub2m+mYVnLu2wt59fuoYWe7nf0uXtGHU8QQ5LDNfzAR0wK7NgDiQ9rcl2WT3fxT2AA9AylAwFtj50A==} + dependencies: + '@volar/language-core': 1.10.10 + path-browserify: 1.0.1 + dev: false + + /@vscode/emmet-helper@2.9.2: + resolution: {integrity: sha512-MaGuyW+fa13q3aYsluKqclmh62Hgp0BpKIqS66fCxfOaBcVQ1OnMQxRRgQUYnCkxFISAQlkJ0qWWPyXjro1Qrg==} + dependencies: + emmet: 2.4.6 + jsonc-parser: 2.3.1 + vscode-languageserver-textdocument: 1.0.11 + vscode-languageserver-types: 3.17.5 + vscode-uri: 2.1.2 + dev: false + + /@vscode/l10n@0.0.16: + resolution: {integrity: sha512-JT5CvrIYYCrmB+dCana8sUqJEcGB1ZDXNLMQ2+42bW995WmNoenijWMUdZfwmuQUTQcEVVIa2OecZzTYWUW9Cg==} + dev: false + + /acorn@8.11.2: + resolution: {integrity: sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: false + + /ansi-align@3.0.1: + resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + dependencies: + string-width: 4.2.3 + dev: false + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: false + + /ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + dev: false + + /ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: false + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: false + + /ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + dev: false + + /anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: false + + /argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: false + + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: false + + /aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + dependencies: + dequal: 2.0.3 + dev: false + + /array-iterate@2.0.1: + resolution: {integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==} + dev: false + + /astro@4.1.1(typescript@5.3.2): + resolution: {integrity: sha512-p/S1Ns4+yVh2lEsFW9hkJNRbnPfFWZ+1Wv7DSR3mDnabgCs49T7EbvOy8YIlLo0gtPAjI+b+4OEKRsxtBay2aA==} + engines: {node: '>=18.14.1', npm: '>=6.14.0'} + hasBin: true + dependencies: + '@astrojs/compiler': 2.4.2 + '@astrojs/internal-helpers': 0.2.1 + '@astrojs/markdown-remark': 4.0.1 + '@astrojs/telemetry': 3.0.4 + '@babel/core': 7.23.7 + '@babel/generator': 7.23.6 + '@babel/parser': 7.23.6 + '@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.23.7) + '@babel/traverse': 7.23.7 + '@babel/types': 7.23.6 + '@types/babel__core': 7.20.5 + acorn: 8.11.2 + aria-query: 5.3.0 + axobject-query: 4.0.0 + boxen: 7.1.1 + chokidar: 3.5.3 + ci-info: 4.0.0 + clsx: 2.0.0 + common-ancestor-path: 1.0.1 + cookie: 0.6.0 + debug: 4.3.4 + deterministic-object-hash: 2.0.2 + devalue: 4.3.2 + diff: 5.1.0 + dlv: 1.1.3 + dset: 3.1.3 + es-module-lexer: 1.4.1 + esbuild: 0.19.11 + estree-walker: 3.0.3 + execa: 8.0.1 + fast-glob: 3.3.2 + flattie: 1.1.0 + github-slugger: 2.0.0 + gray-matter: 4.0.3 + html-escaper: 3.0.3 + http-cache-semantics: 4.1.1 + js-yaml: 4.1.0 + kleur: 4.1.5 + magic-string: 0.30.5 + mdast-util-to-hast: 13.0.2 + mime: 3.0.0 + ora: 7.0.1 + p-limit: 5.0.0 + p-queue: 8.0.1 + path-to-regexp: 6.2.1 + preferred-pm: 3.1.2 + probe-image-size: 7.2.3 + prompts: 2.4.2 + rehype: 13.0.1 + resolve: 1.22.8 + semver: 7.5.4 + server-destroy: 1.0.1 + shikiji: 0.6.13 + string-width: 7.0.0 + strip-ansi: 7.1.0 + tsconfck: 3.0.0(typescript@5.3.2) + unist-util-visit: 5.0.0 + vfile: 6.0.1 + vite: 5.0.11 + vitefu: 0.2.5(vite@5.0.11) + which-pm: 2.1.1 + yargs-parser: 21.1.1 + zod: 3.22.4 + optionalDependencies: + sharp: 0.33.2 + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + - typescript + dev: false + + /astro@4.2.0(typescript@5.3.2): + resolution: {integrity: sha512-zx6Po3h5+VEkG1vwowaXC2T42317Gbs4d5lflkEYzUUseEQn8HMtqTwlbIoFCfyYTc4Kvo+4zEgbGsPjsybiaw==} + engines: {node: '>=18.14.1', npm: '>=6.14.0'} + hasBin: true + dependencies: + '@astrojs/compiler': 2.4.2 + '@astrojs/internal-helpers': 0.2.1 + '@astrojs/markdown-remark': 4.1.0 + '@astrojs/telemetry': 3.0.4 + '@babel/core': 7.23.7 + '@babel/generator': 7.23.6 + '@babel/parser': 7.23.6 + '@babel/plugin-transform-react-jsx': 7.23.4(@babel/core@7.23.7) + '@babel/traverse': 7.23.7 + '@babel/types': 7.23.6 + '@types/babel__core': 7.20.5 + acorn: 8.11.2 + aria-query: 5.3.0 + axobject-query: 4.0.0 + boxen: 7.1.1 + chokidar: 3.5.3 + ci-info: 4.0.0 + clsx: 2.0.0 + common-ancestor-path: 1.0.1 + cookie: 0.6.0 + debug: 4.3.4 + deterministic-object-hash: 2.0.2 + devalue: 4.3.2 + diff: 5.1.0 + dlv: 1.1.3 + dset: 3.1.3 + es-module-lexer: 1.4.1 + esbuild: 0.19.11 + estree-walker: 3.0.3 + execa: 8.0.1 + fast-glob: 3.3.2 + flattie: 1.1.0 + github-slugger: 2.0.0 + gray-matter: 4.0.3 + html-escaper: 3.0.3 + http-cache-semantics: 4.1.1 + js-yaml: 4.1.0 + kleur: 4.1.5 + magic-string: 0.30.5 + mdast-util-to-hast: 13.0.2 + mime: 3.0.0 + ora: 7.0.1 + p-limit: 5.0.0 + p-queue: 8.0.1 + path-to-regexp: 6.2.1 + preferred-pm: 3.1.2 + probe-image-size: 7.2.3 + prompts: 2.4.2 + rehype: 13.0.1 + resolve: 1.22.8 + semver: 7.5.4 + server-destroy: 1.0.1 + shikiji: 0.9.19 + string-width: 7.0.0 + strip-ansi: 7.1.0 + tsconfck: 3.0.0(typescript@5.3.2) + unist-util-visit: 5.0.0 + vfile: 6.0.1 + vite: 5.0.11 + vitefu: 0.2.5(vite@5.0.11) + which-pm: 2.1.1 + yargs-parser: 21.1.1 + zod: 3.22.4 + optionalDependencies: + sharp: 0.32.6 + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + - typescript + dev: false + + /asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: false + + /axobject-query@4.0.0: + resolution: {integrity: sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==} + dependencies: + dequal: 2.0.3 + dev: false + + /b4a@1.6.4: + resolution: {integrity: sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==} + requiresBuild: true + dev: false + optional: true + + /babel-plugin-transform-hook-names@1.0.2(@babel/core@7.23.7): + resolution: {integrity: sha512-5gafyjyyBTTdX/tQQ0hRgu4AhNHG/hqWi0ZZmg2xvs2FgRkJXzDNKBZCyoYqgFkovfDrgM8OoKg8karoUvWeCw==} + peerDependencies: + '@babel/core': ^7.12.10 + dependencies: + '@babel/core': 7.23.7 + dev: false + + /bail@2.0.2: + resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} + dev: false + + /base-64@1.0.0: + resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==} + dev: false + + /base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: false + + /big-integer@1.6.52: + resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} + engines: {node: '>=0.6'} + dev: false + + /binary-extensions@2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + dev: false + + /bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + requiresBuild: true + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: false + optional: true + + /bl@5.1.0: + resolution: {integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==} + dependencies: + buffer: 6.0.3 + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: false + + /boxen@7.1.1: + resolution: {integrity: sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==} + engines: {node: '>=14.16'} + dependencies: + ansi-align: 3.0.1 + camelcase: 7.0.1 + chalk: 5.3.0 + cli-boxes: 3.0.0 + string-width: 5.1.2 + type-fest: 2.19.0 + widest-line: 4.0.1 + wrap-ansi: 8.1.0 + dev: false + + /bplist-parser@0.2.0: + resolution: {integrity: sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==} + engines: {node: '>= 5.10.0'} + dependencies: + big-integer: 1.6.52 + dev: false + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: false + + /browserslist@4.22.1: + resolution: {integrity: sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001564 + electron-to-chromium: 1.4.594 + node-releases: 2.0.13 + update-browserslist-db: 1.0.13(browserslist@4.22.1) + dev: false + + /browserslist@4.22.2: + resolution: {integrity: sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001576 + electron-to-chromium: 1.4.630 + node-releases: 2.0.14 + update-browserslist-db: 1.0.13(browserslist@4.22.2) + dev: false + + /buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + requiresBuild: true + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: false + optional: true + + /buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: false + + /bundle-name@3.0.0: + resolution: {integrity: sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==} + engines: {node: '>=12'} + dependencies: + run-applescript: 5.0.0 + dev: false + + /camelcase@7.0.1: + resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} + engines: {node: '>=14.16'} + dev: false + + /caniuse-lite@1.0.30001564: + resolution: {integrity: sha512-DqAOf+rhof+6GVx1y+xzbFPeOumfQnhYzVnZD6LAXijR77yPtm9mfOcqOnT3mpnJiZVT+kwLAFnRlZcIz+c6bg==} + dev: false + + /caniuse-lite@1.0.30001576: + resolution: {integrity: sha512-ff5BdakGe2P3SQsMsiqmt1Lc8221NR1VzHj5jXN5vBny9A6fpze94HiVV/n7XRosOlsShJcvMv5mdnpjOGCEgg==} + dev: false + + /ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + dev: false + + /chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: false + + /chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: false + + /character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + dev: false + + /character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + dev: false + + /character-entities@2.0.2: + resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + dev: false + + /chokidar@3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + dev: false + + /chownr@1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + requiresBuild: true + dev: false + optional: true + + /ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + dev: false + + /ci-info@4.0.0: + resolution: {integrity: sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==} + engines: {node: '>=8'} + dev: false + + /cli-boxes@3.0.0: + resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} + engines: {node: '>=10'} + dev: false + + /cli-cursor@4.0.0: + resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + restore-cursor: 4.0.0 + dev: false + + /cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + dev: false + + /cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: false + + /clsx@2.0.0: + resolution: {integrity: sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==} + engines: {node: '>=6'} + dev: false + + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: false + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + requiresBuild: true + dependencies: + color-name: 1.1.4 + dev: false + + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: false + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + requiresBuild: true + dev: false + + /color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + requiresBuild: true + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + dev: false + optional: true + + /color@4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + requiresBuild: true + dependencies: + color-convert: 2.0.1 + color-string: 1.9.1 + dev: false + optional: true + + /combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: false + + /comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + dev: false + + /common-ancestor-path@1.0.1: + resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==} + dev: false + + /convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + dev: false + + /cookie@0.6.0: + resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} + engines: {node: '>= 0.6'} + dev: false + + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: false + + /data-uri-to-buffer@4.0.1: + resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} + engines: {node: '>= 12'} + dev: false + + /debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + dev: false + + /debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + dev: false + + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: false + + /decode-named-character-reference@1.0.2: + resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} + dependencies: + character-entities: 2.0.2 + dev: false + + /decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + requiresBuild: true + dependencies: + mimic-response: 3.1.0 + dev: false + optional: true + + /deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + requiresBuild: true + dev: false + optional: true + + /default-browser-id@3.0.0: + resolution: {integrity: sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==} + engines: {node: '>=12'} + dependencies: + bplist-parser: 0.2.0 + untildify: 4.0.0 + dev: false + + /default-browser@4.0.0: + resolution: {integrity: sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==} + engines: {node: '>=14.16'} + dependencies: + bundle-name: 3.0.0 + default-browser-id: 3.0.0 + execa: 7.2.0 + titleize: 3.0.0 + dev: false + + /define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + dev: false + + /delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dev: false + + /depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dev: false + + /dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + dev: false + + /destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dev: false + + /detect-libc@2.0.2: + resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} + engines: {node: '>=8'} + requiresBuild: true + dev: false + + /deterministic-object-hash@2.0.2: + resolution: {integrity: sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ==} + engines: {node: '>=18'} + dependencies: + base-64: 1.0.0 + dev: false + + /devalue@4.3.2: + resolution: {integrity: sha512-KqFl6pOgOW+Y6wJgu80rHpo2/3H07vr8ntR9rkkFIRETewbf5GaYYcakYfiKz89K+sLsuPkQIZaXDMjUObZwWg==} + dev: false + + /devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + dependencies: + dequal: 2.0.3 + dev: false + + /diff@5.1.0: + resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==} + engines: {node: '>=0.3.1'} + dev: false + + /dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + dev: false + + /dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + dev: false + + /domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + dev: false + + /domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + dependencies: + domelementtype: 2.3.0 + dev: false + + /domutils@3.1.0: + resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + dev: false + + /drizzle-orm@0.28.6(@cloudflare/workers-types@4.20231121.0)(@libsql/client@0.4.0-pre.5): + resolution: {integrity: sha512-yBe+F9htrlYER7uXgDJUQsTHFoIrI5yMm5A0bg0GiZ/kY5jNXTWoEy4KQtg35cE27sw1VbgzoMWHAgCckUUUww==} + peerDependencies: + '@aws-sdk/client-rds-data': '>=3' + '@cloudflare/workers-types': '>=3' + '@libsql/client': '*' + '@neondatabase/serverless': '>=0.1' + '@opentelemetry/api': ^1.4.1 + '@planetscale/database': '>=1' + '@types/better-sqlite3': '*' + '@types/pg': '*' + '@types/sql.js': '*' + '@vercel/postgres': '*' + better-sqlite3: '>=7' + bun-types: '*' + knex: '*' + kysely: '*' + mysql2: '>=2' + pg: '>=8' + postgres: '>=3' + sql.js: '>=1' + sqlite3: '>=5' + peerDependenciesMeta: + '@aws-sdk/client-rds-data': + optional: true + '@cloudflare/workers-types': + optional: true + '@libsql/client': + optional: true + '@neondatabase/serverless': + optional: true + '@opentelemetry/api': + optional: true + '@planetscale/database': + optional: true + '@types/better-sqlite3': + optional: true + '@types/pg': + optional: true + '@types/sql.js': + optional: true + '@vercel/postgres': + optional: true + better-sqlite3: + optional: true + bun-types: + optional: true + knex: + optional: true + kysely: + optional: true + mysql2: + optional: true + pg: + optional: true + postgres: + optional: true + sql.js: + optional: true + sqlite3: + optional: true + dependencies: + '@cloudflare/workers-types': 4.20231121.0 + '@libsql/client': 0.4.0-pre.5 + dev: false + + /dset@3.1.3: + resolution: {integrity: sha512-20TuZZHCEZ2O71q9/+8BwKwZ0QtD9D8ObhrihJPr+vLLYlSuAU3/zL4cSlgbfeoGHTjCSJBa7NGcrF9/Bx/WJQ==} + engines: {node: '>=4'} + dev: false + + /eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: false + + /ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + dev: false + + /electron-to-chromium@1.4.594: + resolution: {integrity: sha512-xT1HVAu5xFn7bDfkjGQi9dNpMqGchUkebwf1GL7cZN32NSwwlHRPMSDJ1KN6HkS0bWUtndbSQZqvpQftKG2uFQ==} + dev: false + + /electron-to-chromium@1.4.630: + resolution: {integrity: sha512-osHqhtjojpCsACVnuD11xO5g9xaCyw7Qqn/C2KParkMv42i8jrJJgx3g7mkHfpxwhy9MnOJr8+pKOdZ7qzgizg==} + dev: false + + /emmet@2.4.6: + resolution: {integrity: sha512-dJfbdY/hfeTyf/Ef7Y7ubLYzkBvPQ912wPaeVYpAxvFxkEBf/+hJu4H6vhAvFN6HlxqedlfVn2x1S44FfQ97pg==} + dependencies: + '@emmetio/abbreviation': 2.3.3 + '@emmetio/css-abbreviation': 2.1.8 + dev: false + + /emoji-regex@10.3.0: + resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} + dev: false + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: false + + /emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: false + + /encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + dev: false + + /end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + requiresBuild: true + dependencies: + once: 1.4.0 + dev: false + optional: true + + /entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + dev: false + + /es-module-lexer@1.4.1: + resolution: {integrity: sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==} + dev: false + + /esbuild@0.19.11: + resolution: {integrity: sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/aix-ppc64': 0.19.11 + '@esbuild/android-arm': 0.19.11 + '@esbuild/android-arm64': 0.19.11 + '@esbuild/android-x64': 0.19.11 + '@esbuild/darwin-arm64': 0.19.11 + '@esbuild/darwin-x64': 0.19.11 + '@esbuild/freebsd-arm64': 0.19.11 + '@esbuild/freebsd-x64': 0.19.11 + '@esbuild/linux-arm': 0.19.11 + '@esbuild/linux-arm64': 0.19.11 + '@esbuild/linux-ia32': 0.19.11 + '@esbuild/linux-loong64': 0.19.11 + '@esbuild/linux-mips64el': 0.19.11 + '@esbuild/linux-ppc64': 0.19.11 + '@esbuild/linux-riscv64': 0.19.11 + '@esbuild/linux-s390x': 0.19.11 + '@esbuild/linux-x64': 0.19.11 + '@esbuild/netbsd-x64': 0.19.11 + '@esbuild/openbsd-x64': 0.19.11 + '@esbuild/sunos-x64': 0.19.11 + '@esbuild/win32-arm64': 0.19.11 + '@esbuild/win32-ia32': 0.19.11 + '@esbuild/win32-x64': 0.19.11 + dev: false + + /escalade@3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + dev: false + + /escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + dev: false + + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: false + + /escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + dev: false + + /esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + dev: false + + /estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + dev: false + + /estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + dependencies: + '@types/estree': 1.0.5 + dev: false + + /etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + dev: false + + /eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + dev: false + + /execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + dev: false + + /execa@7.2.0: + resolution: {integrity: sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==} + engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 4.3.1 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.1.0 + onetime: 6.0.0 + signal-exit: 3.0.7 + strip-final-newline: 3.0.0 + dev: false + + /execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.1.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + dev: false + + /expand-template@2.0.3: + resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} + engines: {node: '>=6'} + requiresBuild: true + dev: false + optional: true + + /extend-shallow@2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + dependencies: + is-extendable: 0.1.1 + dev: false + + /extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + dev: false + + /fast-fifo@1.3.2: + resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} + requiresBuild: true + dev: false + optional: true + + /fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: false + + /fastq@1.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + dependencies: + reusify: 1.0.4 + dev: false + + /fetch-blob@3.2.0: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.3.2 + dev: false + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: false + + /find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: false + + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: false + + /find-yarn-workspace-root2@1.2.16: + resolution: {integrity: sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==} + dependencies: + micromatch: 4.0.5 + pkg-dir: 4.2.0 + dev: false + + /flattie@1.1.0: + resolution: {integrity: sha512-xU99gDEnciIwJdGcBmNHnzTJ/w5AT+VFJOu6sTB6WM8diOYNA3Sa+K1DiEBQ7XH4QikQq3iFW1U+jRVcotQnBw==} + engines: {node: '>=8'} + dev: false + + /form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: false + + /formdata-polyfill@4.0.10: + resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} + engines: {node: '>=12.20.0'} + dependencies: + fetch-blob: 3.2.0 + dev: false + + /fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + dev: false + + /fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + requiresBuild: true + dev: false + optional: true + + /fs-extra@11.2.0: + resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} + engines: {node: '>=14.14'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + dev: false + + /fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + dev: false + + /gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + dev: false + + /get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: false + + /get-east-asian-width@1.2.0: + resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} + engines: {node: '>=18'} + dev: false + + /get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: false + + /get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + dev: false + + /github-from-package@0.0.0: + resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} + requiresBuild: true + dev: false + optional: true + + /github-slugger@2.0.0: + resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} + dev: false + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: false + + /globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + dev: false + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: false + + /gray-matter@4.0.3: + resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} + engines: {node: '>=6.0'} + dependencies: + js-yaml: 3.14.1 + kind-of: 6.0.3 + section-matter: 1.0.0 + strip-bom-string: 1.0.0 + dev: false + + /has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: false + + /hasown@2.0.0: + resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + dev: false + + /hast-util-from-html@2.0.1: + resolution: {integrity: sha512-RXQBLMl9kjKVNkJTIO6bZyb2n+cUH8LFaSSzo82jiLT6Tfc+Pt7VQCS+/h3YwG4jaNE2TA2sdJisGWR+aJrp0g==} + dependencies: + '@types/hast': 3.0.3 + devlop: 1.1.0 + hast-util-from-parse5: 8.0.1 + parse5: 7.1.2 + vfile: 6.0.1 + vfile-message: 4.0.2 + dev: false + + /hast-util-from-parse5@8.0.1: + resolution: {integrity: sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==} + dependencies: + '@types/hast': 3.0.3 + '@types/unist': 3.0.2 + devlop: 1.1.0 + hastscript: 8.0.0 + property-information: 6.4.0 + vfile: 6.0.1 + vfile-location: 5.0.2 + web-namespaces: 2.0.1 + dev: false + + /hast-util-parse-selector@4.0.0: + resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==} + dependencies: + '@types/hast': 3.0.3 + dev: false + + /hast-util-raw@9.0.1: + resolution: {integrity: sha512-5m1gmba658Q+lO5uqL5YNGQWeh1MYWZbZmWrM5lncdcuiXuo5E2HT/CIOp0rLF8ksfSwiCVJ3twlgVRyTGThGA==} + dependencies: + '@types/hast': 3.0.3 + '@types/unist': 3.0.2 + '@ungap/structured-clone': 1.2.0 + hast-util-from-parse5: 8.0.1 + hast-util-to-parse5: 8.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.0.2 + parse5: 7.1.2 + unist-util-position: 5.0.0 + unist-util-visit: 5.0.0 + vfile: 6.0.1 + web-namespaces: 2.0.1 + zwitch: 2.0.4 + dev: false + + /hast-util-to-html@9.0.0: + resolution: {integrity: sha512-IVGhNgg7vANuUA2XKrT6sOIIPgaYZnmLx3l/CCOAK0PtgfoHrZwX7jCSYyFxHTrGmC6S9q8aQQekjp4JPZF+cw==} + dependencies: + '@types/hast': 3.0.3 + '@types/unist': 3.0.2 + ccount: 2.0.1 + comma-separated-tokens: 2.0.3 + hast-util-raw: 9.0.1 + hast-util-whitespace: 3.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.0.2 + property-information: 6.4.0 + space-separated-tokens: 2.0.2 + stringify-entities: 4.0.3 + zwitch: 2.0.4 + dev: false + + /hast-util-to-parse5@8.0.0: + resolution: {integrity: sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==} + dependencies: + '@types/hast': 3.0.3 + comma-separated-tokens: 2.0.3 + devlop: 1.1.0 + property-information: 6.4.0 + space-separated-tokens: 2.0.2 + web-namespaces: 2.0.1 + zwitch: 2.0.4 + dev: false + + /hast-util-whitespace@3.0.0: + resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + dependencies: + '@types/hast': 3.0.3 + dev: false + + /hastscript@8.0.0: + resolution: {integrity: sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==} + dependencies: + '@types/hast': 3.0.3 + comma-separated-tokens: 2.0.3 + hast-util-parse-selector: 4.0.0 + property-information: 6.4.0 + space-separated-tokens: 2.0.2 + dev: false + + /html-escaper@3.0.3: + resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==} + dev: false + + /html-void-elements@3.0.0: + resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + dev: false + + /htmlparser2@9.1.0: + resolution: {integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==} + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.1.0 + entities: 4.5.0 + dev: false + + /http-cache-semantics@4.1.1: + resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + dev: false + + /http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + dev: false + + /human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + dev: false + + /human-signals@4.3.1: + resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} + engines: {node: '>=14.18.0'} + dev: false + + /human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + dev: false + + /iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: false + + /ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: false + + /import-meta-resolve@4.0.0: + resolution: {integrity: sha512-okYUR7ZQPH+efeuMJGlq4f8ubUgO50kByRPyt/Cy1Io4PSRsPjxME+YlVaCOx+NIToW7hCsZNFJyTPFFKepRSA==} + dev: false + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: false + + /ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + requiresBuild: true + dev: false + optional: true + + /is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + requiresBuild: true + dev: false + optional: true + + /is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.2.0 + dev: false + + /is-buffer@2.0.5: + resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} + engines: {node: '>=4'} + dev: false + + /is-core-module@2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + dependencies: + hasown: 2.0.0 + dev: false + + /is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + dev: false + + /is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + dev: false + + /is-extendable@0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + dev: false + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: false + + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: false + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: false + + /is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + dependencies: + is-docker: 3.0.0 + dev: false + + /is-interactive@2.0.0: + resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} + engines: {node: '>=12'} + dev: false + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: false + + /is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + dev: false + + /is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + dev: false + + /is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: false + + /is-unicode-supported@1.3.0: + resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} + engines: {node: '>=12'} + dev: false + + /is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + dependencies: + is-docker: 2.2.1 + dev: false + + /is-wsl@3.1.0: + resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} + engines: {node: '>=16'} + dependencies: + is-inside-container: 1.0.0 + dev: false + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: false + + /js-base64@3.7.5: + resolution: {integrity: sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA==} + dev: false + + /js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: false + + /js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + dev: false + + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: false + + /jsesc@2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + dev: false + + /json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + dev: false + + /jsonc-parser@2.3.1: + resolution: {integrity: sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==} + dev: false + + /jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + dev: false + + /just-map-values@3.2.0: + resolution: {integrity: sha512-TyqCKtK3NxiUgOjRYMIKURvBTHesi3XzomDY0QVPZ3rYzLCF+nNq5rSi0B/L5aOd/WMTZo6ukzA4wih4HUbrDg==} + dev: false + + /kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + dev: false + + /kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + dev: false + + /kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + dev: false + + /kolorist@1.8.0: + resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + dev: false + + /libsql@0.2.0-pre.7: + resolution: {integrity: sha512-f2AmB3KvTYfYJUcERjed2RXKrnqZK2KvXkhnrpU+L7SQRtSYZqtChN70Pp0bKHGDkBXWvBLklpcwLpRNtwXStA==} + cpu: [x64, arm64] + os: [darwin, linux, win32] + dependencies: + '@neon-rs/load': 0.0.4 + detect-libc: 2.0.2 + optionalDependencies: + '@libsql/darwin-arm64': 0.2.0-pre.7 + '@libsql/darwin-x64': 0.2.0-pre.7 + '@libsql/linux-arm64-gnu': 0.2.0-pre.7 + '@libsql/linux-arm64-musl': 0.2.0-pre.7 + '@libsql/linux-x64-gnu': 0.2.0-pre.7 + '@libsql/linux-x64-musl': 0.2.0-pre.7 + '@libsql/win32-x64-msvc': 0.2.0-pre.7 + dev: false + + /load-yaml-file@0.2.0: + resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==} + engines: {node: '>=6'} + dependencies: + graceful-fs: 4.2.11 + js-yaml: 3.14.1 + pify: 4.0.1 + strip-bom: 3.0.0 + dev: false + + /locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: false + + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: false + + /lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: false + + /log-symbols@5.1.0: + resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==} + engines: {node: '>=12'} + dependencies: + chalk: 5.3.0 + is-unicode-supported: 1.3.0 + dev: false + + /longest-streak@3.1.0: + resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + dev: false + + /lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + dependencies: + yallist: 3.1.1 + dev: false + + /lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: false + + /magic-string@0.30.5: + resolution: {integrity: sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + dev: false + + /markdown-table@3.0.3: + resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} + dev: false + + /mdast-util-definitions@6.0.0: + resolution: {integrity: sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==} + dependencies: + '@types/mdast': 4.0.3 + '@types/unist': 3.0.2 + unist-util-visit: 5.0.0 + dev: false + + /mdast-util-find-and-replace@3.0.1: + resolution: {integrity: sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==} + dependencies: + '@types/mdast': 4.0.3 + escape-string-regexp: 5.0.0 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 + dev: false + + /mdast-util-from-markdown@2.0.0: + resolution: {integrity: sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==} + dependencies: + '@types/mdast': 4.0.3 + '@types/unist': 3.0.2 + decode-named-character-reference: 1.0.2 + devlop: 1.1.0 + mdast-util-to-string: 4.0.0 + micromark: 4.0.0 + micromark-util-decode-numeric-character-reference: 2.0.1 + micromark-util-decode-string: 2.0.0 + micromark-util-normalize-identifier: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + unist-util-stringify-position: 4.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-gfm-autolink-literal@2.0.0: + resolution: {integrity: sha512-FyzMsduZZHSc3i0Px3PQcBT4WJY/X/RCtEJKuybiC6sjPqLv7h1yqAkmILZtuxMSsUyaLUWNp71+vQH2zqp5cg==} + dependencies: + '@types/mdast': 4.0.3 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-find-and-replace: 3.0.1 + micromark-util-character: 2.0.1 + dev: false + + /mdast-util-gfm-footnote@2.0.0: + resolution: {integrity: sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==} + dependencies: + '@types/mdast': 4.0.3 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + micromark-util-normalize-identifier: 2.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-gfm-strikethrough@2.0.0: + resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==} + dependencies: + '@types/mdast': 4.0.3 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-gfm-table@2.0.0: + resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==} + dependencies: + '@types/mdast': 4.0.3 + devlop: 1.1.0 + markdown-table: 3.0.3 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-gfm-task-list-item@2.0.0: + resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==} + dependencies: + '@types/mdast': 4.0.3 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-gfm@3.0.0: + resolution: {integrity: sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==} + dependencies: + mdast-util-from-markdown: 2.0.0 + mdast-util-gfm-autolink-literal: 2.0.0 + mdast-util-gfm-footnote: 2.0.0 + mdast-util-gfm-strikethrough: 2.0.0 + mdast-util-gfm-table: 2.0.0 + mdast-util-gfm-task-list-item: 2.0.0 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-phrasing@4.0.0: + resolution: {integrity: sha512-xadSsJayQIucJ9n053dfQwVu1kuXg7jCTdYsMK8rqzKZh52nLfSH/k0sAxE0u+pj/zKZX+o5wB+ML5mRayOxFA==} + dependencies: + '@types/mdast': 4.0.3 + unist-util-is: 6.0.0 + dev: false + + /mdast-util-to-hast@13.0.2: + resolution: {integrity: sha512-U5I+500EOOw9e3ZrclN3Is3fRpw8c19SMyNZlZ2IS+7vLsNzb2Om11VpIVOR+/0137GhZsFEF6YiKD5+0Hr2Og==} + dependencies: + '@types/hast': 3.0.3 + '@types/mdast': 4.0.3 + '@ungap/structured-clone': 1.2.0 + devlop: 1.1.0 + micromark-util-sanitize-uri: 2.0.0 + trim-lines: 3.0.1 + unist-util-position: 5.0.0 + unist-util-visit: 5.0.0 + dev: false + + /mdast-util-to-markdown@2.1.0: + resolution: {integrity: sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==} + dependencies: + '@types/mdast': 4.0.3 + '@types/unist': 3.0.2 + longest-streak: 3.1.0 + mdast-util-phrasing: 4.0.0 + mdast-util-to-string: 4.0.0 + micromark-util-decode-string: 2.0.0 + unist-util-visit: 5.0.0 + zwitch: 2.0.4 + dev: false + + /mdast-util-to-string@4.0.0: + resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} + dependencies: + '@types/mdast': 4.0.3 + dev: false + + /merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + dev: false + + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: false + + /micromark-core-commonmark@2.0.0: + resolution: {integrity: sha512-jThOz/pVmAYUtkroV3D5c1osFXAMv9e0ypGDOIZuCeAe91/sD6BoE2Sjzt30yuXtwOYUmySOhMas/PVyh02itA==} + dependencies: + decode-named-character-reference: 1.0.2 + devlop: 1.1.0 + micromark-factory-destination: 2.0.0 + micromark-factory-label: 2.0.0 + micromark-factory-space: 2.0.0 + micromark-factory-title: 2.0.0 + micromark-factory-whitespace: 2.0.0 + micromark-util-character: 2.0.1 + micromark-util-chunked: 2.0.0 + micromark-util-classify-character: 2.0.0 + micromark-util-html-tag-name: 2.0.0 + micromark-util-normalize-identifier: 2.0.0 + micromark-util-resolve-all: 2.0.0 + micromark-util-subtokenize: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-extension-gfm-autolink-literal@2.0.0: + resolution: {integrity: sha512-rTHfnpt/Q7dEAK1Y5ii0W8bhfJlVJFnJMHIPisfPK3gpVNuOP0VnRl96+YJ3RYWV/P4gFeQoGKNlT3RhuvpqAg==} + dependencies: + micromark-util-character: 2.0.1 + micromark-util-sanitize-uri: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-extension-gfm-footnote@2.0.0: + resolution: {integrity: sha512-6Rzu0CYRKDv3BfLAUnZsSlzx3ak6HAoI85KTiijuKIz5UxZxbUI+pD6oHgw+6UtQuiRwnGRhzMmPRv4smcz0fg==} + dependencies: + devlop: 1.1.0 + micromark-core-commonmark: 2.0.0 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.0.1 + micromark-util-normalize-identifier: 2.0.0 + micromark-util-sanitize-uri: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-extension-gfm-strikethrough@2.0.0: + resolution: {integrity: sha512-c3BR1ClMp5fxxmwP6AoOY2fXO9U8uFMKs4ADD66ahLTNcwzSCyRVU4k7LPV5Nxo/VJiR4TdzxRQY2v3qIUceCw==} + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.0 + micromark-util-classify-character: 2.0.0 + micromark-util-resolve-all: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-extension-gfm-table@2.0.0: + resolution: {integrity: sha512-PoHlhypg1ItIucOaHmKE8fbin3vTLpDOUg8KAr8gRCF1MOZI9Nquq2i/44wFvviM4WuxJzc3demT8Y3dkfvYrw==} + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.0.1 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-extension-gfm-tagfilter@2.0.0: + resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==} + dependencies: + micromark-util-types: 2.0.0 + dev: false + + /micromark-extension-gfm-task-list-item@2.0.1: + resolution: {integrity: sha512-cY5PzGcnULaN5O7T+cOzfMoHjBW7j+T9D2sucA5d/KbsBTPcYdebm9zUd9zzdgJGCwahV+/W78Z3nbulBYVbTw==} + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.0.1 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-extension-gfm@3.0.0: + resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==} + dependencies: + micromark-extension-gfm-autolink-literal: 2.0.0 + micromark-extension-gfm-footnote: 2.0.0 + micromark-extension-gfm-strikethrough: 2.0.0 + micromark-extension-gfm-table: 2.0.0 + micromark-extension-gfm-tagfilter: 2.0.0 + micromark-extension-gfm-task-list-item: 2.0.1 + micromark-util-combine-extensions: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-factory-destination@2.0.0: + resolution: {integrity: sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==} + dependencies: + micromark-util-character: 2.0.1 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-factory-label@2.0.0: + resolution: {integrity: sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==} + dependencies: + devlop: 1.1.0 + micromark-util-character: 2.0.1 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-factory-space@2.0.0: + resolution: {integrity: sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==} + dependencies: + micromark-util-character: 2.0.1 + micromark-util-types: 2.0.0 + dev: false + + /micromark-factory-title@2.0.0: + resolution: {integrity: sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==} + dependencies: + micromark-factory-space: 2.0.0 + micromark-util-character: 2.0.1 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-factory-whitespace@2.0.0: + resolution: {integrity: sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==} + dependencies: + micromark-factory-space: 2.0.0 + micromark-util-character: 2.0.1 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-util-character@2.0.1: + resolution: {integrity: sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==} + dependencies: + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-util-chunked@2.0.0: + resolution: {integrity: sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==} + dependencies: + micromark-util-symbol: 2.0.0 + dev: false + + /micromark-util-classify-character@2.0.0: + resolution: {integrity: sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==} + dependencies: + micromark-util-character: 2.0.1 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-util-combine-extensions@2.0.0: + resolution: {integrity: sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==} + dependencies: + micromark-util-chunked: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-util-decode-numeric-character-reference@2.0.1: + resolution: {integrity: sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==} + dependencies: + micromark-util-symbol: 2.0.0 + dev: false + + /micromark-util-decode-string@2.0.0: + resolution: {integrity: sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==} + dependencies: + decode-named-character-reference: 1.0.2 + micromark-util-character: 2.0.1 + micromark-util-decode-numeric-character-reference: 2.0.1 + micromark-util-symbol: 2.0.0 + dev: false + + /micromark-util-encode@2.0.0: + resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==} + dev: false + + /micromark-util-html-tag-name@2.0.0: + resolution: {integrity: sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==} + dev: false + + /micromark-util-normalize-identifier@2.0.0: + resolution: {integrity: sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==} + dependencies: + micromark-util-symbol: 2.0.0 + dev: false + + /micromark-util-resolve-all@2.0.0: + resolution: {integrity: sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==} + dependencies: + micromark-util-types: 2.0.0 + dev: false + + /micromark-util-sanitize-uri@2.0.0: + resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==} + dependencies: + micromark-util-character: 2.0.1 + micromark-util-encode: 2.0.0 + micromark-util-symbol: 2.0.0 + dev: false + + /micromark-util-subtokenize@2.0.0: + resolution: {integrity: sha512-vc93L1t+gpR3p8jxeVdaYlbV2jTYteDje19rNSS/H5dlhxUYll5Fy6vJ2cDwP8RnsXi818yGty1ayP55y3W6fg==} + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-util-symbol@2.0.0: + resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==} + dev: false + + /micromark-util-types@2.0.0: + resolution: {integrity: sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==} + dev: false + + /micromark@4.0.0: + resolution: {integrity: sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==} + dependencies: + '@types/debug': 4.1.12 + debug: 4.3.4 + decode-named-character-reference: 1.0.2 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.0 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.0.1 + micromark-util-chunked: 2.0.0 + micromark-util-combine-extensions: 2.0.0 + micromark-util-decode-numeric-character-reference: 2.0.1 + micromark-util-encode: 2.0.0 + micromark-util-normalize-identifier: 2.0.0 + micromark-util-resolve-all: 2.0.0 + micromark-util-sanitize-uri: 2.0.0 + micromark-util-subtokenize: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: false + + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: false + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: false + + /mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + dev: false + + /mime@3.0.0: + resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} + engines: {node: '>=10.0.0'} + hasBin: true + dev: false + + /mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + dev: false + + /mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + dev: false + + /mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + requiresBuild: true + dev: false + optional: true + + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + requiresBuild: true + dev: false + optional: true + + /mkdirp-classic@0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + requiresBuild: true + dev: false + optional: true + + /ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + dev: false + + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: false + + /ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + dev: false + + /muggle-string@0.3.1: + resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==} + dev: false + + /nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: false + + /nanoid@5.0.4: + resolution: {integrity: sha512-vAjmBf13gsmhXSgBrtIclinISzFFy22WwCYoyilZlsrRXNIHSwgFQ1bEdjRwMT3aoadeIF6HMuDRlOxzfXV8ig==} + engines: {node: ^18 || >=20} + hasBin: true + dev: false + + /napi-build-utils@1.0.2: + resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} + requiresBuild: true + dev: false + optional: true + + /needle@2.9.1: + resolution: {integrity: sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==} + engines: {node: '>= 4.4.x'} + hasBin: true + dependencies: + debug: 3.2.7 + iconv-lite: 0.4.24 + sax: 1.3.0 + transitivePeerDependencies: + - supports-color + dev: false + + /nlcst-to-string@3.1.1: + resolution: {integrity: sha512-63mVyqaqt0cmn2VcI2aH6kxe1rLAmSROqHMA0i4qqg1tidkfExgpb0FGMikMCn86mw5dFtBtEANfmSSK7TjNHw==} + dependencies: + '@types/nlcst': 1.0.4 + dev: false + + /node-abi@3.54.0: + resolution: {integrity: sha512-p7eGEiQil0YUV3ItH4/tBb781L5impVmmx2E9FRKF7d18XXzp4PGT2tdYMFY6wQqgxD0IwNZOiSJ0/K0fSi/OA==} + engines: {node: '>=10'} + requiresBuild: true + dependencies: + semver: 7.5.4 + dev: false + optional: true + + /node-addon-api@6.1.0: + resolution: {integrity: sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==} + requiresBuild: true + dev: false + optional: true + + /node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + dev: false + + /node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + dev: false + + /node-fetch@3.3.2: + resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + data-uri-to-buffer: 4.0.1 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 + dev: false + + /node-releases@2.0.13: + resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==} + dev: false + + /node-releases@2.0.14: + resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + dev: false + + /normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: false + + /npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + dependencies: + path-key: 3.1.1 + dev: false + + /npm-run-path@5.1.0: + resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + path-key: 4.0.0 + dev: false + + /on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + dependencies: + ee-first: 1.1.1 + dev: false + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + requiresBuild: true + dependencies: + wrappy: 1.0.2 + dev: false + optional: true + + /onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + dependencies: + mimic-fn: 2.1.0 + dev: false + + /onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + dependencies: + mimic-fn: 4.0.0 + dev: false + + /open-props@1.6.17: + resolution: {integrity: sha512-6mp/gpLQz/ZwrGLz+i7tSJ3eWNLE1KxLXHO+b6xxRyZ1Alp4TgTcvHiQ89rC2IkvsU3/IRhpIJuxl7rRCwUzLA==} + dev: false + + /open@9.1.0: + resolution: {integrity: sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==} + engines: {node: '>=14.16'} + dependencies: + default-browser: 4.0.0 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + is-wsl: 2.2.0 + dev: false + + /ora@7.0.1: + resolution: {integrity: sha512-0TUxTiFJWv+JnjWm4o9yvuskpEJLXTcng8MJuKd+SzAzp2o+OP3HWqNhB4OdJRt1Vsd9/mR0oyaEYlOnL7XIRw==} + engines: {node: '>=16'} + dependencies: + chalk: 5.3.0 + cli-cursor: 4.0.0 + cli-spinners: 2.9.2 + is-interactive: 2.0.0 + is-unicode-supported: 1.3.0 + log-symbols: 5.1.0 + stdin-discarder: 0.1.0 + string-width: 6.1.0 + strip-ansi: 7.1.0 + dev: false + + /p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: false + + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: false + + /p-limit@5.0.0: + resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} + engines: {node: '>=18'} + dependencies: + yocto-queue: 1.0.0 + dev: false + + /p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: false + + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: false + + /p-queue@8.0.1: + resolution: {integrity: sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==} + engines: {node: '>=18'} + dependencies: + eventemitter3: 5.0.1 + p-timeout: 6.1.2 + dev: false + + /p-timeout@6.1.2: + resolution: {integrity: sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==} + engines: {node: '>=14.16'} + dev: false + + /p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: false + + /parse-latin@5.0.1: + resolution: {integrity: sha512-b/K8ExXaWC9t34kKeDV8kGXBkXZ1HCSAZRYE7HR14eA1GlXX5L8iWhs8USJNhQU9q5ci413jCKF0gOyovvyRBg==} + dependencies: + nlcst-to-string: 3.1.1 + unist-util-modify-children: 3.1.1 + unist-util-visit-children: 2.0.2 + dev: false + + /parse5@7.1.2: + resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + dependencies: + entities: 4.5.0 + dev: false + + /path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + dev: false + + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: false + + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: false + + /path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + dev: false + + /path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: false + + /path-to-regexp@6.2.1: + resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==} + dev: false + + /picocolors@1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: false + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: false + + /pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + dev: false + + /pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + dev: false + + /postcss@8.4.33: + resolution: {integrity: sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: false + + /preact-render-to-string@6.3.1(preact@10.19.2): + resolution: {integrity: sha512-NQ28WrjLtWY6lKDlTxnFpKHZdpjfF+oE6V4tZ0rTrunHrtZp6Dm0oFrcJalt/5PNeqJz4j1DuZDS0Y6rCBoqDA==} + peerDependencies: + preact: '>=10' + dependencies: + preact: 10.19.2 + pretty-format: 3.8.0 + dev: false + + /preact@10.19.2: + resolution: {integrity: sha512-UA9DX/OJwv6YwP9Vn7Ti/vF80XL+YA5H2l7BpCtUr3ya8LWHFzpiO5R+N7dN16ujpIxhekRFuOOF82bXX7K/lg==} + dev: false + + /prebuild-install@7.1.1: + resolution: {integrity: sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==} + engines: {node: '>=10'} + hasBin: true + requiresBuild: true + dependencies: + detect-libc: 2.0.2 + expand-template: 2.0.3 + github-from-package: 0.0.0 + minimist: 1.2.8 + mkdirp-classic: 0.5.3 + napi-build-utils: 1.0.2 + node-abi: 3.54.0 + pump: 3.0.0 + rc: 1.2.8 + simple-get: 4.0.1 + tar-fs: 2.1.1 + tunnel-agent: 0.6.0 + dev: false + optional: true + + /preferred-pm@3.1.2: + resolution: {integrity: sha512-nk7dKrcW8hfCZ4H6klWcdRknBOXWzNQByJ0oJyX97BOupsYD+FzLS4hflgEu/uPUEHZCuRfMxzCBsuWd7OzT8Q==} + engines: {node: '>=10'} + dependencies: + find-up: 5.0.0 + find-yarn-workspace-root2: 1.2.16 + path-exists: 4.0.0 + which-pm: 2.0.0 + dev: false + + /pretty-format@3.8.0: + resolution: {integrity: sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==} + dev: false + + /prismjs@1.29.0: + resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} + engines: {node: '>=6'} + dev: false + + /probe-image-size@7.2.3: + resolution: {integrity: sha512-HubhG4Rb2UH8YtV4ba0Vp5bQ7L78RTONYu/ujmCu5nBI8wGv24s4E9xSKBi0N1MowRpxk76pFCpJtW0KPzOK0w==} + dependencies: + lodash.merge: 4.6.2 + needle: 2.9.1 + stream-parser: 0.3.1 + transitivePeerDependencies: + - supports-color + dev: false + + /prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + dev: false + + /property-information@6.4.0: + resolution: {integrity: sha512-9t5qARVofg2xQqKtytzt+lZ4d1Qvj8t5B8fEwXK6qOfgRLgH/b13QlgEyDh033NOS31nXeFbYv7CLUDG1CeifQ==} + dev: false + + /pump@3.0.0: + resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + requiresBuild: true + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: false + optional: true + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: false + + /queue-tick@1.0.1: + resolution: {integrity: sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==} + requiresBuild: true + dev: false + optional: true + + /range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + dev: false + + /rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + requiresBuild: true + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + dev: false + optional: true + + /readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: false + + /readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: false + + /rehype-parse@9.0.0: + resolution: {integrity: sha512-WG7nfvmWWkCR++KEkZevZb/uw41E8TsH4DsY9UxsTbIXCVGbAs4S+r8FrQ+OtH5EEQAs+5UxKC42VinkmpA1Yw==} + dependencies: + '@types/hast': 3.0.3 + hast-util-from-html: 2.0.1 + unified: 11.0.4 + dev: false + + /rehype-raw@7.0.0: + resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==} + dependencies: + '@types/hast': 3.0.3 + hast-util-raw: 9.0.1 + vfile: 6.0.1 + dev: false + + /rehype-stringify@10.0.0: + resolution: {integrity: sha512-1TX1i048LooI9QoecrXy7nGFFbFSufxVRAfc6Y9YMRAi56l+oB0zP51mLSV312uRuvVLPV1opSlJmslozR1XHQ==} + dependencies: + '@types/hast': 3.0.3 + hast-util-to-html: 9.0.0 + unified: 11.0.4 + dev: false + + /rehype@13.0.1: + resolution: {integrity: sha512-AcSLS2mItY+0fYu9xKxOu1LhUZeBZZBx8//5HKzF+0XP+eP8+6a5MXn2+DW2kfXR6Dtp1FEXMVrjyKAcvcU8vg==} + dependencies: + '@types/hast': 3.0.3 + rehype-parse: 9.0.0 + rehype-stringify: 10.0.0 + unified: 11.0.4 + dev: false + + /remark-gfm@4.0.0: + resolution: {integrity: sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==} + dependencies: + '@types/mdast': 4.0.3 + mdast-util-gfm: 3.0.0 + micromark-extension-gfm: 3.0.0 + remark-parse: 11.0.0 + remark-stringify: 11.0.0 + unified: 11.0.4 + transitivePeerDependencies: + - supports-color + dev: false + + /remark-parse@11.0.0: + resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} + dependencies: + '@types/mdast': 4.0.3 + mdast-util-from-markdown: 2.0.0 + micromark-util-types: 2.0.0 + unified: 11.0.4 + transitivePeerDependencies: + - supports-color + dev: false + + /remark-rehype@11.1.0: + resolution: {integrity: sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==} + dependencies: + '@types/hast': 3.0.3 + '@types/mdast': 4.0.3 + mdast-util-to-hast: 13.0.2 + unified: 11.0.4 + vfile: 6.0.1 + dev: false + + /remark-smartypants@2.0.0: + resolution: {integrity: sha512-Rc0VDmr/yhnMQIz8n2ACYXlfw/P/XZev884QU1I5u+5DgJls32o97Vc1RbK3pfumLsJomS2yy8eT4Fxj/2MDVA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + retext: 8.1.0 + retext-smartypants: 5.2.0 + unist-util-visit: 4.1.2 + dev: false + + /remark-stringify@11.0.0: + resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} + dependencies: + '@types/mdast': 4.0.3 + mdast-util-to-markdown: 2.1.0 + unified: 11.0.4 + dev: false + + /request-light@0.7.0: + resolution: {integrity: sha512-lMbBMrDoxgsyO+yB3sDcrDuX85yYt7sS8BfQd11jtbW/z5ZWgLZRcEGLsLoYw7I0WSUGQBs8CC8ScIxkTX1+6Q==} + dev: false + + /require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: false + + /resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: false + + /restore-cursor@4.0.0: + resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + dev: false + + /retext-latin@3.1.0: + resolution: {integrity: sha512-5MrD1tuebzO8ppsja5eEu+ZbBeUNCjoEarn70tkXOS7Bdsdf6tNahsv2bY0Z8VooFF6cw7/6S+d3yI/TMlMVVQ==} + dependencies: + '@types/nlcst': 1.0.4 + parse-latin: 5.0.1 + unherit: 3.0.1 + unified: 10.1.2 + dev: false + + /retext-smartypants@5.2.0: + resolution: {integrity: sha512-Do8oM+SsjrbzT2UNIKgheP0hgUQTDDQYyZaIY3kfq0pdFzoPk+ZClYJ+OERNXveog4xf1pZL4PfRxNoVL7a/jw==} + dependencies: + '@types/nlcst': 1.0.4 + nlcst-to-string: 3.1.1 + unified: 10.1.2 + unist-util-visit: 4.1.2 + dev: false + + /retext-stringify@3.1.0: + resolution: {integrity: sha512-767TLOaoXFXyOnjx/EggXlb37ZD2u4P1n0GJqVdpipqACsQP+20W+BNpMYrlJkq7hxffnFk+jc6mAK9qrbuB8w==} + dependencies: + '@types/nlcst': 1.0.4 + nlcst-to-string: 3.1.1 + unified: 10.1.2 + dev: false + + /retext@8.1.0: + resolution: {integrity: sha512-N9/Kq7YTn6ZpzfiGW45WfEGJqFf1IM1q8OsRa1CGzIebCJBNCANDRmOrholiDRGKo/We7ofKR4SEvcGAWEMD3Q==} + dependencies: + '@types/nlcst': 1.0.4 + retext-latin: 3.1.0 + retext-stringify: 3.1.0 + unified: 10.1.2 + dev: false + + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: false + + /rollup@4.9.5: + resolution: {integrity: sha512-E4vQW0H/mbNMw2yLSqJyjtkHY9dslf/p0zuT1xehNRqUTBOFMqEjguDvqhXr7N7r/4ttb2jr4T41d3dncmIgbQ==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + dependencies: + '@types/estree': 1.0.5 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.9.5 + '@rollup/rollup-android-arm64': 4.9.5 + '@rollup/rollup-darwin-arm64': 4.9.5 + '@rollup/rollup-darwin-x64': 4.9.5 + '@rollup/rollup-linux-arm-gnueabihf': 4.9.5 + '@rollup/rollup-linux-arm64-gnu': 4.9.5 + '@rollup/rollup-linux-arm64-musl': 4.9.5 + '@rollup/rollup-linux-riscv64-gnu': 4.9.5 + '@rollup/rollup-linux-x64-gnu': 4.9.5 + '@rollup/rollup-linux-x64-musl': 4.9.5 + '@rollup/rollup-win32-arm64-msvc': 4.9.5 + '@rollup/rollup-win32-ia32-msvc': 4.9.5 + '@rollup/rollup-win32-x64-msvc': 4.9.5 + fsevents: 2.3.3 + dev: false + + /run-applescript@5.0.0: + resolution: {integrity: sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==} + engines: {node: '>=12'} + dependencies: + execa: 5.1.1 + dev: false + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: false + + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: false + + /safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: false + + /sax@1.3.0: + resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==} + dev: false + + /section-matter@1.0.0: + resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} + engines: {node: '>=4'} + dependencies: + extend-shallow: 2.0.1 + kind-of: 6.0.3 + dev: false + + /semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + dev: false + + /semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: false + + /send@0.18.0: + resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} + engines: {node: '>= 0.8.0'} + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + dev: false + + /server-destroy@1.0.1: + resolution: {integrity: sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==} + dev: false + + /setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + dev: false + + /sharp@0.32.6: + resolution: {integrity: sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==} + engines: {node: '>=14.15.0'} + requiresBuild: true + dependencies: + color: 4.2.3 + detect-libc: 2.0.2 + node-addon-api: 6.1.0 + prebuild-install: 7.1.1 + semver: 7.5.4 + simple-get: 4.0.1 + tar-fs: 3.0.4 + tunnel-agent: 0.6.0 + dev: false + optional: true + + /sharp@0.33.2: + resolution: {integrity: sha512-WlYOPyyPDiiM07j/UO+E720ju6gtNtHjEGg5vovUk1Lgxyjm2LFO+37Nt/UI3MMh2l6hxTWQWi7qk3cXJTutcQ==} + engines: {libvips: '>=8.15.1', node: ^18.17.0 || ^20.3.0 || >=21.0.0} + requiresBuild: true + dependencies: + color: 4.2.3 + detect-libc: 2.0.2 + semver: 7.5.4 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.33.2 + '@img/sharp-darwin-x64': 0.33.2 + '@img/sharp-libvips-darwin-arm64': 1.0.1 + '@img/sharp-libvips-darwin-x64': 1.0.1 + '@img/sharp-libvips-linux-arm': 1.0.1 + '@img/sharp-libvips-linux-arm64': 1.0.1 + '@img/sharp-libvips-linux-s390x': 1.0.1 + '@img/sharp-libvips-linux-x64': 1.0.1 + '@img/sharp-libvips-linuxmusl-arm64': 1.0.1 + '@img/sharp-libvips-linuxmusl-x64': 1.0.1 + '@img/sharp-linux-arm': 0.33.2 + '@img/sharp-linux-arm64': 0.33.2 + '@img/sharp-linux-s390x': 0.33.2 + '@img/sharp-linux-x64': 0.33.2 + '@img/sharp-linuxmusl-arm64': 0.33.2 + '@img/sharp-linuxmusl-x64': 0.33.2 + '@img/sharp-wasm32': 0.33.2 + '@img/sharp-win32-ia32': 0.33.2 + '@img/sharp-win32-x64': 0.33.2 + dev: false + optional: true + + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: false + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: false + + /shikiji-core@0.9.19: + resolution: {integrity: sha512-AFJu/vcNT21t0e6YrfadZ+9q86gvPum6iywRyt1OtIPjPFe25RQnYJyxHQPMLKCCWA992TPxmEmbNcOZCAJclw==} + dev: false + + /shikiji@0.6.13: + resolution: {integrity: sha512-4T7X39csvhT0p7GDnq9vysWddf2b6BeioiN3Ymhnt3xcy9tXmDcnsEFVxX18Z4YcQgEE/w48dLJ4pPPUcG9KkA==} + dependencies: + hast-util-to-html: 9.0.0 + dev: false + + /shikiji@0.9.19: + resolution: {integrity: sha512-Kw2NHWktdcdypCj1GkKpXH4o6Vxz8B8TykPlPuLHOGSV8VkhoCLcFOH4k19K4LXAQYRQmxg+0X/eM+m2sLhAkg==} + dependencies: + shikiji-core: 0.9.19 + dev: false + + /signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: false + + /signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + dev: false + + /simple-concat@1.0.1: + resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} + requiresBuild: true + dev: false + optional: true + + /simple-get@4.0.1: + resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} + requiresBuild: true + dependencies: + decompress-response: 6.0.0 + once: 1.4.0 + simple-concat: 1.0.1 + dev: false + optional: true + + /simple-stack-form@0.1.10(astro@4.2.0)(zod@3.22.4): + resolution: {integrity: sha512-00eCXPhSbryGunR9N5+jkGLGVVExySwxmAThK/MIedwVCNkbOf16/PFdSha6JgpGhpQxcETr6uOc+Y0zg2GaMg==} + hasBin: true + peerDependencies: + astro: ^3.6.0 || ^4.0.0 + zod: ^3.22.4 + dependencies: + '@clack/prompts': 0.7.0 + astro: 4.2.0(typescript@5.3.2) + fs-extra: 11.2.0 + just-map-values: 3.2.0 + kleur: 4.1.5 + zod: 3.22.4 + dev: false + + /simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + requiresBuild: true + dependencies: + is-arrayish: 0.3.2 + dev: false + optional: true + + /sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + dev: false + + /source-map-js@1.0.2: + resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + engines: {node: '>=0.10.0'} + dev: false + + /space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + dev: false + + /sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: false + + /statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + dev: false + + /stdin-discarder@0.1.0: + resolution: {integrity: sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + bl: 5.1.0 + dev: false + + /stream-parser@0.3.1: + resolution: {integrity: sha512-bJ/HgKq41nlKvlhccD5kaCr/P+Hu0wPNKPJOH7en+YrJu/9EgqUF+88w5Jb6KNcjOFMhfX4B2asfeAtIGuHObQ==} + dependencies: + debug: 2.6.9 + transitivePeerDependencies: + - supports-color + dev: false + + /streamx@2.15.6: + resolution: {integrity: sha512-q+vQL4AAz+FdfT137VF69Cc/APqUbxy+MDOImRrMvchJpigHj9GksgDU2LYbO9rx7RX6osWgxJB2WxhYv4SZAw==} + requiresBuild: true + dependencies: + fast-fifo: 1.3.2 + queue-tick: 1.0.1 + dev: false + optional: true + + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: false + + /string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + dev: false + + /string-width@6.1.0: + resolution: {integrity: sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ==} + engines: {node: '>=16'} + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 10.3.0 + strip-ansi: 7.1.0 + dev: false + + /string-width@7.0.0: + resolution: {integrity: sha512-GPQHj7row82Hjo9hKZieKcHIhaAIKOJvFSIZXuCU9OASVZrMNUaZuz++SPVrBjnLsnk4k+z9f2EIypgxf2vNFw==} + engines: {node: '>=18'} + dependencies: + emoji-regex: 10.3.0 + get-east-asian-width: 1.2.0 + strip-ansi: 7.1.0 + dev: false + + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /stringify-entities@4.0.3: + resolution: {integrity: sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==} + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + dev: false + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: false + + /strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 6.0.1 + dev: false + + /strip-bom-string@1.0.0: + resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} + engines: {node: '>=0.10.0'} + dev: false + + /strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + dev: false + + /strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + dev: false + + /strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + dev: false + + /strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + requiresBuild: true + dev: false + optional: true + + /supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: false + + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: false + + /tar-fs@2.1.1: + resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} + requiresBuild: true + dependencies: + chownr: 1.1.4 + mkdirp-classic: 0.5.3 + pump: 3.0.0 + tar-stream: 2.2.0 + dev: false + optional: true + + /tar-fs@3.0.4: + resolution: {integrity: sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==} + requiresBuild: true + dependencies: + mkdirp-classic: 0.5.3 + pump: 3.0.0 + tar-stream: 3.1.6 + dev: false + optional: true + + /tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + requiresBuild: true + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.4 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + dev: false + optional: true + + /tar-stream@3.1.6: + resolution: {integrity: sha512-B/UyjYwPpMBv+PaFSWAmtYjwdrlEaZQEhMIBFNC5oEG8lpiW8XjcSdmEaClj28ArfKScKHs2nshz3k2le6crsg==} + requiresBuild: true + dependencies: + b4a: 1.6.4 + fast-fifo: 1.3.2 + streamx: 2.15.6 + dev: false + optional: true + + /titleize@3.0.0: + resolution: {integrity: sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==} + engines: {node: '>=12'} + dev: false + + /to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + dev: false + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: false + + /toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + dev: false + + /tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + dev: false + + /trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + dev: false + + /trough@2.1.0: + resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==} + dev: false + + /tsconfck@3.0.0(typescript@5.3.2): + resolution: {integrity: sha512-w3wnsIrJNi7avf4Zb0VjOoodoO0woEqGgZGQm+LHH9przdUI+XDKsWAXwxHA1DaRTjeuZNcregSzr7RaA8zG9A==} + engines: {node: ^18 || >=20} + hasBin: true + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + dependencies: + typescript: 5.3.2 + dev: false + + /tslib@2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + requiresBuild: true + dev: false + optional: true + + /tunnel-agent@0.6.0: + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + requiresBuild: true + dependencies: + safe-buffer: 5.2.1 + dev: false + optional: true + + /type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + dev: false + + /typesafe-path@0.2.2: + resolution: {integrity: sha512-OJabfkAg1WLZSqJAJ0Z6Sdt3utnbzr/jh+NAHoyWHJe8CMSy79Gm085094M9nvTPy22KzTVn5Zq5mbapCI/hPA==} + dev: false + + /typescript-auto-import-cache@0.3.0: + resolution: {integrity: sha512-Rq6/q4O9iyqUdjvOoyas7x/Qf9nWUMeqpP3YeTaLA+uECgfy5wOhfOS+SW/+fZ/uI/ZcKaf+2/ZhFzXh8xfofQ==} + dependencies: + semver: 7.5.4 + dev: false + + /typescript@5.3.2: + resolution: {integrity: sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==} + engines: {node: '>=14.17'} + hasBin: true + dev: false + + /undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + dev: false + + /unherit@3.0.1: + resolution: {integrity: sha512-akOOQ/Yln8a2sgcLj4U0Jmx0R5jpIg2IUyRrWOzmEbjBtGzBdHtSeFKgoEcoH4KYIG/Pb8GQ/BwtYm0GCq1Sqg==} + dev: false + + /unified@10.1.2: + resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==} + dependencies: + '@types/unist': 2.0.10 + bail: 2.0.2 + extend: 3.0.2 + is-buffer: 2.0.5 + is-plain-obj: 4.1.0 + trough: 2.1.0 + vfile: 5.3.7 + dev: false + + /unified@11.0.4: + resolution: {integrity: sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==} + dependencies: + '@types/unist': 3.0.2 + bail: 2.0.2 + devlop: 1.1.0 + extend: 3.0.2 + is-plain-obj: 4.1.0 + trough: 2.1.0 + vfile: 6.0.1 + dev: false + + /unist-util-is@5.2.1: + resolution: {integrity: sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==} + dependencies: + '@types/unist': 2.0.10 + dev: false + + /unist-util-is@6.0.0: + resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} + dependencies: + '@types/unist': 3.0.2 + dev: false + + /unist-util-modify-children@3.1.1: + resolution: {integrity: sha512-yXi4Lm+TG5VG+qvokP6tpnk+r1EPwyYL04JWDxLvgvPV40jANh7nm3udk65OOWquvbMDe+PL9+LmkxDpTv/7BA==} + dependencies: + '@types/unist': 2.0.10 + array-iterate: 2.0.1 + dev: false + + /unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + dependencies: + '@types/unist': 3.0.2 + dev: false + + /unist-util-stringify-position@3.0.3: + resolution: {integrity: sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==} + dependencies: + '@types/unist': 2.0.10 + dev: false + + /unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + dependencies: + '@types/unist': 3.0.2 + dev: false + + /unist-util-visit-children@2.0.2: + resolution: {integrity: sha512-+LWpMFqyUwLGpsQxpumsQ9o9DG2VGLFrpz+rpVXYIEdPy57GSy5HioC0g3bg/8WP9oCLlapQtklOzQ8uLS496Q==} + dependencies: + '@types/unist': 2.0.10 + dev: false + + /unist-util-visit-parents@5.1.3: + resolution: {integrity: sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==} + dependencies: + '@types/unist': 2.0.10 + unist-util-is: 5.2.1 + dev: false + + /unist-util-visit-parents@6.0.1: + resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==} + dependencies: + '@types/unist': 3.0.2 + unist-util-is: 6.0.0 + dev: false + + /unist-util-visit@4.1.2: + resolution: {integrity: sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==} + dependencies: + '@types/unist': 2.0.10 + unist-util-is: 5.2.1 + unist-util-visit-parents: 5.1.3 + dev: false + + /unist-util-visit@5.0.0: + resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} + dependencies: + '@types/unist': 3.0.2 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 + dev: false + + /universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + dev: false + + /untildify@4.0.0: + resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} + engines: {node: '>=8'} + dev: false + + /update-browserslist-db@1.0.13(browserslist@4.22.1): + resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.22.1 + escalade: 3.1.1 + picocolors: 1.0.0 + dev: false + + /update-browserslist-db@1.0.13(browserslist@4.22.2): + resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.22.2 + escalade: 3.1.1 + picocolors: 1.0.0 + dev: false + + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: false + + /vfile-location@5.0.2: + resolution: {integrity: sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==} + dependencies: + '@types/unist': 3.0.2 + vfile: 6.0.1 + dev: false + + /vfile-message@3.1.4: + resolution: {integrity: sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==} + dependencies: + '@types/unist': 2.0.10 + unist-util-stringify-position: 3.0.3 + dev: false + + /vfile-message@4.0.2: + resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} + dependencies: + '@types/unist': 3.0.2 + unist-util-stringify-position: 4.0.0 + dev: false + + /vfile@5.3.7: + resolution: {integrity: sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==} + dependencies: + '@types/unist': 2.0.10 + is-buffer: 2.0.5 + unist-util-stringify-position: 3.0.3 + vfile-message: 3.1.4 + dev: false + + /vfile@6.0.1: + resolution: {integrity: sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==} + dependencies: + '@types/unist': 3.0.2 + unist-util-stringify-position: 4.0.0 + vfile-message: 4.0.2 + dev: false + + /vite@5.0.11: + resolution: {integrity: sha512-XBMnDjZcNAw/G1gEiskiM1v6yzM4GE5aMGvhWTlHAYYhxb7S3/V1s3m2LDHa8Vh6yIWYYB0iJwsEaS523c4oYA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + esbuild: 0.19.11 + postcss: 8.4.33 + rollup: 4.9.5 + optionalDependencies: + fsevents: 2.3.3 + dev: false + + /vitefu@0.2.5(vite@5.0.11): + resolution: {integrity: sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 + peerDependenciesMeta: + vite: + optional: true + dependencies: + vite: 5.0.11 + dev: false + + /volar-service-css@0.0.16(@volar/language-service@1.10.10): + resolution: {integrity: sha512-gK/XD35t/P3SQrUuS8LMlCnE2ItIk+kXI6gPvBYl1NZ7O+tLH8rUWXA32YgpwNoITxYrm/G1seaq08zs4aiPvg==} + peerDependencies: + '@volar/language-service': ~1.10.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + dependencies: + '@volar/language-service': 1.10.10 + vscode-css-languageservice: 6.2.10 + vscode-uri: 3.0.8 + dev: false + + /volar-service-emmet@0.0.16(@volar/language-service@1.10.10): + resolution: {integrity: sha512-8sWWywzVJOD+PWDArOXDWbiRlM7+peydFhXJT71i4X1WPW32RyPxn6FypvciO+amqpfZP2rXfB9eibIJ+EofSQ==} + peerDependencies: + '@volar/language-service': ~1.10.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + dependencies: + '@volar/language-service': 1.10.10 + '@vscode/emmet-helper': 2.9.2 + volar-service-html: 0.0.16(@volar/language-service@1.10.10) + dev: false + + /volar-service-html@0.0.16(@volar/language-service@1.10.10): + resolution: {integrity: sha512-/oEXXgry++1CnTXQBUNf9B8MZfTlYZuJfZA7Zx9MN7WS4ZPxk3BFOdal/cXH6RNR2ruNEYr5QTW9rsqtoUscag==} + peerDependencies: + '@volar/language-service': ~1.10.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + dependencies: + '@volar/language-service': 1.10.10 + vscode-html-languageservice: 5.1.1 + vscode-uri: 3.0.8 + dev: false + + /volar-service-prettier@0.0.16(@volar/language-service@1.10.10): + resolution: {integrity: sha512-Kj2ZdwJGEvfYbsHW8Sjrew/7EB4PgRoas4f8yAJzUUVxIC/kvhUwLDxQc8+N2IibomN76asJGWe+i6VZZvgIkw==} + peerDependencies: + '@volar/language-service': ~1.10.0 + prettier: ^2.2 || ^3.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + prettier: + optional: true + dependencies: + '@volar/language-service': 1.10.10 + dev: false + + /volar-service-typescript-twoslash-queries@0.0.16(@volar/language-service@1.10.10): + resolution: {integrity: sha512-0gPrkDTD2bMj2AnSNykOKhfmPnBFE2LS1lF3LWA7qu1ChRnJF0sodwCCbbeNYJ9+yth956ApoU1BVQ8UrMg+yw==} + peerDependencies: + '@volar/language-service': ~1.10.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + dependencies: + '@volar/language-service': 1.10.10 + dev: false + + /volar-service-typescript@0.0.16(@volar/language-service@1.10.10)(@volar/typescript@1.10.10): + resolution: {integrity: sha512-k/qFKM2oxs/3fhbr/vcBSHnCLZ1HN3Aeh+bGvV9Lc9qIhrNyCVsDFOUJN1Qp4dI72+Y+eFSIDCLHmFEZdsP2EA==} + peerDependencies: + '@volar/language-service': ~1.10.0 + '@volar/typescript': ~1.10.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + dependencies: + '@volar/language-service': 1.10.10 + '@volar/typescript': 1.10.10 + path-browserify: 1.0.1 + semver: 7.5.4 + typescript-auto-import-cache: 0.3.0 + vscode-languageserver-textdocument: 1.0.11 + vscode-nls: 5.2.0 + vscode-uri: 3.0.8 + dev: false + + /vscode-css-languageservice@6.2.10: + resolution: {integrity: sha512-sYUZPku4mQ06AWGCbMyjv2tdR6juBW6hTbVPFwbJvNVzdtEfBioQOgkdXg7yMJNWnXkvWSU1FL2kb4Vxu5Cdyw==} + dependencies: + '@vscode/l10n': 0.0.16 + vscode-languageserver-textdocument: 1.0.11 + vscode-languageserver-types: 3.17.5 + vscode-uri: 3.0.8 + dev: false + + /vscode-html-languageservice@5.1.1: + resolution: {integrity: sha512-JenrspIIG/Q+93R6G3L6HdK96itSisMynE0glURqHpQbL3dKAKzdm8L40lAHNkwJeBg+BBPpAshZKv/38onrTQ==} + dependencies: + '@vscode/l10n': 0.0.16 + vscode-languageserver-textdocument: 1.0.11 + vscode-languageserver-types: 3.17.5 + vscode-uri: 3.0.8 + dev: false + + /vscode-jsonrpc@8.2.0: + resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==} + engines: {node: '>=14.0.0'} + dev: false + + /vscode-languageserver-protocol@3.17.5: + resolution: {integrity: sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==} + dependencies: + vscode-jsonrpc: 8.2.0 + vscode-languageserver-types: 3.17.5 + dev: false + + /vscode-languageserver-textdocument@1.0.11: + resolution: {integrity: sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==} + dev: false + + /vscode-languageserver-types@3.17.5: + resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==} + dev: false + + /vscode-languageserver@9.0.1: + resolution: {integrity: sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==} + hasBin: true + dependencies: + vscode-languageserver-protocol: 3.17.5 + dev: false + + /vscode-nls@5.2.0: + resolution: {integrity: sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==} + dev: false + + /vscode-uri@2.1.2: + resolution: {integrity: sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==} + dev: false + + /vscode-uri@3.0.8: + resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==} + dev: false + + /web-namespaces@2.0.1: + resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} + dev: false + + /web-streams-polyfill@3.3.2: + resolution: {integrity: sha512-3pRGuxRF5gpuZc0W+EpwQRmCD7gRqcDOMt688KmdlDAgAyaB1XlN0zq2njfDNm44XVdIouE7pZ6GzbdyH47uIQ==} + engines: {node: '>= 8'} + dev: false + + /webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + dev: false + + /whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + dev: false + + /which-pm-runs@1.1.0: + resolution: {integrity: sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==} + engines: {node: '>=4'} + dev: false + + /which-pm@2.0.0: + resolution: {integrity: sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==} + engines: {node: '>=8.15'} + dependencies: + load-yaml-file: 0.2.0 + path-exists: 4.0.0 + dev: false + + /which-pm@2.1.1: + resolution: {integrity: sha512-xzzxNw2wMaoCWXiGE8IJ9wuPMU+EYhFksjHxrRT8kMT5SnocBPRg69YAMtyV4D12fP582RA+k3P8H9J5EMdIxQ==} + engines: {node: '>=8.15'} + dependencies: + load-yaml-file: 0.2.0 + path-exists: 4.0.0 + dev: false + + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: false + + /widest-line@4.0.1: + resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==} + engines: {node: '>=12'} + dependencies: + string-width: 5.1.2 + dev: false + + /wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: false + + /wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + dev: false + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + requiresBuild: true + dev: false + optional: true + + /ws@8.14.2: + resolution: {integrity: sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + + /y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + dev: false + + /yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + dev: false + + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: false + + /yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + dev: false + + /yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + dependencies: + cliui: 8.0.1 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + dev: false + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: false + + /yocto-queue@1.0.0: + resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} + engines: {node: '>=12.20'} + dev: false + + /zod@3.22.4: + resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} + dev: false + + /zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + dev: false + + file:astrojs-db-0.1.3.tgz(@cloudflare/workers-types@4.20231121.0)(typescript@5.3.2): + resolution: {integrity: sha512-gXz7mpmgZP7d7MUbmVrAYFha/SMixah/E12d0SjHvrLRDT0Z6AUUHhYtXTfoyAOcl5ZRGVnbTUiTKxJGr5pRGw==, tarball: file:astrojs-db-0.1.3.tgz} + id: file:astrojs-db-0.1.3.tgz + name: '@astrojs/db' + version: 0.1.3 + hasBin: true + dependencies: + '@astrojs/markdoc': 0.8.2(astro@4.1.1) + '@libsql/client': 0.4.0-pre.5 + '@types/yargs-parser': 21.0.3 + astro: 4.1.1(typescript@5.3.2) + drizzle-orm: 0.28.6(@cloudflare/workers-types@4.20231121.0)(@libsql/client@0.4.0-pre.5) + esbuild: 0.19.11 + github-slugger: 2.0.0 + kleur: 4.1.5 + nanoid: 5.0.4 + open: 9.1.0 + prompts: 2.4.2 + yargs-parser: 21.1.1 + zod: 3.22.4 + transitivePeerDependencies: + - '@aws-sdk/client-rds-data' + - '@cloudflare/workers-types' + - '@neondatabase/serverless' + - '@opentelemetry/api' + - '@planetscale/database' + - '@types/better-sqlite3' + - '@types/node' + - '@types/pg' + - '@types/react' + - '@types/sql.js' + - '@vercel/postgres' + - better-sqlite3 + - bufferutil + - bun-types + - encoding + - knex + - kysely + - less + - lightningcss + - mysql2 + - pg + - postgres + - react + - sass + - sql.js + - sqlite3 + - stylus + - sugarss + - supports-color + - terser + - typescript + - utf-8-validate + dev: false diff --git a/packages/db/test/fixtures/ticketing-example/public/favicon.svg b/packages/db/test/fixtures/ticketing-example/public/favicon.svg new file mode 100644 index 0000000000..f157bd1c5e --- /dev/null +++ b/packages/db/test/fixtures/ticketing-example/public/favicon.svg @@ -0,0 +1,9 @@ + + + + diff --git a/packages/db/test/fixtures/ticketing-example/src/components/Form.tsx b/packages/db/test/fixtures/ticketing-example/src/components/Form.tsx new file mode 100644 index 0000000000..a4f69c5585 --- /dev/null +++ b/packages/db/test/fixtures/ticketing-example/src/components/Form.tsx @@ -0,0 +1,119 @@ +// Generated by simple:form + +import { type ComponentProps, createContext, useContext, useState } from 'react'; +import { navigate } from 'astro:transitions/client'; +import { + type FieldErrors, + type FormState, + type FormValidator, + formNameInputProps, + getInitialFormState, + toSetValidationErrors, + toTrackAstroSubmitStatus, + toValidateField, + validateForm, +} from 'simple:form'; + +export function useCreateFormContext(validator: FormValidator, fieldErrors?: FieldErrors) { + const initial = getInitialFormState({ validator, fieldErrors }); + const [formState, setFormState] = useState(initial); + return { + value: formState, + set: setFormState, + setValidationErrors: toSetValidationErrors(setFormState), + validateField: toValidateField(setFormState), + trackAstroSubmitStatus: toTrackAstroSubmitStatus(setFormState), + }; +} + +export function useFormContext() { + const formContext = useContext(FormContext); + if (!formContext) { + throw new Error( + 'Form context not found. `useFormContext()` should only be called from children of a
component.' + ); + } + return formContext; +} + +type FormContextType = ReturnType; + +const FormContext = createContext(undefined); + +export function Form({ + children, + validator, + context, + fieldErrors, + name, + ...formProps +}: { + validator: FormValidator; + context?: FormContextType; + fieldErrors?: FieldErrors; +} & Omit, 'method' | 'onSubmit'>) { + const formContext = context ?? useCreateFormContext(validator, fieldErrors); + + return ( + + { + e.preventDefault(); + e.stopPropagation(); + const formData = new FormData(e.currentTarget); + formContext.set((formState) => ({ + ...formState, + isSubmitPending: true, + submitStatus: 'validating', + })); + const parsed = await validateForm({ formData, validator }); + if (parsed.data) { + navigate(formProps.action ?? '', { formData }); + return formContext.trackAstroSubmitStatus(); + } + + formContext.setValidationErrors(parsed.fieldErrors); + }} + > + {name ? : null} + {children} + + + ); +} + +export function Input(inputProps: ComponentProps<'input'> & { name: string }) { + const formContext = useFormContext(); + const fieldState = formContext.value.fields[inputProps.name]; + if (!fieldState) { + throw new Error( + `Input "${inputProps.name}" not found in form. Did you use the
component?` + ); + } + + const { hasErroredOnce, validationErrors, validator } = fieldState; + return ( + <> + { + const value = e.target.value; + if (value === '') return; + formContext.validateField(inputProps.name, value, validator); + }} + onChange={async (e) => { + if (!hasErroredOnce) return; + const value = e.target.value; + formContext.validateField(inputProps.name, value, validator); + }} + {...inputProps} + /> + {validationErrors?.map((e) => ( +

+ {e} +

+ ))} + + ); +} diff --git a/packages/db/test/fixtures/ticketing-example/src/layouts/Layout.astro b/packages/db/test/fixtures/ticketing-example/src/layouts/Layout.astro new file mode 100644 index 0000000000..114216824d --- /dev/null +++ b/packages/db/test/fixtures/ticketing-example/src/layouts/Layout.astro @@ -0,0 +1,80 @@ +--- +import { ViewTransitions } from 'astro:transitions'; +import 'open-props/normalize'; +import 'open-props/style'; + +interface Props { + title: string; +} + +const { title } = Astro.props; +--- + + + + + + + + + + {title} + + + + + + + diff --git a/packages/db/test/fixtures/ticketing-example/src/pages/[event]/_Ticket.tsx b/packages/db/test/fixtures/ticketing-example/src/pages/[event]/_Ticket.tsx new file mode 100644 index 0000000000..bb244122bd --- /dev/null +++ b/packages/db/test/fixtures/ticketing-example/src/pages/[event]/_Ticket.tsx @@ -0,0 +1,40 @@ +import { useState } from 'react'; +import { z } from 'zod'; +import { Form, Input } from '../../components/Form'; +import { createForm } from 'simple:form'; + +export const ticketForm = createForm({ + email: z.string().email(), + quantity: z.number().max(10), + newsletter: z.boolean(), +}); + +export function TicketForm({ price }: { price: number }) { + const [quantity, setQuantity] = useState(1); + return ( + <> + +

${(quantity * price) / 100}

+ + + { + const value = Number(e.currentTarget.value); + setQuantity(value); + }} + /> + + + + +
+ + +
+ + + + ); +} diff --git a/packages/db/test/fixtures/ticketing-example/src/pages/[event]/index.astro b/packages/db/test/fixtures/ticketing-example/src/pages/[event]/index.astro new file mode 100644 index 0000000000..7c1c4e320c --- /dev/null +++ b/packages/db/test/fixtures/ticketing-example/src/pages/[event]/index.astro @@ -0,0 +1,50 @@ +--- +import { Event, Ticket, db, eq } from 'astro:db'; +import Layout from '../../layouts/Layout.astro'; +import { TicketForm, ticketForm } from './_Ticket'; + +const eventId = Number(Astro.params.event); + +if (isNaN(eventId)) return Astro.redirect('/'); + +const event = await db.select().from(Event).where(eq(Event.id, eventId)).get(); + +if (!event) return Astro.redirect('/'); + +const res = await Astro.locals.form.getData(ticketForm); + +if (res?.data) { + await db.insert(Ticket).values({ + eventId, + email: res.data.email, + quantity: res.data.quantity, + newsletter: res.data.newsletter, + }); +} + +const ticket = await db.select().from(Ticket).where(eq(Ticket.eventId, eventId)).get(); +--- + + +
+

{event.name}

+

+ {event.description} +

+ + + { + ticket && ( +
+

You're going 🙌

+

+ You have purchased {ticket.quantity} tickets for {event.name}! +

+

+ Check {ticket.email} for your tickets. +

+
+ ) + } +
+
diff --git a/packages/db/test/fixtures/ticketing-example/src/pages/index.astro b/packages/db/test/fixtures/ticketing-example/src/pages/index.astro new file mode 100644 index 0000000000..c8bbcbc701 --- /dev/null +++ b/packages/db/test/fixtures/ticketing-example/src/pages/index.astro @@ -0,0 +1,17 @@ +--- +import { Event, db } from 'astro:db'; + +const firstEvent = await db.select().from(Event).get(); +--- + + + + + + + Eventbrite + + + + + diff --git a/packages/db/test/fixtures/ticketing-example/tsconfig.json b/packages/db/test/fixtures/ticketing-example/tsconfig.json new file mode 100644 index 0000000000..b7243b92cc --- /dev/null +++ b/packages/db/test/fixtures/ticketing-example/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "astro/tsconfigs/strict", + "compilerOptions": { + "jsx": "react-jsx", + "jsxImportSource": "react" + } +} diff --git a/packages/db/test/unit/field-queries.test.js b/packages/db/test/unit/field-queries.test.js new file mode 100644 index 0000000000..dc7945f8c8 --- /dev/null +++ b/packages/db/test/unit/field-queries.test.js @@ -0,0 +1,449 @@ +import { expect } from 'chai'; +import { describe, it } from 'mocha'; +import { + getCollectionChangeQueries, + getMigrationQueries, +} from '../../dist/core/cli/migration-queries.js'; +import { getCreateTableQuery } from '../../dist/core/queries.js'; +import { collectionSchema, column, defineReadableTable } from '../../dist/core/types.js'; +import { NOW } from '../../dist/runtime/index.js'; + +const COLLECTION_NAME = 'Users'; + +// `parse` to resolve schema transformations +// ex. convert column.date() to ISO strings +const userInitial = collectionSchema.parse( + defineReadableTable({ + columns: { + name: column.text(), + age: column.number(), + email: column.text({ unique: true }), + mi: column.text({ optional: true }), + }, + }) +); + +const defaultAmbiguityResponses = { + collectionRenames: {}, + columnRenames: {}, +}; + +function userChangeQueries( + oldCollection, + newCollection, + ambiguityResponses = defaultAmbiguityResponses +) { + return getCollectionChangeQueries({ + collectionName: COLLECTION_NAME, + oldCollection, + newCollection, + ambiguityResponses, + }); +} + +function configChangeQueries( + oldCollections, + newCollections, + ambiguityResponses = defaultAmbiguityResponses +) { + return getMigrationQueries({ + oldSnapshot: { schema: oldCollections, experimentalVersion: 1 }, + newSnapshot: { schema: newCollections, experimentalVersion: 1 }, + ambiguityResponses, + }); +} + +describe('column queries', () => { + describe('getMigrationQueries', () => { + it('should be empty when tables are the same', async () => { + const oldCollections = { [COLLECTION_NAME]: userInitial }; + const newCollections = { [COLLECTION_NAME]: userInitial }; + const { queries } = await configChangeQueries(oldCollections, newCollections); + expect(queries).to.deep.equal([]); + }); + + it('should create table for new tables', async () => { + const oldCollections = {}; + const newCollections = { [COLLECTION_NAME]: userInitial }; + const { queries } = await configChangeQueries(oldCollections, newCollections); + expect(queries).to.deep.equal([getCreateTableQuery(COLLECTION_NAME, userInitial)]); + }); + + it('should drop table for removed tables', async () => { + const oldCollections = { [COLLECTION_NAME]: userInitial }; + const newCollections = {}; + const { queries } = await configChangeQueries(oldCollections, newCollections); + expect(queries).to.deep.equal([`DROP TABLE "${COLLECTION_NAME}"`]); + }); + + it('should rename table for renamed tables', async () => { + const rename = 'Peeps'; + const oldCollections = { [COLLECTION_NAME]: userInitial }; + const newCollections = { [rename]: userInitial }; + const { queries } = await configChangeQueries(oldCollections, newCollections, { + ...defaultAmbiguityResponses, + collectionRenames: { [rename]: COLLECTION_NAME }, + }); + expect(queries).to.deep.equal([`ALTER TABLE "${COLLECTION_NAME}" RENAME TO "${rename}"`]); + }); + }); + + describe('getCollectionChangeQueries', () => { + it('should be empty when tables are the same', async () => { + const { queries } = await userChangeQueries(userInitial, userInitial); + expect(queries).to.deep.equal([]); + }); + + it('should be empty when type updated to same underlying SQL type', async () => { + const blogInitial = collectionSchema.parse({ + ...userInitial, + columns: { + title: column.text(), + draft: column.boolean(), + }, + }); + const blogFinal = collectionSchema.parse({ + ...userInitial, + columns: { + ...blogInitial.columns, + draft: column.number(), + }, + }); + const { queries } = await userChangeQueries(blogInitial, blogFinal); + expect(queries).to.deep.equal([]); + }); + + it('should respect user primary key without adding a hidden id', async () => { + const user = collectionSchema.parse({ + ...userInitial, + columns: { + ...userInitial.columns, + id: column.number({ primaryKey: true }), + }, + }); + + const userFinal = collectionSchema.parse({ + ...user, + columns: { + ...user.columns, + name: column.text({ unique: true, optional: true }), + }, + }); + + const { queries } = await userChangeQueries(user, userFinal); + expect(queries[0]).to.not.be.undefined; + const tempTableName = getTempTableName(queries[0]); + + expect(queries).to.deep.equal([ + `CREATE TABLE \"${tempTableName}\" (\"name\" text UNIQUE, \"age\" integer NOT NULL, \"email\" text NOT NULL UNIQUE, \"mi\" text, \"id\" integer PRIMARY KEY)`, + `INSERT INTO \"${tempTableName}\" (\"name\", \"age\", \"email\", \"mi\", \"id\") SELECT \"name\", \"age\", \"email\", \"mi\", \"id\" FROM \"Users\"`, + 'DROP TABLE "Users"', + `ALTER TABLE "${tempTableName}" RENAME TO "Users"`, + ]); + }); + + describe('ALTER RENAME COLUMN', () => { + it('when renaming a column', async () => { + const userFinal = { + ...userInitial, + columns: { + ...userInitial.columns, + }, + }; + userFinal.columns.middleInitial = userFinal.columns.mi; + delete userFinal.columns.mi; + + const { queries } = await userChangeQueries(userInitial, userFinal, { + collectionRenames: {}, + columnRenames: { [COLLECTION_NAME]: { middleInitial: 'mi' } }, + }); + expect(queries).to.deep.equal([ + `ALTER TABLE "${COLLECTION_NAME}" RENAME COLUMN "mi" TO "middleInitial"`, + ]); + }); + }); + + describe('Lossy table recreate', () => { + it('when changing a column type', async () => { + const userFinal = { + ...userInitial, + columns: { + ...userInitial.columns, + age: column.text(), + }, + }; + + const { queries } = await userChangeQueries(userInitial, userFinal); + + expect(queries).to.deep.equal([ + 'DROP TABLE "Users"', + `CREATE TABLE "Users" (_id INTEGER PRIMARY KEY, "name" text NOT NULL, "age" text NOT NULL, "email" text NOT NULL UNIQUE, "mi" text)`, + ]); + }); + + it('when adding a required column without a default', async () => { + const userFinal = { + ...userInitial, + columns: { + ...userInitial.columns, + phoneNumber: column.text(), + }, + }; + + const { queries } = await userChangeQueries(userInitial, userFinal); + + expect(queries).to.deep.equal([ + 'DROP TABLE "Users"', + `CREATE TABLE "Users" (_id INTEGER PRIMARY KEY, "name" text NOT NULL, "age" integer NOT NULL, "email" text NOT NULL UNIQUE, "mi" text, "phoneNumber" text NOT NULL)`, + ]); + }); + }); + + describe('Lossless table recreate', () => { + it('when adding a primary key', async () => { + const userFinal = { + ...userInitial, + columns: { + ...userInitial.columns, + id: column.number({ primaryKey: true }), + }, + }; + + const { queries } = await userChangeQueries(userInitial, userFinal); + expect(queries[0]).to.not.be.undefined; + + const tempTableName = getTempTableName(queries[0]); + expect(queries).to.deep.equal([ + `CREATE TABLE \"${tempTableName}\" (\"name\" text NOT NULL, \"age\" integer NOT NULL, \"email\" text NOT NULL UNIQUE, \"mi\" text, \"id\" integer PRIMARY KEY)`, + `INSERT INTO \"${tempTableName}\" (\"name\", \"age\", \"email\", \"mi\") SELECT \"name\", \"age\", \"email\", \"mi\" FROM \"Users\"`, + 'DROP TABLE "Users"', + `ALTER TABLE "${tempTableName}" RENAME TO "Users"`, + ]); + }); + + it('when dropping a primary key', async () => { + const user = { + ...userInitial, + columns: { + ...userInitial.columns, + id: column.number({ primaryKey: true }), + }, + }; + + const { queries } = await userChangeQueries(user, userInitial); + expect(queries[0]).to.not.be.undefined; + + const tempTableName = getTempTableName(queries[0]); + expect(queries).to.deep.equal([ + `CREATE TABLE \"${tempTableName}\" (_id INTEGER PRIMARY KEY, \"name\" text NOT NULL, \"age\" integer NOT NULL, \"email\" text NOT NULL UNIQUE, \"mi\" text)`, + `INSERT INTO \"${tempTableName}\" (\"name\", \"age\", \"email\", \"mi\") SELECT \"name\", \"age\", \"email\", \"mi\" FROM \"Users\"`, + 'DROP TABLE "Users"', + `ALTER TABLE "${tempTableName}" RENAME TO "Users"`, + ]); + }); + + it('when adding an optional unique column', async () => { + const userFinal = { + ...userInitial, + columns: { + ...userInitial.columns, + phoneNumber: column.text({ unique: true, optional: true }), + }, + }; + + const { queries } = await userChangeQueries(userInitial, userFinal); + expect(queries).to.have.lengthOf(4); + + const tempTableName = getTempTableName(queries[0]); + expect(tempTableName).to.be.a('string'); + expect(queries).to.deep.equal([ + `CREATE TABLE "${tempTableName}" (_id INTEGER PRIMARY KEY, "name" text NOT NULL, "age" integer NOT NULL, "email" text NOT NULL UNIQUE, "mi" text, "phoneNumber" text UNIQUE)`, + `INSERT INTO "${tempTableName}" ("_id", "name", "age", "email", "mi") SELECT "_id", "name", "age", "email", "mi" FROM "Users"`, + 'DROP TABLE "Users"', + `ALTER TABLE "${tempTableName}" RENAME TO "Users"`, + ]); + }); + + it('when dropping unique column', async () => { + const userFinal = { + ...userInitial, + columns: { + ...userInitial.columns, + }, + }; + delete userFinal.columns.email; + + const { queries } = await userChangeQueries(userInitial, userFinal); + expect(queries).to.have.lengthOf(4); + + const tempTableName = getTempTableName(queries[0]); + expect(tempTableName).to.be.a('string'); + expect(queries).to.deep.equal([ + `CREATE TABLE "${tempTableName}" (_id INTEGER PRIMARY KEY, "name" text NOT NULL, "age" integer NOT NULL, "mi" text)`, + `INSERT INTO "${tempTableName}" ("_id", "name", "age", "mi") SELECT "_id", "name", "age", "mi" FROM "Users"`, + 'DROP TABLE "Users"', + `ALTER TABLE "${tempTableName}" RENAME TO "Users"`, + ]); + }); + + it('when updating to a runtime default', async () => { + const initial = collectionSchema.parse({ + ...userInitial, + columns: { + ...userInitial.columns, + age: column.date(), + }, + }); + + const userFinal = collectionSchema.parse({ + ...initial, + columns: { + ...initial.columns, + age: column.date({ default: NOW }), + }, + }); + + const { queries } = await userChangeQueries(initial, userFinal); + expect(queries).to.have.lengthOf(4); + + const tempTableName = getTempTableName(queries[0]); + expect(tempTableName).to.be.a('string'); + expect(queries).to.deep.equal([ + `CREATE TABLE "${tempTableName}" (_id INTEGER PRIMARY KEY, "name" text NOT NULL, "age" text NOT NULL DEFAULT CURRENT_TIMESTAMP, "email" text NOT NULL UNIQUE, "mi" text)`, + `INSERT INTO "${tempTableName}" ("_id", "name", "age", "email", "mi") SELECT "_id", "name", "age", "email", "mi" FROM "Users"`, + 'DROP TABLE "Users"', + `ALTER TABLE "${tempTableName}" RENAME TO "Users"`, + ]); + }); + + it('when adding a column with a runtime default', async () => { + const userFinal = collectionSchema.parse({ + ...userInitial, + columns: { + ...userInitial.columns, + birthday: column.date({ default: NOW }), + }, + }); + + const { queries } = await userChangeQueries(userInitial, userFinal); + expect(queries).to.have.lengthOf(4); + + const tempTableName = getTempTableName(queries[0]); + expect(tempTableName).to.be.a('string'); + expect(queries).to.deep.equal([ + `CREATE TABLE "${tempTableName}" (_id INTEGER PRIMARY KEY, "name" text NOT NULL, "age" integer NOT NULL, "email" text NOT NULL UNIQUE, "mi" text, "birthday" text NOT NULL DEFAULT CURRENT_TIMESTAMP)`, + `INSERT INTO "${tempTableName}" ("_id", "name", "age", "email", "mi") SELECT "_id", "name", "age", "email", "mi" FROM "Users"`, + 'DROP TABLE "Users"', + `ALTER TABLE "${tempTableName}" RENAME TO "Users"`, + ]); + }); + + /** + * REASON: to follow the "expand" and "contract" migration model, + * you'll need to update the schema from NOT NULL to NULL. + * It's up to the user to ensure all data follows the new schema! + * + * @see https://planetscale.com/blog/safely-making-database-schema-changes#backwards-compatible-changes + */ + it('when changing a column to required', async () => { + const userFinal = { + ...userInitial, + columns: { + ...userInitial.columns, + mi: column.text(), + }, + }; + + const { queries } = await userChangeQueries(userInitial, userFinal); + + expect(queries).to.have.lengthOf(4); + + const tempTableName = getTempTableName(queries[0]); + expect(tempTableName).to.be.a('string'); + expect(queries).to.deep.equal([ + `CREATE TABLE "${tempTableName}" (_id INTEGER PRIMARY KEY, "name" text NOT NULL, "age" integer NOT NULL, "email" text NOT NULL UNIQUE, "mi" text NOT NULL)`, + `INSERT INTO "${tempTableName}" ("_id", "name", "age", "email", "mi") SELECT "_id", "name", "age", "email", "mi" FROM "Users"`, + 'DROP TABLE "Users"', + `ALTER TABLE "${tempTableName}" RENAME TO "Users"`, + ]); + }); + + it('when changing a column to unique', async () => { + const userFinal = { + ...userInitial, + columns: { + ...userInitial.columns, + age: column.number({ unique: true }), + }, + }; + + const { queries } = await userChangeQueries(userInitial, userFinal); + expect(queries).to.have.lengthOf(4); + + const tempTableName = getTempTableName(queries[0]); + expect(tempTableName).to.be.a('string'); + expect(queries).to.deep.equal([ + `CREATE TABLE "${tempTableName}" (_id INTEGER PRIMARY KEY, "name" text NOT NULL, "age" integer NOT NULL UNIQUE, "email" text NOT NULL UNIQUE, "mi" text)`, + `INSERT INTO "${tempTableName}" ("_id", "name", "age", "email", "mi") SELECT "_id", "name", "age", "email", "mi" FROM "Users"`, + 'DROP TABLE "Users"', + `ALTER TABLE "${tempTableName}" RENAME TO "Users"`, + ]); + }); + }); + + describe('ALTER ADD COLUMN', () => { + it('when adding an optional column', async () => { + const userFinal = { + ...userInitial, + columns: { + ...userInitial.columns, + birthday: column.date({ optional: true }), + }, + }; + + const { queries } = await userChangeQueries(userInitial, userFinal); + expect(queries).to.deep.equal(['ALTER TABLE "Users" ADD COLUMN "birthday" text']); + }); + + it('when adding a required column with default', async () => { + const defaultDate = new Date('2023-01-01'); + const userFinal = collectionSchema.parse({ + ...userInitial, + columns: { + ...userInitial.columns, + birthday: column.date({ default: new Date('2023-01-01') }), + }, + }); + + const { queries } = await userChangeQueries(userInitial, userFinal); + expect(queries).to.deep.equal([ + `ALTER TABLE "Users" ADD COLUMN "birthday" text NOT NULL DEFAULT '${defaultDate.toISOString()}'`, + ]); + }); + }); + + describe('ALTER DROP COLUMN', () => { + it('when removing optional or required columns', async () => { + const userFinal = { + ...userInitial, + columns: { + name: userInitial.columns.name, + email: userInitial.columns.email, + }, + }; + + const { queries } = await userChangeQueries(userInitial, userFinal); + expect(queries).to.deep.equal([ + 'ALTER TABLE "Users" DROP COLUMN "age"', + 'ALTER TABLE "Users" DROP COLUMN "mi"', + ]); + }); + }); + }); +}); + +/** @param {string} query */ +function getTempTableName(query) { + // eslint-disable-next-line regexp/no-unused-capturing-group + return query.match(/Users_([a-z\d]+)/)?.[0]; +} diff --git a/packages/db/test/unit/index-queries.test.js b/packages/db/test/unit/index-queries.test.js new file mode 100644 index 0000000000..17b2599bde --- /dev/null +++ b/packages/db/test/unit/index-queries.test.js @@ -0,0 +1,97 @@ +import { expect } from 'chai'; +import { describe, it } from 'mocha'; +import { getCollectionChangeQueries } from '../../dist/core/cli/migration-queries.js'; +import { collectionSchema, column } from '../../dist/core/types.js'; + +const userInitial = collectionSchema.parse({ + columns: { + name: column.text(), + age: column.number(), + email: column.text({ unique: true }), + mi: column.text({ optional: true }), + }, + indexes: {}, + writable: false, +}); + +describe('index queries', () => { + it('adds indexes', async () => { + /** @type {import('../../dist/types.js').DBTable} */ + const userFinal = { + ...userInitial, + indexes: { + nameIdx: { on: ['name'], unique: false }, + emailIdx: { on: ['email'], unique: true }, + }, + }; + + const { queries } = await getCollectionChangeQueries({ + collectionName: 'user', + oldCollection: userInitial, + newCollection: userFinal, + }); + + expect(queries).to.deep.equal([ + 'CREATE INDEX "nameIdx" ON "user" ("name")', + 'CREATE UNIQUE INDEX "emailIdx" ON "user" ("email")', + ]); + }); + + it('drops indexes', async () => { + /** @type {import('../../dist/types.js').DBTable} */ + const initial = { + ...userInitial, + indexes: { + nameIdx: { on: ['name'], unique: false }, + emailIdx: { on: ['email'], unique: true }, + }, + }; + + /** @type {import('../../dist/types.js').DBTable} */ + const final = { + ...userInitial, + indexes: {}, + }; + + const { queries } = await getCollectionChangeQueries({ + collectionName: 'user', + oldCollection: initial, + newCollection: final, + }); + + expect(queries).to.deep.equal(['DROP INDEX "nameIdx"', 'DROP INDEX "emailIdx"']); + }); + + it('drops and recreates modified indexes', async () => { + /** @type {import('../../dist/types.js').DBTable} */ + const initial = { + ...userInitial, + indexes: { + nameIdx: { on: ['name'], unique: false }, + emailIdx: { on: ['email'], unique: true }, + }, + }; + + /** @type {import('../../dist/types.js').DBTable} */ + const final = { + ...userInitial, + indexes: { + nameIdx: { on: ['name'], unique: true }, + emailIdx: { on: ['email'] }, + }, + }; + + const { queries } = await getCollectionChangeQueries({ + collectionName: 'user', + oldCollection: initial, + newCollection: final, + }); + + expect(queries).to.deep.equal([ + 'DROP INDEX "nameIdx"', + 'DROP INDEX "emailIdx"', + 'CREATE UNIQUE INDEX "nameIdx" ON "user" ("name")', + 'CREATE INDEX "emailIdx" ON "user" ("email")', + ]); + }); +}); diff --git a/packages/db/test/unit/reference-queries.test.js b/packages/db/test/unit/reference-queries.test.js new file mode 100644 index 0000000000..4c2e3af8d6 --- /dev/null +++ b/packages/db/test/unit/reference-queries.test.js @@ -0,0 +1,178 @@ +import { expect } from 'chai'; +import { describe, it } from 'mocha'; +import { getCollectionChangeQueries } from '../../dist/core/cli/migration-queries.js'; +import { column, defineReadableTable, tablesSchema } from '../../dist/core/types.js'; + +const BaseUser = defineReadableTable({ + columns: { + id: column.number({ primaryKey: true }), + name: column.text(), + age: column.number(), + email: column.text({ unique: true }), + mi: column.text({ optional: true }), + }, +}); + +const BaseSentBox = defineReadableTable({ + columns: { + to: column.number(), + toName: column.text(), + subject: column.text(), + body: column.text(), + }, +}); + +const defaultAmbiguityResponses = { + collectionRenames: {}, + columnRenames: {}, +}; + +/** + * @typedef {import('../../dist/core/types.js').DBTable} DBTable + * @param {{ User: DBTable, SentBox: DBTable }} params + * @returns + */ +function resolveReferences( + { User = BaseUser, SentBox = BaseSentBox } = { + User: BaseUser, + SentBox: BaseSentBox, + } +) { + return tablesSchema.parse({ User, SentBox }); +} + +function userChangeQueries( + oldCollection, + newCollection, + ambiguityResponses = defaultAmbiguityResponses +) { + return getCollectionChangeQueries({ + collectionName: 'User', + oldCollection, + newCollection, + ambiguityResponses, + }); +} + +describe('reference queries', () => { + it('adds references with lossless table recreate', async () => { + const { SentBox: Initial } = resolveReferences(); + const { SentBox: Final } = resolveReferences({ + SentBox: defineReadableTable({ + columns: { + ...BaseSentBox.columns, + to: column.number({ references: () => BaseUser.columns.id }), + }, + }), + }); + + const { queries } = await userChangeQueries(Initial, Final); + + expect(queries[0]).to.not.be.undefined; + const tempTableName = getTempTableName(queries[0]); + expect(tempTableName).to.not.be.undefined; + + expect(queries).to.deep.equal([ + `CREATE TABLE \"${tempTableName}\" (_id INTEGER PRIMARY KEY, \"to\" integer NOT NULL REFERENCES \"User\" (\"id\"), \"toName\" text NOT NULL, \"subject\" text NOT NULL, \"body\" text NOT NULL)`, + `INSERT INTO \"${tempTableName}\" (\"_id\", \"to\", \"toName\", \"subject\", \"body\") SELECT \"_id\", \"to\", \"toName\", \"subject\", \"body\" FROM \"User\"`, + 'DROP TABLE "User"', + `ALTER TABLE \"${tempTableName}\" RENAME TO \"User\"`, + ]); + }); + + it('removes references with lossless table recreate', async () => { + const { SentBox: Initial } = resolveReferences({ + SentBox: defineReadableTable({ + columns: { + ...BaseSentBox.columns, + to: column.number({ references: () => BaseUser.columns.id }), + }, + }), + }); + const { SentBox: Final } = resolveReferences(); + + const { queries } = await userChangeQueries(Initial, Final); + + expect(queries[0]).to.not.be.undefined; + const tempTableName = getTempTableName(queries[0]); + expect(tempTableName).to.not.be.undefined; + + expect(queries).to.deep.equal([ + `CREATE TABLE \"${tempTableName}\" (_id INTEGER PRIMARY KEY, \"to\" integer NOT NULL, \"toName\" text NOT NULL, \"subject\" text NOT NULL, \"body\" text NOT NULL)`, + `INSERT INTO \"${tempTableName}\" (\"_id\", \"to\", \"toName\", \"subject\", \"body\") SELECT \"_id\", \"to\", \"toName\", \"subject\", \"body\" FROM \"User\"`, + 'DROP TABLE "User"', + `ALTER TABLE \"${tempTableName}\" RENAME TO \"User\"`, + ]); + }); + + it('does not use ADD COLUMN when adding optional column with reference', async () => { + const { SentBox: Initial } = resolveReferences(); + const { SentBox: Final } = resolveReferences({ + SentBox: defineReadableTable({ + columns: { + ...BaseSentBox.columns, + from: column.number({ references: () => BaseUser.columns.id, optional: true }), + }, + }), + }); + + const { queries } = await userChangeQueries(Initial, Final); + expect(queries[0]).to.not.be.undefined; + const tempTableName = getTempTableName(queries[0]); + + expect(queries).to.deep.equal([ + `CREATE TABLE \"${tempTableName}\" (_id INTEGER PRIMARY KEY, \"to\" integer NOT NULL, \"toName\" text NOT NULL, \"subject\" text NOT NULL, \"body\" text NOT NULL, \"from\" integer REFERENCES \"User\" (\"id\"))`, + `INSERT INTO \"${tempTableName}\" (\"_id\", \"to\", \"toName\", \"subject\", \"body\") SELECT \"_id\", \"to\", \"toName\", \"subject\", \"body\" FROM \"User\"`, + 'DROP TABLE "User"', + `ALTER TABLE \"${tempTableName}\" RENAME TO \"User\"`, + ]); + }); + + it('adds and updates foreign key with lossless table recreate', async () => { + const { SentBox: InitialWithoutFK } = resolveReferences(); + const { SentBox: InitialWithDifferentFK } = resolveReferences({ + SentBox: defineReadableTable({ + ...BaseSentBox, + foreignKeys: [{ columns: ['to'], references: () => [BaseUser.columns.id] }], + }), + }); + const { SentBox: Final } = resolveReferences({ + SentBox: defineReadableTable({ + ...BaseSentBox, + foreignKeys: [ + { + columns: ['to', 'toName'], + references: () => [BaseUser.columns.id, BaseUser.columns.name], + }, + ], + }), + }); + + const expected = (tempTableName) => [ + `CREATE TABLE \"${tempTableName}\" (_id INTEGER PRIMARY KEY, \"to\" integer NOT NULL, \"toName\" text NOT NULL, \"subject\" text NOT NULL, \"body\" text NOT NULL, FOREIGN KEY (\"to\", \"toName\") REFERENCES \"User\"(\"id\", \"name\"))`, + `INSERT INTO \"${tempTableName}\" (\"_id\", \"to\", \"toName\", \"subject\", \"body\") SELECT \"_id\", \"to\", \"toName\", \"subject\", \"body\" FROM \"User\"`, + 'DROP TABLE "User"', + `ALTER TABLE \"${tempTableName}\" RENAME TO \"User\"`, + ]; + + const addedForeignKey = await userChangeQueries(InitialWithoutFK, Final); + const updatedForeignKey = await userChangeQueries(InitialWithDifferentFK, Final); + + expect(addedForeignKey.queries[0]).to.not.be.undefined; + expect(updatedForeignKey.queries[0]).to.not.be.undefined; + + expect(addedForeignKey.queries).to.deep.equal( + expected(getTempTableName(addedForeignKey.queries[0])) + ); + + expect(updatedForeignKey.queries).to.deep.equal( + expected(getTempTableName(updatedForeignKey.queries[0])) + ); + }); +}); + +/** @param {string | undefined} query */ +function getTempTableName(query) { + // eslint-disable-next-line regexp/no-unused-capturing-group + return query.match(/User_([a-z\d]+)/)?.[0]; +} diff --git a/packages/db/tsconfig.json b/packages/db/tsconfig.json new file mode 100644 index 0000000000..18443cddf2 --- /dev/null +++ b/packages/db/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.base.json", + "include": ["src"], + "compilerOptions": { + "outDir": "./dist" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fe20e801a1..1cd930ed3b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -565,7 +565,7 @@ importers: version: 3.0.0 debug: specifier: ^4.3.4 - version: 4.3.4 + version: 4.3.4(supports-color@8.1.1) deterministic-object-hash: specifier: ^2.0.1 version: 2.0.2 @@ -3788,6 +3788,157 @@ importers: packages/create-astro/test/fixtures/not-empty: {} + packages/db: + dependencies: + '@libsql/client': + specifier: ^0.4.3 + version: 0.4.3 + deep-diff: + specifier: ^1.0.2 + version: 1.0.2 + drizzle-orm: + specifier: ^0.28.6 + version: 0.28.6(@libsql/client@0.4.3) + kleur: + specifier: ^4.1.5 + version: 4.1.5 + nanoid: + specifier: ^5.0.1 + version: 5.0.1 + open: + specifier: ^10.0.3 + version: 10.0.3 + ora: + specifier: ^7.0.1 + version: 7.0.1 + prompts: + specifier: ^2.4.2 + version: 2.4.2 + yargs-parser: + specifier: ^21.1.1 + version: 21.1.1 + zod: + specifier: ^3.22.4 + version: 3.22.4 + devDependencies: + '@types/chai': + specifier: ^4.3.6 + version: 4.3.11 + '@types/deep-diff': + specifier: ^1.0.5 + version: 1.0.5 + '@types/diff': + specifier: ^5.0.8 + version: 5.0.9 + '@types/mocha': + specifier: ^10.0.2 + version: 10.0.6 + '@types/prompts': + specifier: ^2.4.8 + version: 2.4.9 + '@types/yargs-parser': + specifier: ^21.0.3 + version: 21.0.3 + astro: + specifier: workspace:* + version: link:../astro + astro-scripts: + specifier: workspace:* + version: link:../../scripts + chai: + specifier: ^4.3.10 + version: 4.4.1 + cheerio: + specifier: 1.0.0-rc.12 + version: 1.0.0-rc.12 + mocha: + specifier: ^10.2.0 + version: 10.2.0 + typescript: + specifier: ^5.2.2 + version: 5.2.2 + vite: + specifier: ^4.4.11 + version: 4.4.11(@types/node@18.19.4) + + packages/db/test/fixtures/basics: + dependencies: + '@astrojs/db': + specifier: workspace:* + version: link:../../.. + astro: + specifier: workspace:* + version: link:../../../../astro + + packages/db/test/fixtures/glob: + dependencies: + '@astrojs/db': + specifier: workspace:* + version: link:../../.. + astro: + specifier: workspace:* + version: link:../../../../astro + chokidar: + specifier: ^3.5.3 + version: 3.5.3 + drizzle-orm: + specifier: ^0.28.6 + version: 0.28.6(@libsql/client@0.4.3) + fast-glob: + specifier: ^3.3.2 + version: 3.3.2 + + packages/db/test/fixtures/recipes: + dependencies: + '@astrojs/db': + specifier: workspace:* + version: link:../../.. + astro: + specifier: workspace:* + version: link:../../../../astro + + packages/db/test/fixtures/ticketing-example: + dependencies: + '@astrojs/check': + specifier: ^0.5.5 + version: 0.5.5(prettier-plugin-astro@0.12.3)(prettier@3.1.1)(typescript@5.3.2) + '@astrojs/db': + specifier: workspace:* + version: link:../../.. + '@astrojs/node': + specifier: workspace:* + version: link:../../../../integrations/node + '@astrojs/react': + specifier: ^3.0.10 + version: link:../../../../integrations/react + '@types/react': + specifier: ^18.2.57 + version: 18.2.57 + '@types/react-dom': + specifier: ^18.2.19 + version: 18.2.19 + astro: + specifier: workspace:* + version: link:../../../../astro + open-props: + specifier: ^1.6.17 + version: 1.6.17 + react: + specifier: ^18.2.0 + version: 18.2.0 + react-dom: + specifier: ^18.2.0 + version: 18.2.0(react@18.2.0) + simple-stack-form: + specifier: ^0.1.10 + version: 0.1.10(astro@packages+astro)(zod@3.22.4) + typescript: + specifier: ^5.3.2 + version: 5.3.2 + zod: + specifier: ^3.22.4 + version: 3.22.4 + packages/integrations/alpinejs: devDependencies: '@playwright/test': @@ -5103,7 +5254,7 @@ importers: version: 4.0.0 debug: specifier: ^4.3.4 - version: 4.3.4 + version: 4.3.4(supports-color@8.1.1) dlv: specifier: ^1.1.3 version: 1.1.3 @@ -5299,6 +5450,23 @@ packages: - prettier-plugin-astro dev: true + /@astrojs/check@0.5.5(prettier-plugin-astro@0.12.3)(prettier@3.1.1)(typescript@5.3.2): + resolution: {integrity: sha512-05LjyUB14Cv2mkLNqY4r2igI2eu0bq/HcKCfFNIoBPLyNW7VUDr9tciD9VJXXT3s0e6JHneIs6bQW5ipjmaRcw==} + hasBin: true + peerDependencies: + typescript: ^5.0.0 + dependencies: + '@astrojs/language-server': 2.7.5(prettier-plugin-astro@0.12.3)(prettier@3.1.1)(typescript@5.3.2) + chokidar: 3.5.3 + fast-glob: 3.3.2 + kleur: 4.1.5 + typescript: 5.3.2 + yargs: 17.7.2 + transitivePeerDependencies: + - prettier + - prettier-plugin-astro + dev: false + /@astrojs/cli-kit@0.2.5: resolution: {integrity: sha512-j6zpNUjtHJGEIKkTrTPvQD3G/sJUKyseJty42iVR3HqytzqHwLK165vptdT4NZKfZ082yLnUtsOXxRyIdfm/AQ==} dependencies: @@ -5318,7 +5486,6 @@ packages: /@astrojs/compiler@1.8.2: resolution: {integrity: sha512-o/ObKgtMzl8SlpIdzaxFnt7SATKPxu4oIP/1NL+HDJRzxfJcAkOTAb/ZKMRyULbz4q+1t2/DAebs2Z1QairkZw==} - dev: true /@astrojs/compiler@2.5.3: resolution: {integrity: sha512-jzj01BRv/fmo+9Mr2FhocywGzEYiyiP2GVHje1ziGNU6c97kwhYGsnvwMkHrncAy9T9Vi54cjaMK7UE4ClX4vA==} @@ -5359,6 +5526,40 @@ packages: - typescript dev: true + /@astrojs/language-server@2.7.5(prettier-plugin-astro@0.12.3)(prettier@3.1.1)(typescript@5.3.2): + resolution: {integrity: sha512-iMfZ3UaqTgIL+z/eUDOppRa1bGUAteWRihbWq5mGAgvr/hu384ZXUKJcqV3BBux0MBsRXwjxzrC2dJu9IpAaoA==} + hasBin: true + peerDependencies: + prettier: ^3.0.0 + prettier-plugin-astro: '>=0.11.0' + peerDependenciesMeta: + prettier: + optional: true + prettier-plugin-astro: + optional: true + dependencies: + '@astrojs/compiler': 2.5.3 + '@jridgewell/sourcemap-codec': 1.4.15 + '@volar/kit': 2.0.4(typescript@5.3.2) + '@volar/language-core': 2.0.4 + '@volar/language-server': 2.0.4 + '@volar/language-service': 2.0.4 + '@volar/typescript': 2.0.4 + fast-glob: 3.3.2 + prettier: 3.1.1 + prettier-plugin-astro: 0.12.3 + volar-service-css: 0.0.30(@volar/language-service@2.0.4) + volar-service-emmet: 0.0.30(@volar/language-service@2.0.4) + volar-service-html: 0.0.30(@volar/language-service@2.0.4) + volar-service-prettier: 0.0.30(@volar/language-service@2.0.4)(prettier@3.1.1) + volar-service-typescript: 0.0.30(@volar/language-service@2.0.4)(@volar/typescript@2.0.4) + volar-service-typescript-twoslash-queries: 0.0.30(@volar/language-service@2.0.4) + vscode-html-languageservice: 5.1.2 + vscode-uri: 3.0.8 + transitivePeerDependencies: + - typescript + dev: false + /@babel/code-frame@7.23.5: resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} engines: {node: '>=6.9.0'} @@ -5386,7 +5587,7 @@ packages: '@babel/traverse': 7.23.7 '@babel/types': 7.23.6 convert-source-map: 2.0.0 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -5745,7 +5946,7 @@ packages: '@babel/helper-split-export-declaration': 7.22.6 '@babel/parser': 7.23.6 '@babel/types': 7.23.6 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -6059,6 +6260,23 @@ packages: prettier: 2.8.8 dev: true + /@clack/core@0.3.3: + resolution: {integrity: sha512-5ZGyb75BUBjlll6eOa1m/IZBxwk91dooBWhPSL67sWcLS0zt9SnswRL0l26TVdBhb0wnWORRxUn//uH6n4z7+A==} + dependencies: + picocolors: 1.0.0 + sisteransi: 1.0.5 + dev: false + + /@clack/prompts@0.7.0: + resolution: {integrity: sha512-0MhX9/B4iL6Re04jPrttDm+BsP8y6mS7byuv0BvXgdXhbV5PdlsHt55dvNsuBCPZ7xq1oTAOOuotR9NFbQyMSA==} + dependencies: + '@clack/core': 0.3.3 + picocolors: 1.0.0 + sisteransi: 1.0.5 + dev: false + bundledDependencies: + - is-unicode-supported + /@colors/colors@1.5.0: resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} @@ -6453,17 +6671,14 @@ packages: resolution: {integrity: sha512-mgv58UrU3rh4YgbE/TzgLQwJ3pFsHHhCLqY20aJq+9comytTXUDNGG/SMtSeMJdkpxgXSXunBGLD8Boka3JyVA==} dependencies: '@emmetio/scanner': 1.0.4 - dev: true /@emmetio/css-abbreviation@2.1.8: resolution: {integrity: sha512-s9yjhJ6saOO/uk1V74eifykk2CBYi01STTK3WlXWGOepyKa23ymJ053+DNQjpFcy1ingpaO7AxCcwLvHFY9tuw==} dependencies: '@emmetio/scanner': 1.0.4 - dev: true /@emmetio/scanner@1.0.4: resolution: {integrity: sha512-IqRuJtQff7YHHBk4G8YZ45uB9BaAGcwQeVzgj/zj8/UdOhtQpEIupUhSk8dys6spFIWVZVeK20CzGEnqR5SbqA==} - dev: true /@esbuild/aix-ppc64@0.19.11: resolution: {integrity: sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==} @@ -6473,6 +6688,15 @@ packages: requiresBuild: true optional: true + /@esbuild/android-arm64@0.18.20: + resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/android-arm64@0.19.11: resolution: {integrity: sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==} engines: {node: '>=12'} @@ -6481,6 +6705,15 @@ packages: requiresBuild: true optional: true + /@esbuild/android-arm@0.18.20: + resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/android-arm@0.19.11: resolution: {integrity: sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==} engines: {node: '>=12'} @@ -6489,6 +6722,15 @@ packages: requiresBuild: true optional: true + /@esbuild/android-x64@0.18.20: + resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/android-x64@0.19.11: resolution: {integrity: sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==} engines: {node: '>=12'} @@ -6497,6 +6739,15 @@ packages: requiresBuild: true optional: true + /@esbuild/darwin-arm64@0.18.20: + resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@esbuild/darwin-arm64@0.19.11: resolution: {integrity: sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==} engines: {node: '>=12'} @@ -6505,6 +6756,15 @@ packages: requiresBuild: true optional: true + /@esbuild/darwin-x64@0.18.20: + resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@esbuild/darwin-x64@0.19.11: resolution: {integrity: sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==} engines: {node: '>=12'} @@ -6513,6 +6773,15 @@ packages: requiresBuild: true optional: true + /@esbuild/freebsd-arm64@0.18.20: + resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/freebsd-arm64@0.19.11: resolution: {integrity: sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==} engines: {node: '>=12'} @@ -6521,6 +6790,15 @@ packages: requiresBuild: true optional: true + /@esbuild/freebsd-x64@0.18.20: + resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/freebsd-x64@0.19.11: resolution: {integrity: sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==} engines: {node: '>=12'} @@ -6529,6 +6807,15 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-arm64@0.18.20: + resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-arm64@0.19.11: resolution: {integrity: sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==} engines: {node: '>=12'} @@ -6537,6 +6824,15 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-arm@0.18.20: + resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-arm@0.19.11: resolution: {integrity: sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==} engines: {node: '>=12'} @@ -6545,6 +6841,15 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-ia32@0.18.20: + resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-ia32@0.19.11: resolution: {integrity: sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==} engines: {node: '>=12'} @@ -6553,6 +6858,15 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-loong64@0.18.20: + resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-loong64@0.19.11: resolution: {integrity: sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==} engines: {node: '>=12'} @@ -6561,6 +6875,15 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-mips64el@0.18.20: + resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-mips64el@0.19.11: resolution: {integrity: sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==} engines: {node: '>=12'} @@ -6569,6 +6892,15 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-ppc64@0.18.20: + resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-ppc64@0.19.11: resolution: {integrity: sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==} engines: {node: '>=12'} @@ -6577,6 +6909,15 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-riscv64@0.18.20: + resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-riscv64@0.19.11: resolution: {integrity: sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==} engines: {node: '>=12'} @@ -6585,6 +6926,15 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-s390x@0.18.20: + resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-s390x@0.19.11: resolution: {integrity: sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==} engines: {node: '>=12'} @@ -6593,6 +6943,15 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-x64@0.18.20: + resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-x64@0.19.11: resolution: {integrity: sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==} engines: {node: '>=12'} @@ -6601,6 +6960,15 @@ packages: requiresBuild: true optional: true + /@esbuild/netbsd-x64@0.18.20: + resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/netbsd-x64@0.19.11: resolution: {integrity: sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==} engines: {node: '>=12'} @@ -6609,6 +6977,15 @@ packages: requiresBuild: true optional: true + /@esbuild/openbsd-x64@0.18.20: + resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/openbsd-x64@0.19.11: resolution: {integrity: sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==} engines: {node: '>=12'} @@ -6617,6 +6994,15 @@ packages: requiresBuild: true optional: true + /@esbuild/sunos-x64@0.18.20: + resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + /@esbuild/sunos-x64@0.19.11: resolution: {integrity: sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==} engines: {node: '>=12'} @@ -6625,6 +7011,15 @@ packages: requiresBuild: true optional: true + /@esbuild/win32-arm64@0.18.20: + resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@esbuild/win32-arm64@0.19.11: resolution: {integrity: sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==} engines: {node: '>=12'} @@ -6633,6 +7028,15 @@ packages: requiresBuild: true optional: true + /@esbuild/win32-ia32@0.18.20: + resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@esbuild/win32-ia32@0.19.11: resolution: {integrity: sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==} engines: {node: '>=12'} @@ -6641,6 +7045,15 @@ packages: requiresBuild: true optional: true + /@esbuild/win32-x64@0.18.20: + resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@esbuild/win32-x64@0.19.11: resolution: {integrity: sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==} engines: {node: '>=12'} @@ -6669,7 +7082,7 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: ajv: 6.12.6 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) espree: 9.6.1 globals: 13.24.0 ignore: 5.3.0 @@ -6704,7 +7117,7 @@ packages: engines: {node: '>=10.10.0'} dependencies: '@humanwhocodes/object-schema': 2.0.1 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -6766,6 +7179,114 @@ packages: resolution: {integrity: sha512-n5JEf16Wr4mdkRMZ8wMP/wN9/sHmTjRPbouXjJH371mZ2LEGDl72t8tEsMRNFerQN/QJtivOxqK1frdGa4QK5Q==} engines: {node: '>=10'} + /@libsql/client@0.4.3: + resolution: {integrity: sha512-AUYKnSPqAsFBVWBvmtrb4dG3pQlvTKT92eztAest9wQU2iJkabH8WzHLDb3dKFWKql7/kiCqvBQUVpozDwhekQ==} + dependencies: + '@libsql/core': 0.4.3 + '@libsql/hrana-client': 0.5.6 + js-base64: 3.7.6 + optionalDependencies: + libsql: 0.2.0 + transitivePeerDependencies: + - bufferutil + - encoding + - utf-8-validate + dev: false + + /@libsql/core@0.4.3: + resolution: {integrity: sha512-r28iYBtaLBW9RRgXPFh6cGCsVI/rwRlOzSOpAu/1PVTm6EJ3t233pUf97jETVHU0vjdr1d8VvV6fKAvJkokqCw==} + dependencies: + js-base64: 3.7.6 + dev: false + + /@libsql/darwin-arm64@0.2.0: + resolution: {integrity: sha512-+qyT2W/n5CFH1YZWv2mxW4Fsoo4dX9Z9M/nvbQqZ7H84J8hVegvVAsIGYzcK8xAeMEcpU5yGKB1Y9NoDY4hOSQ==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@libsql/darwin-x64@0.2.0: + resolution: {integrity: sha512-hwmO2mF1n8oDHKFrUju6Jv+n9iFtTf5JUK+xlnIE3Td0ZwGC/O1R/Z/btZTd9nD+vsvakC8SJT7/Q6YlWIkhEw==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@libsql/hrana-client@0.5.6: + resolution: {integrity: sha512-mjQoAmejZ1atG+M3YR2ZW+rg6ceBByH/S/h17ZoYZkqbWrvohFhXyz2LFxj++ARMoY9m6w3RJJIRdJdmnEUlFg==} + dependencies: + '@libsql/isomorphic-fetch': 0.1.12 + '@libsql/isomorphic-ws': 0.1.5 + js-base64: 3.7.6 + node-fetch: 3.3.2 + transitivePeerDependencies: + - bufferutil + - encoding + - utf-8-validate + dev: false + + /@libsql/isomorphic-fetch@0.1.12: + resolution: {integrity: sha512-MRo4UcmjAGAa3ac56LoD5OE13m2p0lu0VEtZC2NZMcogM/jc5fU9YtMQ3qbPjFJ+u2BBjFZgMPkQaLS1dlMhpg==} + dependencies: + '@types/node-fetch': 2.6.11 + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + dev: false + + /@libsql/isomorphic-ws@0.1.5: + resolution: {integrity: sha512-DtLWIH29onUYR00i0GlQ3UdcTRC6EP4u9w/h9LxpUZJWRMARk6dQwZ6Jkd+QdwVpuAOrdxt18v0K2uIYR3fwFg==} + dependencies: + '@types/ws': 8.5.10 + ws: 8.16.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: false + + /@libsql/linux-arm64-gnu@0.2.0: + resolution: {integrity: sha512-1w2lPXIYtnBaK5t/Ej5E8x7lPiE+jP3KATI/W4yei5Z/ONJh7jQW5PJ7sYU95vTME3hWEM1FXN6kvzcpFAte7w==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@libsql/linux-arm64-musl@0.2.0: + resolution: {integrity: sha512-lkblBEJ7xuNiWNjP8DDq0rqoWccszfkUS7Efh5EjJ+GDWdCBVfh08mPofIZg0fZVLWQCY3j+VZCG1qZfATBizg==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@libsql/linux-x64-gnu@0.2.0: + resolution: {integrity: sha512-+x/d289KeJydwOhhqSxKT+6MSQTCfLltzOpTzPccsvdt5fxg8CBi+gfvEJ4/XW23Sa+9bc7zodFP0i6MOlxX7w==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@libsql/linux-x64-musl@0.2.0: + resolution: {integrity: sha512-5Xn0c5A6vKf9D1ASpgk7mef//FuY7t5Lktj/eiU4n3ryxG+6WTpqstTittJUgepVjcleLPYxIhQAYeYwTYH1IQ==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@libsql/win32-x64-msvc@0.2.0: + resolution: {integrity: sha512-rpK+trBIpRST15m3cMYg5aPaX7kvCIottxY7jZPINkKAaScvfbn9yulU/iZUM9YtuK96Y1ZmvwyVIK/Y5DzoMQ==} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + /@lit-labs/ssr-client@1.1.5: resolution: {integrity: sha512-rAXd2OsuxfGA579RiDS2YQSm1HreE8knQHj+fcMhGIPYenBoW4M70Yl8K3a35MSLlpQnnF//s2TPfkHFmy2RhA==} dependencies: @@ -6913,6 +7434,12 @@ packages: preact: 10.19.3 dev: false + /@neon-rs/load@0.0.4: + resolution: {integrity: sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw==} + requiresBuild: true + dev: false + optional: true + /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -7076,7 +7603,7 @@ packages: '@prefresh/vite': 2.4.5(preact@10.19.3) '@rollup/pluginutils': 4.2.1 babel-plugin-transform-hook-names: 1.0.2 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) kolorist: 1.8.0 resolve: 1.22.8 transitivePeerDependencies: @@ -7259,7 +7786,7 @@ packages: optional: true dependencies: '@sveltejs/vite-plugin-svelte': 3.0.1(svelte@4.2.8)(vite@5.1.2) - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) svelte: 4.2.8 vite: 5.1.2(@types/node@18.19.4)(sass@1.69.6) transitivePeerDependencies: @@ -7277,7 +7804,7 @@ packages: optional: true dependencies: '@sveltejs/vite-plugin-svelte-inspector': 2.0.0(@sveltejs/vite-plugin-svelte@3.0.1)(svelte@4.2.8)(vite@5.1.2) - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.5 @@ -7387,6 +7914,10 @@ packages: dependencies: '@types/ms': 0.7.34 + /@types/deep-diff@1.0.5: + resolution: {integrity: sha512-PQyNSy1YMZU1hgZA5tTYfHPpUAo9Dorn1PZho2/budQLfqLu3JIP37JAavnwYpR1S2yFZTXa3hxaE4ifGW5jaA==} + dev: true + /@types/diff@5.0.9: resolution: {integrity: sha512-RWVEhh/zGXpAVF/ZChwNnv7r4rvqzJ7lYNSmZSVTxjV0PBLf6Qu7RNg+SUtkpzxmiNkjCx0Xn2tPp7FIkshJwQ==} dev: true @@ -7516,6 +8047,13 @@ packages: '@types/unist': 2.0.10 dev: false + /@types/node-fetch@2.6.11: + resolution: {integrity: sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==} + dependencies: + '@types/node': 18.19.4 + form-data: 4.0.0 + dev: false + /@types/node@12.20.55: resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} dev: true @@ -7563,6 +8101,12 @@ packages: dependencies: '@types/react': 18.2.46 + /@types/react-dom@18.2.19: + resolution: {integrity: sha512-aZvQL6uUbIJpjZk4U8JZGbau9KDeAwMfmhyWorxgBkqDIEf6ROjRozcmPIicqsUwPUjbkDfHKgGee1Lq65APcA==} + dependencies: + '@types/react': 18.2.57 + dev: false + /@types/react@18.2.46: resolution: {integrity: sha512-nNCvVBcZlvX4NU1nRRNV/mFl1nNRuTuslAJglQsq+8ldXe5Xv0Wd2f7WTE3jOxhLH2BFfiZGC6GCp+kHQbgG+w==} dependencies: @@ -7570,6 +8114,14 @@ packages: '@types/scheduler': 0.16.8 csstype: 3.1.3 + /@types/react@18.2.57: + resolution: {integrity: sha512-ZvQsktJgSYrQiMirAN60y4O/LRevIV8hUzSOSNB6gfR3/o3wCBFQx3sPwIYtuDMeiVgsSS3UzCV26tEzgnfvQw==} + dependencies: + '@types/prop-types': 15.7.11 + '@types/scheduler': 0.16.8 + csstype: 3.1.3 + dev: false + /@types/relateurl@0.2.33: resolution: {integrity: sha512-bTQCKsVbIdzLqZhLkF5fcJQreE4y1ro4DIyVrlDNSCJRRwHhB8Z+4zXXa8jN6eDvc2HbRsEYgbvrnGvi54EpSw==} dev: true @@ -7641,6 +8193,12 @@ packages: resolution: {integrity: sha512-M0ZefeDApctHbjqtATOiixiwafG7pXD3exxnjku4XmX9+2DmONGghv5Z8Pnm0lNLBZKvDQyuG+4pLkH2UkP5gg==} dev: true + /@types/ws@8.5.10: + resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} + dependencies: + '@types/node': 18.19.4 + dev: false + /@types/xml2js@0.4.14: resolution: {integrity: sha512-4YnrRemBShWRO2QjvUin8ESA41rH+9nQGLUGZV/1IDhi3SL9OhdpNC/MrulTWuptXKwhx/aDxE7toV0f/ypIXQ==} dependencies: @@ -7668,7 +8226,7 @@ packages: '@typescript-eslint/type-utils': 6.17.0(eslint@8.56.0)(typescript@5.2.2) '@typescript-eslint/utils': 6.17.0(eslint@8.56.0)(typescript@5.2.2) '@typescript-eslint/visitor-keys': 6.17.0 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) eslint: 8.56.0 graphemer: 1.4.0 ignore: 5.3.0 @@ -7694,7 +8252,7 @@ packages: '@typescript-eslint/types': 6.17.0 '@typescript-eslint/typescript-estree': 6.17.0(typescript@5.2.2) '@typescript-eslint/visitor-keys': 6.17.0 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) eslint: 8.56.0 typescript: 5.2.2 transitivePeerDependencies: @@ -7721,7 +8279,7 @@ packages: dependencies: '@typescript-eslint/typescript-estree': 6.17.0(typescript@5.2.2) '@typescript-eslint/utils': 6.17.0(eslint@8.56.0)(typescript@5.2.2) - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) eslint: 8.56.0 ts-api-utils: 1.0.3(typescript@5.2.2) typescript: 5.2.2 @@ -7745,7 +8303,7 @@ packages: dependencies: '@typescript-eslint/types': 6.17.0 '@typescript-eslint/visitor-keys': 6.17.0 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 @@ -7787,7 +8345,7 @@ packages: resolution: {integrity: sha512-kTwMUQ8xtAZaC4wb2XuLkPqFVBj2dNBueMQ89NWEuw87k2nLBbuafeG5cob/QEr6YduxIdTVUjix0MtC7mPlmg==} dependencies: '@typescript/vfs': 1.3.5 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) lz-string: 1.5.0 transitivePeerDependencies: - supports-color @@ -7796,7 +8354,7 @@ packages: /@typescript/vfs@1.3.4: resolution: {integrity: sha512-RbyJiaAGQPIcAGWFa3jAXSuAexU4BFiDRF1g3hy7LmRqfNpYlTQWGXjcrOaVZjJ8YkkpuwG0FcsYvtWQpd9igQ==} dependencies: - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color dev: true @@ -7804,7 +8362,7 @@ packages: /@typescript/vfs@1.3.5: resolution: {integrity: sha512-pI8Saqjupf9MfLw7w2+og+fmb0fZS0J6vsKXXrp4/PDXEFvntgzXmChCXC/KefZZS0YGS6AT8e0hGAJcTsdJlg==} dependencies: - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color dev: true @@ -7946,12 +8504,31 @@ packages: vscode-uri: 3.0.8 dev: true + /@volar/kit@2.0.4(typescript@5.3.2): + resolution: {integrity: sha512-USRx/o0jKz7o8+lEKWMxWqbqvC46XFrf3IE6CZBYzRo9kM7RERQLwUYaoT2bOcHt5DQWublpnTgdgHMm37Gysg==} + peerDependencies: + typescript: '*' + dependencies: + '@volar/language-service': 2.0.4 + '@volar/typescript': 2.0.4 + typesafe-path: 0.2.2 + typescript: 5.3.2 + vscode-languageserver-textdocument: 1.0.11 + vscode-uri: 3.0.8 + dev: false + /@volar/language-core@1.10.10: resolution: {integrity: sha512-nsV1o3AZ5n5jaEAObrS3MWLBWaGwUj/vAsc15FVNIv+DbpizQRISg9wzygsHBr56ELRH8r4K75vkYNMtsSNNWw==} dependencies: '@volar/source-map': 1.10.10 dev: true + /@volar/language-core@2.0.4: + resolution: {integrity: sha512-VhC8i03P0x9LKGLTBi81xNTNWm40yxQ/Iba8IpH+LFr+Yb7c/D7fF90Cvf31MzPDM4G5rjIOlCfs+eQKPBkwQw==} + dependencies: + '@volar/source-map': 2.0.4 + dev: false + /@volar/language-server@1.10.10: resolution: {integrity: sha512-F2PRBU+CRjT7L9qe8bjof/uz/LbAXVmgwNU2gOSX2y1bUl3E8DHmD0dB6pwIVublvkx+Ivg/0r3Z6oyxfPPruQ==} dependencies: @@ -7967,6 +8544,22 @@ packages: vscode-uri: 3.0.8 dev: true + /@volar/language-server@2.0.4: + resolution: {integrity: sha512-VnljhooQjT6RhmvwwJK9+3YYs2ovFmav4IVNHiQgnTMfiOiyABzcghwvJrJrI39rJDI6LNOWF7BYUJq7K07BKQ==} + dependencies: + '@volar/language-core': 2.0.4 + '@volar/language-service': 2.0.4 + '@volar/snapshot-document': 2.0.4 + '@volar/typescript': 2.0.4 + '@vscode/l10n': 0.0.16 + path-browserify: 1.0.1 + request-light: 0.7.0 + vscode-languageserver: 9.0.1 + vscode-languageserver-protocol: 3.17.5 + vscode-languageserver-textdocument: 1.0.11 + vscode-uri: 3.0.8 + dev: false + /@volar/language-service@1.10.10: resolution: {integrity: sha512-P4fiPWDI6fLGO6BghlksCVHs1nr9gvWAMDyma3Bca4aowxXusxjUVTsnJq0EVorIN5uIr1Xel4B/tNdXt/IKyw==} dependencies: @@ -7977,12 +8570,34 @@ packages: vscode-uri: 3.0.8 dev: true + /@volar/language-service@2.0.4: + resolution: {integrity: sha512-DoanyU9I9Nl85lUytDl8jgyk+nrUDR5CFNVMrxWXGXclP4WTqBayBgSFAeF1L/5AwP3MywmWoK4GLAEVvl8D+Q==} + dependencies: + '@volar/language-core': 2.0.4 + vscode-languageserver-protocol: 3.17.5 + vscode-languageserver-textdocument: 1.0.11 + vscode-uri: 3.0.8 + dev: false + + /@volar/snapshot-document@2.0.4: + resolution: {integrity: sha512-YzgdmvpdRFxiBFCOVWga67naAtbPtKmPaFtGnmxWx+KXrjGkpUXT/2tzeKn5FLdtoYV+DRTdpMdP/45ArnVwZQ==} + dependencies: + vscode-languageserver-protocol: 3.17.5 + vscode-languageserver-textdocument: 1.0.11 + dev: false + /@volar/source-map@1.10.10: resolution: {integrity: sha512-GVKjLnifV4voJ9F0vhP56p4+F3WGf+gXlRtjFZsv6v3WxBTWU3ZVeaRaEHJmWrcv5LXmoYYpk/SC25BKemPRkg==} dependencies: muggle-string: 0.3.1 dev: true + /@volar/source-map@2.0.4: + resolution: {integrity: sha512-BbxUinEMoJZqrHsSj1aBa0boCBnN3BoXnf7j9IBwjxosxGXOhCvqmH2L9raJemadaKjeVR8ZQLhV7AOhyoHt/Q==} + dependencies: + muggle-string: 0.4.1 + dev: false + /@volar/typescript@1.10.10: resolution: {integrity: sha512-4a2r5bdUub2m+mYVnLu2wt59fuoYWe7nf0uXtGHU8QQ5LDNfzAR0wK7NgDiQ9rcl2WT3fxT2AA9AylAwFtj50A==} dependencies: @@ -7990,6 +8605,13 @@ packages: path-browserify: 1.0.1 dev: true + /@volar/typescript@2.0.4: + resolution: {integrity: sha512-KF7yh7GIo4iWuAQOKf/ONeFHdQA+wFriitW8LtGZB4iOOT6MdlRlYNsRL8do7XxmXvsBKcs4jTMtGn+uZRwlWg==} + dependencies: + '@volar/language-core': 2.0.4 + path-browserify: 1.0.1 + dev: false + /@vscode/emmet-helper@2.9.2: resolution: {integrity: sha512-MaGuyW+fa13q3aYsluKqclmh62Hgp0BpKIqS66fCxfOaBcVQ1OnMQxRRgQUYnCkxFISAQlkJ0qWWPyXjro1Qrg==} dependencies: @@ -7998,11 +8620,13 @@ packages: vscode-languageserver-textdocument: 1.0.11 vscode-languageserver-types: 3.17.5 vscode-uri: 2.1.2 - dev: true /@vscode/l10n@0.0.16: resolution: {integrity: sha512-JT5CvrIYYCrmB+dCana8sUqJEcGB1ZDXNLMQ2+42bW995WmNoenijWMUdZfwmuQUTQcEVVIa2OecZzTYWUW9Cg==} - dev: true + + /@vscode/l10n@0.0.18: + resolution: {integrity: sha512-KYSIHVmslkaCDyw013pphY+d7x1qV8IZupYfeIfzNA+nsaWHbn5uPuQRvdRFsa9zFzGeudPuoGoZ1Op4jrJXIQ==} + dev: false /@vue/babel-helper-vue-transform-on@1.1.5: resolution: {integrity: sha512-SgUymFpMoAyWeYWLAY+MkCK3QEROsiUnfaw5zxOVD/M64KQs8D/4oK6Q5omVA2hnvEOE0SCkH2TZxs/jnnUj7w==} @@ -8146,7 +8770,7 @@ packages: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} dependencies: - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -8154,7 +8778,7 @@ packages: resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==} engines: {node: '>= 14'} dependencies: - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color dev: false @@ -8188,6 +8812,11 @@ packages: string-width: 4.2.3 dev: false + /ansi-colors@4.1.1: + resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==} + engines: {node: '>=6'} + dev: true + /ansi-colors@4.1.3: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} @@ -8317,7 +8946,6 @@ packages: /assertion-error@1.1.0: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - dev: false /astring@1.8.6: resolution: {integrity: sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==} @@ -8596,6 +9224,10 @@ packages: wcwidth: 1.0.1 dev: true + /browser-stdout@1.3.1: + resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} + dev: true + /browserslist@4.22.2: resolution: {integrity: sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} @@ -8621,6 +9253,13 @@ packages: ieee754: 1.2.1 dev: false + /bundle-name@4.1.0: + resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} + engines: {node: '>=18'} + dependencies: + run-applescript: 7.0.0 + dev: false + /bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} @@ -8672,7 +9311,6 @@ packages: /camelcase@6.3.0: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - dev: false /camelcase@7.0.1: resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} @@ -8700,7 +9338,6 @@ packages: loupe: 2.3.7 pathval: 1.1.1 type-detect: 4.0.8 - dev: false /chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} @@ -8746,7 +9383,6 @@ packages: resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} dependencies: get-func-name: 2.0.2 - dev: false /cheerio-select@2.1.0: resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} @@ -8854,6 +9490,14 @@ packages: wrap-ansi: 6.2.0 dev: true + /cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: true + /cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -8861,7 +9505,6 @@ packages: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - dev: true /clone@1.0.4: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} @@ -8975,7 +9618,7 @@ packages: dev: false /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} /console-control-strings@1.1.0: resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} @@ -9197,7 +9840,7 @@ packages: dependencies: ms: 2.0.0 - /debug@4.3.4: + /debug@4.3.4(supports-color@8.1.1): resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} peerDependencies: @@ -9207,6 +9850,7 @@ packages: optional: true dependencies: ms: 2.1.2 + supports-color: 8.1.1 /decamelize-keys@1.1.1: resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} @@ -9221,6 +9865,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /decamelize@4.0.0: + resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} + engines: {node: '>=10'} + dev: true + /decimal.js@10.4.3: resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} dev: true @@ -9242,12 +9891,15 @@ packages: resolution: {integrity: sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ==} dev: false + /deep-diff@1.0.2: + resolution: {integrity: sha512-aWS3UIVH+NPGCD1kki+DCU9Dua032iSsO43LqQpcs4R3+dVv7tX0qBGjiVHJHjplsoUM2XRO/KB92glqc68awg==} + dev: false + /deep-eql@4.1.3: resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} engines: {node: '>=6'} dependencies: type-detect: 4.0.8 - dev: false /deep-extend@0.6.0: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} @@ -9264,6 +9916,19 @@ packages: engines: {node: '>=0.10.0'} dev: false + /default-browser-id@5.0.0: + resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==} + engines: {node: '>=18'} + dev: false + + /default-browser@5.2.1: + resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==} + engines: {node: '>=18'} + dependencies: + bundle-name: 4.1.0 + default-browser-id: 5.0.0 + dev: false + /defaults@1.0.4: resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} dependencies: @@ -9279,6 +9944,11 @@ packages: has-property-descriptors: 1.0.1 dev: true + /define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + dev: false + /define-properties@1.2.1: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} @@ -9368,6 +10038,11 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dev: false + /diff@5.0.0: + resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==} + engines: {node: '>=0.3.1'} + dev: true + /diff@5.1.0: resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==} engines: {node: '>=0.3.1'} @@ -9431,6 +10106,71 @@ packages: engines: {node: '>=10'} dev: true + /drizzle-orm@0.28.6(@libsql/client@0.4.3): + resolution: {integrity: sha512-yBe+F9htrlYER7uXgDJUQsTHFoIrI5yMm5A0bg0GiZ/kY5jNXTWoEy4KQtg35cE27sw1VbgzoMWHAgCckUUUww==} + peerDependencies: + '@aws-sdk/client-rds-data': '>=3' + '@cloudflare/workers-types': '>=3' + '@libsql/client': '*' + '@neondatabase/serverless': '>=0.1' + '@opentelemetry/api': ^1.4.1 + '@planetscale/database': '>=1' + '@types/better-sqlite3': '*' + '@types/pg': '*' + '@types/sql.js': '*' + '@vercel/postgres': '*' + better-sqlite3: '>=7' + bun-types: '*' + knex: '*' + kysely: '*' + mysql2: '>=2' + pg: '>=8' + postgres: '>=3' + sql.js: '>=1' + sqlite3: '>=5' + peerDependenciesMeta: + '@aws-sdk/client-rds-data': + optional: true + '@cloudflare/workers-types': + optional: true + '@libsql/client': + optional: true + '@neondatabase/serverless': + optional: true + '@opentelemetry/api': + optional: true + '@planetscale/database': + optional: true + '@types/better-sqlite3': + optional: true + '@types/pg': + optional: true + '@types/sql.js': + optional: true + '@vercel/postgres': + optional: true + better-sqlite3: + optional: true + bun-types: + optional: true + knex: + optional: true + kysely: + optional: true + mysql2: + optional: true + pg: + optional: true + postgres: + optional: true + sql.js: + optional: true + sqlite3: + optional: true + dependencies: + '@libsql/client': 0.4.3 + dev: false + /dset@3.1.3: resolution: {integrity: sha512-20TuZZHCEZ2O71q9/+8BwKwZ0QtD9D8ObhrihJPr+vLLYlSuAU3/zL4cSlgbfeoGHTjCSJBa7NGcrF9/Bx/WJQ==} engines: {node: '>=4'} @@ -9460,7 +10200,6 @@ packages: dependencies: '@emmetio/abbreviation': 2.3.3 '@emmetio/css-abbreviation': 2.1.8 - dev: true /emoji-regex@10.3.0: resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} @@ -9598,6 +10337,36 @@ packages: globby: 11.1.0 dev: true + /esbuild@0.18.20: + resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.18.20 + '@esbuild/android-arm64': 0.18.20 + '@esbuild/android-x64': 0.18.20 + '@esbuild/darwin-arm64': 0.18.20 + '@esbuild/darwin-x64': 0.18.20 + '@esbuild/freebsd-arm64': 0.18.20 + '@esbuild/freebsd-x64': 0.18.20 + '@esbuild/linux-arm': 0.18.20 + '@esbuild/linux-arm64': 0.18.20 + '@esbuild/linux-ia32': 0.18.20 + '@esbuild/linux-loong64': 0.18.20 + '@esbuild/linux-mips64el': 0.18.20 + '@esbuild/linux-ppc64': 0.18.20 + '@esbuild/linux-riscv64': 0.18.20 + '@esbuild/linux-s390x': 0.18.20 + '@esbuild/linux-x64': 0.18.20 + '@esbuild/netbsd-x64': 0.18.20 + '@esbuild/openbsd-x64': 0.18.20 + '@esbuild/sunos-x64': 0.18.20 + '@esbuild/win32-arm64': 0.18.20 + '@esbuild/win32-ia32': 0.18.20 + '@esbuild/win32-x64': 0.18.20 + dev: true + /esbuild@0.19.11: resolution: {integrity: sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA==} engines: {node: '>=12'} @@ -9728,7 +10497,7 @@ packages: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -10051,6 +10820,11 @@ packages: rimraf: 3.0.2 dev: true + /flat@5.0.2: + resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} + hasBin: true + dev: true + /flatted@3.2.9: resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} dev: true @@ -10114,6 +10888,15 @@ packages: universalify: 2.0.1 dev: true + /fs-extra@11.2.0: + resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} + engines: {node: '>=14.14'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + dev: false + /fs-extra@7.0.1: resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} engines: {node: '>=6 <7 || >=8'} @@ -10197,7 +10980,6 @@ packages: /get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} - dev: true /get-east-asian-width@1.2.0: resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} @@ -10206,7 +10988,6 @@ packages: /get-func-name@2.0.2: resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} - dev: false /get-intrinsic@1.2.2: resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==} @@ -10275,6 +11056,17 @@ packages: minipass: 7.0.4 path-scurry: 1.10.1 + /glob@7.2.0: + resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + /glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} dependencies: @@ -10681,7 +11473,6 @@ packages: /he@1.2.0: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true - dev: false /hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} @@ -10765,7 +11556,7 @@ packages: dependencies: '@tootallnate/once': 2.0.0 agent-base: 6.0.2 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color dev: true @@ -10775,7 +11566,7 @@ packages: engines: {node: '>= 6'} dependencies: agent-base: 6.0.2 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -10784,7 +11575,7 @@ packages: engines: {node: '>= 14'} dependencies: agent-base: 7.1.0 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color dev: false @@ -11054,6 +11845,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /is-plain-obj@2.1.0: + resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} + engines: {node: '>=8'} + dev: true + /is-plain-obj@4.1.0: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} @@ -11113,6 +11909,11 @@ packages: which-typed-array: 1.1.13 dev: true + /is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + dev: true + /is-unicode-supported@1.3.0: resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} engines: {node: '>=12'} @@ -11160,6 +11961,10 @@ packages: resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} hasBin: true + /js-base64@3.7.6: + resolution: {integrity: sha512-NPrWuHFxFUknr1KqJRDgUQPexQF0uIJWjeT+2KjEePhitQxQEx5EJBG1lVn5/hc8aLycTpXrDOgPQ6Zq+EDiTA==} + dev: false + /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -11272,7 +12077,6 @@ packages: /jsonc-parser@2.3.1: resolution: {integrity: sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==} - dev: true /jsonc-parser@3.2.0: resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} @@ -11294,7 +12098,10 @@ packages: universalify: 2.0.1 optionalDependencies: graceful-fs: 4.2.11 - dev: true + + /just-map-values@3.2.0: + resolution: {integrity: sha512-TyqCKtK3NxiUgOjRYMIKURvBTHesi3XzomDY0QVPZ3rYzLCF+nNq5rSi0B/L5aOd/WMTZo6ukzA4wih4HUbrDg==} + dev: false /katex@0.16.9: resolution: {integrity: sha512-fsSYjWS0EEOwvy81j3vRA8TEAhQhKiqO+FQaKWp0m39qwOzHVBgAUBIXWj1pB+O2W3fIpNa6Y9KSKCVbfPhyAQ==} @@ -11333,6 +12140,25 @@ packages: type-check: 0.4.0 dev: true + /libsql@0.2.0: + resolution: {integrity: sha512-ELBRqhpJx5Dap0187zKQnntZyk4EjlDHSrjIVL8t+fQ5e8IxbQTeYgZgigMjB1EvrETdkm0Y0VxBGhzPQ+t0Jg==} + cpu: [x64, arm64] + os: [darwin, linux, win32] + requiresBuild: true + dependencies: + '@neon-rs/load': 0.0.4 + detect-libc: 2.0.2 + optionalDependencies: + '@libsql/darwin-arm64': 0.2.0 + '@libsql/darwin-x64': 0.2.0 + '@libsql/linux-arm64-gnu': 0.2.0 + '@libsql/linux-arm64-musl': 0.2.0 + '@libsql/linux-x64-gnu': 0.2.0 + '@libsql/linux-x64-musl': 0.2.0 + '@libsql/win32-x64-msvc': 0.2.0 + dev: false + optional: true + /lilconfig@2.1.0: resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} @@ -11483,6 +12309,14 @@ packages: resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} dev: true + /log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + dev: true + /log-symbols@5.1.0: resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==} engines: {node: '>=12'} @@ -11515,7 +12349,6 @@ packages: resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} dependencies: get-func-name: 2.0.2 - dev: false /lower-case@1.1.4: resolution: {integrity: sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==} @@ -12219,7 +13052,7 @@ packages: resolution: {integrity: sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==} dependencies: '@types/debug': 4.1.12 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) decode-named-character-reference: 1.0.2 devlop: 1.1.0 micromark-core-commonmark: 2.0.0 @@ -12291,6 +13124,13 @@ packages: dependencies: brace-expansion: 1.1.11 + /minimatch@5.0.1: + resolution: {integrity: sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: true + /minimatch@7.4.6: resolution: {integrity: sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==} engines: {node: '>=10'} @@ -12376,6 +13216,34 @@ packages: ufo: 1.4.0 dev: false + /mocha@10.2.0: + resolution: {integrity: sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==} + engines: {node: '>= 14.0.0'} + hasBin: true + dependencies: + ansi-colors: 4.1.1 + browser-stdout: 1.3.1 + chokidar: 3.5.3 + debug: 4.3.4(supports-color@8.1.1) + diff: 5.0.0 + escape-string-regexp: 4.0.0 + find-up: 5.0.0 + glob: 7.2.0 + he: 1.2.0 + js-yaml: 4.1.0 + log-symbols: 4.1.0 + minimatch: 5.0.1 + ms: 2.1.3 + nanoid: 3.3.3 + serialize-javascript: 6.0.0 + strip-json-comments: 3.1.1 + supports-color: 8.1.1 + workerpool: 6.2.1 + yargs: 16.2.0 + yargs-parser: 20.2.4 + yargs-unparser: 2.0.0 + dev: true + /mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} @@ -12399,6 +13267,10 @@ packages: resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==} dev: true + /muggle-string@0.4.1: + resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} + dev: false + /mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} dependencies: @@ -12406,11 +13278,23 @@ packages: object-assign: 4.1.1 thenify-all: 1.6.0 + /nanoid@3.3.3: + resolution: {integrity: sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: true + /nanoid@3.3.7: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + /nanoid@5.0.1: + resolution: {integrity: sha512-vWeVtV5Cw68aML/QaZvqN/3QQXc6fBfIieAlu05m7FZW2Dgb+3f0xc0TTxuJW+7u30t7iSDTV/j3kVI0oJqIfQ==} + engines: {node: ^18 || >=20} + hasBin: true + dev: false + /nanostores@0.9.5: resolution: {integrity: sha512-Z+p+g8E7yzaWwOe5gEUB2Ox0rCEeXWYIZWmYvw/ajNYX8DlXdMvMDj8DWfM/subqPAcsf8l8Td4iAwO1DeIIRQ==} engines: {node: ^16.0.0 || ^18.0.0 || >=20.0.0} @@ -12651,6 +13535,20 @@ packages: which-pm-runs: 1.1.0 dev: true + /open-props@1.6.17: + resolution: {integrity: sha512-6mp/gpLQz/ZwrGLz+i7tSJ3eWNLE1KxLXHO+b6xxRyZ1Alp4TgTcvHiQ89rC2IkvsU3/IRhpIJuxl7rRCwUzLA==} + dev: false + + /open@10.0.3: + resolution: {integrity: sha512-dtbI5oW7987hwC9qjJTyABldTaa19SuyJse1QboWv3b0qCcrrLNVDqBx1XgELAjh9QTVQaP/C5b1nhQebd1H2A==} + engines: {node: '>=18'} + dependencies: + default-browser: 5.2.1 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + is-wsl: 3.1.0 + dev: false + /optionator@0.9.3: resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} engines: {node: '>= 0.8.0'} @@ -12857,7 +13755,6 @@ packages: /path-browserify@1.0.1: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} - dev: true /path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} @@ -12924,7 +13821,6 @@ packages: /pathval@1.1.1: resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} - dev: false /periscopic@3.1.0: resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} @@ -13464,7 +14360,6 @@ packages: '@astrojs/compiler': 1.8.2 prettier: 3.1.1 sass-formatter: 0.7.8 - dev: true /prettier@2.8.8: resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} @@ -13476,7 +14371,6 @@ packages: resolution: {integrity: sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==} engines: {node: '>=14'} hasBin: true - dev: true /pretty-bytes@5.6.0: resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==} @@ -13575,6 +14469,12 @@ packages: engines: {node: '>=8'} dev: true + /randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + dependencies: + safe-buffer: 5.2.1 + dev: true + /range-parser@1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} @@ -13942,12 +14842,10 @@ packages: /request-light@0.7.0: resolution: {integrity: sha512-lMbBMrDoxgsyO+yB3sDcrDuX85yYt7sS8BfQd11jtbW/z5ZWgLZRcEGLsLoYw7I0WSUGQBs8CC8ScIxkTX1+6Q==} - dev: true /require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} - dev: true /require-main-filename@2.0.0: resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} @@ -14031,6 +14929,14 @@ packages: dependencies: glob: 7.2.3 + /rollup@3.29.4: + resolution: {integrity: sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==} + engines: {node: '>=14.18.0', npm: '>=8.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.3 + dev: true + /rollup@4.9.2: resolution: {integrity: sha512-66RB8OtFKUTozmVEh3qyNfH+b+z2RXBVloqO2KCC/pjFaGaHtxP9fVfOQKPSGXg2mElmjmxjW/fZ7iKrEpMH5Q==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -14055,6 +14961,11 @@ packages: resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==} dev: true + /run-applescript@7.0.0: + resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} + engines: {node: '>=18'} + dev: false + /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: @@ -14062,7 +14973,6 @@ packages: /s.color@0.0.15: resolution: {integrity: sha512-AUNrbEUHeKY8XsYr/DYpl+qk5+aM+DChopnWOPEzn8YKzOhv4l2zH6LzZms3tOZP3wwdOyc0RmTciyi46HLIuA==} - dev: true /safe-array-concat@1.0.1: resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==} @@ -14093,7 +15003,6 @@ packages: resolution: {integrity: sha512-7fI2a8THglflhhYis7k06eUf92VQuJoXzEs2KRP0r1bluFxKFvLx0Ns7c478oYGM0fPfrr846ZRWVi2MAgHt9Q==} dependencies: suf-log: 2.5.3 - dev: true /sass@1.69.6: resolution: {integrity: sha512-qbRr3k9JGHWXCvZU77SD2OTwUlC+gNT+61JOLcmLm+XqH4h/5D+p4IIsxvpkB89S9AwJOyb5+rWNpIucaFxSFQ==} @@ -14173,6 +15082,12 @@ packages: transitivePeerDependencies: - supports-color + /serialize-javascript@6.0.0: + resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==} + dependencies: + randombytes: 2.1.0 + dev: true + /seroval@0.15.1: resolution: {integrity: sha512-OPVtf0qmeC7RW+ScVX+7aOS+xoIM7pWcZ0jOWg2aTZigCydgRB04adfteBRbecZnnrO1WuGQ+C3tLeBBzX2zSQ==} engines: {node: '>=10'} @@ -14336,6 +15251,21 @@ packages: simple-concat: 1.0.1 dev: false + /simple-stack-form@0.1.10(astro@packages+astro)(zod@3.22.4): + resolution: {integrity: sha512-00eCXPhSbryGunR9N5+jkGLGVVExySwxmAThK/MIedwVCNkbOf16/PFdSha6JgpGhpQxcETr6uOc+Y0zg2GaMg==} + hasBin: true + peerDependencies: + astro: '*' + zod: ^3.22.4 + dependencies: + '@clack/prompts': 0.7.0 + astro: link:packages/astro + fs-extra: 11.2.0 + just-map-values: 3.2.0 + kleur: 4.1.5 + zod: 3.22.4 + dev: false + /simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} requiresBuild: true @@ -14688,7 +15618,6 @@ packages: resolution: {integrity: sha512-KvC8OPjzdNOe+xQ4XWJV2whQA0aM1kGVczMQ8+dStAO6KfEB140JEVQ9dE76ONZ0/Ylf67ni4tILPJB41U0eow==} dependencies: s.color: 0.0.15 - dev: true /supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} @@ -14702,6 +15631,12 @@ packages: dependencies: has-flag: 4.0.0 + /supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + dependencies: + has-flag: 4.0.0 + /supports-hyperlinks@2.3.0: resolution: {integrity: sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==} engines: {node: '>=8'} @@ -15139,7 +16074,6 @@ packages: /type-detect@4.0.8: resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} engines: {node: '>=4'} - dev: false /type-fest@0.13.1: resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} @@ -15223,19 +16157,23 @@ packages: /typesafe-path@0.2.2: resolution: {integrity: sha512-OJabfkAg1WLZSqJAJ0Z6Sdt3utnbzr/jh+NAHoyWHJe8CMSy79Gm085094M9nvTPy22KzTVn5Zq5mbapCI/hPA==} - dev: true /typescript-auto-import-cache@0.3.2: resolution: {integrity: sha512-+laqe5SFL1vN62FPOOJSUDTZxtgsoOXjneYOXIpx5rQ4UMiN89NAtJLpqLqyebv9fgQ/IMeeTX+mQyRnwvJzvg==} dependencies: semver: 7.5.4 - dev: true /typescript@5.2.2: resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==} engines: {node: '>=14.17'} hasBin: true + /typescript@5.3.2: + resolution: {integrity: sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==} + engines: {node: '>=14.17'} + hasBin: true + dev: false + /ufo@1.4.0: resolution: {integrity: sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==} dev: false @@ -15448,7 +16386,6 @@ packages: /universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} - dev: true /unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} @@ -15562,7 +16499,7 @@ packages: hasBin: true dependencies: cac: 6.7.14 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) pathe: 1.1.2 picocolors: 1.0.0 vite: 5.1.2(@types/node@18.19.4)(sass@1.69.6) @@ -15621,6 +16558,42 @@ packages: svgo: 3.2.0 dev: false + /vite@4.4.11(@types/node@18.19.4): + resolution: {integrity: sha512-ksNZJlkcU9b0lBwAGZGGaZHCMqHsc8OpgtoYhsQ4/I2v5cnpmmmqe5pM4nv/4Hn6G/2GhTdj0DhZh2e+Er1q5A==} + engines: {node: ^14.18.0 || >=16.0.0} + hasBin: true + peerDependencies: + '@types/node': '>= 14' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + '@types/node': 18.19.4 + esbuild: 0.18.20 + postcss: 8.4.35 + rollup: 3.29.4 + optionalDependencies: + fsevents: 2.3.3 + dev: true + /vite@5.1.2(@types/node@18.19.4)(sass@1.69.6): resolution: {integrity: sha512-uwiFebQbTWRIGbCaTEBVAfKqgqKNKMJ2uPXsXeLIZxM8MVMjoS3j0cG8NrPxdDIadaWnPSjrkLWffLSC+uiP3Q==} engines: {node: ^18.0.0 || >=20.0.0} @@ -15702,7 +16675,7 @@ packages: acorn-walk: 8.3.2 cac: 6.7.14 chai: 4.4.1 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) execa: 8.0.1 local-pkg: 0.5.0 magic-string: 0.30.7 @@ -15738,6 +16711,19 @@ packages: vscode-uri: 3.0.8 dev: true + /volar-service-css@0.0.30(@volar/language-service@2.0.4): + resolution: {integrity: sha512-jui+1N0HBfjW43tRfhyZp0axhBee4997BRyX4os8xQm/7cjD2KjAuyz92nMIPRt1QDoG4/7uQT28xNhy0TPJTA==} + peerDependencies: + '@volar/language-service': ~2.0.1 + peerDependenciesMeta: + '@volar/language-service': + optional: true + dependencies: + '@volar/language-service': 2.0.4 + vscode-css-languageservice: 6.2.11 + vscode-uri: 3.0.8 + dev: false + /volar-service-emmet@0.0.16(@volar/language-service@1.10.10): resolution: {integrity: sha512-8sWWywzVJOD+PWDArOXDWbiRlM7+peydFhXJT71i4X1WPW32RyPxn6FypvciO+amqpfZP2rXfB9eibIJ+EofSQ==} peerDependencies: @@ -15751,6 +16737,19 @@ packages: volar-service-html: 0.0.16(@volar/language-service@1.10.10) dev: true + /volar-service-emmet@0.0.30(@volar/language-service@2.0.4): + resolution: {integrity: sha512-HEeIrmqQ/DTfuQDI9ER5+YReXXjE9f7W6MlBmn5biUuPyizVTGfuILN8pJhmYvmPHCA7qHhU7CJqwE9DAh9AJg==} + peerDependencies: + '@volar/language-service': ~2.0.1 + peerDependenciesMeta: + '@volar/language-service': + optional: true + dependencies: + '@volar/language-service': 2.0.4 + '@vscode/emmet-helper': 2.9.2 + volar-service-html: 0.0.30(@volar/language-service@2.0.4) + dev: false + /volar-service-html@0.0.16(@volar/language-service@1.10.10): resolution: {integrity: sha512-/oEXXgry++1CnTXQBUNf9B8MZfTlYZuJfZA7Zx9MN7WS4ZPxk3BFOdal/cXH6RNR2ruNEYr5QTW9rsqtoUscag==} peerDependencies: @@ -15764,6 +16763,19 @@ packages: vscode-uri: 3.0.8 dev: true + /volar-service-html@0.0.30(@volar/language-service@2.0.4): + resolution: {integrity: sha512-wW3TEeRTeHv/3mC8Ik6T62SwewMWFungb8ydyEK/2GDHEntBEG/J9wtuh01/J0kYqPerhlT9zhdGB6PGYHAGuA==} + peerDependencies: + '@volar/language-service': ~2.0.1 + peerDependenciesMeta: + '@volar/language-service': + optional: true + dependencies: + '@volar/language-service': 2.0.4 + vscode-html-languageservice: 5.1.2 + vscode-uri: 3.0.8 + dev: false + /volar-service-prettier@0.0.16(@volar/language-service@1.10.10)(prettier@3.1.1): resolution: {integrity: sha512-Kj2ZdwJGEvfYbsHW8Sjrew/7EB4PgRoas4f8yAJzUUVxIC/kvhUwLDxQc8+N2IibomN76asJGWe+i6VZZvgIkw==} peerDependencies: @@ -15779,6 +16791,22 @@ packages: prettier: 3.1.1 dev: true + /volar-service-prettier@0.0.30(@volar/language-service@2.0.4)(prettier@3.1.1): + resolution: {integrity: sha512-Qdc5Zc0y4hJmJbpIQ52cSDjs0uvVug/e2nuL/XZWPJM6Cr5/3RjjoRVKtDQbKItFYlGk+JH+LSXvwQeD5TXZqg==} + peerDependencies: + '@volar/language-service': ~2.0.1 + prettier: ^2.2 || ^3.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + prettier: + optional: true + dependencies: + '@volar/language-service': 2.0.4 + prettier: 3.1.1 + vscode-uri: 3.0.8 + dev: false + /volar-service-typescript-twoslash-queries@0.0.16(@volar/language-service@1.10.10): resolution: {integrity: sha512-0gPrkDTD2bMj2AnSNykOKhfmPnBFE2LS1lF3LWA7qu1ChRnJF0sodwCCbbeNYJ9+yth956ApoU1BVQ8UrMg+yw==} peerDependencies: @@ -15790,6 +16818,17 @@ packages: '@volar/language-service': 1.10.10 dev: true + /volar-service-typescript-twoslash-queries@0.0.30(@volar/language-service@2.0.4): + resolution: {integrity: sha512-ahj6woBxhkZu7icQR58x5TnUaS8ZRKn7a+UvY+andmiTWsOaSu85zj36+LPZgZQi1MG+BtjNwUjKoxtZiN51PA==} + peerDependencies: + '@volar/language-service': ~2.0.1 + peerDependenciesMeta: + '@volar/language-service': + optional: true + dependencies: + '@volar/language-service': 2.0.4 + dev: false + /volar-service-typescript@0.0.16(@volar/language-service@1.10.10)(@volar/typescript@1.10.10): resolution: {integrity: sha512-k/qFKM2oxs/3fhbr/vcBSHnCLZ1HN3Aeh+bGvV9Lc9qIhrNyCVsDFOUJN1Qp4dI72+Y+eFSIDCLHmFEZdsP2EA==} peerDependencies: @@ -15809,6 +16848,25 @@ packages: vscode-uri: 3.0.8 dev: true + /volar-service-typescript@0.0.30(@volar/language-service@2.0.4)(@volar/typescript@2.0.4): + resolution: {integrity: sha512-jA8c0Mhy9rgAsrgtwocK95Smws1M2E0MxlQ/SVo/rmOGH32cX9UGgI0IENWKa3yagp/khfoemOIQDz/KNhI3zg==} + peerDependencies: + '@volar/language-service': ~2.0.1 + '@volar/typescript': ~2.0.1 + peerDependenciesMeta: + '@volar/language-service': + optional: true + dependencies: + '@volar/language-service': 2.0.4 + '@volar/typescript': 2.0.4 + path-browserify: 1.0.1 + semver: 7.5.4 + typescript-auto-import-cache: 0.3.2 + vscode-languageserver-textdocument: 1.0.11 + vscode-nls: 5.2.0 + vscode-uri: 3.0.8 + dev: false + /vscode-css-languageservice@6.2.11: resolution: {integrity: sha512-qn49Wa6K94LnizpVxmlYrcPf1Cb36gq1nNueW0COhi4shylXBzET5wuDbH8ZWQlJD0HM5Mmnn7WE9vQVVs+ULA==} dependencies: @@ -15816,7 +16874,6 @@ packages: vscode-languageserver-textdocument: 1.0.11 vscode-languageserver-types: 3.17.5 vscode-uri: 3.0.8 - dev: true /vscode-html-languageservice@5.1.1: resolution: {integrity: sha512-JenrspIIG/Q+93R6G3L6HdK96itSisMynE0glURqHpQbL3dKAKzdm8L40lAHNkwJeBg+BBPpAshZKv/38onrTQ==} @@ -15827,36 +16884,39 @@ packages: vscode-uri: 3.0.8 dev: true + /vscode-html-languageservice@5.1.2: + resolution: {integrity: sha512-wkWfEx/IIR3s2P5yD4aTGHiOb8IAzFxgkSt1uSC3itJ4oDAm23yG7o0L29JljUdnXDDgLafPAvhv8A2I/8riHw==} + dependencies: + '@vscode/l10n': 0.0.18 + vscode-languageserver-textdocument: 1.0.11 + vscode-languageserver-types: 3.17.5 + vscode-uri: 3.0.8 + dev: false + /vscode-jsonrpc@8.2.0: resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==} engines: {node: '>=14.0.0'} - dev: true /vscode-languageserver-protocol@3.17.5: resolution: {integrity: sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==} dependencies: vscode-jsonrpc: 8.2.0 vscode-languageserver-types: 3.17.5 - dev: true /vscode-languageserver-textdocument@1.0.11: resolution: {integrity: sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==} - dev: true /vscode-languageserver-types@3.17.5: resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==} - dev: true /vscode-languageserver@9.0.1: resolution: {integrity: sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==} hasBin: true dependencies: vscode-languageserver-protocol: 3.17.5 - dev: true /vscode-nls@5.2.0: resolution: {integrity: sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==} - dev: true /vscode-oniguruma@1.7.0: resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==} @@ -15868,11 +16928,9 @@ packages: /vscode-uri@2.1.2: resolution: {integrity: sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==} - dev: true /vscode-uri@3.0.8: resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==} - dev: true /vue@3.4.3(typescript@5.2.2): resolution: {integrity: sha512-GjN+culMAGv/mUbkIv8zMKItno8npcj5gWlXkSxf1SPTQf8eJ4A+YfHIvQFyL1IfuJcMl3soA7SmN1fRxbf/wA==} @@ -16032,6 +17090,10 @@ packages: string-width: 5.1.2 dev: false + /workerpool@6.2.1: + resolution: {integrity: sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==} + dev: true + /wrap-ansi@6.2.0: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} engines: {node: '>=8'} @@ -16071,7 +17133,6 @@ packages: optional: true utf-8-validate: optional: true - dev: true /xml-name-validator@4.0.0: resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} @@ -16107,7 +17168,6 @@ packages: /y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} - dev: true /yallist@2.1.2: resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} @@ -16132,10 +17192,25 @@ packages: decamelize: 1.2.0 dev: true + /yargs-parser@20.2.4: + resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==} + engines: {node: '>=10'} + dev: true + /yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} + /yargs-unparser@2.0.0: + resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} + engines: {node: '>=10'} + dependencies: + camelcase: 6.3.0 + decamelize: 4.0.0 + flat: 5.0.2 + is-plain-obj: 2.1.0 + dev: true + /yargs@15.4.1: resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} engines: {node: '>=8'} @@ -16153,6 +17228,19 @@ packages: yargs-parser: 18.1.3 dev: true + /yargs@16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + dependencies: + cliui: 7.0.4 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.4 + dev: true + /yargs@17.7.2: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} @@ -16164,7 +17252,6 @@ packages: string-width: 4.2.3 y18n: 5.0.8 yargs-parser: 21.1.1 - dev: true /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}