mirror of
https://github.com/nestriness/nestri.git
synced 2026-09-19 09:15:19 +03:00
feat: bring the control plane up to date
Squashes the current state of the internal working tree onto this history. The two trees had grown apart with no common ancestor, so this is a content sync rather than a merge, and the published history is preserved rather than rewritten — a force-push here would break every existing fork and clone to no benefit. What lands: - Waitlist: API route, core module, and migration 0006 alongside game aliases. - User verification. - CI, oxfmt config, editor settings. - Assorted fixes across the API routes and core modules. The repository's own README, the wordmark and the per-package READMEs are kept from this side; the internal tree had dropped them and they are what a stranger arriving here reads first. The marketing site in the internal tree is deliberately not here. It is a separate product with its own repo and its own licence, and this repo is the open one — a closed component does not belong in it regardless of how convenient the directory looked. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
14
.env.example
14
.env.example
@@ -1,13 +1,9 @@
|
|||||||
STEAM_API_KEY=
|
STEAM_API_KEY=
|
||||||
ALCHEMY_PASSWORD=
|
|
||||||
TEST_DATABASE_URL=
|
|
||||||
DATABASE_PASSWORD=
|
DATABASE_PASSWORD=
|
||||||
DATABASE_URL=
|
|
||||||
DATABASE_HOST=
|
DATABASE_HOST=
|
||||||
DATABASE_PORT=
|
|
||||||
DATABASE_USER=
|
|
||||||
ADMIN_SHARED_SECRET=
|
|
||||||
SSH_AUTH_KEY=
|
|
||||||
|
|
||||||
CLOUDFLARE_API_TOKEN=
|
# Isolated database for tests. Required by DB-backed tests; unset tests fail.
|
||||||
CLOUDFLARE_ACCOUNT_ID=
|
TEST_DATABASE_URL=
|
||||||
|
|
||||||
|
# Local development database (docker-compose)
|
||||||
|
DATABASE_URL=
|
||||||
|
|||||||
39
.github/workflows/ci.yml
vendored
Normal file
39
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
web:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:18-alpine
|
||||||
|
env:
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
POSTGRES_PASSWORD: postgres
|
||||||
|
POSTGRES_DB: nestri
|
||||||
|
ports:
|
||||||
|
- 5432:5432
|
||||||
|
options: >-
|
||||||
|
--health-cmd "pg_isready -U postgres"
|
||||||
|
--health-interval 10s
|
||||||
|
--health-timeout 5s
|
||||||
|
--health-retries 5
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: oven-sh/setup-bun@v2
|
||||||
|
with:
|
||||||
|
bun-version: 1.3.11
|
||||||
|
- name: Install
|
||||||
|
run: bun install --frozen-lockfile
|
||||||
|
- name: Push migrations
|
||||||
|
run: bun run db:push
|
||||||
|
env:
|
||||||
|
DATABASE_URL: postgres://postgres:postgres@localhost:5432/nestri
|
||||||
|
- name: Test
|
||||||
|
run: bun test
|
||||||
|
env:
|
||||||
|
TEST_DATABASE_URL: postgres://postgres:postgres@localhost:5432/nestri
|
||||||
23
.oxfmtrc.jsonc
Normal file
23
.oxfmtrc.jsonc
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://raw.githubusercontent.com/oxc-project/oxc/refs/heads/main/npm/oxfmt/configuration_schema.json",
|
||||||
|
"useTabs": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"sortImports": true,
|
||||||
|
"sortObjects": true,
|
||||||
|
"trailingComma": "none",
|
||||||
|
"printWidth": 100,
|
||||||
|
"bracketSameLine": true,
|
||||||
|
"embeddedLanguageFormatting": "auto",
|
||||||
|
"sortTailwindcss": true,
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": ["**/*.svelte", "**/*.svelte.ts", "**/*.svelte.js"],
|
||||||
|
"options": {
|
||||||
|
"svelte": true,
|
||||||
|
"svelte.allowShorthand": true,
|
||||||
|
"svelte.indentScriptAndStyle": true,
|
||||||
|
"svelte.sortOrder": "options-scripts-markup-styles"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
159
.zed/settings.json
Normal file
159
.zed/settings.json
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
{
|
||||||
|
"language_servers": ["!eslint", "!vtsls", "!typescript-language-server", "..."],
|
||||||
|
"lsp": {
|
||||||
|
"oxlint": {
|
||||||
|
"initialization_options": {
|
||||||
|
"settings": {
|
||||||
|
"configPath": "./oxlintrc.json",
|
||||||
|
"run": "onType",
|
||||||
|
"disableNestedConfig": false,
|
||||||
|
"fixKind": "safe_fix",
|
||||||
|
"typeAware": true,
|
||||||
|
"unusedDisableDirectives": "deny"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"oxfmt": {
|
||||||
|
"initialization_options": {
|
||||||
|
"fmt.configPath": "./.oxfmtrc.jsonc"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"languages": {
|
||||||
|
"CSS": {
|
||||||
|
"format_on_save": "on",
|
||||||
|
"prettier": {
|
||||||
|
"allowed": false
|
||||||
|
},
|
||||||
|
"formatter": [
|
||||||
|
{
|
||||||
|
"language_server": {
|
||||||
|
"name": "oxfmt"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"HTML": {
|
||||||
|
"format_on_save": "on",
|
||||||
|
"prettier": {
|
||||||
|
"allowed": false
|
||||||
|
},
|
||||||
|
"formatter": [
|
||||||
|
{
|
||||||
|
"language_server": {
|
||||||
|
"name": "oxfmt"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"JavaScript": {
|
||||||
|
"format_on_save": "on",
|
||||||
|
"prettier": {
|
||||||
|
"allowed": false
|
||||||
|
},
|
||||||
|
"formatter": [
|
||||||
|
{
|
||||||
|
"language_server": {
|
||||||
|
"name": "oxfmt"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code_action": "source.fixAll.oxc"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"JSON": {
|
||||||
|
"format_on_save": "on",
|
||||||
|
"prettier": {
|
||||||
|
"allowed": false
|
||||||
|
},
|
||||||
|
"formatter": [
|
||||||
|
{
|
||||||
|
"language_server": {
|
||||||
|
"name": "oxfmt"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"JSONC": {
|
||||||
|
"format_on_save": "on",
|
||||||
|
"prettier": {
|
||||||
|
"allowed": false
|
||||||
|
},
|
||||||
|
"formatter": [
|
||||||
|
{
|
||||||
|
"language_server": {
|
||||||
|
"name": "oxfmt"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Markdown": {
|
||||||
|
"format_on_save": "on",
|
||||||
|
"prettier": {
|
||||||
|
"allowed": false
|
||||||
|
},
|
||||||
|
"formatter": [
|
||||||
|
{
|
||||||
|
"language_server": {
|
||||||
|
"name": "oxfmt"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"TypeScript": {
|
||||||
|
"format_on_save": "on",
|
||||||
|
"prettier": {
|
||||||
|
"allowed": false
|
||||||
|
},
|
||||||
|
"language_servers": ["typescript-ls", "!vtsls", "!typescript-language-server", "..."],
|
||||||
|
"formatter": [
|
||||||
|
{
|
||||||
|
"language_server": {
|
||||||
|
"name": "oxfmt"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"TSX": {
|
||||||
|
"format_on_save": "on",
|
||||||
|
"prettier": {
|
||||||
|
"allowed": false
|
||||||
|
},
|
||||||
|
"language_servers": ["typescript-ls", "tsgo", "!vtsls", "!typescript-language-server", "..."],
|
||||||
|
"formatter": [
|
||||||
|
{
|
||||||
|
"language_server": {
|
||||||
|
"name": "oxfmt"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Svelte": {
|
||||||
|
"format_on_save": "on",
|
||||||
|
"prettier": {
|
||||||
|
"allowed": false
|
||||||
|
},
|
||||||
|
"language_servers": ["tailwind-language-server", "..."],
|
||||||
|
"formatter": {
|
||||||
|
"external": {
|
||||||
|
"command": "./node_modules/.bin/oxfmt",
|
||||||
|
"arguments": ["--stdin-filepath", "{buffer_path}"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"YAML": {
|
||||||
|
"format_on_save": "on",
|
||||||
|
"prettier": {
|
||||||
|
"allowed": false
|
||||||
|
},
|
||||||
|
"formatter": [
|
||||||
|
{
|
||||||
|
"language_server": {
|
||||||
|
"name": "oxfmt"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,10 +17,10 @@ const Database = Effect.gen(function* () {
|
|||||||
return yield* Cloudflare.Hyperdrive.Connection('db', {
|
return yield* Cloudflare.Hyperdrive.Connection('db', {
|
||||||
origin: {
|
origin: {
|
||||||
scheme: 'postgres',
|
scheme: 'postgres',
|
||||||
host: process.env.DATABASE_HOST ?? 'localhost',
|
host: 'public-nestri-pg-1-atdogthbymao.db.upclouddatabases.com',
|
||||||
port: Number(process.env.DATABASE_PORT ?? 5432),
|
port: 11569,
|
||||||
database,
|
database,
|
||||||
user: process.env.DATABASE_USER ?? 'postgres',
|
user: 'upadmin',
|
||||||
password: Redacted.make(process.env.DATABASE_PASSWORD!)
|
password: Redacted.make(process.env.DATABASE_PASSWORD!)
|
||||||
},
|
},
|
||||||
dev: {
|
dev: {
|
||||||
@@ -29,6 +29,7 @@ const Database = Effect.gen(function* () {
|
|||||||
port: 5432,
|
port: 5432,
|
||||||
database: 'nestri',
|
database: 'nestri',
|
||||||
user: 'postgres',
|
user: 'postgres',
|
||||||
|
sslmode: 'disable',
|
||||||
password: Redacted.make('postgres')
|
password: Redacted.make('postgres')
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -52,24 +53,22 @@ export const Auth = Effect.gen(function* () {
|
|||||||
|
|
||||||
export const Api = Effect.gen(function* () {
|
export const Api = Effect.gen(function* () {
|
||||||
const { stage } = yield* Alchemy.Stack;
|
const { stage } = yield* Alchemy.Stack;
|
||||||
const isPermanent = ["production", "sandbox", "dev"].includes(stage);
|
const isPermanent = ['production', 'sandbox', 'dev'].includes(stage);
|
||||||
const prefix = stage === "production" ? "" : `${stage}.`;
|
const prefix = stage === 'production' ? '' : `${stage}.`;
|
||||||
const authDomain = ["production", "sandbox"].includes(stage)
|
const authDomain = ['production', 'sandbox'].includes(stage)
|
||||||
? `${prefix}auth.nestri.io`
|
? `${prefix}auth.nestri.io`
|
||||||
: undefined;
|
: undefined;
|
||||||
return yield* Cloudflare.Worker("api", {
|
return yield* Cloudflare.Worker('api', {
|
||||||
main: "apps/api/app/index.ts",
|
main: 'apps/api/app/index.ts',
|
||||||
compatibility: { flags: ["nodejs_compat"] },
|
compatibility: { flags: ['nodejs_compat'] },
|
||||||
env: {
|
env: {
|
||||||
AUTH: Auth,
|
AUTH: Auth,
|
||||||
AUTH_ISSUER_URL: authDomain
|
AUTH_ISSUER_URL: authDomain ? `https://${authDomain}` : 'http://localhost:1337',
|
||||||
? `https://${authDomain}`
|
|
||||||
: "http://localhost:1337",
|
|
||||||
HYPERDRIVE: Database,
|
HYPERDRIVE: Database,
|
||||||
STEAM_API_KEY: steamApiKey,
|
STEAM_API_KEY: steamApiKey,
|
||||||
ADMIN_SHARED_SECRET: adminSharedSecret,
|
ADMIN_SHARED_SECRET: adminSharedSecret
|
||||||
},
|
},
|
||||||
...(isPermanent ? { observability: { enabled: true } } : {}),
|
...(isPermanent ? { observability: { enabled: true } } : {})
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -86,39 +85,39 @@ export default Alchemy.Stack(
|
|||||||
const auth = yield* Auth;
|
const auth = yield* Auth;
|
||||||
const api = yield* Api;
|
const api = yield* Api;
|
||||||
|
|
||||||
if (stage === "production" || stage === "sandbox") {
|
if (stage === 'production' || stage === 'sandbox') {
|
||||||
const zone = yield* Cloudflare.Zone.Zone("zone", {
|
const zone = yield* Cloudflare.Zone.Zone('zone', {
|
||||||
name: "nestri.io",
|
name: 'nestri.io'
|
||||||
}).pipe(adopt(true));
|
}).pipe(adopt(true));
|
||||||
|
|
||||||
const prefix = stage === "production" ? "" : `${stage}.`;
|
const prefix = stage === 'production' ? '' : `${stage}.`;
|
||||||
|
|
||||||
yield* Cloudflare.DNS.Record("auth-dns", {
|
yield* Cloudflare.DNS.Record('auth-dns', {
|
||||||
zoneId: zone.zoneId,
|
zoneId: zone.zoneId,
|
||||||
name: `${prefix}auth.nestri.io`,
|
name: `${prefix}auth.nestri.io`,
|
||||||
type: "AAAA",
|
type: 'AAAA',
|
||||||
content: "100::",
|
content: '100::',
|
||||||
proxied: true,
|
proxied: true
|
||||||
});
|
});
|
||||||
|
|
||||||
yield* Cloudflare.DNS.Record("api-dns", {
|
yield* Cloudflare.DNS.Record('api-dns', {
|
||||||
zoneId: zone.zoneId,
|
zoneId: zone.zoneId,
|
||||||
name: `${prefix}api.nestri.io`,
|
name: `${prefix}api.nestri.io`,
|
||||||
type: "AAAA",
|
type: 'AAAA',
|
||||||
content: "100::",
|
content: '100::',
|
||||||
proxied: true,
|
proxied: true
|
||||||
});
|
});
|
||||||
|
|
||||||
yield* Cloudflare.Workers.WorkerRoute("auth-route", {
|
yield* Cloudflare.Workers.WorkerRoute('auth-route', {
|
||||||
zoneId: zone.zoneId,
|
zoneId: zone.zoneId,
|
||||||
pattern: `${prefix}auth.nestri.io/*`,
|
pattern: `${prefix}auth.nestri.io/*`,
|
||||||
script: auth.workerName,
|
script: auth.workerName
|
||||||
});
|
});
|
||||||
|
|
||||||
yield* Cloudflare.Workers.WorkerRoute("api-route", {
|
yield* Cloudflare.Workers.WorkerRoute('api-route', {
|
||||||
zoneId: zone.zoneId,
|
zoneId: zone.zoneId,
|
||||||
pattern: `${prefix}api.nestri.io/*`,
|
pattern: `${prefix}api.nestri.io/*`,
|
||||||
script: api.workerName,
|
script: api.workerName
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import type { Api } from '../../../alchemy.run.ts';
|
|
||||||
import type { InferEnv } from 'alchemy/Cloudflare';
|
|
||||||
|
|
||||||
import { Env } from '@nestri/core/env';
|
import { Env } from '@nestri/core/env';
|
||||||
import { ErrorCodes, VisibleError } from '@nestri/core/error';
|
import { ErrorCodes, VisibleError } from '@nestri/core/error';
|
||||||
|
import type { InferEnv } from 'alchemy/Cloudflare';
|
||||||
import { Hono } from 'hono';
|
import { Hono } from 'hono';
|
||||||
import { openAPISpecs } from 'hono-openapi';
|
import { openAPISpecs } from 'hono-openapi';
|
||||||
import { cors } from 'hono/cors';
|
import { cors } from 'hono/cors';
|
||||||
@@ -10,6 +8,7 @@ import { HTTPException } from 'hono/http-exception';
|
|||||||
import { logger } from 'hono/logger';
|
import { logger } from 'hono/logger';
|
||||||
import { type ContentfulStatusCode } from 'hono/utils/http-status';
|
import { type ContentfulStatusCode } from 'hono/utils/http-status';
|
||||||
|
|
||||||
|
import type { Api } from '../../../alchemy.run.ts';
|
||||||
import { auth } from './middleware/auth.js';
|
import { auth } from './middleware/auth.js';
|
||||||
import { AccessTokenApi } from './routes/access-token.js';
|
import { AccessTokenApi } from './routes/access-token.js';
|
||||||
import { GameApi } from './routes/game.js';
|
import { GameApi } from './routes/game.js';
|
||||||
@@ -19,6 +18,7 @@ import { MachineApi } from './routes/machine.js';
|
|||||||
import { PairingCodeApi } from './routes/pairing-code.js';
|
import { PairingCodeApi } from './routes/pairing-code.js';
|
||||||
import { SteamApi } from './routes/steam.js';
|
import { SteamApi } from './routes/steam.js';
|
||||||
import { UserApi } from './routes/user.js';
|
import { UserApi } from './routes/user.js';
|
||||||
|
import { WaitlistApi } from './routes/waitlist.js';
|
||||||
|
|
||||||
export const app = new Hono();
|
export const app = new Hono();
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ app
|
|||||||
})
|
})
|
||||||
.use(
|
.use(
|
||||||
cors({
|
cors({
|
||||||
origin: () => Env.get().FRONTEND_URL || 'http://localhost:5173',
|
origin: () => 'http://localhost:5173',
|
||||||
credentials: true
|
credentials: true
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
@@ -45,6 +45,7 @@ const routes = app
|
|||||||
.route('/pairing-code', PairingCodeApi.route)
|
.route('/pairing-code', PairingCodeApi.route)
|
||||||
.route('/machine', MachineApi.route)
|
.route('/machine', MachineApi.route)
|
||||||
.route('/access-token', AccessTokenApi.route)
|
.route('/access-token', AccessTokenApi.route)
|
||||||
|
.route('/waitlist', WaitlistApi.route)
|
||||||
.onError((error, c) => {
|
.onError((error, c) => {
|
||||||
if (error instanceof VisibleError) {
|
if (error instanceof VisibleError) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { ErrorResponses, adminOnly, machineOrAdmin, notPublic, Result, validator
|
|||||||
const SyncGameSchema = z.object({
|
const SyncGameSchema = z.object({
|
||||||
steamAppId: z.number().int(),
|
steamAppId: z.number().int(),
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
|
aliases: z.string().optional(),
|
||||||
type: z.string().optional(),
|
type: z.string().optional(),
|
||||||
clientIcon: z.string().optional(),
|
clientIcon: z.string().optional(),
|
||||||
icon: z.string().optional(),
|
icon: z.string().optional(),
|
||||||
@@ -62,7 +63,6 @@ const SyncLibrarySchema = z.object({
|
|||||||
|
|
||||||
export namespace GameApi {
|
export namespace GameApi {
|
||||||
export const route = new Hono()
|
export const route = new Hono()
|
||||||
.use(notPublic)
|
|
||||||
.get(
|
.get(
|
||||||
'/',
|
'/',
|
||||||
describeRoute({
|
describeRoute({
|
||||||
@@ -150,6 +150,7 @@ export namespace GameApi {
|
|||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
'/sync',
|
'/sync',
|
||||||
|
notPublic,
|
||||||
adminOnly,
|
adminOnly,
|
||||||
describeRoute({
|
describeRoute({
|
||||||
tags: ['Games'],
|
tags: ['Games'],
|
||||||
@@ -216,6 +217,7 @@ export namespace GameApi {
|
|||||||
steamAppId: g.steamAppId,
|
steamAppId: g.steamAppId,
|
||||||
slug,
|
slug,
|
||||||
name: g.name,
|
name: g.name,
|
||||||
|
aliases: g.aliases ?? null,
|
||||||
type: g.type ?? null,
|
type: g.type ?? null,
|
||||||
clientIcon: g.clientIcon ?? null,
|
clientIcon: g.clientIcon ?? null,
|
||||||
icon: g.icon ?? null,
|
icon: g.icon ?? null,
|
||||||
@@ -341,6 +343,7 @@ export namespace GameApi {
|
|||||||
)
|
)
|
||||||
.get(
|
.get(
|
||||||
'/:id/download-state',
|
'/:id/download-state',
|
||||||
|
notPublic,
|
||||||
describeRoute({
|
describeRoute({
|
||||||
tags: ['Games'],
|
tags: ['Games'],
|
||||||
summary: 'Get download states for a game',
|
summary: 'Get download states for a game',
|
||||||
@@ -406,6 +409,7 @@ export namespace GameApi {
|
|||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
'/download-state',
|
'/download-state',
|
||||||
|
notPublic,
|
||||||
machineOrAdmin,
|
machineOrAdmin,
|
||||||
describeRoute({
|
describeRoute({
|
||||||
tags: ['Games'],
|
tags: ['Games'],
|
||||||
@@ -517,6 +521,7 @@ export namespace GameApi {
|
|||||||
)
|
)
|
||||||
.post(
|
.post(
|
||||||
'/',
|
'/',
|
||||||
|
notPublic,
|
||||||
adminOnly,
|
adminOnly,
|
||||||
describeRoute({
|
describeRoute({
|
||||||
tags: ['Games'],
|
tags: ['Games'],
|
||||||
|
|||||||
@@ -24,6 +24,36 @@ import { adminOnly, ErrorResponses, notPublic, Result, validator } from '../util
|
|||||||
*/
|
*/
|
||||||
export namespace PairingCodeApi {
|
export namespace PairingCodeApi {
|
||||||
export const route = new Hono()
|
export const route = new Hono()
|
||||||
|
.get(
|
||||||
|
'/',
|
||||||
|
notPublic,
|
||||||
|
describeRoute({
|
||||||
|
tags: ['PairingCode'],
|
||||||
|
summary: 'List your pairing codes',
|
||||||
|
description: 'Every pairing code the current user has generated, newest first.',
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: Result(
|
||||||
|
z.array(PairingCode.Info).meta({
|
||||||
|
description: 'All pairing codes for the current user',
|
||||||
|
example: [Examples.PairingCode]
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
description: 'Pairing codes'
|
||||||
|
},
|
||||||
|
401: ErrorResponses[401],
|
||||||
|
429: ErrorResponses[429]
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
async (c) => {
|
||||||
|
const rows = await PairingCode.listByUser(Actor.userID);
|
||||||
|
return c.json({ data: rows.map((row) => PairingCode.serialize(row)) });
|
||||||
|
}
|
||||||
|
)
|
||||||
.post(
|
.post(
|
||||||
'/',
|
'/',
|
||||||
notPublic,
|
notPublic,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { Actor } from '@nestri/core/actor';
|
|||||||
import { ErrorCodes, VisibleError } from '@nestri/core/error';
|
import { ErrorCodes, VisibleError } from '@nestri/core/error';
|
||||||
import { Examples } from '@nestri/core/examples';
|
import { Examples } from '@nestri/core/examples';
|
||||||
import { Steam } from '@nestri/core/steam/index';
|
import { Steam } from '@nestri/core/steam/index';
|
||||||
|
import { LinkedAccount } from '@nestri/core/user/linked-account';
|
||||||
import { Hono } from 'hono';
|
import { Hono } from 'hono';
|
||||||
import { describeRoute } from 'hono-openapi';
|
import { describeRoute } from 'hono-openapi';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
@@ -9,8 +10,76 @@ import { z } from 'zod';
|
|||||||
import { ErrorResponses, notPublic, Result, validator } from '../utils';
|
import { ErrorResponses, notPublic, Result, validator } from '../utils';
|
||||||
|
|
||||||
export namespace SteamApi {
|
export namespace SteamApi {
|
||||||
export const route = new Hono().use(notPublic).post(
|
export const route = new Hono()
|
||||||
'/link',
|
.use(notPublic)
|
||||||
|
.get(
|
||||||
|
'/linked',
|
||||||
|
describeRoute({
|
||||||
|
tags: ['Steam'],
|
||||||
|
summary: 'Get your linked Steam account',
|
||||||
|
description: 'The Steam account linked to the authenticated user, or null if none.',
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: Result(
|
||||||
|
z
|
||||||
|
.union([LinkedAccount.Info, z.null()])
|
||||||
|
.meta({
|
||||||
|
description: 'The linked Steam account, or null',
|
||||||
|
example: Examples.LinkedAccount
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
description: 'Linked Steam account'
|
||||||
|
},
|
||||||
|
401: ErrorResponses[401],
|
||||||
|
429: ErrorResponses[429]
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
async (c) => {
|
||||||
|
const linked = await LinkedAccount.findSteamByUser(Actor.userID);
|
||||||
|
return c.json({ data: linked ? LinkedAccount.serialize(linked) : null });
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.post(
|
||||||
|
'/unlink',
|
||||||
|
describeRoute({
|
||||||
|
tags: ['Steam'],
|
||||||
|
summary: 'Unlink your Steam account',
|
||||||
|
description: 'Detach the Steam account from the authenticated user.',
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: Result(
|
||||||
|
z.object({ unlinked: z.boolean() })
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
description: 'Steam account unlinked'
|
||||||
|
},
|
||||||
|
401: ErrorResponses[401],
|
||||||
|
404: ErrorResponses[404],
|
||||||
|
429: ErrorResponses[429]
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
async (c) => {
|
||||||
|
const linked = await LinkedAccount.findSteamByUser(Actor.userID);
|
||||||
|
if (!linked) {
|
||||||
|
throw new VisibleError(
|
||||||
|
'not_found',
|
||||||
|
ErrorCodes.NotFound.RESOURCE_NOT_FOUND,
|
||||||
|
'No Steam account is linked to this user'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await LinkedAccount.remove(linked.id);
|
||||||
|
return c.json({ data: { unlinked: true } });
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.post(
|
||||||
|
'/link',
|
||||||
describeRoute({
|
describeRoute({
|
||||||
tags: ['Steam'],
|
tags: ['Steam'],
|
||||||
summary: 'Link a Steam account',
|
summary: 'Link a Steam account',
|
||||||
|
|||||||
@@ -1,13 +1,35 @@
|
|||||||
import { Actor } from '@nestri/core/actor';
|
import { Actor } from '@nestri/core/actor';
|
||||||
|
import { Env } from '@nestri/core/env';
|
||||||
import { ErrorCodes, VisibleError } from '@nestri/core/error';
|
import { ErrorCodes, VisibleError } from '@nestri/core/error';
|
||||||
import { Examples } from '@nestri/core/examples';
|
import { Examples } from '@nestri/core/examples';
|
||||||
import { User } from '@nestri/core/user/index';
|
import { User } from '@nestri/core/user/index';
|
||||||
|
import { Fingerprint } from '@nestri/core/user/fingerprint';
|
||||||
|
import { VERIFICATION_TTL_MINUTES, Verification } from '@nestri/core/user/verification';
|
||||||
import { Hono } from 'hono';
|
import { Hono } from 'hono';
|
||||||
import { describeRoute } from 'hono-openapi';
|
import { describeRoute } from 'hono-openapi';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { ErrorResponses, notPublic, Result, validator } from '../utils';
|
import { ErrorResponses, notPublic, Result, validator } from '../utils';
|
||||||
|
|
||||||
|
const userResponses = {
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: Result(
|
||||||
|
User.Info.meta({
|
||||||
|
description: 'Current user profile',
|
||||||
|
example: Examples.User
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
description: 'Current user'
|
||||||
|
},
|
||||||
|
400: ErrorResponses[400],
|
||||||
|
404: ErrorResponses[404],
|
||||||
|
429: ErrorResponses[429]
|
||||||
|
} as const;
|
||||||
|
|
||||||
export namespace UserApi {
|
export namespace UserApi {
|
||||||
export const route = new Hono()
|
export const route = new Hono()
|
||||||
.use(notPublic)
|
.use(notPublic)
|
||||||
@@ -17,24 +39,7 @@ export namespace UserApi {
|
|||||||
tags: ['User'],
|
tags: ['User'],
|
||||||
summary: 'Get current user',
|
summary: 'Get current user',
|
||||||
description: "Get the authenticated user's profile",
|
description: "Get the authenticated user's profile",
|
||||||
responses: {
|
responses: userResponses
|
||||||
200: {
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: Result(
|
|
||||||
User.Info.meta({
|
|
||||||
description: 'Current user profile',
|
|
||||||
example: Examples.User
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
description: 'Current user'
|
|
||||||
},
|
|
||||||
400: ErrorResponses[400],
|
|
||||||
404: ErrorResponses[404],
|
|
||||||
429: ErrorResponses[429]
|
|
||||||
}
|
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
const user = await User.fromID(Actor.userID);
|
const user = await User.fromID(Actor.userID);
|
||||||
@@ -50,29 +55,247 @@ export namespace UserApi {
|
|||||||
return c.json({ data: user });
|
return c.json({ data: user });
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
.post(
|
||||||
|
'/email',
|
||||||
|
describeRoute({
|
||||||
|
tags: ['User'],
|
||||||
|
summary: 'Set your email address',
|
||||||
|
description:
|
||||||
|
'Attach (or replace) the authenticated users email. Verification is reset until the new address is verified.',
|
||||||
|
responses: {
|
||||||
|
...userResponses,
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: Result(
|
||||||
|
User.Info.meta({
|
||||||
|
description: 'The updated user profile',
|
||||||
|
example: Examples.User
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
description: 'Email updated'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
validator(
|
||||||
|
'json',
|
||||||
|
z.object({
|
||||||
|
email: z.email().meta({
|
||||||
|
description: 'The new email address',
|
||||||
|
example: Examples.User.email
|
||||||
|
})
|
||||||
|
})
|
||||||
|
),
|
||||||
|
async (c) => {
|
||||||
|
const { email } = c.req.valid('json');
|
||||||
|
const user = await User.setEmail({
|
||||||
|
id: Actor.userID,
|
||||||
|
email,
|
||||||
|
emailVerified: false
|
||||||
|
});
|
||||||
|
return c.json({ data: user });
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.post(
|
||||||
|
'/email/send-code',
|
||||||
|
describeRoute({
|
||||||
|
tags: ['User'],
|
||||||
|
summary: 'Send an email verification code',
|
||||||
|
description:
|
||||||
|
'Create a fresh verification code for the users email. In development and test the code is returned as devCode; production will deliver it by email.',
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: Result(
|
||||||
|
z.object({
|
||||||
|
expiresInMinutes: z.number(),
|
||||||
|
devCode: z.string().optional().meta({
|
||||||
|
description: 'The code itself — only in development and test environments'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
description: 'Verification code created'
|
||||||
|
},
|
||||||
|
400: ErrorResponses[400],
|
||||||
|
429: ErrorResponses[429]
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
async (c) => {
|
||||||
|
const user = await User.fromID(Actor.userID);
|
||||||
|
if (!user?.email) {
|
||||||
|
throw new VisibleError(
|
||||||
|
'validation',
|
||||||
|
ErrorCodes.Validation.INVALID_STATE,
|
||||||
|
'Set an email address before requesting a verification code'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const code = await Verification.create({
|
||||||
|
userId: Actor.userID,
|
||||||
|
kind: 'email'
|
||||||
|
});
|
||||||
|
|
||||||
|
const isProd = Env.get().NODE_ENV === 'production';
|
||||||
|
return c.json({
|
||||||
|
data: {
|
||||||
|
expiresInMinutes: VERIFICATION_TTL_MINUTES,
|
||||||
|
...(isProd ? {} : { devCode: code })
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.post(
|
||||||
|
'/email/verify',
|
||||||
|
describeRoute({
|
||||||
|
tags: ['User'],
|
||||||
|
summary: 'Verify your email address',
|
||||||
|
description: 'Redeem a verification code to mark the email address as verified.',
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: Result(
|
||||||
|
z.object({ verified: z.boolean() })
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
description: 'Email verified'
|
||||||
|
},
|
||||||
|
400: ErrorResponses[400],
|
||||||
|
429: ErrorResponses[429]
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
validator(
|
||||||
|
'json',
|
||||||
|
z.object({
|
||||||
|
code: z.string().min(6).max(6).meta({
|
||||||
|
description: 'The 6-digit code from the email',
|
||||||
|
example: '123456'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
),
|
||||||
|
async (c) => {
|
||||||
|
const { code } = c.req.valid('json');
|
||||||
|
const result = await Verification.verifyEmail({ userId: Actor.userID, code });
|
||||||
|
|
||||||
|
if (result.reason === 'no_active_code') {
|
||||||
|
throw new VisibleError(
|
||||||
|
'validation',
|
||||||
|
ErrorCodes.Validation.INVALID_STATE,
|
||||||
|
'No active verification code — request a new one first'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (result.reason === 'wrong_code') {
|
||||||
|
throw new VisibleError(
|
||||||
|
'validation',
|
||||||
|
ErrorCodes.Validation.INVALID_PARAMETER,
|
||||||
|
'That verification code is not correct'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return c.json({ data: { verified: true } });
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.get(
|
||||||
|
'/devices',
|
||||||
|
describeRoute({
|
||||||
|
tags: ['User'],
|
||||||
|
summary: 'List your devices',
|
||||||
|
description: 'Every SSH key (fingerprint) enrolled to the authenticated user.',
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: Result(
|
||||||
|
z.array(Fingerprint.Info).meta({
|
||||||
|
description: 'Enrolled devices',
|
||||||
|
example: [Examples.Fingerprint]
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
description: 'Devices'
|
||||||
|
},
|
||||||
|
429: ErrorResponses[429]
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
async (c) => {
|
||||||
|
const rows = await Fingerprint.listByUser(Actor.userID);
|
||||||
|
return c.json({ data: rows.map((row) => Fingerprint.serialize(row)) });
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.patch(
|
||||||
|
'/devices/:id',
|
||||||
|
describeRoute({
|
||||||
|
tags: ['User'],
|
||||||
|
summary: 'Rename a device',
|
||||||
|
description: 'Give one of your SSH devices a human-readable name.',
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: Result(
|
||||||
|
Fingerprint.Info.meta({
|
||||||
|
description: 'The renamed device',
|
||||||
|
example: Examples.Fingerprint
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
description: 'Device renamed'
|
||||||
|
},
|
||||||
|
400: ErrorResponses[400],
|
||||||
|
404: ErrorResponses[404]
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
validator(
|
||||||
|
'param',
|
||||||
|
z.object({
|
||||||
|
id: z.string().meta({
|
||||||
|
description: 'ID of the device to rename',
|
||||||
|
example: Examples.Fingerprint.id
|
||||||
|
})
|
||||||
|
})
|
||||||
|
),
|
||||||
|
validator(
|
||||||
|
'json',
|
||||||
|
z.object({
|
||||||
|
name: z.string().min(1).max(64).nullable().meta({
|
||||||
|
description: 'The new name (or null to clear it)',
|
||||||
|
example: 'MacBook Air'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
),
|
||||||
|
async (c) => {
|
||||||
|
const { id } = c.req.valid('param');
|
||||||
|
const { name } = c.req.valid('json');
|
||||||
|
const userId = Actor.userID;
|
||||||
|
|
||||||
|
const device = await Fingerprint.fromID(id);
|
||||||
|
if (!device || device.userId !== userId) {
|
||||||
|
throw new VisibleError(
|
||||||
|
'not_found',
|
||||||
|
ErrorCodes.NotFound.RESOURCE_NOT_FOUND,
|
||||||
|
`Device ${id} not found`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await Fingerprint.updateName({ id, name });
|
||||||
|
const updated = await Fingerprint.fromID(id);
|
||||||
|
return c.json({ data: updated ? Fingerprint.serialize(updated) : null });
|
||||||
|
}
|
||||||
|
)
|
||||||
.get(
|
.get(
|
||||||
'/:id',
|
'/:id',
|
||||||
describeRoute({
|
describeRoute({
|
||||||
tags: ['User'],
|
tags: ['User'],
|
||||||
summary: 'Get user',
|
summary: 'Get user',
|
||||||
description: 'Get a user by their ID',
|
description: 'Get a user by their ID',
|
||||||
responses: {
|
responses: userResponses
|
||||||
200: {
|
|
||||||
content: {
|
|
||||||
'application/json': {
|
|
||||||
schema: Result(
|
|
||||||
User.Info.meta({
|
|
||||||
description: 'User details',
|
|
||||||
example: Examples.User
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
description: 'User details'
|
|
||||||
},
|
|
||||||
400: ErrorResponses[400],
|
|
||||||
429: ErrorResponses[429]
|
|
||||||
}
|
|
||||||
}),
|
}),
|
||||||
validator(
|
validator(
|
||||||
'param',
|
'param',
|
||||||
|
|||||||
86
apps/api/app/routes/waitlist.ts
Normal file
86
apps/api/app/routes/waitlist.ts
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
import { Examples } from '@nestri/core/examples';
|
||||||
|
import { Waitlist } from '@nestri/core/waitlist/index';
|
||||||
|
import { Hono } from 'hono';
|
||||||
|
import { describeRoute } from 'hono-openapi';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
import { adminOnly, ErrorResponses, Result, validator } from '../utils';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public signups for not-yet-launched features (the machines waitlist).
|
||||||
|
*
|
||||||
|
* Deliberately unauthenticated: a visitor without an account should be able
|
||||||
|
* to leave an email. The list itself is admin-only so a scraper cannot mine
|
||||||
|
* every address out of the response.
|
||||||
|
*/
|
||||||
|
export namespace WaitlistApi {
|
||||||
|
export const route = new Hono()
|
||||||
|
.post(
|
||||||
|
'/',
|
||||||
|
describeRoute({
|
||||||
|
tags: ['Waitlist'],
|
||||||
|
summary: 'Join the waitlist',
|
||||||
|
description: 'Leave an email to be notified when a feature launches. Public.',
|
||||||
|
responses: {
|
||||||
|
201: {
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: Result(
|
||||||
|
Waitlist.Info.meta({
|
||||||
|
description: 'The waitlist entry (the existing one if already joined)',
|
||||||
|
example: Examples.WaitlistEntry
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
description: 'Joined the waitlist'
|
||||||
|
},
|
||||||
|
400: ErrorResponses[400]
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
validator(
|
||||||
|
'json',
|
||||||
|
z.object({
|
||||||
|
email: z.email().meta({
|
||||||
|
description: 'The email to notify',
|
||||||
|
example: Examples.WaitlistEntry.email
|
||||||
|
}),
|
||||||
|
source: z.string().default('machines').meta({
|
||||||
|
description: 'What the signup is for',
|
||||||
|
example: Examples.WaitlistEntry.source
|
||||||
|
})
|
||||||
|
})
|
||||||
|
),
|
||||||
|
async (c) => {
|
||||||
|
const { email, source } = c.req.valid('json');
|
||||||
|
const entry = await Waitlist.join({ email, source });
|
||||||
|
return c.json({ data: entry }, 201);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.get(
|
||||||
|
'/',
|
||||||
|
adminOnly,
|
||||||
|
describeRoute({
|
||||||
|
tags: ['Waitlist'],
|
||||||
|
summary: 'List waitlist entries',
|
||||||
|
description: 'Every email currently on the waitlist. Admin only.',
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: Result(
|
||||||
|
z.array(Waitlist.Info).meta({
|
||||||
|
description: 'All waitlist entries',
|
||||||
|
example: [Examples.WaitlistEntry]
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
description: 'Waitlist entries'
|
||||||
|
},
|
||||||
|
403: ErrorResponses[403]
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
async (c) => c.json({ data: await Waitlist.list() })
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -18,22 +18,29 @@ describe('Index', () => {
|
|||||||
|
|
||||||
describe('Auth middleware', () => {
|
describe('Auth middleware', () => {
|
||||||
test('public access to a protected route returns 401', async () => {
|
test('public access to a protected route returns 401', async () => {
|
||||||
const res = await app.request('/games');
|
const res = await app.request('/library');
|
||||||
expect(res.status).toBe(401);
|
expect(res.status).toBe(401);
|
||||||
const body = (await res.json()) as any;
|
const body = (await res.json()) as any;
|
||||||
expect(body.type).toBe('authentication');
|
expect(body.type).toBe('authentication');
|
||||||
expect(body.code).toBe('unauthorized');
|
expect(body.code).toBe('unauthorized');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('game catalog search is public', async () => {
|
||||||
|
// The search-first TUI browses before it logs in, so the catalog
|
||||||
|
// must not sit behind auth.
|
||||||
|
const res = await app.request('/games');
|
||||||
|
expect(res.status).toBe(200);
|
||||||
|
});
|
||||||
|
|
||||||
test('admin token gains access to protected routes', async () => {
|
test('admin token gains access to protected routes', async () => {
|
||||||
const res = await app.request('/games', {
|
const res = await app.request('/waitlist', {
|
||||||
headers: adminHeaders()
|
headers: adminHeaders()
|
||||||
});
|
});
|
||||||
expect(res.status).toBe(200);
|
expect(res.status).toBe(200);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('wrong admin token is treated as public → 401', async () => {
|
test('wrong admin token is treated as public → 401', async () => {
|
||||||
const res = await app.request('/games', {
|
const res = await app.request('/library', {
|
||||||
headers: { 'x-nestri-admin-token': 'wrong-secret' }
|
headers: { 'x-nestri-admin-token': 'wrong-secret' }
|
||||||
});
|
});
|
||||||
expect(res.status).toBe(401);
|
expect(res.status).toBe(401);
|
||||||
@@ -46,7 +53,7 @@ describe('Auth middleware', () => {
|
|||||||
// not make the request a server fault. `verify` reports a malformed or
|
// not make the request a server fault. `verify` reports a malformed or
|
||||||
// expired token in `err`, but throws when it cannot reach the auth
|
// expired token in `err`, but throws when it cannot reach the auth
|
||||||
// service at all, and that throw used to surface as a 500.
|
// service at all, and that throw used to surface as a 500.
|
||||||
const res = await app.request('/games', {
|
const res = await app.request('/library', {
|
||||||
headers: { authorization: 'Bearer not-a-real-token' }
|
headers: { authorization: 'Bearer not-a-real-token' }
|
||||||
});
|
});
|
||||||
expect(res.status).toBe(401);
|
expect(res.status).toBe(401);
|
||||||
@@ -177,7 +184,13 @@ describe('OpenAPI doc', () => {
|
|||||||
expect(paths).toContain('/library');
|
expect(paths).toContain('/library');
|
||||||
expect(paths).toContain('/library/sync');
|
expect(paths).toContain('/library/sync');
|
||||||
expect(paths).toContain('/steam/link');
|
expect(paths).toContain('/steam/link');
|
||||||
|
expect(paths).toContain('/steam/linked');
|
||||||
|
expect(paths).toContain('/steam/unlink');
|
||||||
expect(paths).toContain('/user');
|
expect(paths).toContain('/user');
|
||||||
|
expect(paths).toContain('/user/email');
|
||||||
|
expect(paths).toContain('/user/devices');
|
||||||
|
expect(paths).toContain('/pairing-code');
|
||||||
|
expect(paths).toContain('/waitlist');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('doc has security schemes defined', async () => {
|
test('doc has security schemes defined', async () => {
|
||||||
@@ -340,7 +353,7 @@ describe('Access tokens', () => {
|
|||||||
test('an unknown access token is unauthenticated, not a server error', async () => {
|
test('an unknown access token is unauthenticated, not a server error', async () => {
|
||||||
// A `pat_` prefix routes to the database rather than JWT verification.
|
// A `pat_` prefix routes to the database rather than JWT verification.
|
||||||
// A miss there must read as "not signed in", the same as a bad JWT.
|
// A miss there must read as "not signed in", the same as a bad JWT.
|
||||||
const res = await app.request('/games', {
|
const res = await app.request('/library', {
|
||||||
headers: { authorization: 'Bearer pat_nosuchtokenvalue' }
|
headers: { authorization: 'Bearer pat_nosuchtokenvalue' }
|
||||||
});
|
});
|
||||||
expect(res.status).toBe(401);
|
expect(res.status).toBe(401);
|
||||||
@@ -539,4 +552,110 @@ describe('Pairing code routes', () => {
|
|||||||
});
|
});
|
||||||
expect(res.status).toBe(400);
|
expect(res.status).toBe(400);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('GET /pairing-code requires auth', async () => {
|
||||||
|
const res = await app.request('/pairing-code');
|
||||||
|
expect(res.status).toBe(401);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Email routes', () => {
|
||||||
|
test('POST /user/email requires auth', async () => {
|
||||||
|
const res = await app.request('/user/email', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'content-type': 'application/json' },
|
||||||
|
body: JSON.stringify({ email: 'a@b.com' })
|
||||||
|
});
|
||||||
|
expect(res.status).toBe(401);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('POST /user/email rejects a malformed address', async () => {
|
||||||
|
const res = await app.request('/user/email', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { ...adminHeaders(), 'content-type': 'application/json' },
|
||||||
|
body: JSON.stringify({ email: 'not-an-email' })
|
||||||
|
});
|
||||||
|
expect(res.status).toBe(400);
|
||||||
|
const body = (await res.json()) as any;
|
||||||
|
expect(body.type).toBe('validation');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('POST /user/email/send-code requires auth', async () => {
|
||||||
|
const res = await app.request('/user/email/send-code', { method: 'POST' });
|
||||||
|
expect(res.status).toBe(401);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('POST /user/email/verify requires auth', async () => {
|
||||||
|
const res = await app.request('/user/email/verify', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'content-type': 'application/json' },
|
||||||
|
body: JSON.stringify({ code: '123456' })
|
||||||
|
});
|
||||||
|
expect(res.status).toBe(401);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('POST /user/email/verify requires a 6-digit code', async () => {
|
||||||
|
const res = await app.request('/user/email/verify', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { ...adminHeaders(), 'content-type': 'application/json' },
|
||||||
|
body: JSON.stringify({ code: '12' })
|
||||||
|
});
|
||||||
|
expect(res.status).toBe(400);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Device routes', () => {
|
||||||
|
test('GET /user/devices requires auth', async () => {
|
||||||
|
const res = await app.request('/user/devices');
|
||||||
|
expect(res.status).toBe(401);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('PATCH /user/devices/:id requires auth', async () => {
|
||||||
|
const res = await app.request('/user/devices/ufp_whatever', {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: { 'content-type': 'application/json' },
|
||||||
|
body: JSON.stringify({ name: 'MacBook Air' })
|
||||||
|
});
|
||||||
|
expect(res.status).toBe(401);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Steam account routes', () => {
|
||||||
|
test('GET /steam/linked requires auth', async () => {
|
||||||
|
const res = await app.request('/steam/linked');
|
||||||
|
expect(res.status).toBe(401);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('POST /steam/unlink requires auth', async () => {
|
||||||
|
const res = await app.request('/steam/unlink', { method: 'POST' });
|
||||||
|
expect(res.status).toBe(401);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Waitlist routes', () => {
|
||||||
|
test('POST /waitlist joins without auth', async () => {
|
||||||
|
const res = await app.request('/waitlist', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'content-type': 'application/json' },
|
||||||
|
body: JSON.stringify({ email: 'waitlist@example.com' })
|
||||||
|
});
|
||||||
|
expect(res.status).toBe(201);
|
||||||
|
const body = (await res.json()) as any;
|
||||||
|
expect(body.data.email).toBe('waitlist@example.com');
|
||||||
|
expect(body.data.source).toBe('machines');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('POST /waitlist rejects a malformed email', async () => {
|
||||||
|
const res = await app.request('/waitlist', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'content-type': 'application/json' },
|
||||||
|
body: JSON.stringify({ email: 'nope' })
|
||||||
|
});
|
||||||
|
expect(res.status).toBe(400);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('GET /waitlist is admin-only', async () => {
|
||||||
|
const res = await app.request('/waitlist');
|
||||||
|
expect(res.status).toBe(403);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
399
bun.lock
399
bun.lock
@@ -57,37 +57,6 @@
|
|||||||
"typescript": "catalog:",
|
"typescript": "catalog:",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"apps/web": {
|
|
||||||
"name": "web",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"dependencies": {
|
|
||||||
"@fontsource-variable/geist": "^5.2.8",
|
|
||||||
"@fontsource-variable/geist-mono": "^5.2.7",
|
|
||||||
"@fontsource/ibm-plex-serif": "^5.2.7",
|
|
||||||
"@fontsource/instrument-serif": "^5.3.0",
|
|
||||||
"evlog": "^2.20.0",
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@cloudflare/workers-types": "^4.20250805.0",
|
|
||||||
"@nestri/core": "workspace:",
|
|
||||||
"@sveltejs/adapter-cloudflare": "^7.0.4",
|
|
||||||
"@sveltejs/kit": "^2.65.0",
|
|
||||||
"@sveltejs/vite-plugin-svelte": "^7.1.2",
|
|
||||||
"@tailwindcss/forms": "^0.5.11",
|
|
||||||
"@tailwindcss/typography": "^0.5.19",
|
|
||||||
"@tailwindcss/vite": "^4.1.18",
|
|
||||||
"@types/node": "^24",
|
|
||||||
"globals": "^17.3.0",
|
|
||||||
"oxfmt": "^0.58.0",
|
|
||||||
"oxlint": "^1.73.0",
|
|
||||||
"svelte": "^5.56.4",
|
|
||||||
"svelte-check": "^4.7.1",
|
|
||||||
"tailwindcss": "^4.1.18",
|
|
||||||
"typescript": "^7.0.1-rc",
|
|
||||||
"vite": "^8.1.1",
|
|
||||||
"wrangler": "^4.118.0",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"packages/auth": {
|
"packages/auth": {
|
||||||
"name": "@nestri/auth",
|
"name": "@nestri/auth",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
@@ -196,24 +165,20 @@
|
|||||||
|
|
||||||
"@clack/prompts": ["@clack/prompts@1.7.0", "", { "dependencies": { "@clack/core": "1.4.3", "fast-string-width": "^3.0.2", "fast-wrap-ansi": "^0.2.0", "sisteransi": "^1.0.5" } }, "sha512-y7/yvZ2TPAnR9+jnc00klvNNLkJiXFFrQA/hlLCcxA9a2A4zQIOimyFQ9XfwYKiGD1fb5GY8vbKIIgO8d5Tb2A=="],
|
"@clack/prompts": ["@clack/prompts@1.7.0", "", { "dependencies": { "@clack/core": "1.4.3", "fast-string-width": "^3.0.2", "fast-wrap-ansi": "^0.2.0", "sisteransi": "^1.0.5" } }, "sha512-y7/yvZ2TPAnR9+jnc00klvNNLkJiXFFrQA/hlLCcxA9a2A4zQIOimyFQ9XfwYKiGD1fb5GY8vbKIIgO8d5Tb2A=="],
|
||||||
|
|
||||||
"@cloudflare/kv-asset-handler": ["@cloudflare/kv-asset-handler@0.5.0", "", {}, "sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg=="],
|
|
||||||
|
|
||||||
"@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.16.1", "", { "peerDependencies": { "unenv": "2.0.0-rc.24", "workerd": ">1.20260305.0 <2.0.0-0" }, "optionalPeers": ["workerd"] }, "sha512-ECxObrMfyTl5bhQf/lZCXwo5G6xX9IAUo+nDMKK4SZ8m4Jvvxp52vilxyySSWh2YTZz8+HQ07qGH/2rEom1vDw=="],
|
"@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.16.1", "", { "peerDependencies": { "unenv": "2.0.0-rc.24", "workerd": ">1.20260305.0 <2.0.0-0" }, "optionalPeers": ["workerd"] }, "sha512-ECxObrMfyTl5bhQf/lZCXwo5G6xX9IAUo+nDMKK4SZ8m4Jvvxp52vilxyySSWh2YTZz8+HQ07qGH/2rEom1vDw=="],
|
||||||
|
|
||||||
"@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20260730.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-+MBHmPaiTe2KajryW0T24rZvWFxb41hD3d8anNzQqHzft6vSEb18+sp0znSwxgij7ApPhSM1+vhkNg4f3YMguA=="],
|
"@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20260704.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-XO+vvdhhTNZSsIWCkZ+JaE/JrFUmQAB0H0y/sVkAf32xa2TYBRvFUMwjSqf6WxtlxcKPQvmbLfpO/UQ0l/q4eQ=="],
|
||||||
|
|
||||||
"@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20260730.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-SBHKntPkKvNPgaCrTe99xC1CAl8ygJDzlYfK0LbuJ1muKadIw35WnhO0wu894fKBtllsVQdNzDLee+cm0ppLSQ=="],
|
"@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20260704.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-6iI7nbOOO8PzEQ6UZVBZB/hv95m8jl0yvyjMuWrF5cJbiLb5zPw3KnpqvGi+aeOs2ZmUkc81i1FWKfXwLXzPRA=="],
|
||||||
|
|
||||||
"@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20260730.1", "", { "os": "linux", "cpu": "x64" }, "sha512-ouyPOSMbiKPeSwUJUvxtMcxGAXs2J4aPE4T5ABIYX5ClcQx5j5bbHTmnqOQEY8sAuLTPjH7dY+iB6UI5ISlwwA=="],
|
"@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20260704.1", "", { "os": "linux", "cpu": "x64" }, "sha512-3mT0YHtxT7eLjghu3hKSJDUQoz+AYv8FM43nLPYhM0YiHOxr8OlmvnCb2Lp7v/U3bwd3Gnx7WEqjSppR583mGg=="],
|
||||||
|
|
||||||
"@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20260730.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-YQ+Mi78U3TPdgBPtwq+Sm6rJU+Ihl2y0pjYtuuKkdmUbYzL7oLR6Xqq9wljhasnuCFICssDJaqhMep5WizYoEQ=="],
|
"@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20260704.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-Opo7cPTPg4x0WwK+eZSDszCyFLKQkOGNCWxF005HRTJ5SJH8h0K9KyrC1k4LBwx3haXSVi+E1eGqo1gZ1Hmhkg=="],
|
||||||
|
|
||||||
"@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20260730.1", "", { "os": "win32", "cpu": "x64" }, "sha512-27fAN+vUECW1oYVc1KOcHYpkL8COM2Uxtxql7TL595kxbjoqS5yckw7NLz7bTf2pALFCZWjqXDjZGJ/xbG4ZKQ=="],
|
"@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20260704.1", "", { "os": "win32", "cpu": "x64" }, "sha512-a97Ecnzhy04x3U052VKPCNp863F7Wf00WY7Ga5P0SbtYvaO1PDzylsHrvFMPKeiDFcOwqiredawmJ+v6bhIgeQ=="],
|
||||||
|
|
||||||
"@cloudflare/workers-types": ["@cloudflare/workers-types@5.20260722.1", "", {}, "sha512-8+kivCgFGzwrAfNOWgSpzy/VDvmT/i5KWBgQhnygv3d1kajNn6mCYTbLKpouG0aY8mXjhv+IQm1a8r2K/H4pqQ=="],
|
"@cloudflare/workers-types": ["@cloudflare/workers-types@5.20260722.1", "", {}, "sha512-8+kivCgFGzwrAfNOWgSpzy/VDvmT/i5KWBgQhnygv3d1kajNn6mCYTbLKpouG0aY8mXjhv+IQm1a8r2K/H4pqQ=="],
|
||||||
|
|
||||||
"@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="],
|
|
||||||
|
|
||||||
"@distilled.cloud/aws": ["@distilled.cloud/aws@0.30.3", "", { "dependencies": { "@aws-crypto/crc32": "^5.2.0", "@aws-crypto/util": "^5.2.0", "@aws-sdk/credential-providers": "^3.994.0", "@aws-sdk/types": "^3.973.1", "@distilled.cloud/core": "0.30.3", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "aws4fetch": "^1.0.20", "fast-xml-parser": "^5.3.2" }, "peerDependencies": { "effect": ">=4.0.0-beta.100 || >=4.0.0" } }, "sha512-6U/wO+fLNnqBlRnqFpF79edS5t6njDl/6UmnCVUfWpIQ4n23X0VY1ft0lzsaBa506xRtF4vRhMELR9FIp5DKUA=="],
|
"@distilled.cloud/aws": ["@distilled.cloud/aws@0.30.3", "", { "dependencies": { "@aws-crypto/crc32": "^5.2.0", "@aws-crypto/util": "^5.2.0", "@aws-sdk/credential-providers": "^3.994.0", "@aws-sdk/types": "^3.973.1", "@distilled.cloud/core": "0.30.3", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "aws4fetch": "^1.0.20", "fast-xml-parser": "^5.3.2" }, "peerDependencies": { "effect": ">=4.0.0-beta.100 || >=4.0.0" } }, "sha512-6U/wO+fLNnqBlRnqFpF79edS5t6njDl/6UmnCVUfWpIQ4n23X0VY1ft0lzsaBa506xRtF4vRhMELR9FIp5DKUA=="],
|
||||||
|
|
||||||
"@distilled.cloud/axiom": ["@distilled.cloud/axiom@0.30.3", "", { "dependencies": { "@distilled.cloud/core": "0.30.3" }, "peerDependencies": { "effect": ">=4.0.0-beta.100 || >=4.0.0" } }, "sha512-U4YvXsvz/TDYfIbZNRVAv8Yx1mnbms/rBQ/RHnRQWhL0JzxZOZOQvToxkB4kh/oa8KT+QbjTkDxRJP/f6P0M1g=="],
|
"@distilled.cloud/axiom": ["@distilled.cloud/axiom@0.30.3", "", { "dependencies": { "@distilled.cloud/core": "0.30.3" }, "peerDependencies": { "effect": ">=4.0.0-beta.100 || >=4.0.0" } }, "sha512-U4YvXsvz/TDYfIbZNRVAv8Yx1mnbms/rBQ/RHnRQWhL0JzxZOZOQvToxkB4kh/oa8KT+QbjTkDxRJP/f6P0M1g=="],
|
||||||
@@ -314,72 +279,10 @@
|
|||||||
|
|
||||||
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="],
|
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="],
|
||||||
|
|
||||||
"@fontsource-variable/geist": ["@fontsource-variable/geist@5.3.0", "", {}, "sha512-j0m+vLQuG5XAYoHtGCVu0spvlGreR3EzpECUVzkFmI1mTVnAO38l/NEPDCFgZ177JxzYJCLSmTQibIiYPilGrA=="],
|
|
||||||
|
|
||||||
"@fontsource-variable/geist-mono": ["@fontsource-variable/geist-mono@5.3.0", "", {}, "sha512-vBbuwDEo9AkrqADMXOrlAR3DFcJi4/JxeuU43FoiQERnNwsfXNnvxvReZG02cQKmyk4DZkZdBZX3oTDvy2zBAw=="],
|
|
||||||
|
|
||||||
"@fontsource/ibm-plex-serif": ["@fontsource/ibm-plex-serif@5.3.0", "", {}, "sha512-zwPfHB7EJbS5B8qnitPigJYzNdnt6PUeaoOA1gAAt//1pjpTVZN5sOU14NIAZ+C1xypL6GWsUG2VMYJW9bhJqQ=="],
|
|
||||||
|
|
||||||
"@fontsource/instrument-serif": ["@fontsource/instrument-serif@5.3.0", "", {}, "sha512-mDiaIg0u67sYV59fie92Wz4sM8UiVlbL7fLxnFPCKkX15DMASEnQTREbaP5S5/3DCcsoAOcQ0sV9E4AeY4QqYQ=="],
|
|
||||||
|
|
||||||
"@hono/node-server": ["@hono/node-server@1.19.9", "", { "peerDependencies": { "hono": "^4" } }, "sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw=="],
|
"@hono/node-server": ["@hono/node-server@1.19.9", "", { "peerDependencies": { "hono": "^4" } }, "sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw=="],
|
||||||
|
|
||||||
"@hono/zod-validator": ["@hono/zod-validator@0.9.0", "", { "peerDependencies": { "hono": ">=4.11.2", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-n0ZSXmCiHVIp4Y5wlOOyZCeTd/rsawA/qW1cipB8QOYKZ9N8Tk0nZUZCXho9cu374AN4JpDNKioNKBJ/W+LBug=="],
|
"@hono/zod-validator": ["@hono/zod-validator@0.9.0", "", { "peerDependencies": { "hono": ">=4.11.2", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-n0ZSXmCiHVIp4Y5wlOOyZCeTd/rsawA/qW1cipB8QOYKZ9N8Tk0nZUZCXho9cu374AN4JpDNKioNKBJ/W+LBug=="],
|
||||||
|
|
||||||
"@img/colour": ["@img/colour@1.1.0", "", {}, "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ=="],
|
|
||||||
|
|
||||||
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.3.1" }, "os": "darwin", "cpu": "arm64" }, "sha512-eEieHsMksAW4IiO5NzauESRl2D2qz3J/kwUxUrSfV06A93eEaRfMpHXyUb1mAqrR7i8U9A0GRqE9pjn6u1Jjpg=="],
|
|
||||||
|
|
||||||
"@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.3.1" }, "os": "darwin", "cpu": "x64" }, "sha512-BaktuGPCeHJMARpodR8jK4uKiZrPAy9WrfQW0sdI37clracq8Bp01AYS3SZgi5FS/y5twa9t4+LIuuxQjqRrWw=="],
|
|
||||||
|
|
||||||
"@img/sharp-freebsd-wasm32": ["@img/sharp-freebsd-wasm32@0.35.2", "", { "dependencies": { "@img/sharp-wasm32": "0.35.2" }, "os": "freebsd" }, "sha512-YoAxdnd8hPUkvLHd3bWY+YA8nw3xM/RyRopYucNsWHVSan8NLVM3X2volsfoRDcXdUJPg6tXahSd7HXPK7lRnw=="],
|
|
||||||
|
|
||||||
"@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.3.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-4V/M3roRMTYjiwZY9IOVQOE8OyeCxFAkYmyZDrZl51uOKjibm3oeEJ4WAmLxutAfzFbC9jqUiPs2gbnGflH+7g=="],
|
|
||||||
|
|
||||||
"@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.3.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-c0/DxItpJv2+dGhgycJBBgotdqruGYDvA79drdh0MD1dFpy7JzJ/PlXwi1H4rFf0eTy8tgbI91aHDnZIceY3jQ=="],
|
|
||||||
|
|
||||||
"@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.3.1", "", { "os": "linux", "cpu": "arm" }, "sha512-aGGy9aWzXgHBG7HNyQPWorZthlp7+x6fDRoPAQbGO3ThcttuTyKIx3NuSHb6zb4gBNq6/yNn9f1cy9nFKS/Vmg=="],
|
|
||||||
|
|
||||||
"@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.3.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-JznefmcK9j1JKPz8AkQDh89kjojubyfOasWBPKfzMIhPwsgDy9evpE/naJTXXXmghS1iFwR8u/kTwh/I2/+GCw=="],
|
|
||||||
|
|
||||||
"@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.3.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1EkwGNCZk6iWNCMWqrvdJ+r1j0PT1zIz60CNPhYnJlK/zyeWqlsPZIe+ocBVqPF8k/Ssee/NCk+tE9Ryrko6ng=="],
|
|
||||||
|
|
||||||
"@img/sharp-libvips-linux-riscv64": ["@img/sharp-libvips-linux-riscv64@1.3.1", "", { "os": "linux", "cpu": "none" }, "sha512-Ilays+w2bXdnxzxtQdmXR62u8o8GYa3eL4+Gr+1KiE4xperMZUslRaVPJwwPkzlHEjGfXAfRVAa/7CYCtSqsBw=="],
|
|
||||||
|
|
||||||
"@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.3.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-VfBwVHQTbRoj4XlpA/KLZ7ltgMpz+4WSejFzQ+GnoImjo1PtEJ59QB2qR1xQEeRPYIkNrPIm2L4cICMvz4C2ew=="],
|
|
||||||
|
|
||||||
"@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.3.1", "", { "os": "linux", "cpu": "x64" }, "sha512-+c8ukgwU62DS54nCAjw7keOfHUkmr0B5QHEdcOqRnodF/MNXJbVI8Eopoj4B/0H8Asr65I+A4Amrn7a85/md6A=="],
|
|
||||||
|
|
||||||
"@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.3.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-qlKb/pwbkAi1WMsJrYHk7CuDrd12s27U2QnRhFYUoJNrRCmkosMTttuRFat/DDB3IlDm5qE1TJgZ4JDnHX8Ldw=="],
|
|
||||||
|
|
||||||
"@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.3.1", "", { "os": "linux", "cpu": "x64" }, "sha512-yO21HwoUVLN8Qa+/SBjQLMYwBWAVJjeGPNe+hc0OUeMeifEtJqu5a1c4HayE1nNpDih9y3/KkoltfkDodmKAlg=="],
|
|
||||||
|
|
||||||
"@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.3.1" }, "os": "linux", "cpu": "arm" }, "sha512-SE4kzF2mepn6z+6E7L6lsV8FzuLL6IPQdyX8ZiwROAG/G8td+hP/m7FsFPwidtrF19gvajuC9l6TxAVcsA4S7A=="],
|
|
||||||
|
|
||||||
"@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.3.1" }, "os": "linux", "cpu": "arm64" }, "sha512-af12Pnd0ZGu2HfP8NayB0kk6eC/lrfbQE6HlR4jD+34wdJ1Vw9TF6TMn6ZvffT+WgqVsl0hRbmNvz2u/23VmwA=="],
|
|
||||||
|
|
||||||
"@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.3.1" }, "os": "linux", "cpu": "ppc64" }, "sha512-hYSBm7zcNtDCozCxQHYZJiu63b/bXsgRZuOxCIBZsStMM9Vap47iFHdbX4kCvQsblPB/k+clhELpdQJHQLSHvg=="],
|
|
||||||
|
|
||||||
"@img/sharp-linux-riscv64": ["@img/sharp-linux-riscv64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-riscv64": "1.3.1" }, "os": "linux", "cpu": "none" }, "sha512-qQt0Kc13+Hoan/Awq/qMSQw3L+RI1NCRPgD5cUJ/1WSSmIoysLOc72jlRM3E0OHN9Yr313jgeQ2T+zW+F03QFA=="],
|
|
||||||
|
|
||||||
"@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.3.1" }, "os": "linux", "cpu": "s390x" }, "sha512-E4fLLfRPzDLlEeDaTzI98OFLcv++WL5ChLLMwPoVd0CIoZQqupBSNbOisPL5am9XsbQ9T84+iiMpUvbFtkunbA=="],
|
|
||||||
|
|
||||||
"@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.3.1" }, "os": "linux", "cpu": "x64" }, "sha512-gi0zFJJRLswfCZmHtJdikXPOc5u7qamSOS3NHedLqLd4W8Q0NqjdBr6TTRIgsfFjqfTsHFgdfvJ9LwqSgcHiAA=="],
|
|
||||||
|
|
||||||
"@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.3.1" }, "os": "linux", "cpu": "arm64" }, "sha512-siWbOW1u6HFnFLrp0waKyW7VEf7jYvcDWdrXEFa8AkdAQgEvuu5Fz8/Y70w9EeqAdwDtfU012BhEHHaDqvQNzg=="],
|
|
||||||
|
|
||||||
"@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.3.1" }, "os": "linux", "cpu": "x64" }, "sha512-YBqMMcjDi4QGYiSn4vNOYBhmlC4z5AXqkOUUqI2e0AFA4urNv4ESgOgwNl3K+4etQhha0twXlzeF20bbULm9Yg=="],
|
|
||||||
|
|
||||||
"@img/sharp-wasm32": ["@img/sharp-wasm32@0.35.2", "", { "dependencies": { "@emnapi/runtime": "^1.11.1" } }, "sha512-Mrv4JQNYVQ94xH+jzZ9r+gowleN8mv2FTgKT+PI6bx5C0G8TdNYndu161pg2i7uoBwxy2ImPMHrJOM2LZef7Bw=="],
|
|
||||||
|
|
||||||
"@img/sharp-webcontainers-wasm32": ["@img/sharp-webcontainers-wasm32@0.35.2", "", { "dependencies": { "@img/sharp-wasm32": "0.35.2" }, "cpu": "none" }, "sha512-QNV27pxs9wpApEiCfvHM1RDoP1w1+2KrUWWDPEhEwg+latvOrfuhWrHWZKwdSFwU6jh3myjw/yOCRsUIuOft3g=="],
|
|
||||||
|
|
||||||
"@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.35.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-BiVRYc/t6/Vl3e1hBx0hugG4oN9Pydf4fgMSpxTQJmwGUg/YoXTWHiFeRymHfCZzifxu4F4rpk/I67D0LQ20wQ=="],
|
|
||||||
|
|
||||||
"@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.35.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-YYEhx9PImCC7T0tI8JDMi4DB9LwLCXCU5OWNYEXAxh5Q1ShKkyC6byxzoBJ3gEFDnH2lQckWuDe70G7mB2XJog=="],
|
|
||||||
|
|
||||||
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.35.2", "", { "os": "win32", "cpu": "x64" }, "sha512-imoOyBcoM/iiUr4J6VPpCNjPnjvP/Gks95898yB8YqoGGYmHYbOyCuNv9FMhFgtaiHFGbHW8bxKqRV6VjtXThQ=="],
|
|
||||||
|
|
||||||
"@ioredis/commands": ["@ioredis/commands@1.10.0", "", {}, "sha512-UmeW7z4LfctwoQ5wkhVzgq8tXkreED2xZGpX+Bg+zA+WJFZCT6c062AfCK/Dfk81xZnnwdhJCUMkitihRaoC2Q=="],
|
"@ioredis/commands": ["@ioredis/commands@1.10.0", "", {}, "sha512-UmeW7z4LfctwoQ5wkhVzgq8tXkreED2xZGpX+Bg+zA+WJFZCT6c062AfCK/Dfk81xZnnwdhJCUMkitihRaoC2Q=="],
|
||||||
|
|
||||||
"@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="],
|
"@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="],
|
||||||
@@ -574,14 +477,6 @@
|
|||||||
|
|
||||||
"@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.76.0", "", { "os": "win32", "cpu": "x64" }, "sha512-5qcirPHO8nKfkoowEVWtpAoVTcYDy6g0UT0NGic450Qv8J2NrOqg4uQ8QppRP4MDTC7Xx47lbZnmadTH03CGGA=="],
|
"@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.76.0", "", { "os": "win32", "cpu": "x64" }, "sha512-5qcirPHO8nKfkoowEVWtpAoVTcYDy6g0UT0NGic450Qv8J2NrOqg4uQ8QppRP4MDTC7Xx47lbZnmadTH03CGGA=="],
|
||||||
|
|
||||||
"@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="],
|
|
||||||
|
|
||||||
"@poppinss/colors": ["@poppinss/colors@4.1.6", "", { "dependencies": { "kleur": "^4.1.5" } }, "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg=="],
|
|
||||||
|
|
||||||
"@poppinss/dumper": ["@poppinss/dumper@0.6.5", "", { "dependencies": { "@poppinss/colors": "^4.1.5", "@sindresorhus/is": "^7.0.2", "supports-color": "^10.0.0" } }, "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw=="],
|
|
||||||
|
|
||||||
"@poppinss/exception": ["@poppinss/exception@1.2.3", "", {}, "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw=="],
|
|
||||||
|
|
||||||
"@prisma/debug": ["@prisma/debug@7.2.0", "", {}, "sha512-YSGTiSlBAVJPzX4ONZmMotL+ozJwQjRmZweQNIq/ER0tQJKJynNkRB3kyvt37eOfsbMCXk3gnLF6J9OJ4QWftw=="],
|
"@prisma/debug": ["@prisma/debug@7.2.0", "", {}, "sha512-YSGTiSlBAVJPzX4ONZmMotL+ozJwQjRmZweQNIq/ER0tQJKJynNkRB3kyvt37eOfsbMCXk3gnLF6J9OJ4QWftw=="],
|
||||||
|
|
||||||
"@prisma/dev": ["@prisma/dev@0.20.0", "", { "dependencies": { "@electric-sql/pglite": "0.3.15", "@electric-sql/pglite-socket": "0.0.20", "@electric-sql/pglite-tools": "0.2.20", "@hono/node-server": "1.19.9", "@mrleebo/prisma-ast": "0.13.1", "@prisma/get-platform": "7.2.0", "@prisma/query-plan-executor": "7.2.0", "foreground-child": "3.3.1", "get-port-please": "3.2.0", "hono": "4.11.4", "http-status-codes": "2.3.0", "pathe": "2.0.3", "proper-lockfile": "4.1.2", "remeda": "2.33.4", "std-env": "3.10.0", "valibot": "1.2.0", "zeptomatch": "2.1.0" } }, "sha512-ovlBYwWor0OzG+yH4J3Ot+AneD818BttLA+Ii7wjbcLHUrnC4tbUPVGyNd3c/+71KETPKZfjhkTSpdS15dmXNQ=="],
|
"@prisma/dev": ["@prisma/dev@0.20.0", "", { "dependencies": { "@electric-sql/pglite": "0.3.15", "@electric-sql/pglite-socket": "0.0.20", "@electric-sql/pglite-tools": "0.2.20", "@hono/node-server": "1.19.9", "@mrleebo/prisma-ast": "0.13.1", "@prisma/get-platform": "7.2.0", "@prisma/query-plan-executor": "7.2.0", "foreground-child": "3.3.1", "get-port-please": "3.2.0", "hono": "4.11.4", "http-status-codes": "2.3.0", "pathe": "2.0.3", "proper-lockfile": "4.1.2", "remeda": "2.33.4", "std-env": "3.10.0", "valibot": "1.2.0", "zeptomatch": "2.1.0" } }, "sha512-ovlBYwWor0OzG+yH4J3Ot+AneD818BttLA+Ii7wjbcLHUrnC4tbUPVGyNd3c/+71KETPKZfjhkTSpdS15dmXNQ=="],
|
||||||
@@ -634,8 +529,6 @@
|
|||||||
|
|
||||||
"@rollup/pluginutils": ["@rollup/pluginutils@5.4.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg=="],
|
"@rollup/pluginutils": ["@rollup/pluginutils@5.4.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg=="],
|
||||||
|
|
||||||
"@sindresorhus/is": ["@sindresorhus/is@7.2.0", "", {}, "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw=="],
|
|
||||||
|
|
||||||
"@smithy/core": ["@smithy/core@3.29.6", "", { "dependencies": { "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-TO3w25cdGWBeYqKNDaqH3v4O3jjMPpKwf39YlG5X5xhqWfpOWJbi5gQi1lrllukuwohdhY0TPB8jBEv6UC50Vg=="],
|
"@smithy/core": ["@smithy/core@3.29.6", "", { "dependencies": { "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-TO3w25cdGWBeYqKNDaqH3v4O3jjMPpKwf39YlG5X5xhqWfpOWJbi5gQi1lrllukuwohdhY0TPB8jBEv6UC50Vg=="],
|
||||||
|
|
||||||
"@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.4.11", "", { "dependencies": { "@smithy/core": "^3.29.6", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-6CUvZwS0tCcVCrcvh2TpwTXxmAkuY6JGNPeKODYRLjHtUUhFLGS3dNkNdRvT/ttJyqimqnhFMTS2nqp4pDZ7oQ=="],
|
"@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.4.11", "", { "dependencies": { "@smithy/core": "^3.29.6", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-6CUvZwS0tCcVCrcvh2TpwTXxmAkuY6JGNPeKODYRLjHtUUhFLGS3dNkNdRvT/ttJyqimqnhFMTS2nqp4pDZ7oQ=="],
|
||||||
@@ -660,54 +553,10 @@
|
|||||||
|
|
||||||
"@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="],
|
"@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="],
|
||||||
|
|
||||||
"@speed-highlight/core": ["@speed-highlight/core@1.2.17", "", {}, "sha512-Z92FwKpCtfaW1V0jTU/fh3QzYEZN8wDwrzRIBoADCJfn4mJCNcJN/XegifX7BDrQ8/h9Xh/JnbyMchL0FqXrkg=="],
|
|
||||||
|
|
||||||
"@standard-schema/spec": ["@standard-schema/spec@1.0.0-beta.3", "", {}, "sha512-0ifF3BjA1E8SY9C+nUew8RefNOIq0cDlYALPty4rhUm8Rrl6tCM8hBT4bhGhx7I7iXD0uAgt50lgo8dD73ACMw=="],
|
"@standard-schema/spec": ["@standard-schema/spec@1.0.0-beta.3", "", {}, "sha512-0ifF3BjA1E8SY9C+nUew8RefNOIq0cDlYALPty4rhUm8Rrl6tCM8hBT4bhGhx7I7iXD0uAgt50lgo8dD73ACMw=="],
|
||||||
|
|
||||||
"@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.11", "", { "peerDependencies": { "acorn": "^8.9.0" } }, "sha512-LFuZUkjJ9iF7JZye/aG5XM0SFcQ5VyL0oVX4WJ9dc0Va3R3s0OauX1BESVCb+YN/ol8TAfqGDDAQsTG627Y5kw=="],
|
"@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.11", "", { "peerDependencies": { "acorn": "^8.9.0" } }, "sha512-LFuZUkjJ9iF7JZye/aG5XM0SFcQ5VyL0oVX4WJ9dc0Va3R3s0OauX1BESVCb+YN/ol8TAfqGDDAQsTG627Y5kw=="],
|
||||||
|
|
||||||
"@sveltejs/adapter-cloudflare": ["@sveltejs/adapter-cloudflare@7.2.9", "", { "dependencies": { "@cloudflare/workers-types": "^4.20250507.0", "worktop": "0.8.0-next.18" }, "peerDependencies": { "@sveltejs/kit": "^2.0.0", "wrangler": "^4.0.0" } }, "sha512-LEfLRYKZIiNYBPYk9Cu4dFCCIX37NO96jESNRDv7yr3vvblKU4Yh05FPUMRSrOWFKtG6bJcGIvdG/M2DSf4D1w=="],
|
|
||||||
|
|
||||||
"@sveltejs/kit": ["@sveltejs/kit@2.70.1", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@sveltejs/acorn-typescript": "^1.0.9", "@types/cookie": "^0.6.0", "acorn": "^8.16.0", "cookie": "^0.6.0", "devalue": "^5.8.1", "esm-env": "^1.2.2", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "set-cookie-parser": "^3.0.0", "sirv": "^3.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0 || ^7.0.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": "^5.3.3 || ^6.0.0", "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0 || ^8.0.0" }, "optionalPeers": ["@opentelemetry/api", "typescript"], "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-nY9SPHGOZro3doud9vZXDBwl9tCZIouuJztjgSHs6PAIrv9M/z5O7eOhPV5xU7CgVHA976Jwu3BA1hIFvXztkA=="],
|
|
||||||
|
|
||||||
"@sveltejs/load-config": ["@sveltejs/load-config@0.2.0", "", {}, "sha512-1LgZ/qUqSoq+QorD83lk2hka79Px0wXNW2q5V1nZlxGhQgw1jrsIbVz5YiCeucVLo4XvFLjXukUaQjIiqowkcg=="],
|
|
||||||
|
|
||||||
"@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@7.2.0", "", { "dependencies": { "deepmerge": "^4.3.1", "magic-string": "^0.30.21", "obug": "^2.1.0", "vitefu": "^1.1.2" }, "peerDependencies": { "svelte": "^5.46.4", "vite": "^8.0.0-beta.7 || ^8.0.0" } }, "sha512-1SpkuMSRLfugrVX+IrKfE1RUegzo8AQzKQ6qQPfVzbcWi5IhuTPaKb5ZrLpucleFznkc4/RTeSPoRnGWFxX+EQ=="],
|
|
||||||
|
|
||||||
"@tailwindcss/forms": ["@tailwindcss/forms@0.5.11", "", { "dependencies": { "mini-svg-data-uri": "^1.2.3" }, "peerDependencies": { "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1" } }, "sha512-h9wegbZDPurxG22xZSoWtdzc41/OlNEUQERNqI/0fOwa2aVlWGu7C35E/x6LDyD3lgtztFSSjKZyuVM0hxhbgA=="],
|
|
||||||
|
|
||||||
"@tailwindcss/node": ["@tailwindcss/node@4.3.3", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "^5.24.1", "jiti": "^2.7.0", "lightningcss": "1.32.0", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.3.3" } }, "sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.3.3", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.3.3", "@tailwindcss/oxide-darwin-arm64": "4.3.3", "@tailwindcss/oxide-darwin-x64": "4.3.3", "@tailwindcss/oxide-freebsd-x64": "4.3.3", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.3", "@tailwindcss/oxide-linux-arm64-gnu": "4.3.3", "@tailwindcss/oxide-linux-arm64-musl": "4.3.3", "@tailwindcss/oxide-linux-x64-gnu": "4.3.3", "@tailwindcss/oxide-linux-x64-musl": "4.3.3", "@tailwindcss/oxide-wasm32-wasi": "4.3.3", "@tailwindcss/oxide-win32-arm64-msvc": "4.3.3", "@tailwindcss/oxide-win32-x64-msvc": "4.3.3" } }, "sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.3.3", "", { "os": "android", "cpu": "arm64" }, "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.3.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.3.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.3.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3", "", { "os": "linux", "cpu": "arm" }, "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.3.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.3.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.3.3", "", { "os": "linux", "cpu": "x64" }, "sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.3.3", "", { "os": "linux", "cpu": "x64" }, "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.3.3", "", { "dependencies": { "@emnapi/core": "^1.11.1", "@emnapi/runtime": "^1.11.1", "@emnapi/wasi-threads": "^1.2.2", "@napi-rs/wasm-runtime": "^1.1.4", "@tybys/wasm-util": "^0.10.2", "tslib": "^2.8.1" }, "cpu": "none" }, "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.3.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.3.3", "", { "os": "win32", "cpu": "x64" }, "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw=="],
|
|
||||||
|
|
||||||
"@tailwindcss/typography": ["@tailwindcss/typography@0.5.20", "", { "dependencies": { "postcss-selector-parser": "6.0.10" }, "peerDependencies": { "tailwindcss": ">=3.0.0 || >=4.0.0 || insiders" } }, "sha512-hwbzQuNUfcPvbegQFatVPl/MY/tcM9KLl963hQ5laJKPh81TEZ1+dNG9PirGvcaDBkp+BCshExAyKVPW91dozw=="],
|
|
||||||
|
|
||||||
"@tailwindcss/vite": ["@tailwindcss/vite@4.3.3", "", { "dependencies": { "@tailwindcss/node": "4.3.3", "@tailwindcss/oxide": "4.3.3", "tailwindcss": "4.3.3" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7 || ^8" } }, "sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw=="],
|
|
||||||
|
|
||||||
"@tsconfig/node22": ["@tsconfig/node22@22.0.5", "", {}, "sha512-hLf2ld+sYN/BtOJjHUWOk568dvjFQkHnLNa6zce25GIH+vxKfvTgm3qpaH6ToF5tu/NN0IH66s+Bb5wElHrLcw=="],
|
"@tsconfig/node22": ["@tsconfig/node22@22.0.5", "", {}, "sha512-hLf2ld+sYN/BtOJjHUWOk568dvjFQkHnLNa6zce25GIH+vxKfvTgm3qpaH6ToF5tu/NN0IH66s+Bb5wElHrLcw=="],
|
||||||
|
|
||||||
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg=="],
|
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg=="],
|
||||||
@@ -718,8 +567,6 @@
|
|||||||
|
|
||||||
"@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="],
|
"@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="],
|
||||||
|
|
||||||
"@types/cookie": ["@types/cookie@0.6.0", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="],
|
|
||||||
|
|
||||||
"@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="],
|
"@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="],
|
||||||
|
|
||||||
"@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="],
|
"@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="],
|
||||||
@@ -840,8 +687,6 @@
|
|||||||
|
|
||||||
"bindings": ["bindings@1.5.0", "", { "dependencies": { "file-uri-to-path": "1.0.0" } }, "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ=="],
|
"bindings": ["bindings@1.5.0", "", { "dependencies": { "file-uri-to-path": "1.0.0" } }, "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ=="],
|
||||||
|
|
||||||
"blake3-wasm": ["blake3-wasm@2.1.5", "", {}, "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g=="],
|
|
||||||
|
|
||||||
"bowser": ["bowser@2.14.1", "", {}, "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg=="],
|
"bowser": ["bowser@2.14.1", "", {}, "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg=="],
|
||||||
|
|
||||||
"brace-expansion": ["brace-expansion@5.0.9", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg=="],
|
"brace-expansion": ["brace-expansion@5.0.9", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg=="],
|
||||||
@@ -862,8 +707,6 @@
|
|||||||
|
|
||||||
"chevrotain": ["chevrotain@10.5.0", "", { "dependencies": { "@chevrotain/cst-dts-gen": "10.5.0", "@chevrotain/gast": "10.5.0", "@chevrotain/types": "10.5.0", "@chevrotain/utils": "10.5.0", "lodash": "4.17.21", "regexp-to-ast": "0.5.0" } }, "sha512-Pkv5rBY3+CsHOYfV5g/Vs5JY9WTHHDEKOlohI2XeygaZhUeqhAlldZ8Hz9cRmxu709bvS08YzxHdTPHhffc13A=="],
|
"chevrotain": ["chevrotain@10.5.0", "", { "dependencies": { "@chevrotain/cst-dts-gen": "10.5.0", "@chevrotain/gast": "10.5.0", "@chevrotain/types": "10.5.0", "@chevrotain/utils": "10.5.0", "lodash": "4.17.21", "regexp-to-ast": "0.5.0" } }, "sha512-Pkv5rBY3+CsHOYfV5g/Vs5JY9WTHHDEKOlohI2XeygaZhUeqhAlldZ8Hz9cRmxu709bvS08YzxHdTPHhffc13A=="],
|
||||||
|
|
||||||
"chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
|
|
||||||
|
|
||||||
"chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="],
|
"chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="],
|
||||||
|
|
||||||
"cli-boxes": ["cli-boxes@3.0.0", "", {}, "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g=="],
|
"cli-boxes": ["cli-boxes@3.0.0", "", {}, "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g=="],
|
||||||
@@ -888,21 +731,15 @@
|
|||||||
|
|
||||||
"convert-to-spaces": ["convert-to-spaces@2.0.1", "", {}, "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ=="],
|
"convert-to-spaces": ["convert-to-spaces@2.0.1", "", {}, "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ=="],
|
||||||
|
|
||||||
"cookie": ["cookie@0.6.0", "", {}, "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="],
|
|
||||||
|
|
||||||
"core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="],
|
"core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="],
|
||||||
|
|
||||||
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||||
|
|
||||||
"cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
|
|
||||||
|
|
||||||
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||||
|
|
||||||
"deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="],
|
|
||||||
|
|
||||||
"denque": ["denque@2.1.0", "", {}, "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw=="],
|
"denque": ["denque@2.1.0", "", {}, "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw=="],
|
||||||
|
|
||||||
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
"detect-libc": ["detect-libc@2.0.2", "", {}, "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw=="],
|
||||||
|
|
||||||
"devalue": ["devalue@5.8.2", "", {}, "sha512-DObPPAfdtFbXjxLqK8s2Xk9ZuWz5+ZoFEhC7J76es4GU/rEiXwHTmbImoCdyoCOcBH1UF3+Cz6Z2sYD4hyl5TA=="],
|
"devalue": ["devalue@5.8.2", "", {}, "sha512-DObPPAfdtFbXjxLqK8s2Xk9ZuWz5+ZoFEhC7J76es4GU/rEiXwHTmbImoCdyoCOcBH1UF3+Cz6Z2sYD4hyl5TA=="],
|
||||||
|
|
||||||
@@ -916,12 +753,8 @@
|
|||||||
|
|
||||||
"empty-dir": ["empty-dir@0.1.0", "", {}, "sha512-EatTcJH5cVS/NXEpy7IWBSpH0WxvJdBnmRkz8Gqr2Jn4GmSqc4Q4E81SmVGOrHHHtCys1SsFKmAoHlhaFkRlmg=="],
|
"empty-dir": ["empty-dir@0.1.0", "", {}, "sha512-EatTcJH5cVS/NXEpy7IWBSpH0WxvJdBnmRkz8Gqr2Jn4GmSqc4Q4E81SmVGOrHHHtCys1SsFKmAoHlhaFkRlmg=="],
|
||||||
|
|
||||||
"enhanced-resolve": ["enhanced-resolve@5.24.3", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-PwKooW9JUzh5chmYfHM3IQl5OkK2u2Nm011MgeZrss3JmFraUx/fqrf78kk8GUMYoibx/14MdwTl/1WKkG7TpQ=="],
|
|
||||||
|
|
||||||
"environment": ["environment@1.1.0", "", {}, "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q=="],
|
"environment": ["environment@1.1.0", "", {}, "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q=="],
|
||||||
|
|
||||||
"error-stack-parser-es": ["error-stack-parser-es@1.0.5", "", {}, "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA=="],
|
|
||||||
|
|
||||||
"es-module-lexer": ["es-module-lexer@2.3.1", "", {}, "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA=="],
|
"es-module-lexer": ["es-module-lexer@2.3.1", "", {}, "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA=="],
|
||||||
|
|
||||||
"es-toolkit": ["es-toolkit@1.50.0", "", {}, "sha512-OyZKhUVvEep9ITEiwHn8GKnMRQIVqoSIX7WnRbkWgJkllCujilqP2rD0u979tkl8wqyc8ICwlc1UBVv/Sl1G6w=="],
|
"es-toolkit": ["es-toolkit@1.50.0", "", {}, "sha512-OyZKhUVvEep9ITEiwHn8GKnMRQIVqoSIX7WnRbkWgJkllCujilqP2rD0u979tkl8wqyc8ICwlc1UBVv/Sl1G6w=="],
|
||||||
@@ -936,8 +769,6 @@
|
|||||||
|
|
||||||
"estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
"estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
||||||
|
|
||||||
"evlog": ["evlog@2.22.1", "", { "peerDependencies": { "@nestjs/common": ">=11.1.28", "@nuxt/kit": "^4.4.2", "@orpc/server": ">=1.14.8", "@tanstack/start-client-core": "^1.170.14", "ai": ">=6.0.168 <8.0.0", "elysia": ">=1.4.29", "eve": ">=0.24.3", "express": ">=5.2.1", "fastify": ">=5.10.0", "h3": "^1.15.11", "hono": ">=4.12.30", "next": ">=16.2.10", "nitro": "^3.0.260311-beta", "nitropack": "^2.13.4", "ofetch": "^1.5.1", "react": ">=19.2.7", "react-router": ">=7.18.1", "vite": "^7.0.0 || ^8.0.0" }, "optionalPeers": ["@nestjs/common", "@nuxt/kit", "@orpc/server", "@tanstack/start-client-core", "ai", "elysia", "eve", "express", "fastify", "h3", "hono", "next", "nitro", "nitropack", "ofetch", "react", "react-router", "vite"] }, "sha512-5IfmtCk4Mq/ZsCtykxftgWV8LkqjQu28ssEcwWpqbnqYxkolzo4iyh+my2tM8cZoTCDMnnIFp+X9tyspVE8NsA=="],
|
|
||||||
|
|
||||||
"expect-type": ["expect-type@1.4.0", "", {}, "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA=="],
|
"expect-type": ["expect-type@1.4.0", "", {}, "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA=="],
|
||||||
|
|
||||||
"fast-check": ["fast-check@4.9.0", "", { "dependencies": { "pure-rand": "^8.0.0" } }, "sha512-7ms6T7SybUev/PQITciI0yLM2pOSFy5zpG8Ty7tQofcVaQUvrMXp6CBwqF6fThLCLOrfBtuHAtwq6Yu4XPCllg=="],
|
"fast-check": ["fast-check@4.9.0", "", { "dependencies": { "pure-rand": "^8.0.0" } }, "sha512-7ms6T7SybUev/PQITciI0yLM2pOSFy5zpG8Ty7tQofcVaQUvrMXp6CBwqF6fThLCLOrfBtuHAtwq6Yu4XPCllg=="],
|
||||||
@@ -980,8 +811,6 @@
|
|||||||
|
|
||||||
"glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
"glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
||||||
|
|
||||||
"globals": ["globals@17.7.0", "", {}, "sha512-Czmyns5dUsq4seFBR/Kdydhmo8y9kC79hiSkPn0YcGtNnYWnrgt0vjrSjx9tspoDGWm2CMarffRuLjM4xUz8xg=="],
|
|
||||||
|
|
||||||
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
||||||
|
|
||||||
"grammex": ["grammex@3.1.13", "", {}, "sha512-LnPnhOBLEJEVKS8WFDVaA397L9Kq55Q9oSITJiVLHVdhAclfUkWzQv74KhvZHKL2Q09Pb1XdsrOsZ4LfTFFTEg=="],
|
"grammex": ["grammex@3.1.13", "", {}, "sha512-LnPnhOBLEJEVKS8WFDVaA397L9Kq55Q9oSITJiVLHVdhAclfUkWzQv74KhvZHKL2Q09Pb1XdsrOsZ4LfTFFTEg=="],
|
||||||
@@ -1044,8 +873,6 @@
|
|||||||
|
|
||||||
"jszip": ["jszip@3.10.1", "", { "dependencies": { "lie": "~3.3.0", "pako": "~1.0.2", "readable-stream": "~2.3.6", "setimmediate": "^1.0.5" } }, "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g=="],
|
"jszip": ["jszip@3.10.1", "", { "dependencies": { "lie": "~3.3.0", "pako": "~1.0.2", "readable-stream": "~2.3.6", "setimmediate": "^1.0.5" } }, "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g=="],
|
||||||
|
|
||||||
"kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],
|
|
||||||
|
|
||||||
"kubernetes-types": ["kubernetes-types@1.30.0", "", {}, "sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q=="],
|
"kubernetes-types": ["kubernetes-types@1.30.0", "", {}, "sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q=="],
|
||||||
|
|
||||||
"kysely": ["kysely@0.29.4", "", {}, "sha512-y5mVgQNkMbs1eK9Xyc0pmNdabN2wHhRYY/5r4W5HrUT1rYCEPeVNSj1RUJeSDKT3U0p+mXCvLgkrFuIafYI6BA=="],
|
"kysely": ["kysely@0.29.4", "", {}, "sha512-y5mVgQNkMbs1eK9Xyc0pmNdabN2wHhRYY/5r4W5HrUT1rYCEPeVNSj1RUJeSDKT3U0p+mXCvLgkrFuIafYI6BA=="],
|
||||||
@@ -1106,10 +933,6 @@
|
|||||||
|
|
||||||
"mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
|
"mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
|
||||||
|
|
||||||
"mini-svg-data-uri": ["mini-svg-data-uri@1.4.4", "", { "bin": { "mini-svg-data-uri": "cli.js" } }, "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg=="],
|
|
||||||
|
|
||||||
"miniflare": ["miniflare@5.20260730.0-alpha", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "sharp": "0.35.2", "undici": "7.28.0", "workerd": "1.20260730.1", "ws": "8.21.0", "youch": "4.1.0-beta.10" } }, "sha512-8/dspSXDshP6nSkCpjKO7BYc2qZoYSXm7iM+QxY7qJyJpAB3onnQSaiu0cvKJlfuMGwULl55hG69FJCcCMXU1Q=="],
|
|
||||||
|
|
||||||
"minimatch": ["minimatch@10.2.6", "", { "dependencies": { "brace-expansion": "^5.0.8" } }, "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A=="],
|
"minimatch": ["minimatch@10.2.6", "", { "dependencies": { "brace-expansion": "^5.0.8" } }, "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A=="],
|
||||||
|
|
||||||
"minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="],
|
"minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="],
|
||||||
@@ -1120,10 +943,6 @@
|
|||||||
|
|
||||||
"mongodb-connection-string-url": ["mongodb-connection-string-url@3.0.2", "", { "dependencies": { "@types/whatwg-url": "^11.0.2", "whatwg-url": "^14.1.0 || ^13.0.0" } }, "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA=="],
|
"mongodb-connection-string-url": ["mongodb-connection-string-url@3.0.2", "", { "dependencies": { "@types/whatwg-url": "^11.0.2", "whatwg-url": "^14.1.0 || ^13.0.0" } }, "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA=="],
|
||||||
|
|
||||||
"mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="],
|
|
||||||
|
|
||||||
"mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="],
|
|
||||||
|
|
||||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||||
|
|
||||||
"msgpackr": ["msgpackr@2.0.5", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.4" } }, "sha512-cef05H/dSYpLpqp3sj/qyZh5vhUYCalnaLO7j1yOmpsR0y/XwLVtK7r5gn+U/F7CTEfMowcGhlUQJDLcLf7jcA=="],
|
"msgpackr": ["msgpackr@2.0.5", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.4" } }, "sha512-cef05H/dSYpLpqp3sj/qyZh5vhUYCalnaLO7j1yOmpsR0y/XwLVtK7r5gn+U/F7CTEfMowcGhlUQJDLcLf7jcA=="],
|
||||||
@@ -1168,8 +987,6 @@
|
|||||||
|
|
||||||
"path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="],
|
"path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="],
|
||||||
|
|
||||||
"path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="],
|
|
||||||
|
|
||||||
"pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
"pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
||||||
|
|
||||||
"pg": ["pg@8.22.0", "", { "dependencies": { "pg-connection-string": "^2.14.0", "pg-pool": "^3.14.0", "pg-protocol": "^1.15.0", "pg-types": "2.2.0", "pgpass": "1.0.5" }, "optionalDependencies": { "pg-cloudflare": "^1.4.0" }, "peerDependencies": { "pg-native": ">=3.0.1" }, "optionalPeers": ["pg-native"] }, "sha512-8wih1vVIBMxoUM2oB4soJsD9tDnDpLv4OXBJ+EJzFsvycD+lfyIreC2gGHq78f8jbLLt+bvlPTFdFZfJkOuzAA=="],
|
"pg": ["pg@8.22.0", "", { "dependencies": { "pg-connection-string": "^2.14.0", "pg-pool": "^3.14.0", "pg-protocol": "^1.15.0", "pg-types": "2.2.0", "pgpass": "1.0.5" }, "optionalDependencies": { "pg-cloudflare": "^1.4.0" }, "peerDependencies": { "pg-native": ">=3.0.1" }, "optionalPeers": ["pg-native"] }, "sha512-8wih1vVIBMxoUM2oB4soJsD9tDnDpLv4OXBJ+EJzFsvycD+lfyIreC2gGHq78f8jbLLt+bvlPTFdFZfJkOuzAA=="],
|
||||||
@@ -1198,8 +1015,6 @@
|
|||||||
|
|
||||||
"postcss": ["postcss@8.5.20", "", { "dependencies": { "nanoid": "^3.3.16", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-lW616l85ucIQL+FocMmL7pQFPqBmwejrCMg+iPxyImlrANNJG9NHq/RkyCZopDhd8C3LA03PHRJDjkbGu8vvug=="],
|
"postcss": ["postcss@8.5.20", "", { "dependencies": { "nanoid": "^3.3.16", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-lW616l85ucIQL+FocMmL7pQFPqBmwejrCMg+iPxyImlrANNJG9NHq/RkyCZopDhd8C3LA03PHRJDjkbGu8vvug=="],
|
||||||
|
|
||||||
"postcss-selector-parser": ["postcss-selector-parser@6.0.10", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w=="],
|
|
||||||
|
|
||||||
"postgres": ["postgres@3.4.9", "", {}, "sha512-GD3qdB0x1z9xgFI6cdRD6xu2Sp2WCOEoe3mtnyB5Ee0XrrL5Pe+e4CCnJrRMnL1zYtRDZmQQVbvOttLnKDLnaw=="],
|
"postgres": ["postgres@3.4.9", "", {}, "sha512-GD3qdB0x1z9xgFI6cdRD6xu2Sp2WCOEoe3mtnyB5Ee0XrrL5Pe+e4CCnJrRMnL1zYtRDZmQQVbvOttLnKDLnaw=="],
|
||||||
|
|
||||||
"postgres-array": ["postgres-array@3.0.4", "", {}, "sha512-nAUSGfSDGOaOAEGwqsRY27GPOea7CNipJPOA7lPbdEpx5Kg3qzdP0AaWC5MlhTWV9s4hFX39nomVZ+C4tnGOJQ=="],
|
"postgres-array": ["postgres-array@3.0.4", "", {}, "sha512-nAUSGfSDGOaOAEGwqsRY27GPOea7CNipJPOA7lPbdEpx5Kg3qzdP0AaWC5MlhTWV9s4hFX39nomVZ+C4tnGOJQ=="],
|
||||||
@@ -1232,8 +1047,6 @@
|
|||||||
|
|
||||||
"readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
|
"readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
|
||||||
|
|
||||||
"readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
|
|
||||||
|
|
||||||
"redis": ["redis@6.1.0", "", { "dependencies": { "@redis/bloom": "6.1.0", "@redis/client": "6.1.0", "@redis/json": "6.1.0", "@redis/search": "6.1.0", "@redis/time-series": "6.1.0" } }, "sha512-0kvUPM8RHP/ZMa0xYaDTcG5e8tIGW6kz6MToVT0V8iOnk6bkXp2jncGRGe2bZEk41lZwiDspUqjZCSk5ohjcKw=="],
|
"redis": ["redis@6.1.0", "", { "dependencies": { "@redis/bloom": "6.1.0", "@redis/client": "6.1.0", "@redis/json": "6.1.0", "@redis/search": "6.1.0", "@redis/time-series": "6.1.0" } }, "sha512-0kvUPM8RHP/ZMa0xYaDTcG5e8tIGW6kz6MToVT0V8iOnk6bkXp2jncGRGe2bZEk41lZwiDspUqjZCSk5ohjcKw=="],
|
||||||
|
|
||||||
"redis-errors": ["redis-errors@1.2.0", "", {}, "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w=="],
|
"redis-errors": ["redis-errors@1.2.0", "", {}, "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w=="],
|
||||||
@@ -1242,8 +1055,6 @@
|
|||||||
|
|
||||||
"regexp-to-ast": ["regexp-to-ast@0.5.0", "", {}, "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw=="],
|
"regexp-to-ast": ["regexp-to-ast@0.5.0", "", {}, "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw=="],
|
||||||
|
|
||||||
"regexparam": ["regexparam@3.0.0", "", {}, "sha512-RSYAtP31mvYLkAHrOlh25pCNQ5hWnT106VukGaaFfuJrZFkGRX5GhUAdPqpSDXxOhA2c4akmRuplv1mRqnBn6Q=="],
|
|
||||||
|
|
||||||
"remeda": ["remeda@2.33.4", "", {}, "sha512-ygHswjlc/opg2VrtiYvUOPLjxjtdKvjGz1/plDhkG66hjNjFr1xmfrs2ClNFo/E6TyUFiwYNh53bKV26oBoMGQ=="],
|
"remeda": ["remeda@2.33.4", "", {}, "sha512-ygHswjlc/opg2VrtiYvUOPLjxjtdKvjGz1/plDhkG66hjNjFr1xmfrs2ClNFo/E6TyUFiwYNh53bKV26oBoMGQ=="],
|
||||||
|
|
||||||
"resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="],
|
"resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="],
|
||||||
@@ -1260,8 +1071,6 @@
|
|||||||
|
|
||||||
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
|
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
|
||||||
|
|
||||||
"sade": ["sade@1.8.1", "", { "dependencies": { "mri": "^1.1.0" } }, "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A=="],
|
|
||||||
|
|
||||||
"safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
|
"safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="],
|
||||||
|
|
||||||
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
||||||
@@ -1270,12 +1079,8 @@
|
|||||||
|
|
||||||
"semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="],
|
"semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="],
|
||||||
|
|
||||||
"set-cookie-parser": ["set-cookie-parser@3.1.2", "", {}, "sha512-5/r/lTwbJ3zQ+qwdUFZYeRNqda7P5HD8zQKqlSjdGt1/S0cjLAphHusj4Y58ahDtWn/g32xrIS58/ikOvwl0Lw=="],
|
|
||||||
|
|
||||||
"setimmediate": ["setimmediate@1.0.5", "", {}, "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="],
|
"setimmediate": ["setimmediate@1.0.5", "", {}, "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="],
|
||||||
|
|
||||||
"sharp": ["sharp@0.35.2", "", { "dependencies": { "@img/colour": "^1.1.0", "detect-libc": "^2.1.2", "semver": "^7.8.4" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.35.2", "@img/sharp-darwin-x64": "0.35.2", "@img/sharp-freebsd-wasm32": "0.35.2", "@img/sharp-libvips-darwin-arm64": "1.3.1", "@img/sharp-libvips-darwin-x64": "1.3.1", "@img/sharp-libvips-linux-arm": "1.3.1", "@img/sharp-libvips-linux-arm64": "1.3.1", "@img/sharp-libvips-linux-ppc64": "1.3.1", "@img/sharp-libvips-linux-riscv64": "1.3.1", "@img/sharp-libvips-linux-s390x": "1.3.1", "@img/sharp-libvips-linux-x64": "1.3.1", "@img/sharp-libvips-linuxmusl-arm64": "1.3.1", "@img/sharp-libvips-linuxmusl-x64": "1.3.1", "@img/sharp-linux-arm": "0.35.2", "@img/sharp-linux-arm64": "0.35.2", "@img/sharp-linux-ppc64": "0.35.2", "@img/sharp-linux-riscv64": "0.35.2", "@img/sharp-linux-s390x": "0.35.2", "@img/sharp-linux-x64": "0.35.2", "@img/sharp-linuxmusl-arm64": "0.35.2", "@img/sharp-linuxmusl-x64": "0.35.2", "@img/sharp-webcontainers-wasm32": "0.35.2", "@img/sharp-win32-arm64": "0.35.2", "@img/sharp-win32-ia32": "0.35.2", "@img/sharp-win32-x64": "0.35.2" } }, "sha512-FVtFjtBCMiJS6yb5CX7Sop45WFMpeGw6oRKuJnXYgf/f1ms/D7LE/ZUSNxnW7rZ/dbslQWYkoqFHGPaDBtaK4w=="],
|
|
||||||
|
|
||||||
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
||||||
|
|
||||||
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||||
@@ -1284,8 +1089,6 @@
|
|||||||
|
|
||||||
"signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
|
"signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
|
||||||
|
|
||||||
"sirv": ["sirv@3.0.2", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g=="],
|
|
||||||
|
|
||||||
"sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],
|
"sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],
|
||||||
|
|
||||||
"slice-ansi": ["slice-ansi@8.0.0", "", { "dependencies": { "ansi-styles": "^6.2.3", "is-fullwidth-code-point": "^5.1.0" } }, "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg=="],
|
"slice-ansi": ["slice-ansi@8.0.0", "", { "dependencies": { "ansi-styles": "^6.2.3", "is-fullwidth-code-point": "^5.1.0" } }, "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg=="],
|
||||||
@@ -1318,18 +1121,10 @@
|
|||||||
|
|
||||||
"strnum": ["strnum@2.4.1", "", { "dependencies": { "anynum": "^1.0.1" } }, "sha512-M9eUSMT2dCB2cTNPG7UYj6KuK7RJR2SN2+yCV/fTW3xzTCS6EaGZ5pSMgDIjB7r8zSfTGk+dvvn9rTjpVS9Mwg=="],
|
"strnum": ["strnum@2.4.1", "", { "dependencies": { "anynum": "^1.0.1" } }, "sha512-M9eUSMT2dCB2cTNPG7UYj6KuK7RJR2SN2+yCV/fTW3xzTCS6EaGZ5pSMgDIjB7r8zSfTGk+dvvn9rTjpVS9Mwg=="],
|
||||||
|
|
||||||
"supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="],
|
|
||||||
|
|
||||||
"svelte": ["svelte@5.56.7", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.10", "@types/estree": "^1.0.5", "@types/trusted-types": "^2.0.7", "acorn": "^8.12.1", "aria-query": "5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "devalue": "^5.8.1", "esm-env": "^1.2.1", "esrap": "^2.2.12", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-5qERUZX80oQj6XrDMUmD2Uhd/cIpCPDWWKBK3ZHmyRUC9apPyamWM8xMo31mbWsIQxwG2hVoSnOJ/EcnhVkkzQ=="],
|
"svelte": ["svelte@5.56.7", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.10", "@types/estree": "^1.0.5", "@types/trusted-types": "^2.0.7", "acorn": "^8.12.1", "aria-query": "5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", "devalue": "^5.8.1", "esm-env": "^1.2.1", "esrap": "^2.2.12", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", "zimmerframe": "^1.1.2" } }, "sha512-5qERUZX80oQj6XrDMUmD2Uhd/cIpCPDWWKBK3ZHmyRUC9apPyamWM8xMo31mbWsIQxwG2hVoSnOJ/EcnhVkkzQ=="],
|
||||||
|
|
||||||
"svelte-check": ["svelte-check@4.7.3", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "@sveltejs/load-config": "^0.2.0", "chokidar": "^4.0.1", "fdir": "^6.2.0", "picocolors": "^1.0.0", "sade": "^1.7.4" }, "peerDependencies": { "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": ">=5.0.0" }, "bin": { "svelte-check": "bin/svelte-check" } }, "sha512-DHdTCGX62R0fCxBEaT+USdASAnoaRBaaNczkRJl0K7o3WyoCeVUbVxo6fKqpOll/B+WMWCsiFK0eFrJSNBKZIg=="],
|
|
||||||
|
|
||||||
"tagged-tag": ["tagged-tag@1.0.0", "", {}, "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng=="],
|
"tagged-tag": ["tagged-tag@1.0.0", "", {}, "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng=="],
|
||||||
|
|
||||||
"tailwindcss": ["tailwindcss@4.3.3", "", {}, "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ=="],
|
|
||||||
|
|
||||||
"tapable": ["tapable@2.3.3", "", {}, "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A=="],
|
|
||||||
|
|
||||||
"tar": ["tar@7.5.22", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA=="],
|
"tar": ["tar@7.5.22", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA=="],
|
||||||
|
|
||||||
"terminal-size": ["terminal-size@4.0.1", "", {}, "sha512-avMLDQpUI9I5XFrklECw1ZEUPJhqzcwSWsyyI8blhRLT+8N1jLJWLWWYQpB2q2xthq8xDvjZPISVh53T/+CLYQ=="],
|
"terminal-size": ["terminal-size@4.0.1", "", {}, "sha512-avMLDQpUI9I5XFrklECw1ZEUPJhqzcwSWsyyI8blhRLT+8N1jLJWLWWYQpB2q2xthq8xDvjZPISVh53T/+CLYQ=="],
|
||||||
@@ -1348,8 +1143,6 @@
|
|||||||
|
|
||||||
"toml": ["toml@4.3.0", "", {}, "sha512-lVb8X9BsPVuH0M4BKeS91tXAmJvCjQ5UIyAbQFaxkKGyUFK2RPkhwaFSQH8vbpl1d23eu/IBH+dwVMHWaq9A5A=="],
|
"toml": ["toml@4.3.0", "", {}, "sha512-lVb8X9BsPVuH0M4BKeS91tXAmJvCjQ5UIyAbQFaxkKGyUFK2RPkhwaFSQH8vbpl1d23eu/IBH+dwVMHWaq9A5A=="],
|
||||||
|
|
||||||
"totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="],
|
|
||||||
|
|
||||||
"tr46": ["tr46@5.1.1", "", { "dependencies": { "punycode": "^2.3.1" } }, "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw=="],
|
"tr46": ["tr46@5.1.1", "", { "dependencies": { "punycode": "^2.3.1" } }, "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw=="],
|
||||||
|
|
||||||
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||||
@@ -1376,12 +1169,8 @@
|
|||||||
|
|
||||||
"vite": ["vite@8.1.5", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.5", "postcss": "^8.5.17", "rolldown": "~1.1.5", "tinyglobby": "^0.2.17" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.3.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw=="],
|
"vite": ["vite@8.1.5", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.5", "postcss": "^8.5.17", "rolldown": "~1.1.5", "tinyglobby": "^0.2.17" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.3.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw=="],
|
||||||
|
|
||||||
"vitefu": ["vitefu@1.1.3", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["vite"] }, "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg=="],
|
|
||||||
|
|
||||||
"vitest": ["vitest@4.1.10", "", { "dependencies": { "@vitest/expect": "4.1.10", "@vitest/mocker": "4.1.10", "@vitest/pretty-format": "4.1.10", "@vitest/runner": "4.1.10", "@vitest/snapshot": "4.1.10", "@vitest/spy": "4.1.10", "@vitest/utils": "4.1.10", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.1.0", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.1.10", "@vitest/browser-preview": "4.1.10", "@vitest/browser-webdriverio": "4.1.10", "@vitest/coverage-istanbul": "4.1.10", "@vitest/coverage-v8": "4.1.10", "@vitest/ui": "4.1.10", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/coverage-istanbul", "@vitest/coverage-v8", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "./vitest.mjs" } }, "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw=="],
|
"vitest": ["vitest@4.1.10", "", { "dependencies": { "@vitest/expect": "4.1.10", "@vitest/mocker": "4.1.10", "@vitest/pretty-format": "4.1.10", "@vitest/runner": "4.1.10", "@vitest/snapshot": "4.1.10", "@vitest/spy": "4.1.10", "@vitest/utils": "4.1.10", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.1.0", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.1.10", "@vitest/browser-preview": "4.1.10", "@vitest/browser-webdriverio": "4.1.10", "@vitest/coverage-istanbul": "4.1.10", "@vitest/coverage-v8": "4.1.10", "@vitest/ui": "4.1.10", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/coverage-istanbul", "@vitest/coverage-v8", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "./vitest.mjs" } }, "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw=="],
|
||||||
|
|
||||||
"web": ["web@workspace:apps/web"],
|
|
||||||
|
|
||||||
"webidl-conversions": ["webidl-conversions@7.0.0", "", {}, "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g=="],
|
"webidl-conversions": ["webidl-conversions@7.0.0", "", {}, "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g=="],
|
||||||
|
|
||||||
"whatwg-url": ["whatwg-url@14.2.0", "", { "dependencies": { "tr46": "^5.1.0", "webidl-conversions": "^7.0.0" } }, "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw=="],
|
"whatwg-url": ["whatwg-url@14.2.0", "", { "dependencies": { "tr46": "^5.1.0", "webidl-conversions": "^7.0.0" } }, "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw=="],
|
||||||
@@ -1392,11 +1181,7 @@
|
|||||||
|
|
||||||
"widest-line": ["widest-line@6.0.0", "", { "dependencies": { "string-width": "^8.1.0" } }, "sha512-U89AsyEeAsyoF0zVJBkG9zBgekjgjK7yk9sje3F4IQpXBJ10TF6ByLlIfjMhcmHMJgHZI4KHt4rdNfktzxIAMA=="],
|
"widest-line": ["widest-line@6.0.0", "", { "dependencies": { "string-width": "^8.1.0" } }, "sha512-U89AsyEeAsyoF0zVJBkG9zBgekjgjK7yk9sje3F4IQpXBJ10TF6ByLlIfjMhcmHMJgHZI4KHt4rdNfktzxIAMA=="],
|
||||||
|
|
||||||
"workerd": ["workerd@1.20260730.1", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20260730.1", "@cloudflare/workerd-darwin-arm64": "1.20260730.1", "@cloudflare/workerd-linux-64": "1.20260730.1", "@cloudflare/workerd-linux-arm64": "1.20260730.1", "@cloudflare/workerd-windows-64": "1.20260730.1" }, "bin": { "workerd": "bin/workerd" } }, "sha512-zmfNIjwYSWFY5chGBOjWtH3xAE7p97FTC6vR4Ep98290ho6AeAR/NVcBD274YCLEUYzqm8yxdtZlxMybU8a3jA=="],
|
"workerd": ["workerd@1.20260704.1", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20260704.1", "@cloudflare/workerd-darwin-arm64": "1.20260704.1", "@cloudflare/workerd-linux-64": "1.20260704.1", "@cloudflare/workerd-linux-arm64": "1.20260704.1", "@cloudflare/workerd-windows-64": "1.20260704.1" }, "bin": { "workerd": "bin/workerd" } }, "sha512-GDZ0jzIYDYfN7rCt/oFJv4BG3QJ+4IS2kfRvxEMY9VKIfPhzo63PH69Ir7ug8LfORCgCtmfkiQVXrqbot7pZTQ=="],
|
||||||
|
|
||||||
"worktop": ["worktop@0.8.0-next.18", "", { "dependencies": { "mrmime": "^2.0.0", "regexparam": "^3.0.0" } }, "sha512-+TvsA6VAVoMC3XDKR5MoC/qlLqDixEfOBysDEKnPIPou/NvoPWCAuXHXMsswwlvmEuvX56lQjvELLyLuzTKvRw=="],
|
|
||||||
|
|
||||||
"wrangler": ["wrangler@4.118.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.5.0", "@cloudflare/unenv-preset": "2.16.1", "blake3-wasm": "2.1.5", "esbuild": "0.28.1", "miniflare": "5.20260730.0-alpha", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.24", "workerd": "1.20260730.1" }, "optionalDependencies": { "fsevents": "2.3.3" }, "peerDependencies": { "@cloudflare/workers-types": "^5.20260730.1" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js", "cf-wrangler": "bin/cf-wrangler.js" } }, "sha512-9pkBw/b8zWqGx2S+oLhgHMR1M/4VOE8SynUFABnGWiSFGlcOQ4xiI/B71Xf66RYP2xzngU37IQFPtUruij3lYw=="],
|
|
||||||
|
|
||||||
"wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="],
|
"wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="],
|
||||||
|
|
||||||
@@ -1412,10 +1197,6 @@
|
|||||||
|
|
||||||
"yoga-layout": ["yoga-layout@3.2.1", "", {}, "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ=="],
|
"yoga-layout": ["yoga-layout@3.2.1", "", {}, "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ=="],
|
||||||
|
|
||||||
"youch": ["youch@4.1.0-beta.10", "", { "dependencies": { "@poppinss/colors": "^4.1.5", "@poppinss/dumper": "^0.6.4", "@speed-highlight/core": "^1.2.7", "cookie": "^1.0.2", "youch-core": "^0.3.3" } }, "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ=="],
|
|
||||||
|
|
||||||
"youch-core": ["youch-core@0.3.3", "", { "dependencies": { "@poppinss/exception": "^1.2.2", "error-stack-parser-es": "^1.0.5" } }, "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA=="],
|
|
||||||
|
|
||||||
"zeptomatch": ["zeptomatch@2.1.0", "", { "dependencies": { "grammex": "^3.1.11", "graphmatch": "^1.1.0" } }, "sha512-KiGErG2J0G82LSpniV0CtIzjlJ10E04j02VOudJsPyPwNZgGnRKQy7I1R7GMyg/QswnE4l7ohSGrQbQbjXPPDA=="],
|
"zeptomatch": ["zeptomatch@2.1.0", "", { "dependencies": { "grammex": "^3.1.11", "graphmatch": "^1.1.0" } }, "sha512-KiGErG2J0G82LSpniV0CtIzjlJ10E04j02VOudJsPyPwNZgGnRKQy7I1R7GMyg/QswnE4l7ohSGrQbQbjXPPDA=="],
|
||||||
|
|
||||||
"zimmerframe": ["zimmerframe@1.1.4", "", {}, "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ=="],
|
"zimmerframe": ["zimmerframe@1.1.4", "", {}, "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ=="],
|
||||||
@@ -1424,13 +1205,9 @@
|
|||||||
|
|
||||||
"zod-openapi": ["zod-openapi@6.0.0", "", { "peerDependencies": { "zod": "^4.0.0" } }, "sha512-mS4eRJ4DGCPrg6elRbJqc/3nLe4EPVi8KiHRKZ7dcTR5m5orPy8EfoWmceAyGZAq71MAWuyrTTOag7W5N61ZPQ=="],
|
"zod-openapi": ["zod-openapi@6.0.0", "", { "peerDependencies": { "zod": "^4.0.0" } }, "sha512-mS4eRJ4DGCPrg6elRbJqc/3nLe4EPVi8KiHRKZ7dcTR5m5orPy8EfoWmceAyGZAq71MAWuyrTTOag7W5N61ZPQ=="],
|
||||||
|
|
||||||
"@cspotcode/source-map-support/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="],
|
|
||||||
|
|
||||||
"@distilled.cloud/cloudflare-runtime/workerd": ["workerd@1.20260704.1", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20260704.1", "@cloudflare/workerd-darwin-arm64": "1.20260704.1", "@cloudflare/workerd-linux-64": "1.20260704.1", "@cloudflare/workerd-linux-arm64": "1.20260704.1", "@cloudflare/workerd-windows-64": "1.20260704.1" }, "bin": { "workerd": "bin/workerd" } }, "sha512-GDZ0jzIYDYfN7rCt/oFJv4BG3QJ+4IS2kfRvxEMY9VKIfPhzo63PH69Ir7ug8LfORCgCtmfkiQVXrqbot7pZTQ=="],
|
|
||||||
|
|
||||||
"@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "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" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="],
|
"@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "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" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="],
|
||||||
|
|
||||||
"@img/sharp-wasm32/@emnapi/runtime": ["@emnapi/runtime@1.11.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA=="],
|
"@mapbox/node-pre-gyp/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
||||||
|
|
||||||
"@octokit/plugin-paginate-rest/@octokit/types": ["@octokit/types@16.0.0", "", { "dependencies": { "@octokit/openapi-types": "^27.0.0" } }, "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg=="],
|
"@octokit/plugin-paginate-rest/@octokit/types": ["@octokit/types@16.0.0", "", { "dependencies": { "@octokit/openapi-types": "^27.0.0" } }, "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg=="],
|
||||||
|
|
||||||
@@ -1448,24 +1225,6 @@
|
|||||||
|
|
||||||
"@smithy/util-base64/@smithy/core": ["@smithy/core@3.31.1", "", { "dependencies": { "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-CyogUINxvi7C7LDsh8Syo6hVJOT9ckz4rG8dRZfTJ8r91HkMY59PnNooaj7WcHyxEkxPfBAmbgztZU+xTo76lg=="],
|
"@smithy/util-base64/@smithy/core": ["@smithy/core@3.31.1", "", { "dependencies": { "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-CyogUINxvi7C7LDsh8Syo6hVJOT9ckz4rG8dRZfTJ8r91HkMY59PnNooaj7WcHyxEkxPfBAmbgztZU+xTo76lg=="],
|
||||||
|
|
||||||
"@sveltejs/adapter-cloudflare/@cloudflare/workers-types": ["@cloudflare/workers-types@4.20260702.1", "", {}, "sha512-mOhf5TUEB1m2vPrxtqoIGfz0fUC9xyxRDx5gWHy5s+OCo6dcV+g7wI1R7gYCMFohhqF/2y2xeKVwMwCJjfn/WA=="],
|
|
||||||
|
|
||||||
"@sveltejs/kit/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
|
||||||
|
|
||||||
"@tailwindcss/node/lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.11.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" }, "bundled": true }, "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.11.2", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.2", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.6", "", { "dependencies": { "@tybys/wasm-util": "^0.10.3" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" }, "bundled": true }, "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.3", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
|
||||||
|
|
||||||
"@vitest/expect/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
"@vitest/expect/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
||||||
|
|
||||||
"@vitest/mocker/estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],
|
"@vitest/mocker/estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],
|
||||||
@@ -1478,44 +1237,22 @@
|
|||||||
|
|
||||||
"foreground-child/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
|
"foreground-child/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
|
||||||
|
|
||||||
"libsql/detect-libc": ["detect-libc@2.0.2", "", {}, "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw=="],
|
"lightningcss/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
||||||
|
|
||||||
"micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="],
|
"micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="],
|
||||||
|
|
||||||
"miniflare/undici": ["undici@7.28.0", "", {}, "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA=="],
|
|
||||||
|
|
||||||
"miniflare/ws": ["ws@8.21.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g=="],
|
|
||||||
|
|
||||||
"node-fetch/whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="],
|
"node-fetch/whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="],
|
||||||
|
|
||||||
|
"node-gyp-build-optional-packages/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
||||||
|
|
||||||
"pg/pg-types": ["pg-types@2.2.0", "", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="],
|
"pg/pg-types": ["pg-types@2.2.0", "", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="],
|
||||||
|
|
||||||
"tsx/esbuild": ["esbuild@0.28.1", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.28.1", "@esbuild/android-arm": "0.28.1", "@esbuild/android-arm64": "0.28.1", "@esbuild/android-x64": "0.28.1", "@esbuild/darwin-arm64": "0.28.1", "@esbuild/darwin-x64": "0.28.1", "@esbuild/freebsd-arm64": "0.28.1", "@esbuild/freebsd-x64": "0.28.1", "@esbuild/linux-arm": "0.28.1", "@esbuild/linux-arm64": "0.28.1", "@esbuild/linux-ia32": "0.28.1", "@esbuild/linux-loong64": "0.28.1", "@esbuild/linux-mips64el": "0.28.1", "@esbuild/linux-ppc64": "0.28.1", "@esbuild/linux-riscv64": "0.28.1", "@esbuild/linux-s390x": "0.28.1", "@esbuild/linux-x64": "0.28.1", "@esbuild/netbsd-arm64": "0.28.1", "@esbuild/netbsd-x64": "0.28.1", "@esbuild/openbsd-arm64": "0.28.1", "@esbuild/openbsd-x64": "0.28.1", "@esbuild/openharmony-arm64": "0.28.1", "@esbuild/sunos-x64": "0.28.1", "@esbuild/win32-arm64": "0.28.1", "@esbuild/win32-ia32": "0.28.1", "@esbuild/win32-x64": "0.28.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw=="],
|
"tsx/esbuild": ["esbuild@0.28.1", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.28.1", "@esbuild/android-arm": "0.28.1", "@esbuild/android-arm64": "0.28.1", "@esbuild/android-x64": "0.28.1", "@esbuild/darwin-arm64": "0.28.1", "@esbuild/darwin-x64": "0.28.1", "@esbuild/freebsd-arm64": "0.28.1", "@esbuild/freebsd-x64": "0.28.1", "@esbuild/linux-arm": "0.28.1", "@esbuild/linux-arm64": "0.28.1", "@esbuild/linux-ia32": "0.28.1", "@esbuild/linux-loong64": "0.28.1", "@esbuild/linux-mips64el": "0.28.1", "@esbuild/linux-ppc64": "0.28.1", "@esbuild/linux-riscv64": "0.28.1", "@esbuild/linux-s390x": "0.28.1", "@esbuild/linux-x64": "0.28.1", "@esbuild/netbsd-arm64": "0.28.1", "@esbuild/netbsd-x64": "0.28.1", "@esbuild/openbsd-arm64": "0.28.1", "@esbuild/openbsd-x64": "0.28.1", "@esbuild/openharmony-arm64": "0.28.1", "@esbuild/sunos-x64": "0.28.1", "@esbuild/win32-arm64": "0.28.1", "@esbuild/win32-ia32": "0.28.1", "@esbuild/win32-x64": "0.28.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw=="],
|
||||||
|
|
||||||
"vitest/std-env": ["std-env@4.2.0", "", {}, "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw=="],
|
"vitest/std-env": ["std-env@4.2.0", "", {}, "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw=="],
|
||||||
|
|
||||||
"web/@cloudflare/workers-types": ["@cloudflare/workers-types@4.20260702.1", "", {}, "sha512-mOhf5TUEB1m2vPrxtqoIGfz0fUC9xyxRDx5gWHy5s+OCo6dcV+g7wI1R7gYCMFohhqF/2y2xeKVwMwCJjfn/WA=="],
|
|
||||||
|
|
||||||
"web/@types/node": ["@types/node@24.13.3", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q=="],
|
|
||||||
|
|
||||||
"web/oxfmt": ["oxfmt@0.58.0", "", { "dependencies": { "tinypool": "2.1.0" }, "optionalDependencies": { "@oxfmt/binding-android-arm-eabi": "0.58.0", "@oxfmt/binding-android-arm64": "0.58.0", "@oxfmt/binding-darwin-arm64": "0.58.0", "@oxfmt/binding-darwin-x64": "0.58.0", "@oxfmt/binding-freebsd-x64": "0.58.0", "@oxfmt/binding-linux-arm-gnueabihf": "0.58.0", "@oxfmt/binding-linux-arm-musleabihf": "0.58.0", "@oxfmt/binding-linux-arm64-gnu": "0.58.0", "@oxfmt/binding-linux-arm64-musl": "0.58.0", "@oxfmt/binding-linux-ppc64-gnu": "0.58.0", "@oxfmt/binding-linux-riscv64-gnu": "0.58.0", "@oxfmt/binding-linux-riscv64-musl": "0.58.0", "@oxfmt/binding-linux-s390x-gnu": "0.58.0", "@oxfmt/binding-linux-x64-gnu": "0.58.0", "@oxfmt/binding-linux-x64-musl": "0.58.0", "@oxfmt/binding-openharmony-arm64": "0.58.0", "@oxfmt/binding-win32-arm64-msvc": "0.58.0", "@oxfmt/binding-win32-ia32-msvc": "0.58.0", "@oxfmt/binding-win32-x64-msvc": "0.58.0" }, "peerDependencies": { "svelte": "^5.0.0", "vite-plus": "*" }, "optionalPeers": ["svelte", "vite-plus"], "bin": { "oxfmt": "bin/oxfmt" } }, "sha512-8feG/7NVEHDVwc1OUpP6Pks+TnaDFUw2jLLFIMi5bcmmwxAX2wBQvjSzj62RRTYBf2Op1Wt8xbkmagmPTR5ETg=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild": ["esbuild@0.28.1", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.28.1", "@esbuild/android-arm": "0.28.1", "@esbuild/android-arm64": "0.28.1", "@esbuild/android-x64": "0.28.1", "@esbuild/darwin-arm64": "0.28.1", "@esbuild/darwin-x64": "0.28.1", "@esbuild/freebsd-arm64": "0.28.1", "@esbuild/freebsd-x64": "0.28.1", "@esbuild/linux-arm": "0.28.1", "@esbuild/linux-arm64": "0.28.1", "@esbuild/linux-ia32": "0.28.1", "@esbuild/linux-loong64": "0.28.1", "@esbuild/linux-mips64el": "0.28.1", "@esbuild/linux-ppc64": "0.28.1", "@esbuild/linux-riscv64": "0.28.1", "@esbuild/linux-s390x": "0.28.1", "@esbuild/linux-x64": "0.28.1", "@esbuild/netbsd-arm64": "0.28.1", "@esbuild/netbsd-x64": "0.28.1", "@esbuild/openbsd-arm64": "0.28.1", "@esbuild/openbsd-x64": "0.28.1", "@esbuild/openharmony-arm64": "0.28.1", "@esbuild/sunos-x64": "0.28.1", "@esbuild/win32-arm64": "0.28.1", "@esbuild/win32-ia32": "0.28.1", "@esbuild/win32-x64": "0.28.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw=="],
|
|
||||||
|
|
||||||
"wrap-ansi/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
|
"wrap-ansi/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
|
||||||
|
|
||||||
"youch/cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="],
|
|
||||||
|
|
||||||
"@distilled.cloud/cloudflare-runtime/workerd/@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20260704.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-XO+vvdhhTNZSsIWCkZ+JaE/JrFUmQAB0H0y/sVkAf32xa2TYBRvFUMwjSqf6WxtlxcKPQvmbLfpO/UQ0l/q4eQ=="],
|
|
||||||
|
|
||||||
"@distilled.cloud/cloudflare-runtime/workerd/@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20260704.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-6iI7nbOOO8PzEQ6UZVBZB/hv95m8jl0yvyjMuWrF5cJbiLb5zPw3KnpqvGi+aeOs2ZmUkc81i1FWKfXwLXzPRA=="],
|
|
||||||
|
|
||||||
"@distilled.cloud/cloudflare-runtime/workerd/@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20260704.1", "", { "os": "linux", "cpu": "x64" }, "sha512-3mT0YHtxT7eLjghu3hKSJDUQoz+AYv8FM43nLPYhM0YiHOxr8OlmvnCb2Lp7v/U3bwd3Gnx7WEqjSppR583mGg=="],
|
|
||||||
|
|
||||||
"@distilled.cloud/cloudflare-runtime/workerd/@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20260704.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-Opo7cPTPg4x0WwK+eZSDszCyFLKQkOGNCWxF005HRTJ5SJH8h0K9KyrC1k4LBwx3haXSVi+E1eGqo1gZ1Hmhkg=="],
|
|
||||||
|
|
||||||
"@distilled.cloud/cloudflare-runtime/workerd/@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20260704.1", "", { "os": "win32", "cpu": "x64" }, "sha512-a97Ecnzhy04x3U052VKPCNp863F7Wf00WY7Ga5P0SbtYvaO1PDzylsHrvFMPKeiDFcOwqiredawmJ+v6bhIgeQ=="],
|
|
||||||
|
|
||||||
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="],
|
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="],
|
||||||
|
|
||||||
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="],
|
"@esbuild-kit/core-utils/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="],
|
||||||
@@ -1564,28 +1301,6 @@
|
|||||||
|
|
||||||
"@octokit/plugin-rest-endpoint-methods/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="],
|
"@octokit/plugin-rest-endpoint-methods/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="],
|
||||||
|
|
||||||
"@tailwindcss/node/lightningcss/lightningcss-android-arm64": ["lightningcss-android-arm64@1.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg=="],
|
|
||||||
|
|
||||||
"@tailwindcss/node/lightningcss/lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ=="],
|
|
||||||
|
|
||||||
"@tailwindcss/node/lightningcss/lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.32.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w=="],
|
|
||||||
|
|
||||||
"@tailwindcss/node/lightningcss/lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.32.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig=="],
|
|
||||||
|
|
||||||
"@tailwindcss/node/lightningcss/lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.32.0", "", { "os": "linux", "cpu": "arm" }, "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw=="],
|
|
||||||
|
|
||||||
"@tailwindcss/node/lightningcss/lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ=="],
|
|
||||||
|
|
||||||
"@tailwindcss/node/lightningcss/lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg=="],
|
|
||||||
|
|
||||||
"@tailwindcss/node/lightningcss/lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA=="],
|
|
||||||
|
|
||||||
"@tailwindcss/node/lightningcss/lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg=="],
|
|
||||||
|
|
||||||
"@tailwindcss/node/lightningcss/lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.32.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw=="],
|
|
||||||
|
|
||||||
"@tailwindcss/node/lightningcss/lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="],
|
|
||||||
|
|
||||||
"node-fetch/whatwg-url/tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="],
|
"node-fetch/whatwg-url/tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="],
|
||||||
|
|
||||||
"node-fetch/whatwg-url/webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="],
|
"node-fetch/whatwg-url/webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="],
|
||||||
@@ -1649,97 +1364,5 @@
|
|||||||
"tsx/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.28.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg=="],
|
"tsx/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.28.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg=="],
|
||||||
|
|
||||||
"tsx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.1", "", { "os": "win32", "cpu": "x64" }, "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A=="],
|
"tsx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.1", "", { "os": "win32", "cpu": "x64" }, "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A=="],
|
||||||
|
|
||||||
"web/@types/node/undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
|
|
||||||
|
|
||||||
"web/oxfmt/@oxfmt/binding-android-arm-eabi": ["@oxfmt/binding-android-arm-eabi@0.58.0", "", { "os": "android", "cpu": "arm" }, "sha512-Uz62sHduGGPftXtILGyxdSW4PX82rUg+rfdNqhsgxe881g4rIoXlIqmZQ6HVKcF4f+F8qMhdD03Bx5u7gmeTdg=="],
|
|
||||||
|
|
||||||
"web/oxfmt/@oxfmt/binding-android-arm64": ["@oxfmt/binding-android-arm64@0.58.0", "", { "os": "android", "cpu": "arm64" }, "sha512-rD0lRaJp1b+9vw6X4A2dJWKukd6X8yxiicN4JxXcXayolmUypRZxk+lKR+fVOu5q/iYc0fh5fR4bgmfOfVlbaA=="],
|
|
||||||
|
|
||||||
"web/oxfmt/@oxfmt/binding-darwin-arm64": ["@oxfmt/binding-darwin-arm64@0.58.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-uzbPPk7O6M+w2K65vcQ1woga3wgP8zghjL1KOG5b6qJ8dvYHZJ1VShaslg2KOK6yQIwCQtcMCXqLBM6sqXUNTg=="],
|
|
||||||
|
|
||||||
"web/oxfmt/@oxfmt/binding-darwin-x64": ["@oxfmt/binding-darwin-x64@0.58.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-L0nKYDxU32oxeQqJj21W9SlIMnf81VZEhyah6iDvFhf5q0oynq498Fopth7blErUJVBpVtxQ98RMCfMPqpJX6w=="],
|
|
||||||
|
|
||||||
"web/oxfmt/@oxfmt/binding-freebsd-x64": ["@oxfmt/binding-freebsd-x64@0.58.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-woNwfD58dC5PGS9LSLSD5JYfo/EFK5iG9vhDWkcCg3q78ag7KC8bpDqgvPHrMoXpx83OLXxoSOhu6z8FsVTHlg=="],
|
|
||||||
|
|
||||||
"web/oxfmt/@oxfmt/binding-linux-arm-gnueabihf": ["@oxfmt/binding-linux-arm-gnueabihf@0.58.0", "", { "os": "linux", "cpu": "arm" }, "sha512-Sqs8nMLxuQpY21NKJ1u4stPDmO5hskBCNNh2E3AdCfI1QqWtf4m+Qn4mGEIUO4KGmuq3SWc/SZ80uy5IiwTCDw=="],
|
|
||||||
|
|
||||||
"web/oxfmt/@oxfmt/binding-linux-arm-musleabihf": ["@oxfmt/binding-linux-arm-musleabihf@0.58.0", "", { "os": "linux", "cpu": "arm" }, "sha512-Vd4exzBI5B5hB9m22JiTQzIL23WvHo/Pe+sNXPNeBLXSP9swCBPKCEBRwKpmpQzYhlgYaCgfPcGXPKAJBRIiZQ=="],
|
|
||||||
|
|
||||||
"web/oxfmt/@oxfmt/binding-linux-arm64-gnu": ["@oxfmt/binding-linux-arm64-gnu@0.58.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-bUWi5mHV+4Vi56RLHE1h6q/HHfwAIT3XoB9vJAVeRzfu5NriXM8y6eeJu0vlKa0C9kq2rq1sOWRClhdLHPocrg=="],
|
|
||||||
|
|
||||||
"web/oxfmt/@oxfmt/binding-linux-arm64-musl": ["@oxfmt/binding-linux-arm64-musl@0.58.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-2ZHxemzgHcjtktAuVUwSoyXmGo/t+aF5tS1ciPpPei4rhSyrz3JOqDosXXrmhN/yLUSzJjtuW7ToTWqfQpCj2w=="],
|
|
||||||
|
|
||||||
"web/oxfmt/@oxfmt/binding-linux-ppc64-gnu": ["@oxfmt/binding-linux-ppc64-gnu@0.58.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-AwKkVwjVmFQ3bcO7j0McGYAqCKH2a326fswfofng/E8VewCT/raeeGQr4huVhY704deK8AWASSTlxzMj0eZc6Q=="],
|
|
||||||
|
|
||||||
"web/oxfmt/@oxfmt/binding-linux-riscv64-gnu": ["@oxfmt/binding-linux-riscv64-gnu@0.58.0", "", { "os": "linux", "cpu": "none" }, "sha512-xsRpTxfUnJF8D3AUKko/qyWdjw4GZVHlCVFuGlzSCTeewLmykKINW8em1+wx+axsDVtJJcMtvsiaXggXxrlHgw=="],
|
|
||||||
|
|
||||||
"web/oxfmt/@oxfmt/binding-linux-riscv64-musl": ["@oxfmt/binding-linux-riscv64-musl@0.58.0", "", { "os": "linux", "cpu": "none" }, "sha512-Z4AYOTcy7nYEIiXwD62PlerimyYRcfJOgUbQAEBjXz098kxKuERBlRntofGy69HHhe9E0TLVNMl1yspVNu+efw=="],
|
|
||||||
|
|
||||||
"web/oxfmt/@oxfmt/binding-linux-s390x-gnu": ["@oxfmt/binding-linux-s390x-gnu@0.58.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-A3nhhtZPC/TKVWOPj9q/H3p2znJDCcHWYlJBhWL8hGq/bFmBaNBHC8Np6E581yVq1w9Mi3rMDNzDalWvtUfJtQ=="],
|
|
||||||
|
|
||||||
"web/oxfmt/@oxfmt/binding-linux-x64-gnu": ["@oxfmt/binding-linux-x64-gnu@0.58.0", "", { "os": "linux", "cpu": "x64" }, "sha512-2g+tVkgwqphw8R4hgo+kF4oz8+P5RwVOtr9+irsC7uwEp0e9j7Crw8kDGKL20uYlLPD7g02DqA61mC/UNYx98A=="],
|
|
||||||
|
|
||||||
"web/oxfmt/@oxfmt/binding-linux-x64-musl": ["@oxfmt/binding-linux-x64-musl@0.58.0", "", { "os": "linux", "cpu": "x64" }, "sha512-rc15P6AbyyB7426aN8AakLd02Trb3a6ML/mmfAQeVHJEfVofWLcWIrBdy6zDEY+DIaL/s8E4GGPboVw+oP3+EA=="],
|
|
||||||
|
|
||||||
"web/oxfmt/@oxfmt/binding-openharmony-arm64": ["@oxfmt/binding-openharmony-arm64@0.58.0", "", { "os": "none", "cpu": "arm64" }, "sha512-ZWoTM27/HYPOh9iq86DAbhPu9nXb8qKvvGU/h8OfliyVUFAMMNTLDkGsWDKKnDqIkqvZ9+dXlgUOsH1LYO3O7g=="],
|
|
||||||
|
|
||||||
"web/oxfmt/@oxfmt/binding-win32-arm64-msvc": ["@oxfmt/binding-win32-arm64-msvc@0.58.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-LHZnqFXe2dEfkRI4XdZS/57nEOT/I4UCRX5IyM9v4GYW9XwQCjGe1IUK59SuKw3POwvcgWQ4pme2cYXmNqTNPg=="],
|
|
||||||
|
|
||||||
"web/oxfmt/@oxfmt/binding-win32-ia32-msvc": ["@oxfmt/binding-win32-ia32-msvc@0.58.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-mZKpg20TpheCJym1rarcZCUJeW1sSruw8zAAaCYWvuVfwIUDN1CXdrPU/JgCWReXTCTrEfCB8Wyo3hh9jSZ2EA=="],
|
|
||||||
|
|
||||||
"web/oxfmt/@oxfmt/binding-win32-x64-msvc": ["@oxfmt/binding-win32-x64-msvc@0.58.0", "", { "os": "win32", "cpu": "x64" }, "sha512-N/wUU4N5PZ2orBtI+Ko7MnMfYLfE7K91UrGMY/c/pYyHR3lA9kwst1XugkZx+92YcRh/Eo+iv2eTESSWXfiZPA=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.28.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.28.1", "", { "os": "android", "cpu": "arm" }, "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.28.1", "", { "os": "android", "cpu": "arm64" }, "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.28.1", "", { "os": "android", "cpu": "x64" }, "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.28.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.28.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.28.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.28.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.28.1", "", { "os": "linux", "cpu": "arm" }, "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.28.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.28.1", "", { "os": "linux", "cpu": "ia32" }, "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.28.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.28.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.28.1", "", { "os": "linux", "cpu": "x64" }, "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.28.1", "", { "os": "none", "cpu": "arm64" }, "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.28.1", "", { "os": "none", "cpu": "x64" }, "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.28.1", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.28.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.28.1", "", { "os": "none", "cpu": "arm64" }, "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.28.1", "", { "os": "sunos", "cpu": "x64" }, "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.28.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.28.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg=="],
|
|
||||||
|
|
||||||
"wrangler/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.1", "", { "os": "win32", "cpu": "x64" }, "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A=="],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
CREATE TYPE "public"."verification_kind" AS ENUM('email');--> statement-breakpoint
|
||||||
|
CREATE TABLE "verification" (
|
||||||
|
"id" char(30) PRIMARY KEY NOT NULL,
|
||||||
|
"time_created" timestamp with time zone DEFAULT now() NOT NULL,
|
||||||
|
"time_updated" timestamp with time zone DEFAULT now() NOT NULL,
|
||||||
|
"time_deleted" timestamp with time zone,
|
||||||
|
"user_id" char(30) NOT NULL,
|
||||||
|
"kind" "verification_kind" NOT NULL,
|
||||||
|
"code_hash" text NOT NULL,
|
||||||
|
"expires_at" timestamp with time zone NOT NULL,
|
||||||
|
"attempts" integer DEFAULT 0 NOT NULL,
|
||||||
|
"consumed_at" timestamp with time zone
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
CREATE TABLE "waitlist_entry" (
|
||||||
|
"id" char(30) PRIMARY KEY NOT NULL,
|
||||||
|
"time_created" timestamp with time zone DEFAULT now() NOT NULL,
|
||||||
|
"time_updated" timestamp with time zone DEFAULT now() NOT NULL,
|
||||||
|
"time_deleted" timestamp with time zone,
|
||||||
|
"email" text NOT NULL,
|
||||||
|
"source" text DEFAULT 'machines' NOT NULL
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
ALTER TABLE "game" ADD COLUMN "aliases" text;--> statement-breakpoint
|
||||||
|
ALTER TABLE "verification" ADD CONSTRAINT "verification_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||||
|
CREATE INDEX "verification_user_kind_idx" ON "verification" USING btree ("user_id","kind");--> statement-breakpoint
|
||||||
|
CREATE UNIQUE INDEX "waitlist_entry_email_unique" ON "waitlist_entry" USING btree ("email");--> statement-breakpoint
|
||||||
|
CREATE INDEX "waitlist_entry_source_idx" ON "waitlist_entry" USING btree ("source");
|
||||||
1908
packages/core/migrations/meta/0006_snapshot.json
Normal file
1908
packages/core/migrations/meta/0006_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -43,6 +43,13 @@
|
|||||||
"when": 1785909838801,
|
"when": 1785909838801,
|
||||||
"tag": "0005_flaky_may_parker",
|
"tag": "0005_flaky_may_parker",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 6,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1786205230097,
|
||||||
|
"tag": "0006_waitlist_verification_game_aliases",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -61,6 +61,7 @@ export namespace Examples {
|
|||||||
steamAppId: 730,
|
steamAppId: 730,
|
||||||
slug: 'counter-strike-2',
|
slug: 'counter-strike-2',
|
||||||
name: 'Counter-Strike 2',
|
name: 'Counter-Strike 2',
|
||||||
|
aliases: 'cs2 csgo',
|
||||||
type: 'game',
|
type: 'game',
|
||||||
clientIcon: '5aad412d01a9b91ba0379f0b35f4eb0b69d9db08',
|
clientIcon: '5aad412d01a9b91ba0379f0b35f4eb0b69d9db08',
|
||||||
icon: 'f92b09dab91f1d1738f72fe0dd9be18dcc2901f9',
|
icon: 'f92b09dab91f1d1738f72fe0dd9be18dcc2901f9',
|
||||||
@@ -138,4 +139,11 @@ export namespace Examples {
|
|||||||
timeCompleted: null,
|
timeCompleted: null,
|
||||||
errorMessage: null
|
errorMessage: null
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const WaitlistEntry = {
|
||||||
|
id: Id('waitlistEntry'),
|
||||||
|
email: 'johndoe@example.com',
|
||||||
|
source: 'machines',
|
||||||
|
timeCreated: '2026-07-28T12:00:00.000Z'
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ export const GameTable = pgTable(
|
|||||||
slug: text('slug').notNull(),
|
slug: text('slug').notNull(),
|
||||||
name: text('name').notNull(),
|
name: text('name').notNull(),
|
||||||
type: text('type'),
|
type: text('type'),
|
||||||
|
// Space-separated nicknames ("tf2", "pubg") so search can match them.
|
||||||
|
aliases: text('aliases'),
|
||||||
|
|
||||||
clientIcon: text('client_icon'),
|
clientIcon: text('client_icon'),
|
||||||
icon: text('icon'),
|
icon: text('icon'),
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { eq, and, isNull, sql, inArray } from 'drizzle-orm';
|
import { eq, and, isNull, sql, inArray, or } from 'drizzle-orm';
|
||||||
import z from 'zod';
|
import z from 'zod';
|
||||||
|
|
||||||
import { Database } from '../db/index.js';
|
import { Database } from '../db/index.js';
|
||||||
@@ -28,6 +28,10 @@ export namespace Game {
|
|||||||
description: 'Game title',
|
description: 'Game title',
|
||||||
example: Examples.Game.name
|
example: Examples.Game.name
|
||||||
}),
|
}),
|
||||||
|
aliases: z.string().nullable().optional().meta({
|
||||||
|
description: 'Space-separated nicknames ("tf2", "pubg") for search',
|
||||||
|
example: Examples.Game.aliases
|
||||||
|
}),
|
||||||
type: z.string().nullable().optional().meta({
|
type: z.string().nullable().optional().meta({
|
||||||
description: 'Content type (game, dlc, demo, tool)',
|
description: 'Content type (game, dlc, demo, tool)',
|
||||||
example: Examples.Game.type
|
example: Examples.Game.type
|
||||||
@@ -131,6 +135,7 @@ export namespace Game {
|
|||||||
steamAppId: true,
|
steamAppId: true,
|
||||||
slug: true,
|
slug: true,
|
||||||
name: true,
|
name: true,
|
||||||
|
aliases: true,
|
||||||
type: true,
|
type: true,
|
||||||
clientIcon: true,
|
clientIcon: true,
|
||||||
icon: true,
|
icon: true,
|
||||||
@@ -161,6 +166,7 @@ export namespace Game {
|
|||||||
steamAppId: input.steamAppId,
|
steamAppId: input.steamAppId,
|
||||||
slug: input.slug,
|
slug: input.slug,
|
||||||
name: input.name,
|
name: input.name,
|
||||||
|
aliases: input.aliases ?? null,
|
||||||
type: input.type ?? null,
|
type: input.type ?? null,
|
||||||
clientIcon: input.clientIcon ?? null,
|
clientIcon: input.clientIcon ?? null,
|
||||||
icon: input.icon ?? null,
|
icon: input.icon ?? null,
|
||||||
@@ -215,6 +221,7 @@ export namespace Game {
|
|||||||
steamAppId: true,
|
steamAppId: true,
|
||||||
slug: true,
|
slug: true,
|
||||||
name: true,
|
name: true,
|
||||||
|
aliases: true,
|
||||||
type: true,
|
type: true,
|
||||||
clientIcon: true,
|
clientIcon: true,
|
||||||
icon: true,
|
icon: true,
|
||||||
@@ -247,6 +254,7 @@ export namespace Game {
|
|||||||
steamAppId: input.steamAppId,
|
steamAppId: input.steamAppId,
|
||||||
slug: input.slug,
|
slug: input.slug,
|
||||||
name: input.name,
|
name: input.name,
|
||||||
|
aliases: input.aliases ?? null,
|
||||||
type: input.type ?? null,
|
type: input.type ?? null,
|
||||||
clientIcon: input.clientIcon ?? null,
|
clientIcon: input.clientIcon ?? null,
|
||||||
icon: input.icon ?? null,
|
icon: input.icon ?? null,
|
||||||
@@ -275,6 +283,7 @@ export namespace Game {
|
|||||||
set: {
|
set: {
|
||||||
slug: input.slug,
|
slug: input.slug,
|
||||||
name: input.name,
|
name: input.name,
|
||||||
|
aliases: input.aliases ?? null,
|
||||||
type: input.type ?? null,
|
type: input.type ?? null,
|
||||||
clientIcon: input.clientIcon ?? null,
|
clientIcon: input.clientIcon ?? null,
|
||||||
icon: input.icon ?? null,
|
icon: input.icon ?? null,
|
||||||
@@ -305,11 +314,15 @@ export namespace Game {
|
|||||||
|
|
||||||
export const searchByName = fn(z.string(), async (query) => {
|
export const searchByName = fn(z.string(), async (query) => {
|
||||||
return Database.use(async (tx) => {
|
return Database.use(async (tx) => {
|
||||||
|
const pattern = '%' + query + '%';
|
||||||
return tx
|
return tx
|
||||||
.select()
|
.select()
|
||||||
.from(GameTable)
|
.from(GameTable)
|
||||||
.where(
|
.where(
|
||||||
and(isNull(GameTable.timeDeleted), sql`${GameTable.name} ILIKE ${'%' + query + '%'}`)
|
and(
|
||||||
|
isNull(GameTable.timeDeleted),
|
||||||
|
or(sql`${GameTable.name} ILIKE ${pattern}`, sql`${GameTable.aliases} ILIKE ${pattern}`)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
.orderBy(GameTable.name)
|
.orderBy(GameTable.name)
|
||||||
.limit(50);
|
.limit(50);
|
||||||
@@ -361,6 +374,7 @@ export namespace Game {
|
|||||||
steamAppId: input.steamAppId,
|
steamAppId: input.steamAppId,
|
||||||
slug: input.slug,
|
slug: input.slug,
|
||||||
name: input.name,
|
name: input.name,
|
||||||
|
aliases: input.aliases,
|
||||||
type: input.type,
|
type: input.type,
|
||||||
clientIcon: input.clientIcon,
|
clientIcon: input.clientIcon,
|
||||||
icon: input.icon,
|
icon: input.icon,
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ export namespace Identifier {
|
|||||||
game: 'gam',
|
game: 'gam',
|
||||||
userLibrary: 'ulb',
|
userLibrary: 'ulb',
|
||||||
gameDepot: 'gdp',
|
gameDepot: 'gdp',
|
||||||
gameDownload: 'gdl'
|
gameDownload: 'gdl',
|
||||||
|
waitlistEntry: 'wle'
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export function schema(prefix: keyof typeof prefixes) {
|
export function schema(prefix: keyof typeof prefixes) {
|
||||||
|
|||||||
@@ -56,6 +56,16 @@ export namespace Fingerprint {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const fromID = fn(Info.shape.id, async (id) => {
|
||||||
|
return Database.use(async (tx) => {
|
||||||
|
return tx
|
||||||
|
.select()
|
||||||
|
.from(UserFingerprintTable)
|
||||||
|
.where(and(eq(UserFingerprintTable.id, id), isNull(UserFingerprintTable.timeDeleted)))
|
||||||
|
.then((rows) => rows.at(0) ?? null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
export const findByFingerprint = fn(Info.shape.fingerprint, async (fingerprint) => {
|
export const findByFingerprint = fn(Info.shape.fingerprint, async (fingerprint) => {
|
||||||
return Database.use(async (tx) => {
|
return Database.use(async (tx) => {
|
||||||
return tx
|
return tx
|
||||||
|
|||||||
@@ -103,6 +103,23 @@ export namespace User {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const setEmail = fn(
|
||||||
|
Info.pick({ id: true }).extend({ email: z.email(), emailVerified: z.boolean() }),
|
||||||
|
async (input) => {
|
||||||
|
return Database.use(async (tx) => {
|
||||||
|
const [row] = await tx
|
||||||
|
.update(UserTable)
|
||||||
|
.set({
|
||||||
|
email: input.email,
|
||||||
|
emailVerified: input.emailVerified
|
||||||
|
})
|
||||||
|
.where(eq(UserTable.id, input.id))
|
||||||
|
.returning();
|
||||||
|
return row ? serialize(row) : null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
export const remove = fn(Info.shape.id, async (id) => {
|
export const remove = fn(Info.shape.id, async (id) => {
|
||||||
await Database.use(async (tx) => {
|
await Database.use(async (tx) => {
|
||||||
await tx
|
await tx
|
||||||
|
|||||||
30
packages/core/src/user/verification.sql.ts
Normal file
30
packages/core/src/user/verification.sql.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { index, integer, pgEnum, pgTable, text } from 'drizzle-orm/pg-core';
|
||||||
|
|
||||||
|
import { id, timestamps, ulid, utc } from '../db/types.js';
|
||||||
|
import { UserTable } from './user.sql.js';
|
||||||
|
|
||||||
|
export const VerificationKindEnum = pgEnum('verification_kind', ['email']);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A short-lived code proving the owner of an email address.
|
||||||
|
*
|
||||||
|
* The `ver` id prefix was reserved for this before the table existed. Codes
|
||||||
|
* are hashed at rest so a leaked database cannot be used to verify on behalf
|
||||||
|
* of its users.
|
||||||
|
*/
|
||||||
|
export const VerificationTable = pgTable(
|
||||||
|
'verification',
|
||||||
|
{
|
||||||
|
...id,
|
||||||
|
...timestamps,
|
||||||
|
userId: ulid('user_id')
|
||||||
|
.notNull()
|
||||||
|
.references(() => UserTable.id, { onDelete: 'cascade' }),
|
||||||
|
kind: VerificationKindEnum('kind').notNull(),
|
||||||
|
codeHash: text('code_hash').notNull(),
|
||||||
|
expiresAt: utc('expires_at').notNull(),
|
||||||
|
attempts: integer('attempts').notNull().default(0),
|
||||||
|
consumedAt: utc('consumed_at')
|
||||||
|
},
|
||||||
|
(t) => [index('verification_user_kind_idx').on(t.userId, t.kind)]
|
||||||
|
);
|
||||||
146
packages/core/src/user/verification.ts
Normal file
146
packages/core/src/user/verification.ts
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
import { createHash, randomBytes } from 'node:crypto';
|
||||||
|
|
||||||
|
import { and, desc, eq, gt, isNull, sql } from 'drizzle-orm';
|
||||||
|
import z from 'zod';
|
||||||
|
|
||||||
|
import { Database } from '../db/index.js';
|
||||||
|
import { fn } from '../fn.js';
|
||||||
|
import { Identifier } from '../id.js';
|
||||||
|
import { UserTable } from './user.sql.js';
|
||||||
|
import { VerificationKindEnum, VerificationTable } from './verification.sql.js';
|
||||||
|
|
||||||
|
export function hashCode(code: string): string {
|
||||||
|
return createHash('sha256').update(code).digest('hex');
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateCode(): string {
|
||||||
|
const bytes = randomBytes(3);
|
||||||
|
return String((bytes[0]! << 16) | (bytes[1]! << 8) | bytes[2]!)
|
||||||
|
.padStart(6, '0')
|
||||||
|
.slice(0, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MAX_VERIFICATION_ATTEMPTS = 5;
|
||||||
|
export const VERIFICATION_TTL_MINUTES = 10;
|
||||||
|
|
||||||
|
export namespace Verification {
|
||||||
|
export const create = fn(
|
||||||
|
z.object({
|
||||||
|
userId: z.string(),
|
||||||
|
kind: z.enum(VerificationKindEnum.enumValues),
|
||||||
|
code: z.string().optional()
|
||||||
|
}),
|
||||||
|
async (input) => {
|
||||||
|
const code = input.code ?? generateCode();
|
||||||
|
// Old codes must not stay valid once a fresh one exists.
|
||||||
|
await Database.use(async (tx) => {
|
||||||
|
await tx
|
||||||
|
.update(VerificationTable)
|
||||||
|
.set({ consumedAt: sql`now()` })
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(VerificationTable.userId, input.userId),
|
||||||
|
eq(VerificationTable.kind, input.kind),
|
||||||
|
isNull(VerificationTable.consumedAt)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
await tx.insert(VerificationTable).values({
|
||||||
|
id: Identifier.ascending('verification'),
|
||||||
|
userId: input.userId,
|
||||||
|
kind: input.kind,
|
||||||
|
codeHash: hashCode(code),
|
||||||
|
expiresAt: sql`now() + interval '${sql.raw(String(VERIFICATION_TTL_MINUTES))} minutes'`,
|
||||||
|
attempts: 0,
|
||||||
|
consumedAt: null
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redeem a code for the user's email.
|
||||||
|
*
|
||||||
|
* The whole flow — find the active code, check the hash, burn the code,
|
||||||
|
* flip the flag — happens in one transaction so a code cannot be raced
|
||||||
|
* into double use.
|
||||||
|
*/
|
||||||
|
export const verifyEmail = fn(
|
||||||
|
z.object({ userId: z.string(), code: z.string() }),
|
||||||
|
async (input) => {
|
||||||
|
return Database.transaction(async (tx) => {
|
||||||
|
const active = await tx
|
||||||
|
.select()
|
||||||
|
.from(VerificationTable)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(VerificationTable.userId, input.userId),
|
||||||
|
eq(VerificationTable.kind, 'email'),
|
||||||
|
isNull(VerificationTable.consumedAt),
|
||||||
|
gt(VerificationTable.expiresAt, sql`now()`)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.orderBy(desc(VerificationTable.timeCreated))
|
||||||
|
.then((rows) => rows.at(0) ?? null);
|
||||||
|
|
||||||
|
if (!active) {
|
||||||
|
return { ok: false as const, reason: 'no_active_code' as const };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hashCode(input.code) !== active.codeHash) {
|
||||||
|
const burn = active.attempts + 1 >= MAX_VERIFICATION_ATTEMPTS;
|
||||||
|
await tx
|
||||||
|
.update(VerificationTable)
|
||||||
|
.set({
|
||||||
|
attempts: sql`${VerificationTable.attempts} + 1`,
|
||||||
|
// Exhausted codes are consumed so the next attempt
|
||||||
|
// asks for a fresh one instead of counting forever.
|
||||||
|
consumedAt: burn ? sql`now()` : undefined
|
||||||
|
})
|
||||||
|
.where(eq(VerificationTable.id, active.id));
|
||||||
|
return { ok: false as const, reason: 'wrong_code' as const };
|
||||||
|
}
|
||||||
|
|
||||||
|
await tx
|
||||||
|
.update(VerificationTable)
|
||||||
|
.set({ consumedAt: sql`now()` })
|
||||||
|
.where(eq(VerificationTable.id, active.id));
|
||||||
|
await tx
|
||||||
|
.update(UserTable)
|
||||||
|
.set({ emailVerified: true })
|
||||||
|
.where(eq(UserTable.id, input.userId));
|
||||||
|
return { ok: true as const };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export const findActiveByUserAndKind = fn(
|
||||||
|
z.object({ userId: z.string(), kind: z.enum(VerificationKindEnum.enumValues) }),
|
||||||
|
async (input) => {
|
||||||
|
return Database.use(async (tx) => {
|
||||||
|
return tx
|
||||||
|
.select()
|
||||||
|
.from(VerificationTable)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(VerificationTable.userId, input.userId),
|
||||||
|
eq(VerificationTable.kind, input.kind),
|
||||||
|
isNull(VerificationTable.consumedAt),
|
||||||
|
gt(VerificationTable.expiresAt, sql`now()`)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.orderBy(desc(VerificationTable.timeCreated))
|
||||||
|
.then((rows) => rows.at(0) ?? null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export const consume = fn(z.string(), async (id) => {
|
||||||
|
await Database.use(async (tx) => {
|
||||||
|
await tx
|
||||||
|
.update(VerificationTable)
|
||||||
|
.set({ consumedAt: sql`now()` })
|
||||||
|
.where(eq(VerificationTable.id, id));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
83
packages/core/src/waitlist/index.ts
Normal file
83
packages/core/src/waitlist/index.ts
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import { and, eq, isNull } from 'drizzle-orm';
|
||||||
|
import z from 'zod';
|
||||||
|
|
||||||
|
import { Database } from '../db/index.js';
|
||||||
|
import { Examples } from '../examples.js';
|
||||||
|
import { fn } from '../fn.js';
|
||||||
|
import { Identifier } from '../id.js';
|
||||||
|
import { WaitlistEntryTable } from './waitlist.sql.js';
|
||||||
|
|
||||||
|
export namespace Waitlist {
|
||||||
|
export const Info = z
|
||||||
|
.object({
|
||||||
|
id: z.string().meta({
|
||||||
|
description: 'Unique identifier for the waitlist entry',
|
||||||
|
example: Examples.WaitlistEntry.id
|
||||||
|
}),
|
||||||
|
email: z.email().meta({
|
||||||
|
description: 'The email to notify',
|
||||||
|
example: Examples.WaitlistEntry.email
|
||||||
|
}),
|
||||||
|
source: z.string().meta({
|
||||||
|
description: 'What the signup was for',
|
||||||
|
example: Examples.WaitlistEntry.source
|
||||||
|
}),
|
||||||
|
timeCreated: z.iso.datetime().meta({
|
||||||
|
description: 'When the signup happened',
|
||||||
|
example: Examples.WaitlistEntry.timeCreated
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.meta({
|
||||||
|
ref: 'WaitlistEntry',
|
||||||
|
description: 'A waitlist signup for a not-yet-launched feature',
|
||||||
|
example: Examples.WaitlistEntry
|
||||||
|
});
|
||||||
|
|
||||||
|
export type Info = z.infer<typeof Info>;
|
||||||
|
|
||||||
|
export const join = fn(Info.pick({ email: true, source: true }), async (input) => {
|
||||||
|
const existing = await Database.use(async (tx) => {
|
||||||
|
return tx
|
||||||
|
.select()
|
||||||
|
.from(WaitlistEntryTable)
|
||||||
|
.where(and(eq(WaitlistEntryTable.email, input.email), isNull(WaitlistEntryTable.timeDeleted)))
|
||||||
|
.then((rows) => rows.at(0) ?? null);
|
||||||
|
});
|
||||||
|
if (existing) {
|
||||||
|
// Joining twice changes nothing; the entry stays as it was.
|
||||||
|
return serialize(existing);
|
||||||
|
}
|
||||||
|
|
||||||
|
const row = await Database.use(async (tx) => {
|
||||||
|
return tx
|
||||||
|
.insert(WaitlistEntryTable)
|
||||||
|
.values({
|
||||||
|
id: Identifier.ascending('waitlistEntry'),
|
||||||
|
email: input.email,
|
||||||
|
source: input.source
|
||||||
|
})
|
||||||
|
.returning()
|
||||||
|
.then((rows) => rows.at(0));
|
||||||
|
});
|
||||||
|
return row ? serialize(row) : null;
|
||||||
|
});
|
||||||
|
|
||||||
|
export async function list() {
|
||||||
|
return Database.use(async (tx) => {
|
||||||
|
return tx
|
||||||
|
.select()
|
||||||
|
.from(WaitlistEntryTable)
|
||||||
|
.where(isNull(WaitlistEntryTable.timeDeleted))
|
||||||
|
.orderBy(WaitlistEntryTable.timeCreated);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function serialize(input: typeof WaitlistEntryTable.$inferSelect): Info {
|
||||||
|
return {
|
||||||
|
id: input.id,
|
||||||
|
email: input.email,
|
||||||
|
source: input.source,
|
||||||
|
timeCreated: input.timeCreated.toISOString()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
25
packages/core/src/waitlist/waitlist.sql.ts
Normal file
25
packages/core/src/waitlist/waitlist.sql.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { index, pgTable, text, uniqueIndex } from 'drizzle-orm/pg-core';
|
||||||
|
|
||||||
|
import { id, timestamps } from '../db/types.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Someone asking to be told when a self-hosted machines feature launches.
|
||||||
|
*
|
||||||
|
* Kept deliberately dumb: an email and where it came from. No auth — the whole
|
||||||
|
* point is that a visitor without an account can leave one.
|
||||||
|
*/
|
||||||
|
export const WaitlistEntryTable = pgTable(
|
||||||
|
'waitlist_entry',
|
||||||
|
{
|
||||||
|
...id,
|
||||||
|
...timestamps,
|
||||||
|
email: text('email').notNull(),
|
||||||
|
// What the signup was for (e.g. "machines"), so one form can grow
|
||||||
|
// into several without a schema change.
|
||||||
|
source: text('source').notNull().default('machines')
|
||||||
|
},
|
||||||
|
(t) => [
|
||||||
|
uniqueIndex('waitlist_entry_email_unique').on(t.email),
|
||||||
|
index('waitlist_entry_source_idx').on(t.source)
|
||||||
|
]
|
||||||
|
);
|
||||||
Reference in New Issue
Block a user