diff --git a/.env b/.env
index 3e76ccab6..123e4bd74 100644
--- a/.env
+++ b/.env
@@ -11,11 +11,13 @@ APP_NAME=Acme Co.
APP_HOSTNAME=localhost
APP_ORIGIN=http://localhost:5173
API_ORIGIN=https://api-mcfytwakla-uc.a.run.app
+APP_STORAGE_BUCKET=example.com
# Google Cloud
# https://console.cloud.google.com/
GOOGLE_CLOUD_PROJECT=kriasoft
GOOGLE_CLOUD_REGION=us-central1
+GOOGLE_CLOUD_DATABASE="(default)"
GOOGLE_CLOUD_CREDENTIALS={"type":"service_account","project_id":"example","private_key_id":"xxx","private_key":"-----BEGIN PRIVATE KEY-----\nxxxxx\n-----END PRIVATE KEY-----\n","client_email":"application@exmaple.iam.gserviceaccount.com","client_id":"xxxxx","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_x509_cert_url":"https://www.googleapis.com/robot/v1/metadata/x509/application%40example.iam.gserviceaccount.com"}
# Firebase
@@ -24,6 +26,11 @@ FIREBASE_APP_ID=1:736557952746:web:b5ee23841e24c0b883b193
FIREBASE_API_KEY=AIzaSyAZDmdeRWvlYgZpwm6LBCkYJM6ySIMF2Hw
FIREBASE_AUTH_DOMAIN=kriasoft.web.app
+# OpenAI
+# https://platform.openai.com/
+OPENAI_ORGANIZATION=xxxxx
+OPENAI_API_KEY=xxxxx
+
# Cloudflare
# https://dash.cloudflare.com/
# https://developers.cloudflare.com/api/tokens/create
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 5162a0e85..d2ac34e86 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -61,6 +61,7 @@
"firestore",
"globby",
"hono",
+ "identitytoolkit",
"jamstack",
"kriasoft",
"localforage",
@@ -68,16 +69,20 @@
"nodenext",
"notistack",
"oidc",
+ "openai",
"pathinfo",
+ "pino",
"pnpify",
"reactstarter",
"refetch",
"refetchable",
+ "relyingparty",
"sendgrid",
"signup",
"sourcemap",
"spdx",
"swapi",
+ "trpc",
"tslib",
"typechecking",
"vite",
diff --git a/README.md b/README.md
index 0e53aa73a..ae0224eb3 100644
--- a/README.md
+++ b/README.md
@@ -31,9 +31,11 @@ Be sure to join our [Discord channel](https://discord.com/invite/2nKEnKq) for as
`├──`[`.github`](.github) — GitHub configuration including CI/CD workflows
`├──`[`.vscode`](.vscode) — VSCode settings including code snippets, recommended extensions etc.
`├──`[`app`](./app) — Web application front-end built with [React](https://react.dev/) and [Joy UI](https://mui.com/joy-ui/getting-started/)
+`├──`[`db`](./db) — Firestore database schema, seed data, and admin tools
`├──`[`edge`](./edge) — Cloudflare Workers (CDN) edge endpoint
`├──`[`env`](./env) — Application settings, API keys, etc.
`├──`[`scripts`](./scripts) — Automation scripts such as `yarn deploy`
+`├──`[`server`](./server) — Node.js application server built with [tRPC](https://trpc.io/)
`├──`[`tsconfig.base.json`](./tsconfig.base.json) — The common/shared TypeScript configuration
`└──`[`tsconfig.json`](./tsconfig.json) — The root TypeScript configuration
diff --git a/app/package.json b/app/package.json
index 524f4bcb9..50fde8331 100644
--- a/app/package.json
+++ b/app/package.json
@@ -36,7 +36,7 @@
"devDependencies": {
"@babel/core": "^7.23.7",
"@emotion/babel-plugin": "^11.11.0",
- "@types/node": "^20.10.6",
+ "@types/node": "^20.10.7",
"@types/react": "^18.2.47",
"@types/react-dom": "^18.2.18",
"@vitejs/plugin-react": "^4.2.1",
diff --git a/db/README.md b/db/README.md
new file mode 100644
index 000000000..12d758756
--- /dev/null
+++ b/db/README.md
@@ -0,0 +1,20 @@
+# Firestore Database
+
+Database schema, security rules, indexes, and seed data for the [Firestore](https://cloud.google.com/firestore) database.
+
+## Directory Structure
+
+- [`/models`](./models/) — Database schema definitions using [Zod](https://zod.dev/).
+- [`/seeds`](./seeds/) — Sample / reference data for the database.
+- [`/scripts`](./scripts/) — Scripts for managing the database.
+- [`/firestore.indexes.json`](./firestore.indexes.json) — Firestore indexes.
+- [`/firestore.rules`](./firestore.rules) — Firestore security rules.
+
+## Scripts
+
+- `yarn workspace db seed` - Seed the database with data from [`/seeds`](./seeds/).
+
+## References
+
+- https://zod.dev/
+- https://cloud.google.com/firestore
diff --git a/db/firestore.indexes.json b/db/firestore.indexes.json
new file mode 100644
index 000000000..19272370d
--- /dev/null
+++ b/db/firestore.indexes.json
@@ -0,0 +1,13 @@
+{
+ "indexes": [
+ {
+ "collectionGroup": "workspace",
+ "queryScope": "COLLECTION",
+ "fields": [
+ { "fieldPath": "ownerId", "order": "ASCENDING" },
+ { "fieldPath": "archived", "order": "DESCENDING" }
+ ]
+ }
+ ],
+ "fieldOverrides": []
+}
diff --git a/db/firestore.rules b/db/firestore.rules
new file mode 100644
index 000000000..23b616177
--- /dev/null
+++ b/db/firestore.rules
@@ -0,0 +1,19 @@
+// Firestore security rules.
+// https://cloud.google.com/firestore/docs/security/get-started
+
+rules_version = '2';
+
+service cloud.firestore {
+ match /databases/{database}/documents {
+ match /workspace/{id} {
+ allow read: if request.auth != null && (
+ resource.data.ownerId = request.auth.uid ||
+ request.auth.token.admin == true
+ );
+ }
+
+ match /{document=**} {
+ allow read, write: if false;
+ }
+ }
+}
diff --git a/db/index.ts b/db/index.ts
new file mode 100644
index 000000000..a4c50fa4b
--- /dev/null
+++ b/db/index.ts
@@ -0,0 +1,6 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+export * from "./models";
+export { testUsers } from "./seeds/01-users";
+export { testWorkspaces } from "./seeds/02-workspaces";
diff --git a/db/models/index.ts b/db/models/index.ts
new file mode 100644
index 000000000..0690c018f
--- /dev/null
+++ b/db/models/index.ts
@@ -0,0 +1,4 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+export * from "./workspace";
diff --git a/db/models/workspace.ts b/db/models/workspace.ts
new file mode 100644
index 000000000..7794839ed
--- /dev/null
+++ b/db/models/workspace.ts
@@ -0,0 +1,16 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+import { Timestamp } from "@google-cloud/firestore";
+import { z } from "zod";
+
+export const WorkspaceSchema = z.object({
+ name: z.string().max(100),
+ ownerId: z.string().max(50),
+ created: z.instanceof(Timestamp),
+ updated: z.instanceof(Timestamp),
+ archived: z.instanceof(Timestamp).nullable(),
+});
+
+export type Workspace = z.output;
+export type WorkspaceInput = z.input;
diff --git a/db/package.json b/db/package.json
new file mode 100644
index 000000000..c8c41afa7
--- /dev/null
+++ b/db/package.json
@@ -0,0 +1,30 @@
+{
+ "name": "db",
+ "version": "0.0.0",
+ "private": true,
+ "type": "module",
+ "exports": {
+ ".": {
+ "default": "./index.ts"
+ },
+ "./package.json": "./package.json"
+ },
+ "scripts": {
+ "seed": "vite-node ./scripts/seed.ts",
+ "test": "vitest"
+ },
+ "dependencies": {
+ "@google-cloud/firestore": "^7.1.0",
+ "@googleapis/identitytoolkit": "^8.0.0",
+ "zod": "^3.22.4"
+ },
+ "devDependencies": {
+ "@types/node": "^20.10.7",
+ "dotenv": "^16.3.1",
+ "ora": "^8.0.1",
+ "typescript": "~5.3.3",
+ "vite": "~5.0.11",
+ "vite-node": "~1.1.3",
+ "vitest": "~1.1.3"
+ }
+}
diff --git a/db/scripts/seed.ts b/db/scripts/seed.ts
new file mode 100644
index 000000000..5fa0eafda
--- /dev/null
+++ b/db/scripts/seed.ts
@@ -0,0 +1,43 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+import { Firestore } from "@google-cloud/firestore";
+import { configDotenv } from "dotenv";
+import { relative, resolve } from "node:path";
+import { oraPromise } from "ora";
+
+const rootDir = resolve(__dirname, "../..");
+
+// Load environment variables from .env files.
+configDotenv({ path: resolve(rootDir, ".env.local") });
+configDotenv({ path: resolve(rootDir, ".env") });
+
+let db: Firestore | null = null;
+
+// Seed the database with test / sample data.
+try {
+ db = new Firestore({
+ projectId: process.env.GOOGLE_CLOUD_PROJECT,
+ databaseId: process.env.GOOGLE_CLOUD_DATABASE,
+ });
+
+ // Import all seed modules from the `/seeds` folder.
+ const files = import.meta.glob("../seeds/*.ts");
+
+ // Sequentially seed the database with data from each module.
+ for (const [path, load] of Object.entries(files)) {
+ const message = `Seeding ${relative("../seeds", path)}`;
+ const action = (async () => {
+ const { seed } = await load();
+ await seed(db);
+ })();
+
+ await oraPromise(action, message);
+ }
+} finally {
+ await db?.terminate();
+}
+
+type SeedModule = {
+ seed: (db: Firestore) => Promise;
+};
diff --git a/db/seeds/01-users.ts b/db/seeds/01-users.ts
new file mode 100644
index 000000000..09f23fb58
--- /dev/null
+++ b/db/seeds/01-users.ts
@@ -0,0 +1,87 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+import {
+ AuthPlus,
+ identitytoolkit,
+ identitytoolkit_v3,
+} from "@googleapis/identitytoolkit";
+
+/**
+ * Test user accounts generated by https://randomuser.me/.
+ */
+export const testUsers: identitytoolkit_v3.Schema$UserInfo[] = [
+ {
+ localId: "test-erika",
+ screenName: "erika",
+ email: "erika.pearson@example.com",
+ emailVerified: true,
+ phoneNumber: "+14788078434",
+ displayName: "Erika Pearson",
+ photoUrl: "https://randomuser.me/api/portraits/women/29.jpg",
+ rawPassword: "paloma",
+ createdAt: new Date("2024-01-01T12:00:00Z").getTime().toString(),
+ lastLoginAt: new Date("2024-01-01T12:00:00Z").getTime().toString(),
+ },
+ {
+ localId: "test-ryan",
+ screenName: "ryan",
+ email: "ryan.hunt@example.com",
+ emailVerified: true,
+ phoneNumber: "+16814758216",
+ displayName: "Ryan Hunt",
+ photoUrl: "https://randomuser.me/api/portraits/men/20.jpg",
+ rawPassword: "baggins",
+ createdAt: new Date("2024-01-02T12:00:00Z").getTime().toString(),
+ lastLoginAt: new Date("2024-01-02T12:00:00Z").getTime().toString(),
+ },
+ {
+ localId: "test-marian",
+ screenName: "marian",
+ email: "marian.stone@example.com",
+ emailVerified: true,
+ phoneNumber: "+19243007975",
+ displayName: "Marian Stone",
+ photoUrl: "https://randomuser.me/api/portraits/women/2.jpg",
+ rawPassword: "winter1",
+ createdAt: new Date("2024-01-03T12:00:00Z").getTime().toString(),
+ lastLoginAt: new Date("2024-01-03T12:00:00Z").getTime().toString(),
+ },
+ {
+ localId: "test-kurt",
+ screenName: "kurt",
+ email: "kurt.howward@example.com",
+ emailVerified: true,
+ phoneNumber: "+19243007975",
+ displayName: "Kurt Howard",
+ photoUrl: "https://randomuser.me/api/portraits/men/23.jpg",
+ rawPassword: "mayday",
+ createdAt: new Date("2024-01-04T12:00:00Z").getTime().toString(),
+ lastLoginAt: new Date("2024-01-04T12:00:00Z").getTime().toString(),
+ },
+ {
+ localId: "test-dan",
+ screenName: "dan",
+ email: "dan.day@example.com",
+ emailVerified: true,
+ phoneNumber: "+12046748092",
+ displayName: "Dan Day",
+ photoUrl: "https://randomuser.me/api/portraits/men/65.jpg",
+ rawPassword: "teresa",
+ createdAt: new Date("2024-01-05T12:00:00Z").getTime().toString(),
+ lastLoginAt: new Date("2024-01-05T12:00:00Z").getTime().toString(),
+ customAttributes: JSON.stringify({ admin: true }),
+ },
+];
+
+/**
+ * Seeds the Google Identity Platform (Firebase Auth) with test user accounts.
+ *
+ * @see https://randomuser.me/
+ * @see https://cloud.google.com/identity-platform
+ */
+export async function seed() {
+ const auth = new AuthPlus();
+ const { relyingparty } = identitytoolkit({ version: "v3", auth });
+ await relyingparty.uploadAccount({ requestBody: { users: testUsers } });
+}
diff --git a/db/seeds/02-workspaces.ts b/db/seeds/02-workspaces.ts
new file mode 100644
index 000000000..1455ec2d7
--- /dev/null
+++ b/db/seeds/02-workspaces.ts
@@ -0,0 +1,63 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+import { Firestore, Timestamp } from "@google-cloud/firestore";
+import { WorkspaceInput } from "../models";
+import { testUsers as users } from "./01-users";
+
+/**
+ * Test workspaces.
+ */
+export const testWorkspaces: (WorkspaceInput & { id: string })[] = [
+ {
+ id: "DwYchGFGpk",
+ ownerId: users[0].localId!,
+ name: "Personal workspace",
+ created: Timestamp.fromDate(new Date(+users[0].createdAt!)),
+ updated: Timestamp.fromDate(new Date(+users[0].createdAt!)),
+ archived: null,
+ },
+ {
+ id: "YfYKTcO9q9",
+ ownerId: users[1].localId!,
+ name: "Personal workspace",
+ created: Timestamp.fromDate(new Date(+users[1].createdAt!)),
+ updated: Timestamp.fromDate(new Date(+users[1].createdAt!)),
+ archived: null,
+ },
+ {
+ id: "c2OsmUvFMY",
+ ownerId: users[2].localId!,
+ name: "Personal workspace",
+ created: Timestamp.fromDate(new Date(+users[2].createdAt!)),
+ updated: Timestamp.fromDate(new Date(+users[2].createdAt!)),
+ archived: null,
+ },
+ {
+ id: "uTqcGw4qn7",
+ ownerId: users[3].localId!,
+ name: "Personal workspace",
+ created: Timestamp.fromDate(new Date(+users[3].createdAt!)),
+ updated: Timestamp.fromDate(new Date(+users[3].createdAt!)),
+ archived: null,
+ },
+ {
+ id: "vBHHgg5ydn",
+ ownerId: users[4].localId!,
+ name: "Personal workspace",
+ created: Timestamp.fromDate(new Date(+users[4].createdAt!)),
+ updated: Timestamp.fromDate(new Date(+users[4].createdAt!)),
+ archived: null,
+ },
+];
+
+export async function seed(db: Firestore) {
+ const batch = db.batch();
+
+ for (const { id, ...workspace } of testWorkspaces) {
+ const ref = db.doc(`workspace/${id}`);
+ batch.set(ref, workspace, { merge: true });
+ }
+
+ await batch.commit();
+}
diff --git a/db/tsconfig.json b/db/tsconfig.json
new file mode 100644
index 000000000..22d7921eb
--- /dev/null
+++ b/db/tsconfig.json
@@ -0,0 +1,14 @@
+{
+ "extends": "../tsconfig.base.json",
+ "compilerOptions": {
+ "composite": true,
+ "emitDeclarationOnly": true,
+ "module": "ESNext",
+ "moduleResolution": "Bundler",
+ "noEmit": false,
+ "outDir": "../.cache/ts-db",
+ "types": ["node", "vite/client"]
+ },
+ "include": ["**/*.ts", "**/*.json"],
+ "exclude": ["**/dist/**/*", "**/node_modules/**/*"]
+}
diff --git a/edge/package.json b/edge/package.json
index 2bb7a65cf..5af88ab69 100644
--- a/edge/package.json
+++ b/edge/package.json
@@ -26,7 +26,7 @@
},
"devDependencies": {
"@cloudflare/workers-types": "^4.20231218.0",
- "@types/node": "^20.10.6",
+ "@types/node": "^20.10.7",
"happy-dom": "^12.10.3",
"toml": "^3.0.0",
"typescript": "~5.3.3",
diff --git a/package.json b/package.json
index c9191ffb9..70e0fb324 100644
--- a/package.json
+++ b/package.json
@@ -1,16 +1,18 @@
{
"name": "root",
"version": "0.0.0",
- "private": true,
"packageManager": "yarn@4.0.2",
+ "private": true,
"type": "module",
"workspaces": [
"app",
+ "db",
"edge",
- "scripts"
+ "scripts",
+ "server"
],
"scripts": {
- "postinstall": "husky install && node ./scripts/postinstall.js",
+ "postinstall": "husky install && node ./scripts/post-install.js",
"start": "yarn workspace app start",
"lint": "eslint --cache --report-unused-disable-directives .",
"test": "vitest",
@@ -21,8 +23,8 @@
"@emotion/babel-plugin": "^11.11.0",
"@emotion/eslint-plugin": "^11.11.0",
"@types/eslint": "^8.56.1",
- "@typescript-eslint/eslint-plugin": "^6.17.0",
- "@typescript-eslint/parser": "^6.17.0",
+ "@typescript-eslint/eslint-plugin": "^6.18.0",
+ "@typescript-eslint/parser": "^6.18.0",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.1",
diff --git a/scripts/bundle-yarn.js b/scripts/bundle-yarn.js
new file mode 100644
index 000000000..81f85e741
--- /dev/null
+++ b/scripts/bundle-yarn.js
@@ -0,0 +1,33 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+import { execa } from "execa";
+import { copyFile, readFile, writeFile } from "node:fs/promises";
+import { resolve } from "node:path";
+import { fileURLToPath } from "node:url";
+
+const rootDir = resolve(fileURLToPath(import.meta.url), "../..");
+const rootPkg = JSON.parse(await readFile(`${rootDir}/package.json`, "utf-8"));
+const pkg = JSON.parse(await readFile("./package.json", "utf-8"));
+
+pkg.packageManager = rootPkg.packageManager;
+delete pkg.scripts;
+delete pkg.devDependencies;
+delete pkg.dependencies.db;
+
+// Create ./dist/package.json
+await writeFile("./dist/package.json", JSON.stringify(pkg, null, 2), "utf-8");
+
+// Create ./dist/yarn.lock
+await copyFile(`${rootDir}/yarn.lock`, "./dist/yarn.lock");
+
+// Install production dependencies
+await execa("yarn", ["install", "--mode=update-lockfile"], {
+ env: {
+ ...process.env,
+ NODE_OPTIONS: undefined,
+ YARN_ENABLE_IMMUTABLE_INSTALLS: "false",
+ },
+ cwd: "./dist",
+ stdio: "inherit",
+});
diff --git a/scripts/package.json b/scripts/package.json
index a479911a0..95f50a766 100644
--- a/scripts/package.json
+++ b/scripts/package.json
@@ -7,7 +7,7 @@
"dotenv": "^16.3.1",
"execa": "^8.0.1",
"get-port": "^7.0.0",
- "got": "^14.0.0",
+ "got": "^13.0.0",
"graphql": "^16.8.1",
"lodash-es": "^4.17.21",
"miniflare": "^3.20231218.1",
diff --git a/scripts/post-install.js b/scripts/post-install.js
new file mode 100644
index 000000000..447844f92
--- /dev/null
+++ b/scripts/post-install.js
@@ -0,0 +1,31 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+import { execa } from "execa";
+import fs from "node:fs";
+import { EOL } from "node:os";
+
+// Create Git-ignored files for environment variable overrides
+if (!fs.existsSync("./.env.local")) {
+ await fs.writeFile(
+ "./.env.local",
+ [
+ `# Overrides for the ``.env`` file in the root folder.`,
+ "#",
+ "# CLOUDFLARE_API_TOKEN=xxxxx",
+ "# GOOGLE_CLOUD_CREDENTIALS=xxxxx",
+ "# SENDGRID_API_KEY=xxxxx",
+ "#",
+ "",
+ "API_URL=http://localhost:8080",
+ "",
+ ].join(EOL),
+ "utf-8",
+ );
+}
+
+try {
+ await execa("yarn", ["tsc", "--build"], { stdin: "inherit" });
+} catch (err) {
+ console.error(err);
+}
diff --git a/scripts/postinstall.js b/scripts/postinstall.js
deleted file mode 100644
index 51cd15cb4..000000000
--- a/scripts/postinstall.js
+++ /dev/null
@@ -1,39 +0,0 @@
-/* SPDX-FileCopyrightText: 2014-present Kriasoft */
-/* SPDX-License-Identifier: MIT */
-
-import { execa } from "execa";
-import fs from "node:fs";
-import { EOL } from "node:os";
-
-const environments = [
- { name: "local", description: "development" },
- { name: "test", description: "staging/QA" },
- { name: "prod", description: "production" },
-];
-
-// Create Git-ignored files for environment variable overrides
-for (const env of environments) {
- const filename = `./env/.${env.name}.override.env`;
-
- if (!fs.existsSync(filename)) {
- await fs.writeFile(
- filename,
- [
- `# Overrides for the "${env.name}" (${env.description}) environment`,
- "#",
- "# CLOUDFLARE_API_TOKEN=xxxxx",
- "# GOOGLE_CLOUD_CREDENTIALS=xxxxx",
- "# SENDGRID_API_KEY=xxxxx",
- "#",
- "",
- ].join(EOL),
- "utf-8",
- );
- }
-}
-
-try {
- await execa("yarn", ["tsc", "--build"], { stdin: "inherit" });
-} catch (err) {
- console.error(err);
-}
diff --git a/server/Dockerfile b/server/Dockerfile
new file mode 100644
index 000000000..66b13e51a
--- /dev/null
+++ b/server/Dockerfile
@@ -0,0 +1,34 @@
+# SPDX-FileCopyrightText: 2014-present Kriasoft
+# SPDX-License-Identifier: MIT
+
+# Docker image for a Cloud Run service.
+#
+# https://cloud.google.com/run/docs/container-contract
+# https://cloud.google.com/run/docs/quickstarts/build-and-deploy/nodejs
+# https://github.com/GoogleCloudPlatform/cloud-run-microservice-template-nodejs/blob/main/Dockerfile
+
+# Use the official lightweight Node.js image.
+# https://hub.docker.com/_/node
+FROM node:20.10.0-slim
+
+# Upgrade OS packages.
+RUN apt-get update && apt-get upgrade -y
+
+# Set environment variables.
+ENV NODE_ENV=production
+
+# Create and change to the app directory.
+WORKDIR /usr/src/app
+
+# Copy application dependency manifests to the container image.
+# Copying this separately prevents re-running npm install on every code change.
+COPY dist/package.json dist/yarn.lock ./
+
+# Install dependencies.
+RUN corepack enable && yarn config set nodeLinker node-modules && yarn install --immutable
+
+# Copy compiled code to the container image.
+COPY ./dist .
+
+# Run the web service on container startup.
+CMD [ "node", "index.js" ]
diff --git a/server/README.md b/server/README.md
new file mode 100644
index 000000000..6fa39a911
--- /dev/null
+++ b/server/README.md
@@ -0,0 +1,9 @@
+# Application Server
+
+Node.js application server for web and mobile clients using [tRPC](https://trpc.io/) with HTTP and WebSocket transports.
+
+## Scripts
+
+- `yarn workspace server start` — Start the server in development mode.
+- `yarn workspace server build` — Build the server for production.
+- `yarn workspace server test` — Run tests.
diff --git a/server/app.test.ts b/server/app.test.ts
new file mode 100644
index 000000000..b8c7854ac
--- /dev/null
+++ b/server/app.test.ts
@@ -0,0 +1,30 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+import supertest from "supertest";
+import { describe, expect, it } from "vitest";
+import { app } from "./app";
+
+describe("GET /trpc", () => {
+ it("returns NOT_FOUND response for unknown requests", async () => {
+ const res = await supertest(app).get("/trpc");
+
+ expect({
+ statusCode: res.statusCode,
+ body: res.body,
+ }).toEqual({
+ statusCode: 404,
+ body: {
+ error: {
+ code: -32004,
+ data: {
+ code: "NOT_FOUND",
+ httpStatus: 404,
+ path: "",
+ },
+ message: 'No "query"-procedure on path ""',
+ },
+ },
+ });
+ });
+});
diff --git a/server/app.ts b/server/app.ts
new file mode 100644
index 000000000..ddf6d6f90
--- /dev/null
+++ b/server/app.ts
@@ -0,0 +1,54 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+import { createExpressMiddleware } from "@trpc/server/adapters/express";
+import express from "express";
+import { createProxyMiddleware } from "http-proxy-middleware";
+import { sessionMiddleware } from "./core/auth";
+import { env } from "./core/env";
+import { loggerMiddleware } from "./core/logging";
+import { createContext } from "./core/trpc";
+import { router } from "./routes/index";
+
+export const app = express();
+
+app.disable("x-powered-by");
+app.set("trust proxy", 1); // Trust first proxy
+
+app.use(loggerMiddleware);
+app.use(sessionMiddleware);
+
+/**
+ * tRPC HTTP handler for Express.js.
+ *
+ * @see https://trpc.io/docs/getting-started
+ * @see https://trpc.io/docs/server/adapters/express
+ */
+app.use("/trpc", createExpressMiddleware({ router, createContext }));
+
+/**
+ * Proxy auth requests to Google Identity Platform.
+ *
+ * @see https://firebase.google.com/docs/auth/web/redirect-best-practices
+ */
+app.use(
+ createProxyMiddleware("/__", {
+ target: `https://${env.GOOGLE_CLOUD_PROJECT}.firebaseapp.com`,
+ changeOrigin: true,
+ logLevel: "warn",
+ }),
+);
+
+/**
+ * Proxy static assets to Google Cloud Storage.
+ */
+app.use(
+ createProxyMiddleware("/", {
+ target: "https://c.storage.googleapis.com",
+ changeOrigin: true,
+ logLevel: "warn",
+ onProxyReq(proxyReq) {
+ proxyReq.setHeader("host", env.APP_STORAGE_BUCKET);
+ },
+ }),
+);
diff --git a/server/core/auth.test.ts b/server/core/auth.test.ts
new file mode 100644
index 000000000..248d4f757
--- /dev/null
+++ b/server/core/auth.test.ts
@@ -0,0 +1,52 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+import express from "express";
+import supertest from "supertest";
+import { describe, expect, it } from "vitest";
+import { fetchCertificates, sessionMiddleware } from "./auth";
+import { env } from "./env";
+
+describe("fetchCertificates()", () => {
+ it("should fetch certificates from Google", async () => {
+ const certs = await fetchCertificates();
+ expect(certs).toEqual(expect.any(Object));
+ expect(Object.values(certs)).toEqual(
+ expect.arrayContaining([
+ expect.stringMatching(/^-----BEGIN CERTIFICATE-----/),
+ ]),
+ );
+ });
+});
+
+describe("sessionMiddleware()", () => {
+ it.skip("should verify a valid ID token", async () => {
+ const app = express();
+ app.get("/", sessionMiddleware, (req, res) => {
+ res.type("json");
+ res.send(JSON.stringify(req.token));
+ });
+
+ const idToken = "eyJhbGciOiJSUzI1NiIsImtpZCI6ImQxNjg5NDE1ZWMyM2EzMzdlMmJiYWE1ZTNlNjhiNjZkYzk5MzY4ODQiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiS3JpYXNvZnQiLCJwaWN0dXJlIjoiaHR0cHM6Ly9saDMuZ29vZ2xldXNlcmNvbnRlbnQuY29tL2EvQUNnOG9jS0hBRVhvRXpJMnpoMWNpN3lna0FVZXFiRWppQ1ZxUE96VkZQYnZmUGtXcGc9czk2LWMiLCJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20va3JpYXNvZnQiLCJhdWQiOiJrcmlhc29mdCIsImF1dGhfdGltZSI6MTcwNDU0MjYyOCwidXNlcl9pZCI6IkpRdWxWbjhaMUhZelRIR0J5YnhlcndGRUhsNzIiLCJzdWIiOiJKUXVsVm44WjFIWXpUSEdCeWJ4ZXJ3RkVIbDcyIiwiaWF0IjoxNzA0NTQyNjI4LCJleHAiOjE3MDQ1NDYyMjgsImVtYWlsIjoia3JpYXNvZnRAZ21haWwuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImZpcmViYXNlIjp7ImlkZW50aXRpZXMiOnsiZ29vZ2xlLmNvbSI6WyIxMDI2NTQwODA3NzUxNTYyOTI2ODYiXSwiZW1haWwiOlsia3JpYXNvZnRAZ21haWwuY29tIl19LCJzaWduX2luX3Byb3ZpZGVyIjoiZ29vZ2xlLmNvbSJ9fQ.E1sOoIeLH0269m4K4DXfXOJk97cxc8h3D62u3q9Kqyk0AsmwQfKURRl34IiOtNEzizjesLex6EHSetFr8kS1GSgVrW6yxHowmJZCY8tsgSWfunZ7Vj8l1kG4y0iM7hdFw3t0dhilK8-vDlKpLeRfLVHG8qgt46qI7Rxmdb928llJoa7H6NuuS5heavNJadLfiYItJyUq7i5kjys6-WfndQQcRb7kTt07arHb_1w2jtZnyjZE_S3ErZcIgwnE9M_gqXZ4y1MucpGPR2_nHzicRBBYOMwZDVG7Y0tI9IWRaTyTF3Psd7XKisE6GorZ_X1cDwkaT5ffoXZ1tkBOjeMjfw"; // prettier-ignore
+ const res = await supertest(app).get("/").auth(idToken, { type: "bearer" });
+
+ expect({ status: res.status, body: res.body }).toEqual({
+ status: 200,
+ body: expect.objectContaining({
+ name: expect.any(String),
+ picture: expect.any(String),
+ iss: `https://securetoken.google.com/${env.GOOGLE_CLOUD_PROJECT}`,
+ aud: env.GOOGLE_CLOUD_PROJECT,
+ auth_time: expect.any(Number),
+ sub: expect.any(String),
+ iat: expect.any(Number),
+ exp: expect.any(Number),
+ email: expect.any(String),
+ email_verified: true,
+ firebase: expect.objectContaining({
+ sign_in_provider: "google.com",
+ }),
+ }),
+ });
+ });
+});
diff --git a/server/core/auth.ts b/server/core/auth.ts
new file mode 100644
index 000000000..9affeaea2
--- /dev/null
+++ b/server/core/auth.ts
@@ -0,0 +1,188 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+import { NextFunction, Request, Response } from "express";
+import {
+ Certificates,
+ GoogleAuth,
+ IdTokenClient,
+ TokenPayload,
+} from "google-auth-library";
+import { got } from "got";
+import { env } from "./env";
+
+export const auth = new GoogleAuth({
+ scopes: ["https://www.googleapis.com/auth/cloud-platform"],
+});
+
+const certificatesURL = "https://www.googleapis.com/service_accounts/v1/metadata/x509/securetoken@system.gserviceaccount.com"; // prettier-ignore
+const certificatesCache = new Map();
+
+/**
+ * Fetches the latest Google Cloud Identity Platform certificates.
+ */
+export function fetchCertificates(options?: { signal: AbortSignal }) {
+ return got.get(certificatesURL, {
+ cache: certificatesCache,
+ resolveBodyOnly: true,
+ responseType: "json",
+ signal: options?.signal,
+ });
+}
+
+// Refresh certificates every 6 hours.
+const cleanup = (() => {
+ const ac = new AbortController();
+ const int = setInterval(() => fetchCertificates(), 2.16e7);
+ fetchCertificates({ signal: ac.signal });
+ return () => {
+ clearInterval(int);
+ ac.abort();
+ };
+})();
+
+process.on("SIGTERM", cleanup);
+process.on("SIGINT", cleanup);
+
+const idTokenClients = new Map();
+
+/**
+ * Express middleware that verifies that the request has a valid Firebase ID
+ * token attached, and adds the decoded token to `req.token`.
+ */
+export async function sessionMiddleware(
+ req: Request,
+ res: Response,
+ next: NextFunction,
+) {
+ try {
+ req.token = null;
+ const idToken = req.headers.authorization?.replace(/^Bearer /i, "");
+
+ if (idToken) {
+ const certificatesPromise = fetchCertificates();
+ const audience = env.GOOGLE_CLOUD_PROJECT;
+ let idTokenClient = idTokenClients.get(audience);
+
+ if (!idTokenClient) {
+ idTokenClient = await auth.getIdTokenClient(audience);
+ idTokenClients.set(audience, idTokenClient);
+ }
+
+ const ticket = await idTokenClient.verifySignedJwtWithCertsAsync(
+ idToken,
+ await certificatesPromise,
+ audience,
+ [`https://securetoken.google.com/${env.GOOGLE_CLOUD_PROJECT}`],
+ );
+
+ const token = ticket.getPayload();
+
+ if (token) {
+ if ("user_id" in token) delete token.user_id;
+ Object.assign(token, { uid: token.sub });
+ req.token = token as DecodedIdToken;
+ }
+ }
+
+ next();
+ } catch (err) {
+ req.log?.warn(err);
+ next();
+ }
+}
+
+// #region Types
+
+/**
+ * Interface representing a decoded Firebase ID token, returned from the
+ * {@link verifyIdToken} method.
+ *
+ * Firebase ID tokens are OpenID Connect spec-compliant JSON Web Tokens (JWTs).
+ * See the
+ * [ID Token section of the OpenID Connect spec](http://openid.net/specs/openid-connect-core-1_0.html#IDToken)
+ * for more information about the specific properties below.
+ */
+export interface DecodedIdToken extends TokenPayload {
+ /**
+ * Time, in seconds since the Unix epoch, when the end-user authentication
+ * occurred.
+ *
+ * This value is not set when this particular ID token was created, but when the
+ * user initially logged in to this session. In a single session, the Firebase
+ * SDKs will refresh a user's ID tokens every hour. Each ID token will have a
+ * different [`iat`](#iat) value, but the same `auth_time` value.
+ */
+ auth_time: number;
+
+ /**
+ * Information about the sign in event, including which sign in provider was
+ * used and provider-specific identity details.
+ *
+ * This data is provided by the Firebase Authentication service and is a
+ * reserved claim in the ID token.
+ */
+ firebase: {
+ /**
+ * Provider-specific identity details corresponding
+ * to the provider used to sign in the user.
+ */
+ identities: {
+ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
+ [key: string]: any;
+ };
+
+ /**
+ * The ID of the provider used to sign in the user.
+ * One of `"anonymous"`, `"password"`, `"facebook.com"`, `"github.com"`,
+ * `"google.com"`, `"twitter.com"`, `"apple.com"`, `"microsoft.com"`,
+ * `"yahoo.com"`, `"phone"`, `"playgames.google.com"`, `"gc.apple.com"`,
+ * or `"custom"`.
+ *
+ * Additional Identity Platform provider IDs include `"linkedin.com"`,
+ * OIDC and SAML identity providers prefixed with `"saml."` and `"oidc."`
+ * respectively.
+ */
+ sign_in_provider: string;
+
+ /**
+ * The type identifier or `factorId` of the second factor, provided the
+ * ID token was obtained from a multi-factor authenticated user.
+ * For phone, this is `"phone"`.
+ */
+ sign_in_second_factor?: string;
+
+ /**
+ * The `uid` of the second factor used to sign in, provided the
+ * ID token was obtained from a multi-factor authenticated user.
+ */
+ second_factor_identifier?: string;
+
+ /**
+ * The ID of the tenant the user belongs to, if available.
+ */
+ tenant?: string;
+ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
+ [key: string]: any;
+ };
+
+ /**
+ * The phone number of the user to whom the ID token belongs, if available.
+ */
+ phone_number?: string;
+
+ /**
+ * The `uid` corresponding to the user who the ID token belonged to.
+ *
+ * This value is not actually in the JWT token claims itself. It is added as a
+ * convenience, and is set as the value of the [`sub`](#sub) property.
+ */
+ uid: string;
+
+ /**
+ * Indicates whether or not the user is an admin.
+ */
+ admin?: boolean;
+}
+
+// #endregion
diff --git a/server/core/env.ts b/server/core/env.ts
new file mode 100644
index 000000000..6feccc153
--- /dev/null
+++ b/server/core/env.ts
@@ -0,0 +1,21 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+import { cleanEnv, str } from "envalid";
+
+/**
+ * Environment variables that has been validated and sanitized.
+ *
+ * @see https://github.com/ilyakaznacheev/cleanenv#readme
+ */
+export const env = cleanEnv(process.env, {
+ VERSION: str({ default: "latest" }),
+
+ APP_STORAGE_BUCKET: str(),
+
+ GOOGLE_CLOUD_PROJECT: str(),
+ GOOGLE_CLOUD_DATABASE: str(),
+
+ OPENAI_ORGANIZATION: str(),
+ OPENAI_API_KEY: str(),
+});
diff --git a/server/core/firestore.ts b/server/core/firestore.ts
new file mode 100644
index 000000000..5c1965721
--- /dev/null
+++ b/server/core/firestore.ts
@@ -0,0 +1,18 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+import { Firestore } from "@google-cloud/firestore";
+import { env } from "./env";
+
+let db: Firestore | undefined;
+
+export function getFirestore() {
+ if (!db) {
+ db = new Firestore({
+ projectId: env.GOOGLE_CLOUD_PROJECT,
+ databaseId: env.GOOGLE_CLOUD_DATABASE,
+ });
+ }
+
+ return db;
+}
diff --git a/server/core/logging.ts b/server/core/logging.ts
new file mode 100644
index 000000000..b8ca332db
--- /dev/null
+++ b/server/core/logging.ts
@@ -0,0 +1,60 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+import { Request, Response } from "express";
+import { pino } from "pino";
+import { pinoHttp } from "pino-http";
+import { env } from "./env";
+
+/**
+ * Low overhead Node.js logger.
+ *
+ * @see https://github.com/pinojs/pino
+ */
+export const logger = pino({
+ // Custom formatter to set the "severity" property in the JSON payload
+ // to the log level to be automatically parsed.
+ // https://cloud.google.com/run/docs/logging#special-fields
+ formatters: {
+ level(label) {
+ return { severity: label };
+ },
+ },
+ transport: {
+ // Enable pretty printing in development.
+ // https://github.com/pinojs/pino-pretty#readme
+ target: env.isProduction ? "pino/file" : "pino-pretty",
+ options: {
+ ...(!env.isProduction && { colorize: true }),
+ ignore: env.isProduction
+ ? "pid,hostname"
+ : "pid,hostname,req.headers,req.remoteAddress,req.remotePort,res.headers",
+ },
+ },
+});
+
+/**
+ * Creates a request-based logger with trace ID field for logging correlation.
+ *
+ * @see https://cloud.google.com/run/docs/logging#correlate-logs
+ */
+export const loggerMiddleware = pinoHttp({
+ logger,
+ customProps(req) {
+ const traceHeader = req.header("X-Cloud-Trace-Context");
+
+ let trace;
+
+ if (traceHeader) {
+ const [traceId] = traceHeader.split("/");
+ trace = `projects/${env.GOOGLE_CLOUD_PROJECT}/traces/${traceId}`;
+ }
+
+ return {
+ "logging.googleapis.com/trace": trace,
+ };
+ },
+ redact: {
+ paths: ["req.headers.authorization", "req.headers.cookie"],
+ },
+});
diff --git a/server/core/openai.ts b/server/core/openai.ts
new file mode 100644
index 000000000..c3fe75560
--- /dev/null
+++ b/server/core/openai.ts
@@ -0,0 +1,15 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+import { OpenAI } from "openai";
+import { env } from "./env";
+
+/**
+ * OpenAI API client.
+ *
+ * @see https://github.com/openai/openai-node#readme
+ */
+export const openai = new OpenAI({
+ organization: env.OPENAI_ORGANIZATION,
+ apiKey: env.OPENAI_API_KEY,
+});
diff --git a/server/core/trpc.ts b/server/core/trpc.ts
new file mode 100644
index 000000000..31c67c604
--- /dev/null
+++ b/server/core/trpc.ts
@@ -0,0 +1,102 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+import { Firestore } from "@google-cloud/firestore";
+import { TRPCError, initTRPC } from "@trpc/server";
+import { CreateExpressContextOptions } from "@trpc/server/adapters/express";
+import { Logger } from "pino";
+import { SetNonNullable } from "type-fest";
+import { ZodError } from "zod";
+import { DecodedIdToken } from "./auth";
+import { env } from "./env";
+import { getFirestore } from "./firestore";
+import { logger } from "./logging";
+
+/**
+ * tRPC instance.
+ *
+ * @see https://trpc.io/docs/quickstart
+ */
+export const t = initTRPC.context().create({
+ isDev: env.isDev,
+
+ // https://trpc.io/docs/server/error-formatting
+ errorFormatter(opts) {
+ const { shape, error } = opts;
+ return {
+ ...shape,
+ data: {
+ ...shape.data,
+ ...(error.code === "BAD_REQUEST" &&
+ error.cause instanceof ZodError && {
+ zodError: error.cause.flatten(),
+ }),
+ },
+ };
+ },
+});
+
+/**
+ * Creates a tRPC context for an incoming HTTP request.
+ */
+export async function createContext(
+ ctx: CreateExpressContextOptions,
+): Promise {
+ return new HttpContext(getFirestore(), ctx.req.log, ctx.req.token);
+}
+
+/**
+ * Creates a tRPC context for an incoming WebSocket request.
+ */
+export async function createWsContext(): Promise {
+ return new WsContext(getFirestore(), logger);
+}
+
+class HttpContext {
+ constructor(
+ readonly db: Firestore,
+ readonly log: Logger,
+ readonly token: DecodedIdToken | null,
+ ) {}
+}
+
+class WsContext {
+ constructor(
+ readonly db: Firestore,
+ readonly log: Logger,
+ ) {}
+
+ get token(): DecodedIdToken | null {
+ throw new Error("ID token is not available in WebSocket context.");
+ }
+}
+
+/**
+ * Ensures that the user is authenticated.
+ */
+export const authorize = t.middleware((opts) => {
+ if (!opts.ctx.token) {
+ throw new TRPCError({ code: "UNAUTHORIZED" });
+ }
+
+ return opts.next({
+ ...opts,
+ ctx: opts.ctx as SetNonNullable,
+ });
+});
+
+/**
+ * Ensures that the user is an admin.
+ */
+export const authorizeAdmin = authorize.unstable_pipe((opts) => {
+ if (!opts.ctx.token.admin) {
+ throw new TRPCError({ code: "FORBIDDEN" });
+ }
+
+ return opts.next(opts);
+});
+
+/**
+ * tRPC context.
+ */
+export type Context = HttpContext;
diff --git a/server/core/utils.ts b/server/core/utils.ts
new file mode 100644
index 000000000..ce7480e6b
--- /dev/null
+++ b/server/core/utils.ts
@@ -0,0 +1,13 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+import { customAlphabet, urlAlphabet } from "nanoid";
+
+const shortIdAlphabet = urlAlphabet.replace(/[-_]/g, "");
+
+/**
+ * Generates secure unique ID using URL friendly characters.
+ *
+ * @see https://github.com/ai/nanoid#readme
+ */
+export const newId = customAlphabet(shortIdAlphabet, 10);
diff --git a/server/global.d.ts b/server/global.d.ts
new file mode 100644
index 000000000..4d3c00163
--- /dev/null
+++ b/server/global.d.ts
@@ -0,0 +1,13 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+import "express";
+import { DecodedIdToken } from "./core/auth";
+
+declare global {
+ namespace Express {
+ interface Request {
+ token: DecodedIdToken | null;
+ }
+ }
+}
diff --git a/server/index.ts b/server/index.ts
new file mode 100644
index 000000000..6000ae8f9
--- /dev/null
+++ b/server/index.ts
@@ -0,0 +1,65 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+import { applyWSSHandler } from "@trpc/server/adapters/ws";
+import { WebSocketServer } from "ws";
+import { app } from "./app";
+import { logger } from "./core/logging";
+import { createWsContext as createContext } from "./core/trpc";
+import { router } from "./routes";
+
+// Detect if running in Google Cloud environment
+const isCloudRun = !!process.env.K_SERVICE;
+
+/**
+ * Starts the HTTP and WebSocket servers.
+ */
+export function listen(port: number) {
+ const server = app.listen(port, () => {
+ logger.info(`API listening on ${port}`);
+ });
+
+ const wss = new WebSocketServer({ server, path: "/trpc" });
+ const handler = applyWSSHandler({ wss, router, createContext });
+
+ wss.on("connection", (ws) => {
+ logger.info({ clients: wss.clients.size }, "wss:connection");
+ ws.once("close", () => {
+ logger.info({ clients: wss.clients.size }, "wss:close");
+ });
+ });
+
+ return function dispose(cb?: () => void) {
+ handler.broadcastReconnectNotification();
+ wss.close((err) => {
+ if (err) logger.error(err);
+ if (isCloudRun) logger.info("WebSocket server closed");
+ server.close((err) => {
+ if (err) logger.error(err);
+ if (isCloudRun) logger.info("HTTP server closed");
+ logger.flush((err) => {
+ if (err) console.error(err);
+ if (isCloudRun) {
+ process.exit(0);
+ } else {
+ cb?.();
+ }
+ });
+ });
+ });
+ };
+}
+
+if (process.env.PORT && process.env.K_SERVICE?.startsWith("server")) {
+ const port = parseInt(process.env.PORT);
+ const dispose = listen(port);
+
+ /* eslint-disable-next-line no-inner-declarations */
+ function handleClose(code: NodeJS.Signals) {
+ logger.info(`${code} signal received`);
+ dispose();
+ }
+
+ process.on("SIGINT", handleClose);
+ process.on("SIGTERM", handleClose);
+}
diff --git a/server/package.json b/server/package.json
new file mode 100644
index 000000000..92bdcaa12
--- /dev/null
+++ b/server/package.json
@@ -0,0 +1,52 @@
+{
+ "name": "server",
+ "version": "0.0.0",
+ "private": true,
+ "type": "module",
+ "exports": {
+ ".": {
+ "types": "./types.ts"
+ },
+ "./package.json": "./package.json"
+ },
+ "scripts": {
+ "start": "vite-node --watch ./start.ts",
+ "build": "vite build && yarn node ../scripts/bundle-yarn.js",
+ "test": "vitest"
+ },
+ "dependencies": {
+ "@google-cloud/firestore": "^7.1.0",
+ "@googleapis/identitytoolkit": "^8.0.0",
+ "@trpc/server": "^10.45.0",
+ "db": "workspace:*",
+ "envalid": "^8.0.0",
+ "express": "^4.18.2",
+ "google-auth-library": "^9.4.1",
+ "got": "^13.0.0",
+ "http-errors": "^2.0.0",
+ "http-proxy-middleware": "^2.0.6",
+ "nanoid": "^5.0.4",
+ "openai": "^4.24.1",
+ "pino": "^8.17.2",
+ "pino-http": "^9.0.0",
+ "pino-pretty": "^10.3.1",
+ "type-fest": "^4.9.0",
+ "ws": "^8.16.0",
+ "zod": "^3.22.4"
+ },
+ "devDependencies": {
+ "@types/express": "^4.17.21",
+ "@types/http-errors": "^2.0.4",
+ "@types/node": "^20.10.7",
+ "@types/supertest": "^6.0.2",
+ "@types/ws": "^8.5.10",
+ "envars": "^1.0.2",
+ "get-port": "^7.0.0",
+ "supertest": "^6.3.3",
+ "type-fest": "^4.9.0",
+ "typescript": "~5.3.3",
+ "vite": "~5.0.11",
+ "vite-node": "~1.1.3",
+ "vitest": "~1.1.3"
+ }
+}
diff --git a/server/routes/index.ts b/server/routes/index.ts
new file mode 100644
index 000000000..93a7b37e6
--- /dev/null
+++ b/server/routes/index.ts
@@ -0,0 +1,15 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+import { t } from "../core/trpc";
+import { workspace } from "./workspace";
+
+/**
+ * The root tRPC router.
+ * @see https://trpc.io/docs/quickstart
+ */
+export const router = t.router({
+ workspace,
+});
+
+export type AppRouter = typeof router;
diff --git a/server/routes/workspace.test.ts b/server/routes/workspace.test.ts
new file mode 100644
index 000000000..6eea0ea0e
--- /dev/null
+++ b/server/routes/workspace.test.ts
@@ -0,0 +1,63 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+import { TRPCError } from "@trpc/server";
+import { testWorkspaces } from "db";
+import { describe, expect, it } from "vitest";
+import { createClient } from "../test/context";
+import * as router from "./workspace";
+
+describe("workspace.update()", () => {
+ it("requires authentication", async () => {
+ const [client] = createClient(router.workspace);
+ const action = client.update({
+ id: "xxxxxxxxxx",
+ name: "My Workspace",
+ });
+
+ await expect(action).rejects.toThrowError(
+ new TRPCError({ code: "UNAUTHORIZED" }),
+ );
+ });
+
+ it("workspace must exist", async () => {
+ const [client] = createClient(router.workspace, { user: "erika" });
+ const action = client.update({
+ id: "xxxxxxxxxx", // Non-existent workspace ID
+ name: "My Workspace",
+ });
+
+ await expect(action).rejects.toThrowError(
+ new TRPCError({ code: "NOT_FOUND" }),
+ );
+ });
+
+ it("workspace must belong to the user", async () => {
+ const [client, ctx] = createClient(router.workspace, { user: "erika" });
+ const id = testWorkspaces.find((x) => x.ownerId !== ctx.token?.uid)?.id;
+ expect(id).toEqual(expect.any(String));
+
+ const action = client.update({
+ id: id!, // Workspace ID that belongs to another user
+ name: "My Workspace",
+ });
+
+ await expect(action).rejects.toThrowError(
+ new TRPCError({ code: "NOT_FOUND" }),
+ );
+ });
+
+ it("updates the workspace", async () => {
+ const [client, ctx] = createClient(router.workspace, { user: "erika" });
+ const id = testWorkspaces.find((x) => x.ownerId === ctx.token?.uid)?.id;
+ expect(id).toEqual(expect.any(String));
+
+ await client.update({ id: id!, name: "My Workspace" });
+ const doc1 = await ctx.db.doc(`workspace/${id}`).get();
+ expect(doc1.data()?.name).toBe("My Workspace");
+
+ await client.update({ id: id!, name: "Personal workspace" });
+ const doc2 = await ctx.db.doc(`workspace/${id}`).get();
+ expect(doc2.data()?.name).toBe("Personal workspace");
+ });
+});
diff --git a/server/routes/workspace.ts b/server/routes/workspace.ts
new file mode 100644
index 000000000..c98eb4835
--- /dev/null
+++ b/server/routes/workspace.ts
@@ -0,0 +1,39 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+import { Timestamp } from "@google-cloud/firestore";
+import { TRPCError } from "@trpc/server";
+import { z } from "zod";
+import { authorize, t } from "../core/trpc";
+
+/**
+ * Workspace API.
+ */
+export const workspace = t.router({
+ /**
+ * Updates the workspace.
+ */
+ update: t.procedure
+ .use(authorize)
+ .input(
+ z.object({
+ id: z.string(),
+ name: z.string().max(100),
+ }),
+ )
+ .query(async ({ input, ctx }) => {
+ const { db } = ctx;
+ const doc = await db.doc(`workspace/${input.id}`).get();
+
+ if (!doc.exists || doc.data()?.ownerId !== ctx.token.uid) {
+ throw new TRPCError({ code: "NOT_FOUND" });
+ }
+
+ await doc.ref.update({
+ name: input.name,
+ updated: Timestamp.now(),
+ });
+ }),
+});
+
+export type WorkspaceRouter = typeof workspace;
diff --git a/server/start.ts b/server/start.ts
new file mode 100644
index 000000000..6d73dbb02
--- /dev/null
+++ b/server/start.ts
@@ -0,0 +1,26 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+import getPort, { portNumbers } from "get-port";
+import { listen } from "./index";
+
+const port = await getPort({ port: portNumbers(8080, 9000) });
+
+let dispose = listen(port);
+
+if (import.meta.hot) {
+ import.meta.hot.accept("/index.ts", () => {
+ dispose(() => {
+ import("./index").then(({ listen }) => {
+ dispose = listen(port);
+ });
+ });
+ });
+}
+
+function cleanUp() {
+ dispose(() => process.exit());
+}
+
+process.on("SIGINT", cleanUp);
+process.on("SIGTERM", cleanUp);
diff --git a/server/test/context.ts b/server/test/context.ts
new file mode 100644
index 000000000..c74b7eeac
--- /dev/null
+++ b/server/test/context.ts
@@ -0,0 +1,80 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+import { Firestore } from "@google-cloud/firestore";
+import {
+ AnyRootConfig,
+ AnyRouterDef,
+ Router,
+ createCallerFactory,
+} from "@trpc/server";
+import { testUsers } from "db";
+import { IdTokenClient } from "google-auth-library";
+import { auth } from "../core/auth";
+import { env } from "../core/env";
+import { getFirestore } from "../core/firestore";
+import { logger } from "../core/logging";
+import { Context } from "../core/trpc";
+
+let idTokenClient: IdTokenClient | undefined;
+
+export async function getIdToken(audience: string) {
+ idTokenClient = idTokenClient ?? (await auth.getIdTokenClient(audience));
+ return await idTokenClient.idTokenProvider.fetchIdToken(audience);
+}
+
+/**
+ * Create a tRPC context for unit testing.
+ */
+export function createContext(options?: ContextOptions): Context {
+ const user = testUsers.find((u) => u.screenName === options?.user);
+ const now = Math.floor(Date.now() / 1000);
+
+ if (options?.user && !user) {
+ throw new Error(`User not found: ${options.user}`);
+ }
+
+ return {
+ db: options?.db ?? getFirestore(),
+ log: logger,
+ token: user
+ ? {
+ uid: user.localId,
+ sub: user.localId,
+ email: user.email,
+ email_verified: user.emailVerified,
+ aud: env.GOOGLE_CLOUD_PROJECT,
+ iss: `https://securetoken.google.com/${env.GOOGLE_CLOUD_PROJECT}`,
+ iat: now,
+ exp: now + 3600,
+ auth_time: parseInt(user.lastLoginAt!, 10),
+ firebase: {
+ identities: {},
+ sign_in_provider: "google.com",
+ },
+ ...(user.customAttributes && JSON.parse(user.customAttributes)),
+ }
+ : null,
+ };
+}
+
+export function createClient<
+ TRouter extends Router>,
+>(router: TRouter, options?: ContextOptions) {
+ const createCaller = createCallerFactory();
+ const ctx = createContext(options);
+ const client = createCaller(router)(ctx);
+ return [client, ctx] as const;
+}
+
+// #region Types
+
+type ContextOptions = {
+ /**
+ * The user to impersonate. Use `dan` if you need admin permissions.
+ */
+ user?: "erika" | "ryan" | "marian" | "kurt" | "dan";
+ db?: Firestore;
+};
+
+// #endregion Types
diff --git a/server/tsconfig.json b/server/tsconfig.json
new file mode 100644
index 000000000..74dd02c1a
--- /dev/null
+++ b/server/tsconfig.json
@@ -0,0 +1,15 @@
+{
+ "extends": "../tsconfig.base.json",
+ "compilerOptions": {
+ "composite": true,
+ "emitDeclarationOnly": true,
+ "module": "ESNext",
+ "moduleResolution": "Bundler",
+ "noEmit": false,
+ "outDir": "../.cache/ts-server",
+ "types": ["node", "vite/client"]
+ },
+ "include": ["**/*.ts", "**/*.json"],
+ "exclude": ["**/dist/**/*", "**/node_modules/**/*"],
+ "references": [{ "path": "../db" }]
+}
diff --git a/server/types.ts b/server/types.ts
new file mode 100644
index 000000000..97af82379
--- /dev/null
+++ b/server/types.ts
@@ -0,0 +1,4 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+export type { AppRouter } from "./routes/index";
diff --git a/server/vite.config.ts b/server/vite.config.ts
new file mode 100644
index 000000000..34c038937
--- /dev/null
+++ b/server/vite.config.ts
@@ -0,0 +1,38 @@
+/* SPDX-FileCopyrightText: 2014-present Kriasoft */
+/* SPDX-License-Identifier: MIT */
+
+import { loadEnv } from "envars";
+import { defineConfig } from "vitest/config";
+
+/**
+ * Vite configuration for the server-side bundle.
+ *
+ * @see https://vitejs.dev/config/
+ */
+export default defineConfig(async ({ mode }) => {
+ await loadEnv(mode, {
+ root: "..",
+ schema: "./core/env.ts",
+ mergeTo: process.env,
+ });
+
+ return {
+ cacheDir: "../.cache/vite-server",
+
+ build: {
+ ssr: "./index.ts",
+ sourcemap: true,
+ },
+
+ ssr: {
+ ...(mode === "production" && {
+ noExternal: ["http-errors"],
+ }),
+ },
+
+ test: {
+ environment: "node",
+ testTimeout: 20000,
+ },
+ };
+});
diff --git a/tsconfig.json b/tsconfig.json
index 8c8c9f712..7adb4d357 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -3,6 +3,7 @@
"references": [
{ "path": "./app" },
{ "path": "./edge" },
- { "path": "./scripts" }
+ { "path": "./scripts" },
+ { "path": "./server" }
]
}
diff --git a/yarn.lock b/yarn.lock
index cfcd7bde8..3322766c8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1443,11 +1443,21 @@ __metadata:
linkType: hard
"@floating-ui/utils@npm:^0.2.0":
- version: 0.2.0
- resolution: "@floating-ui/utils@npm:0.2.0"
- peerDependencies:
- react: ">=16.8.0"
- checksum: 892a7a272a350f32ceab68bf0be7773378bd0d7ccf1c27385f935f18dc38327fc44633e8286191f9a836ae063684386d48e43ee6026f17be149bf02ca20433d7
+ version: 0.2.1
+ resolution: "@floating-ui/utils@npm:0.2.1"
+ checksum: 33c9ab346e7b05c5a1e6a95bc902aafcfc2c9d513a147e2491468843bd5607531b06d0b9aa56aa491cbf22a6c2495c18ccfc4c0344baec54a689a7bb8e4898d6
+ languageName: node
+ linkType: hard
+
+"@google-cloud/firestore@npm:^7.1.0":
+ version: 7.1.0
+ resolution: "@google-cloud/firestore@npm:7.1.0"
+ dependencies:
+ fast-deep-equal: "npm:^3.1.1"
+ functional-red-black-tree: "npm:^1.0.1"
+ google-gax: "npm:^4.0.4"
+ protobufjs: "npm:^7.2.5"
+ checksum: 141c03bec6ba55c80308ea105ca1319d29a7fbea1ecb95a5c2f58aa454d7f1d44112b67440a960639344b6562f0c89ffbda206fd74d875023e7addc4cdfa876f
languageName: node
linkType: hard
@@ -1460,6 +1470,15 @@ __metadata:
languageName: node
linkType: hard
+"@googleapis/identitytoolkit@npm:^8.0.0":
+ version: 8.0.0
+ resolution: "@googleapis/identitytoolkit@npm:8.0.0"
+ dependencies:
+ googleapis-common: "npm:^7.0.0"
+ checksum: 59b20c6c130d00cbeeaaca0bdf2efc0e8a06ebb20725c96b5a63efbee24b50d4d7ced9f032c691fce1acb13cc906eaf698b6e21b03d63a17fb98287a9e42a135
+ languageName: node
+ linkType: hard
+
"@grpc/grpc-js@npm:~1.9.0, @grpc/grpc-js@npm:~1.9.6":
version: 1.9.13
resolution: "@grpc/grpc-js@npm:1.9.13"
@@ -2260,10 +2279,10 @@ __metadata:
languageName: node
linkType: hard
-"@sindresorhus/is@npm:^6.1.0":
- version: 6.1.0
- resolution: "@sindresorhus/is@npm:6.1.0"
- checksum: e15c4abdca53a938e177d70c4e0562234a7ae32fa7c09ca318919d6ad28aa4ba68f58bd5339c3c38f2e912d40a201df169b9ed84579f2ef6f25d9da2d7b05334
+"@sindresorhus/is@npm:^5.2.0":
+ version: 5.6.0
+ resolution: "@sindresorhus/is@npm:5.6.0"
+ checksum: b077c325acec98e30f7d86df158aaba2e7af2acb9bb6a00fda4b91578539fbff4ecebe9b934e24fec0e6950de3089d89d79ec02d9062476b20ce185be0e01bd6
languageName: node
linkType: hard
@@ -2283,6 +2302,13 @@ __metadata:
languageName: node
linkType: hard
+"@trpc/server@npm:^10.45.0":
+ version: 10.45.0
+ resolution: "@trpc/server@npm:10.45.0"
+ checksum: 87f3c0f0169d73e7a4ce4df0cbbe5a7dd18a67a29e8a932db135bfa72301adbc656558e9bc8478317ec4007b32d6988f456aefd37a66624041714333d64d81e0
+ languageName: node
+ linkType: hard
+
"@types/babel__core@npm:^7.20.5":
version: 7.20.5
resolution: "@types/babel__core@npm:7.20.5"
@@ -2333,6 +2359,16 @@ __metadata:
languageName: node
linkType: hard
+"@types/body-parser@npm:*":
+ version: 1.19.5
+ resolution: "@types/body-parser@npm:1.19.5"
+ dependencies:
+ "@types/connect": "npm:*"
+ "@types/node": "npm:*"
+ checksum: 1e251118c4b2f61029cc43b0dc028495f2d1957fe8ee49a707fb940f86a9bd2f9754230805598278fe99958b49e9b7e66eec8ef6a50ab5c1f6b93e1ba2aaba82
+ languageName: node
+ linkType: hard
+
"@types/caseless@npm:*":
version: 0.12.5
resolution: "@types/caseless@npm:0.12.5"
@@ -2340,6 +2376,22 @@ __metadata:
languageName: node
linkType: hard
+"@types/connect@npm:*":
+ version: 3.4.38
+ resolution: "@types/connect@npm:3.4.38"
+ dependencies:
+ "@types/node": "npm:*"
+ checksum: 7eb1bc5342a9604facd57598a6c62621e244822442976c443efb84ff745246b10d06e8b309b6e80130026a396f19bf6793b7cecd7380169f369dac3bfc46fb99
+ languageName: node
+ linkType: hard
+
+"@types/cookiejar@npm:^2.1.5":
+ version: 2.1.5
+ resolution: "@types/cookiejar@npm:2.1.5"
+ checksum: 04d5990e87b6387532d15a87d9ec9b2eb783039291193863751dcfd7fc723a3b3aa30ce4c06b03975cba58632e933772f1ff031af23eaa3ac7f94e71afa6e073
+ languageName: node
+ linkType: hard
+
"@types/eslint@npm:^8.56.1":
version: 8.56.1
resolution: "@types/eslint@npm:8.56.1"
@@ -2357,6 +2409,30 @@ __metadata:
languageName: node
linkType: hard
+"@types/express-serve-static-core@npm:^4.17.33":
+ version: 4.17.41
+ resolution: "@types/express-serve-static-core@npm:4.17.41"
+ dependencies:
+ "@types/node": "npm:*"
+ "@types/qs": "npm:*"
+ "@types/range-parser": "npm:*"
+ "@types/send": "npm:*"
+ checksum: 7647e19d9c3d57ddd18947d2b161b90ef0aedd15875140e5b824209be41c1084ae942d4fb43cd5f2051a6a5f8c044519ef6c9ac1b2ad86b9aa546b4f1f023303
+ languageName: node
+ linkType: hard
+
+"@types/express@npm:^4.17.21":
+ version: 4.17.21
+ resolution: "@types/express@npm:4.17.21"
+ dependencies:
+ "@types/body-parser": "npm:*"
+ "@types/express-serve-static-core": "npm:^4.17.33"
+ "@types/qs": "npm:*"
+ "@types/serve-static": "npm:*"
+ checksum: 7a6d26cf6f43d3151caf4fec66ea11c9d23166e4f3102edfe45a94170654a54ea08cf3103d26b3928d7ebcc24162c90488e33986b7e3a5f8941225edd5eb18c7
+ languageName: node
+ linkType: hard
+
"@types/fs-extra@npm:^11.0.1":
version: 11.0.4
resolution: "@types/fs-extra@npm:11.0.4"
@@ -2374,6 +2450,22 @@ __metadata:
languageName: node
linkType: hard
+"@types/http-errors@npm:*, @types/http-errors@npm:^2.0.4":
+ version: 2.0.4
+ resolution: "@types/http-errors@npm:2.0.4"
+ checksum: 1f3d7c3b32c7524811a45690881736b3ef741bf9849ae03d32ad1ab7062608454b150a4e7f1351f83d26a418b2d65af9bdc06198f1c079d75578282884c4e8e3
+ languageName: node
+ linkType: hard
+
+"@types/http-proxy@npm:^1.17.8":
+ version: 1.17.14
+ resolution: "@types/http-proxy@npm:1.17.14"
+ dependencies:
+ "@types/node": "npm:*"
+ checksum: aa1a3e66cd43cbf06ea5901bf761d2031200a0ab42ba7e462a15c752e70f8669f21fb3be7c2f18fefcb83b95132dfa15740282e7421b856745598fbaea8e3a42
+ languageName: node
+ linkType: hard
+
"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.12":
version: 7.0.15
resolution: "@types/json-schema@npm:7.0.15"
@@ -2404,6 +2496,27 @@ __metadata:
languageName: node
linkType: hard
+"@types/methods@npm:^1.1.4":
+ version: 1.1.4
+ resolution: "@types/methods@npm:1.1.4"
+ checksum: ad2a7178486f2fd167750f3eb920ab032a947ff2e26f55c86670a6038632d790b46f52e5b6ead5823f1e53fc68028f1e9ddd15cfead7903e04517c88debd72b1
+ languageName: node
+ linkType: hard
+
+"@types/mime@npm:*":
+ version: 3.0.4
+ resolution: "@types/mime@npm:3.0.4"
+ checksum: a6139c8e1f705ef2b064d072f6edc01f3c099023ad7c4fce2afc6c2bf0231888202adadbdb48643e8e20da0ce409481a49922e737eca52871b3dc08017455843
+ languageName: node
+ linkType: hard
+
+"@types/mime@npm:^1":
+ version: 1.3.5
+ resolution: "@types/mime@npm:1.3.5"
+ checksum: e29a5f9c4776f5229d84e525b7cd7dd960b51c30a0fb9a028c0821790b82fca9f672dab56561e2acd9e8eed51d431bde52eafdfef30f643586c4162f1aecfc78
+ languageName: node
+ linkType: hard
+
"@types/minimist@npm:^1.2.2":
version: 1.2.5
resolution: "@types/minimist@npm:1.2.5"
@@ -2411,6 +2524,16 @@ __metadata:
languageName: node
linkType: hard
+"@types/node-fetch@npm:^2.6.4":
+ version: 2.6.10
+ resolution: "@types/node-fetch@npm:2.6.10"
+ dependencies:
+ "@types/node": "npm:*"
+ form-data: "npm:^4.0.0"
+ checksum: 121c0c2d4d28e784006cbff26383b31538aa4f113475dcf05a2744d18b4f44d6b30184fb2460a6ef8ec66b289abc6d9b80bf54518f8a5803fec614514b022c6b
+ languageName: node
+ linkType: hard
+
"@types/node-forge@npm:^1.3.0":
version: 1.3.11
resolution: "@types/node-forge@npm:1.3.11"
@@ -2420,21 +2543,21 @@ __metadata:
languageName: node
linkType: hard
-"@types/node@npm:*, @types/node@npm:>=12.12.47, @types/node@npm:>=13.7.0, @types/node@npm:^20.10.6":
- version: 20.10.6
- resolution: "@types/node@npm:20.10.6"
+"@types/node@npm:*, @types/node@npm:>=12.12.47, @types/node@npm:>=13.7.0, @types/node@npm:^20.10.7":
+ version: 20.10.7
+ resolution: "@types/node@npm:20.10.7"
dependencies:
undici-types: "npm:~5.26.4"
- checksum: 08471220d3cbbb6669835c4b78541edf5eface8f2c2e36c550cfa4ff73da73071c90e200a06359fac25d6564127597c23e178128058fb676824ec23d5178a017
+ checksum: 4a1ba3fb7fc0a262c6b2d5ec763cec7abf5b5d6b2d277798ddbf05227f5778f9a806987821fd4d3eacd6f37c946ac61a9c64fb79ae4b84daaec12354158835a3
languageName: node
linkType: hard
-"@types/node@npm:^18.16.3":
- version: 18.19.4
- resolution: "@types/node@npm:18.19.4"
+"@types/node@npm:^18.11.18, @types/node@npm:^18.16.3":
+ version: 18.19.5
+ resolution: "@types/node@npm:18.19.5"
dependencies:
undici-types: "npm:~5.26.4"
- checksum: 4eaf6e1bb588da960c7e5974e8a0112633138b5468f0e48fc959d5585863baca549bc8c5f5f7b751c61dd282b8c2879842220f6eeed33aa54c255e876ec16536
+ checksum: 215bc65e464e5c9f042dc2e475298851dc4ba9cb68a3648ad816075b515fd1051bc19dcfab49f661938a64f40d62cc462e9c469c7aff971d1cda7095b52be9ec
languageName: node
linkType: hard
@@ -2466,6 +2589,20 @@ __metadata:
languageName: node
linkType: hard
+"@types/qs@npm:*":
+ version: 6.9.11
+ resolution: "@types/qs@npm:6.9.11"
+ checksum: 620ca1628bf3da65662c54ed6ebb120b18a3da477d0bfcc872b696685a9bb1893c3c92b53a1190a8f54d52eaddb6af8b2157755699ac83164604329935e8a7f2
+ languageName: node
+ linkType: hard
+
+"@types/range-parser@npm:*":
+ version: 1.2.7
+ resolution: "@types/range-parser@npm:1.2.7"
+ checksum: 95640233b689dfbd85b8c6ee268812a732cf36d5affead89e806fe30da9a430767af8ef2cd661024fd97e19d61f3dec75af2df5e80ec3bea000019ab7028629a
+ languageName: node
+ linkType: hard
+
"@types/react-dom@npm:^18.2.18":
version: 18.2.18
resolution: "@types/react-dom@npm:18.2.18"
@@ -2521,6 +2658,48 @@ __metadata:
languageName: node
linkType: hard
+"@types/send@npm:*":
+ version: 0.17.4
+ resolution: "@types/send@npm:0.17.4"
+ dependencies:
+ "@types/mime": "npm:^1"
+ "@types/node": "npm:*"
+ checksum: 28320a2aa1eb704f7d96a65272a07c0bf3ae7ed5509c2c96ea5e33238980f71deeed51d3631927a77d5250e4091b3e66bce53b42d770873282c6a20bb8b0280d
+ languageName: node
+ linkType: hard
+
+"@types/serve-static@npm:*":
+ version: 1.15.5
+ resolution: "@types/serve-static@npm:1.15.5"
+ dependencies:
+ "@types/http-errors": "npm:*"
+ "@types/mime": "npm:*"
+ "@types/node": "npm:*"
+ checksum: 49aa21c367fffe4588fc8c57ea48af0ea7cbadde7418bc53cde85d8bd57fd2a09a293970d9ea86e79f17a87f8adeb3e20da76aab38e1c4d1567931fa15c8af38
+ languageName: node
+ linkType: hard
+
+"@types/superagent@npm:^8.1.0":
+ version: 8.1.1
+ resolution: "@types/superagent@npm:8.1.1"
+ dependencies:
+ "@types/cookiejar": "npm:^2.1.5"
+ "@types/methods": "npm:^1.1.4"
+ "@types/node": "npm:*"
+ checksum: 02b987833cf0d85da9b137fd296fe8ad25a470d60f7e9d81a6ed3f8f8a5d6bace8780816bd35885e2928f467e819a4aa509879a7da0f28018ab1453845eb91e2
+ languageName: node
+ linkType: hard
+
+"@types/supertest@npm:^6.0.2":
+ version: 6.0.2
+ resolution: "@types/supertest@npm:6.0.2"
+ dependencies:
+ "@types/methods": "npm:^1.1.4"
+ "@types/superagent": "npm:^8.1.0"
+ checksum: 4b67fb2d1bfbb7ff0a7dfaaf190cdf2e0014522615fb2dc53c214bdac95b4ee42696dd1df13332c90a7765cc52934c9cc0c428bf0f9e8189167aef01042e7448
+ languageName: node
+ linkType: hard
+
"@types/tough-cookie@npm:*":
version: 4.0.5
resolution: "@types/tough-cookie@npm:4.0.5"
@@ -2535,15 +2714,24 @@ __metadata:
languageName: node
linkType: hard
-"@typescript-eslint/eslint-plugin@npm:^6.17.0":
- version: 6.17.0
- resolution: "@typescript-eslint/eslint-plugin@npm:6.17.0"
+"@types/ws@npm:^8.5.10":
+ version: 8.5.10
+ resolution: "@types/ws@npm:8.5.10"
+ dependencies:
+ "@types/node": "npm:*"
+ checksum: 9b414dc5e0b6c6f1ea4b1635b3568c58707357f68076df9e7cd33194747b7d1716d5189c0dbdd68c8d2521b148e88184cf881bac7429eb0e5c989b001539ed31
+ languageName: node
+ linkType: hard
+
+"@typescript-eslint/eslint-plugin@npm:^6.18.0":
+ version: 6.18.0
+ resolution: "@typescript-eslint/eslint-plugin@npm:6.18.0"
dependencies:
"@eslint-community/regexpp": "npm:^4.5.1"
- "@typescript-eslint/scope-manager": "npm:6.17.0"
- "@typescript-eslint/type-utils": "npm:6.17.0"
- "@typescript-eslint/utils": "npm:6.17.0"
- "@typescript-eslint/visitor-keys": "npm:6.17.0"
+ "@typescript-eslint/scope-manager": "npm:6.18.0"
+ "@typescript-eslint/type-utils": "npm:6.18.0"
+ "@typescript-eslint/utils": "npm:6.18.0"
+ "@typescript-eslint/visitor-keys": "npm:6.18.0"
debug: "npm:^4.3.4"
graphemer: "npm:^1.4.0"
ignore: "npm:^5.2.4"
@@ -2556,44 +2744,44 @@ __metadata:
peerDependenciesMeta:
typescript:
optional: true
- checksum: f2a5774e9cc03e491a5a488501e5622c7eebd766f5a4fc2c30642864a3b89b0807946bde33a678f326ba7032f3f6a51aa0bf9c2d10adc823804fc9fb47db55a6
+ checksum: 7810a84f6d9cb735f6848aa4a7ef64c77740812afc0248fda63ec182910a1d045cd9a32d8e49b0e5323266db6da12a2fe50171147927b3186815a56f12c16ee7
languageName: node
linkType: hard
-"@typescript-eslint/parser@npm:^6.17.0":
- version: 6.17.0
- resolution: "@typescript-eslint/parser@npm:6.17.0"
+"@typescript-eslint/parser@npm:^6.18.0":
+ version: 6.18.0
+ resolution: "@typescript-eslint/parser@npm:6.18.0"
dependencies:
- "@typescript-eslint/scope-manager": "npm:6.17.0"
- "@typescript-eslint/types": "npm:6.17.0"
- "@typescript-eslint/typescript-estree": "npm:6.17.0"
- "@typescript-eslint/visitor-keys": "npm:6.17.0"
+ "@typescript-eslint/scope-manager": "npm:6.18.0"
+ "@typescript-eslint/types": "npm:6.18.0"
+ "@typescript-eslint/typescript-estree": "npm:6.18.0"
+ "@typescript-eslint/visitor-keys": "npm:6.18.0"
debug: "npm:^4.3.4"
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
peerDependenciesMeta:
typescript:
optional: true
- checksum: 2ed0ed4a5b30e953430ce3279df3655af09fa1caed2abf11804d239717daefc32a22864f6620ef57bb9c684c74a99a13241384fea5096e961385e3678fc2e920
+ checksum: 6798332819f839454a8405e31cfaa0fe908d5966be929bef55e78ac51a0ff3868feb42b38e7772cedf88277f6b2841b3d91f6c573eacb945e2741ecae94047c7
languageName: node
linkType: hard
-"@typescript-eslint/scope-manager@npm:6.17.0":
- version: 6.17.0
- resolution: "@typescript-eslint/scope-manager@npm:6.17.0"
+"@typescript-eslint/scope-manager@npm:6.18.0":
+ version: 6.18.0
+ resolution: "@typescript-eslint/scope-manager@npm:6.18.0"
dependencies:
- "@typescript-eslint/types": "npm:6.17.0"
- "@typescript-eslint/visitor-keys": "npm:6.17.0"
- checksum: fe09c628553c9336e6a36d32c1d34e78ebd20aa02130a6bf535329621ba5a98aaac171f607bc6e4d17b3478c42e7de6476376636897ce3f227c754eb99acd07e
+ "@typescript-eslint/types": "npm:6.18.0"
+ "@typescript-eslint/visitor-keys": "npm:6.18.0"
+ checksum: c2c465e6803f78d3300142167a8a79dd2613c64cf464a40a9cf6b13a2c10c3d82ca30bb9c2d26aba7f054b8740b38e1d25f377fcdf917aba489d5b5ea2550858
languageName: node
linkType: hard
-"@typescript-eslint/type-utils@npm:6.17.0":
- version: 6.17.0
- resolution: "@typescript-eslint/type-utils@npm:6.17.0"
+"@typescript-eslint/type-utils@npm:6.18.0":
+ version: 6.18.0
+ resolution: "@typescript-eslint/type-utils@npm:6.18.0"
dependencies:
- "@typescript-eslint/typescript-estree": "npm:6.17.0"
- "@typescript-eslint/utils": "npm:6.17.0"
+ "@typescript-eslint/typescript-estree": "npm:6.18.0"
+ "@typescript-eslint/utils": "npm:6.18.0"
debug: "npm:^4.3.4"
ts-api-utils: "npm:^1.0.1"
peerDependencies:
@@ -2601,23 +2789,23 @@ __metadata:
peerDependenciesMeta:
typescript:
optional: true
- checksum: dc7938429193acfda61b7282197ec046039e2c4da41cdcddf4daaf300d10229e4e23bb0fcf0503b19c0b99a874849c8a9f5bb35ce106260f56a14106d2b41d8c
+ checksum: 9f4a392fe7b7f6b1fb02acbdaa331e764775f6404c29ca66774419e39552523d878227020526ca9c438d997555a99600f8d711496e9a435fb14a779e25ed094e
languageName: node
linkType: hard
-"@typescript-eslint/types@npm:6.17.0":
- version: 6.17.0
- resolution: "@typescript-eslint/types@npm:6.17.0"
- checksum: 87ab1b5a3270ab34b917c22a2fb90a9ad7d9f3b19d73a337bc9efbe65f924da13482c97e8ccbe3bd3d081aa96039eeff50de41c1da2a2128066429b931cdb21d
+"@typescript-eslint/types@npm:6.18.0":
+ version: 6.18.0
+ resolution: "@typescript-eslint/types@npm:6.18.0"
+ checksum: fc507ca7a1bfec04467087165ff6722f7b9aa9a089ecf0c17656824a951b92ca014766e480122de850057c63a3066628985eb0681c5bbb80ab41d94e7bb52288
languageName: node
linkType: hard
-"@typescript-eslint/typescript-estree@npm:6.17.0":
- version: 6.17.0
- resolution: "@typescript-eslint/typescript-estree@npm:6.17.0"
+"@typescript-eslint/typescript-estree@npm:6.18.0":
+ version: 6.18.0
+ resolution: "@typescript-eslint/typescript-estree@npm:6.18.0"
dependencies:
- "@typescript-eslint/types": "npm:6.17.0"
- "@typescript-eslint/visitor-keys": "npm:6.17.0"
+ "@typescript-eslint/types": "npm:6.18.0"
+ "@typescript-eslint/visitor-keys": "npm:6.18.0"
debug: "npm:^4.3.4"
globby: "npm:^11.1.0"
is-glob: "npm:^4.0.3"
@@ -2627,34 +2815,34 @@ __metadata:
peerDependenciesMeta:
typescript:
optional: true
- checksum: 1671b0d2f2fdf07074fb1e2524d61935cec173bd8db6e482cc5b2dcc77aed3ffa831396736ffa0ee2fdbddd8585ae9ca8d6c97bcaea1385b23907a1ec0508f83
+ checksum: b65392e944baba97ed98e99a1e7122b7b05fa0d9a082b48d0190b377ae9e2ae4ed72d505a2f0f05f2ca78908f0e4b0f1acd44d345c7f4f4415fcec6bb2c57791
languageName: node
linkType: hard
-"@typescript-eslint/utils@npm:6.17.0":
- version: 6.17.0
- resolution: "@typescript-eslint/utils@npm:6.17.0"
+"@typescript-eslint/utils@npm:6.18.0":
+ version: 6.18.0
+ resolution: "@typescript-eslint/utils@npm:6.18.0"
dependencies:
"@eslint-community/eslint-utils": "npm:^4.4.0"
"@types/json-schema": "npm:^7.0.12"
"@types/semver": "npm:^7.5.0"
- "@typescript-eslint/scope-manager": "npm:6.17.0"
- "@typescript-eslint/types": "npm:6.17.0"
- "@typescript-eslint/typescript-estree": "npm:6.17.0"
+ "@typescript-eslint/scope-manager": "npm:6.18.0"
+ "@typescript-eslint/types": "npm:6.18.0"
+ "@typescript-eslint/typescript-estree": "npm:6.18.0"
semver: "npm:^7.5.4"
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
- checksum: 37c63afcf66124bf84808699997953b8c84a378aa2c490a771b611d82cdac8499c58fac8eeb8378528e97660b59563d99297bfec4b982cd68760b0ffe54aa714
+ checksum: f91798069e337ed42b7e415aabded833d540dab9adf66ae88183003428892584946f20a5496aae2dc65fc0f65b66496baed785a3470ee782b6e2dd25b9200c6c
languageName: node
linkType: hard
-"@typescript-eslint/visitor-keys@npm:6.17.0":
- version: 6.17.0
- resolution: "@typescript-eslint/visitor-keys@npm:6.17.0"
+"@typescript-eslint/visitor-keys@npm:6.18.0":
+ version: 6.18.0
+ resolution: "@typescript-eslint/visitor-keys@npm:6.18.0"
dependencies:
- "@typescript-eslint/types": "npm:6.17.0"
+ "@typescript-eslint/types": "npm:6.18.0"
eslint-visitor-keys: "npm:^3.4.1"
- checksum: a2aed0e1437fdab8858ab9c7c8e355f8b72a5fa4b0adc54f28b8a2bbc29d4bb93214968ee940f83d013d0a4b83d00cd4eeeb05fb4c2c7d0ead324c6793f7d6d4
+ checksum: bf34a357549d515607c761f385b7c7c82aaa07795cada0be2e1e3860c5103fbf731408ac07eaeb0517b51426d77ef9b194dfb94f205c776107a46e0d0027b452
languageName: node
linkType: hard
@@ -2750,6 +2938,16 @@ __metadata:
languageName: node
linkType: hard
+"accepts@npm:~1.3.8":
+ version: 1.3.8
+ resolution: "accepts@npm:1.3.8"
+ dependencies:
+ mime-types: "npm:~2.1.34"
+ negotiator: "npm:0.6.3"
+ checksum: 67eaaa90e2917c58418e7a9b89392002d2b1ccd69bcca4799135d0c632f3b082f23f4ae4ddeedbced5aa59bcc7bdf4699c69ebed4593696c922462b7bc5744d6
+ languageName: node
+ linkType: hard
+
"acorn-jsx@npm:^5.3.2":
version: 5.3.2
resolution: "acorn-jsx@npm:5.3.2"
@@ -2793,6 +2991,15 @@ __metadata:
languageName: node
linkType: hard
+"agentkeepalive@npm:^4.2.1":
+ version: 4.5.0
+ resolution: "agentkeepalive@npm:4.5.0"
+ dependencies:
+ humanize-ms: "npm:^1.2.1"
+ checksum: dd210ba2a2e2482028f027b1156789744aadbfd773a6c9dd8e4e8001930d5af82382abe19a69240307b1d8003222ce6b0542935038313434b900e351914fc15f
+ languageName: node
+ linkType: hard
+
"aggregate-error@npm:^3.0.0":
version: 3.1.0
resolution: "aggregate-error@npm:3.1.0"
@@ -2885,7 +3092,7 @@ __metadata:
"@mui/joy": "npm:^5.0.0-beta.21"
"@mui/lab": "npm:^5.0.0-alpha.159"
"@mui/material": "npm:^5.15.3"
- "@types/node": "npm:^20.10.6"
+ "@types/node": "npm:^20.10.7"
"@types/react": "npm:^18.2.47"
"@types/react-dom": "npm:^18.2.18"
"@vitejs/plugin-react": "npm:^4.2.1"
@@ -2940,6 +3147,13 @@ __metadata:
languageName: node
linkType: hard
+"array-flatten@npm:1.1.1":
+ version: 1.1.1
+ resolution: "array-flatten@npm:1.1.1"
+ checksum: e13c9d247241be82f8b4ec71d035ed7204baa82fae820d4db6948d30d3c4a9f2b3905eb2eec2b937d4aa3565200bd3a1c500480114cff649fa748747d2a50feb
+ languageName: node
+ linkType: hard
+
"array-includes@npm:^3.1.6, array-includes@npm:^3.1.7":
version: 3.1.7
resolution: "array-includes@npm:3.1.7"
@@ -3034,6 +3248,13 @@ __metadata:
languageName: node
linkType: hard
+"asap@npm:^2.0.0":
+ version: 2.0.6
+ resolution: "asap@npm:2.0.6"
+ checksum: b244c0458c571945e4b3be0b14eb001bea5596f9868cc50cc711dc03d58a7e953517d3f0dad81ccde3ff37d1f074701fa76a6f07d41aaa992d7204a37b915dda
+ languageName: node
+ linkType: hard
+
"assertion-error@npm:^1.1.0":
version: 1.1.0
resolution: "assertion-error@npm:1.1.0"
@@ -3064,6 +3285,13 @@ __metadata:
languageName: node
linkType: hard
+"atomic-sleep@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "atomic-sleep@npm:1.0.0"
+ checksum: 3ab6d2cf46b31394b4607e935ec5c1c3c4f60f3e30f0913d35ea74b51b3585e84f590d09e58067f11762eec71c87d25314ce859030983dc0e4397eed21daa12e
+ languageName: node
+ linkType: hard
+
"available-typed-arrays@npm:^1.0.5":
version: 1.0.5
resolution: "available-typed-arrays@npm:1.0.5"
@@ -3105,7 +3333,14 @@ __metadata:
languageName: node
linkType: hard
-"base64-js@npm:^1.3.0":
+"base-64@npm:^0.1.0":
+ version: 0.1.0
+ resolution: "base-64@npm:0.1.0"
+ checksum: 5a42938f82372ab5392cbacc85a5a78115cbbd9dbef9f7540fa47d78763a3a8bd7d598475f0d92341f66285afd377509851a9bb5c67bbecb89686e9255d5b3eb
+ languageName: node
+ linkType: hard
+
+"base64-js@npm:^1.3.0, base64-js@npm:^1.3.1":
version: 1.5.1
resolution: "base64-js@npm:1.5.1"
checksum: 669632eb3745404c2f822a18fc3a0122d2f9a7a13f7fb8b5823ee19d1d2ff9ee5b52c53367176ea4ad093c332fd5ab4bd0ebae5a8e27917a4105a4cfc86b1005
@@ -3133,6 +3368,26 @@ __metadata:
languageName: node
linkType: hard
+"body-parser@npm:1.20.1":
+ version: 1.20.1
+ resolution: "body-parser@npm:1.20.1"
+ dependencies:
+ bytes: "npm:3.1.2"
+ content-type: "npm:~1.0.4"
+ debug: "npm:2.6.9"
+ depd: "npm:2.0.0"
+ destroy: "npm:1.2.0"
+ http-errors: "npm:2.0.0"
+ iconv-lite: "npm:0.4.24"
+ on-finished: "npm:2.4.1"
+ qs: "npm:6.11.0"
+ raw-body: "npm:2.5.1"
+ type-is: "npm:~1.6.18"
+ unpipe: "npm:1.0.0"
+ checksum: 5f8d128022a2fb8b6e7990d30878a0182f300b70e46b3f9d358a9433ad6275f0de46add6d63206da3637c01c3b38b6111a7480f7e7ac2e9f7b989f6133fe5510
+ languageName: node
+ linkType: hard
+
"brace-expansion@npm:^1.1.7":
version: 1.1.11
resolution: "brace-expansion@npm:1.1.11"
@@ -3182,6 +3437,16 @@ __metadata:
languageName: node
linkType: hard
+"buffer@npm:^6.0.3":
+ version: 6.0.3
+ resolution: "buffer@npm:6.0.3"
+ dependencies:
+ base64-js: "npm:^1.3.1"
+ ieee754: "npm:^1.2.1"
+ checksum: b6bc68237ebf29bdacae48ce60e5e28fc53ae886301f2ad9496618efac49427ed79096750033e7eab1897a4f26ae374ace49106a5758f38fb70c78c9fda2c3b1
+ languageName: node
+ linkType: hard
+
"builtins@npm:^5.0.0":
version: 5.0.1
resolution: "builtins@npm:5.0.1"
@@ -3200,6 +3465,13 @@ __metadata:
languageName: node
linkType: hard
+"bytes@npm:3.1.2":
+ version: 3.1.2
+ resolution: "bytes@npm:3.1.2"
+ checksum: a10abf2ba70c784471d6b4f58778c0beeb2b5d405148e66affa91f23a9f13d07603d0a0354667310ae1d6dc141474ffd44e2a074be0f6e2254edb8fc21445388
+ languageName: node
+ linkType: hard
+
"cac@npm:^6.7.14":
version: 6.7.14
resolution: "cac@npm:6.7.14"
@@ -3234,7 +3506,7 @@ __metadata:
languageName: node
linkType: hard
-"cacheable-request@npm:^10.2.14":
+"cacheable-request@npm:^10.2.8":
version: 10.2.14
resolution: "cacheable-request@npm:10.2.14"
dependencies:
@@ -3300,9 +3572,9 @@ __metadata:
linkType: hard
"caniuse-lite@npm:^1.0.30001565":
- version: 1.0.30001574
- resolution: "caniuse-lite@npm:1.0.30001574"
- checksum: 159ebd04d9bbef11bd08499f058f70bf795a55641929be5efadf0f6b17216d4b923506778e59bbb939246834304b753b2e88ff1e2430f6a5aef0a86971f98bd3
+ version: 1.0.30001576
+ resolution: "caniuse-lite@npm:1.0.30001576"
+ checksum: 51632942733593f310e581bd91c9558b8d75fbf67160a39f8036d2976cd7df9183e96d4c9d9e6f18e0205950b940d9c761bcfb7810962d7899f8a1179fde6e3f
languageName: node
linkType: hard
@@ -3352,13 +3624,20 @@ __metadata:
languageName: node
linkType: hard
-"chalk@npm:^5.2.0":
+"chalk@npm:^5.2.0, chalk@npm:^5.3.0":
version: 5.3.0
resolution: "chalk@npm:5.3.0"
checksum: 6373caaab21bd64c405bfc4bd9672b145647fc9482657b5ea1d549b3b2765054e9d3d928870cdf764fb4aad67555f5061538ff247b8310f110c5c888d92397ea
languageName: node
linkType: hard
+"charenc@npm:0.0.2":
+ version: 0.0.2
+ resolution: "charenc@npm:0.0.2"
+ checksum: 81dcadbe57e861d527faf6dd3855dc857395a1c4d6781f4847288ab23cffb7b3ee80d57c15bba7252ffe3e5e8019db767757ee7975663ad2ca0939bb8fcaf2e5
+ languageName: node
+ linkType: hard
+
"check-error@npm:^1.0.3":
version: 1.0.3
resolution: "check-error@npm:1.0.3"
@@ -3401,6 +3680,22 @@ __metadata:
languageName: node
linkType: hard
+"cli-cursor@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "cli-cursor@npm:4.0.0"
+ dependencies:
+ restore-cursor: "npm:^4.0.0"
+ checksum: ab3f3ea2076e2176a1da29f9d64f72ec3efad51c0960898b56c8a17671365c26e67b735920530eaf7328d61f8bd41c27f46b9cf6e4e10fe2fa44b5e8c0e392cc
+ languageName: node
+ linkType: hard
+
+"cli-spinners@npm:^2.9.2":
+ version: 2.9.2
+ resolution: "cli-spinners@npm:2.9.2"
+ checksum: a0a863f442df35ed7294424f5491fa1756bd8d2e4ff0c8736531d886cec0ece4d85e8663b77a5afaf1d296e3cbbebff92e2e99f52bbea89b667cbe789b994794
+ languageName: node
+ linkType: hard
+
"cliui@npm:^8.0.1":
version: 8.0.1
resolution: "cliui@npm:8.0.1"
@@ -3458,7 +3753,14 @@ __metadata:
languageName: node
linkType: hard
-"combined-stream@npm:^1.0.6":
+"colorette@npm:^2.0.7":
+ version: 2.0.20
+ resolution: "colorette@npm:2.0.20"
+ checksum: 0b8de48bfa5d10afc160b8eaa2b9938f34a892530b2f7d7897e0458d9535a066e3998b49da9d21161c78225b272df19ae3a64d6df28b4c9734c0e55bbd02406f
+ languageName: node
+ linkType: hard
+
+"combined-stream@npm:^1.0.6, combined-stream@npm:^1.0.8":
version: 1.0.8
resolution: "combined-stream@npm:1.0.8"
dependencies:
@@ -3467,6 +3769,13 @@ __metadata:
languageName: node
linkType: hard
+"component-emitter@npm:^1.3.0":
+ version: 1.3.1
+ resolution: "component-emitter@npm:1.3.1"
+ checksum: 94550aa462c7bd5a61c1bc480e28554aa306066930152d1b1844a0dd3845d4e5db7e261ddec62ae184913b3e59b55a2ad84093b9d3596a8f17c341514d6c483d
+ languageName: node
+ linkType: hard
+
"concat-map@npm:0.0.1":
version: 0.0.1
resolution: "concat-map@npm:0.0.1"
@@ -3474,6 +3783,22 @@ __metadata:
languageName: node
linkType: hard
+"content-disposition@npm:0.5.4":
+ version: 0.5.4
+ resolution: "content-disposition@npm:0.5.4"
+ dependencies:
+ safe-buffer: "npm:5.2.1"
+ checksum: b7f4ce176e324f19324be69b05bf6f6e411160ac94bc523b782248129eb1ef3be006f6cff431aaea5e337fe5d176ce8830b8c2a1b721626ead8933f0cbe78720
+ languageName: node
+ linkType: hard
+
+"content-type@npm:~1.0.4":
+ version: 1.0.5
+ resolution: "content-type@npm:1.0.5"
+ checksum: 585847d98dc7fb8035c02ae2cb76c7a9bd7b25f84c447e5ed55c45c2175e83617c8813871b4ee22f368126af6b2b167df655829007b21aa10302873ea9c62662
+ languageName: node
+ linkType: hard
+
"convert-source-map@npm:^1.5.0":
version: 1.9.0
resolution: "convert-source-map@npm:1.9.0"
@@ -3488,13 +3813,27 @@ __metadata:
languageName: node
linkType: hard
-"cookie@npm:^0.5.0":
+"cookie-signature@npm:1.0.6":
+ version: 1.0.6
+ resolution: "cookie-signature@npm:1.0.6"
+ checksum: f4e1b0a98a27a0e6e66fd7ea4e4e9d8e038f624058371bf4499cfcd8f3980be9a121486995202ba3fca74fbed93a407d6d54d43a43f96fd28d0bd7a06761591a
+ languageName: node
+ linkType: hard
+
+"cookie@npm:0.5.0, cookie@npm:^0.5.0":
version: 0.5.0
resolution: "cookie@npm:0.5.0"
checksum: aae7911ddc5f444a9025fbd979ad1b5d60191011339bce48e555cb83343d0f98b865ff5c4d71fecdfb8555a5cafdc65632f6fce172f32aaf6936830a883a0380
languageName: node
linkType: hard
+"cookiejar@npm:^2.1.4":
+ version: 2.1.4
+ resolution: "cookiejar@npm:2.1.4"
+ checksum: 4a184f5a0591df8b07d22a43ea5d020eacb4572c383e853a33361a99710437eaa0971716c688684075bbf695b484f5872e9e3f562382e46858716cb7fc8ce3f4
+ languageName: node
+ linkType: hard
+
"cosmiconfig@npm:^5.0.5":
version: 5.2.1
resolution: "cosmiconfig@npm:5.2.1"
@@ -3531,6 +3870,13 @@ __metadata:
languageName: node
linkType: hard
+"crypt@npm:0.0.2":
+ version: 0.0.2
+ resolution: "crypt@npm:0.0.2"
+ checksum: 2c72768de3d28278c7c9ffd81a298b26f87ecdfe94415084f339e6632f089b43fe039f2c93f612bcb5ffe447238373d93b2e8c90894cba6cfb0ac7a74616f8b9
+ languageName: node
+ linkType: hard
+
"css.escape@npm:^1.5.1":
version: 1.5.1
resolution: "css.escape@npm:1.5.1"
@@ -3566,6 +3912,39 @@ __metadata:
languageName: node
linkType: hard
+"dateformat@npm:^4.6.3":
+ version: 4.6.3
+ resolution: "dateformat@npm:4.6.3"
+ checksum: 5c149c91bf9ce2142c89f84eee4c585f0cb1f6faf2536b1af89873f862666a28529d1ccafc44750aa01384da2197c4f76f4e149a3cc0c1cb2c46f5cc45f2bcb5
+ languageName: node
+ linkType: hard
+
+"db@workspace:*, db@workspace:db":
+ version: 0.0.0-use.local
+ resolution: "db@workspace:db"
+ dependencies:
+ "@google-cloud/firestore": "npm:^7.1.0"
+ "@googleapis/identitytoolkit": "npm:^8.0.0"
+ "@types/node": "npm:^20.10.7"
+ dotenv: "npm:^16.3.1"
+ ora: "npm:^8.0.1"
+ typescript: "npm:~5.3.3"
+ vite: "npm:~5.0.11"
+ vite-node: "npm:~1.1.3"
+ vitest: "npm:~1.1.3"
+ zod: "npm:^3.22.4"
+ languageName: unknown
+ linkType: soft
+
+"debug@npm:2.6.9":
+ version: 2.6.9
+ resolution: "debug@npm:2.6.9"
+ dependencies:
+ ms: "npm:2.0.0"
+ checksum: e07005f2b40e04f1bd14a3dd20520e9c4f25f60224cb006ce9d6781732c917964e9ec029fc7f1a151083cd929025ad5133814d4dc624a9aaf020effe4914ed14
+ languageName: node
+ linkType: hard
+
"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4":
version: 4.3.4
resolution: "debug@npm:4.3.4"
@@ -3648,6 +4027,13 @@ __metadata:
languageName: node
linkType: hard
+"depd@npm:2.0.0":
+ version: 2.0.0
+ resolution: "depd@npm:2.0.0"
+ checksum: c0c8ff36079ce5ada64f46cc9d6fd47ebcf38241105b6e0c98f412e8ad91f084bcf906ff644cc3a4bd876ca27a62accb8b0fff72ea6ed1a414b89d8506f4a5ca
+ languageName: node
+ linkType: hard
+
"dequal@npm:^2.0.3":
version: 2.0.3
resolution: "dequal@npm:2.0.3"
@@ -3655,6 +4041,23 @@ __metadata:
languageName: node
linkType: hard
+"destroy@npm:1.2.0":
+ version: 1.2.0
+ resolution: "destroy@npm:1.2.0"
+ checksum: 0acb300b7478a08b92d810ab229d5afe0d2f4399272045ab22affa0d99dbaf12637659411530a6fcd597a9bdac718fc94373a61a95b4651bbc7b83684a565e38
+ languageName: node
+ linkType: hard
+
+"dezalgo@npm:^1.0.4":
+ version: 1.0.4
+ resolution: "dezalgo@npm:1.0.4"
+ dependencies:
+ asap: "npm:^2.0.0"
+ wrappy: "npm:1"
+ checksum: 895389c6aead740d2ab5da4d3466d20fa30f738010a4d3f4dcccc9fc645ca31c9d10b7e1804ae489b1eb02c7986f9f1f34ba132d409b043082a86d9a4e745624
+ languageName: node
+ linkType: hard
+
"diff-sequences@npm:^29.6.3":
version: 29.6.3
resolution: "diff-sequences@npm:29.6.3"
@@ -3662,6 +4065,16 @@ __metadata:
languageName: node
linkType: hard
+"digest-fetch@npm:^1.3.0":
+ version: 1.3.0
+ resolution: "digest-fetch@npm:1.3.0"
+ dependencies:
+ base-64: "npm:^0.1.0"
+ md5: "npm:^2.3.0"
+ checksum: 5a90f350ed19600aab44753ad19e8b2e5409b0a07a2a6949c9eed589bfc7a735308be020d63c6ddff97ad83d0b5d56405e0577ed4c291baccadec3e61ebca189
+ languageName: node
+ linkType: hard
+
"dir-glob@npm:^3.0.1":
version: 3.0.1
resolution: "dir-glob@npm:3.0.1"
@@ -3761,7 +4174,7 @@ __metadata:
dependencies:
"@cloudflare/workers-types": "npm:^4.20231218.0"
"@hono/zod-validator": "npm:^0.1.11"
- "@types/node": "npm:^20.10.6"
+ "@types/node": "npm:^20.10.7"
happy-dom: "npm:^12.10.3"
hono: "npm:^3.12.0"
jose: "npm:^5.2.0"
@@ -3775,6 +4188,13 @@ __metadata:
languageName: unknown
linkType: soft
+"ee-first@npm:1.1.1":
+ version: 1.1.1
+ resolution: "ee-first@npm:1.1.1"
+ checksum: 1b4cac778d64ce3b582a7e26b218afe07e207a0f9bfe13cc7395a6d307849cfe361e65033c3251e00c27dd060cab43014c2d6b2647676135e18b77d2d05b3f4f
+ languageName: node
+ linkType: hard
+
"electron-to-chromium@npm:^1.4.601":
version: 1.4.623
resolution: "electron-to-chromium@npm:1.4.623"
@@ -3782,6 +4202,13 @@ __metadata:
languageName: node
linkType: hard
+"emoji-regex@npm:^10.3.0":
+ version: 10.3.0
+ resolution: "emoji-regex@npm:10.3.0"
+ checksum: b9b084ebe904f13bb4b66ee4c29fb41a7a4a1165adcc33c1ce8056c0194b882cc91ebdc782f1a779b5d7ea7375c5064643a7734893d7c657b44c5c6b9d7bf1e7
+ languageName: node
+ linkType: hard
+
"emoji-regex@npm:^8.0.0":
version: 8.0.0
resolution: "emoji-regex@npm:8.0.0"
@@ -3796,6 +4223,13 @@ __metadata:
languageName: node
linkType: hard
+"encodeurl@npm:~1.0.2":
+ version: 1.0.2
+ resolution: "encodeurl@npm:1.0.2"
+ checksum: e50e3d508cdd9c4565ba72d2012e65038e5d71bdc9198cb125beb6237b5b1ade6c0d343998da9e170fb2eae52c1bed37d4d6d98a46ea423a0cddbed5ac3f780c
+ languageName: node
+ linkType: hard
+
"encoding@npm:^0.1.13":
version: 0.1.13
resolution: "encoding@npm:0.1.13"
@@ -3805,7 +4239,7 @@ __metadata:
languageName: node
linkType: hard
-"end-of-stream@npm:^1.4.1":
+"end-of-stream@npm:^1.1.0, end-of-stream@npm:^1.4.1":
version: 1.4.4
resolution: "end-of-stream@npm:1.4.4"
dependencies:
@@ -3838,6 +4272,15 @@ __metadata:
languageName: node
linkType: hard
+"envalid@npm:^8.0.0":
+ version: 8.0.0
+ resolution: "envalid@npm:8.0.0"
+ dependencies:
+ tslib: "npm:2.6.2"
+ checksum: cf2159a070c7335ecc9cd01523654fb7c8fdc63b92bef47d18027c406dfcf2b4a72663e70ddd91fa91967fa71c7716fe643dcd4a652f9ab0f93722feddb9e1b2
+ languageName: node
+ linkType: hard
+
"envars@npm:^1.0.2":
version: 1.0.2
resolution: "envars@npm:1.0.2"
@@ -4350,6 +4793,13 @@ __metadata:
languageName: node
linkType: hard
+"escape-html@npm:~1.0.3":
+ version: 1.0.3
+ resolution: "escape-html@npm:1.0.3"
+ checksum: 6213ca9ae00d0ab8bccb6d8d4e0a98e76237b2410302cf7df70aaa6591d509a2a37ce8998008cbecae8fc8ffaadf3fb0229535e6a145f3ce0b211d060decbb24
+ languageName: node
+ linkType: hard
+
"escape-string-regexp@npm:^1.0.5":
version: 1.0.5
resolution: "escape-string-regexp@npm:1.0.5"
@@ -4638,6 +5088,13 @@ __metadata:
languageName: node
linkType: hard
+"etag@npm:~1.8.1":
+ version: 1.8.1
+ resolution: "etag@npm:1.8.1"
+ checksum: 571aeb3dbe0f2bbd4e4fadbdb44f325fc75335cd5f6f6b6a091e6a06a9f25ed5392f0863c5442acb0646787446e816f13cbfc6edce5b07658541dff573cab1ff
+ languageName: node
+ linkType: hard
+
"event-stream@npm:=3.3.4":
version: 3.3.4
resolution: "event-stream@npm:3.3.4"
@@ -4660,6 +5117,20 @@ __metadata:
languageName: node
linkType: hard
+"eventemitter3@npm:^4.0.0":
+ version: 4.0.7
+ resolution: "eventemitter3@npm:4.0.7"
+ checksum: 8030029382404942c01d0037079f1b1bc8fed524b5849c237b80549b01e2fc49709e1d0c557fa65ca4498fc9e24cff1475ef7b855121fcc15f9d61f93e282346
+ languageName: node
+ linkType: hard
+
+"events@npm:^3.3.0":
+ version: 3.3.0
+ resolution: "events@npm:3.3.0"
+ checksum: a3d47e285e28d324d7180f1e493961a2bbb4cad6412090e4dec114f4db1f5b560c7696ee8e758f55e23913ede856e3689cd3aa9ae13c56b5d8314cd3b3ddd1be
+ languageName: node
+ linkType: hard
+
"execa@npm:^6.1.0":
version: 6.1.0
resolution: "execa@npm:6.1.0"
@@ -4708,6 +5179,45 @@ __metadata:
languageName: node
linkType: hard
+"express@npm:^4.18.2":
+ version: 4.18.2
+ resolution: "express@npm:4.18.2"
+ dependencies:
+ accepts: "npm:~1.3.8"
+ array-flatten: "npm:1.1.1"
+ body-parser: "npm:1.20.1"
+ content-disposition: "npm:0.5.4"
+ content-type: "npm:~1.0.4"
+ cookie: "npm:0.5.0"
+ cookie-signature: "npm:1.0.6"
+ debug: "npm:2.6.9"
+ depd: "npm:2.0.0"
+ encodeurl: "npm:~1.0.2"
+ escape-html: "npm:~1.0.3"
+ etag: "npm:~1.8.1"
+ finalhandler: "npm:1.2.0"
+ fresh: "npm:0.5.2"
+ http-errors: "npm:2.0.0"
+ merge-descriptors: "npm:1.0.1"
+ methods: "npm:~1.1.2"
+ on-finished: "npm:2.4.1"
+ parseurl: "npm:~1.3.3"
+ path-to-regexp: "npm:0.1.7"
+ proxy-addr: "npm:~2.0.7"
+ qs: "npm:6.11.0"
+ range-parser: "npm:~1.2.1"
+ safe-buffer: "npm:5.2.1"
+ send: "npm:0.18.0"
+ serve-static: "npm:1.15.0"
+ setprototypeof: "npm:1.2.0"
+ statuses: "npm:2.0.1"
+ type-is: "npm:~1.6.18"
+ utils-merge: "npm:1.0.1"
+ vary: "npm:~1.1.2"
+ checksum: 869ae89ed6ff4bed7b373079dc58e5dddcf2915a2669b36037ff78c99d675ae930e5fe052b35c24f56557d28a023bb1cbe3e2f2fb87eaab96a1cedd7e597809d
+ languageName: node
+ linkType: hard
+
"extend@npm:^3.0.2":
version: 3.0.2
resolution: "extend@npm:3.0.2"
@@ -4715,6 +5225,13 @@ __metadata:
languageName: node
linkType: hard
+"fast-copy@npm:^3.0.0":
+ version: 3.0.1
+ resolution: "fast-copy@npm:3.0.1"
+ checksum: 2f655f1e84440f990cddf7895f0acce38b2eb090a27dc0f97f1654cd6f2e38f67d9603471856c2af13e0bfbdf04c2c0b8d446fee1dd1f6f485992e4cc4693c7a
+ languageName: node
+ linkType: hard
+
"fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3":
version: 3.1.3
resolution: "fast-deep-equal@npm:3.1.3"
@@ -4749,12 +5266,26 @@ __metadata:
languageName: node
linkType: hard
-"fastq@npm:^1.6.0":
- version: 1.16.0
- resolution: "fastq@npm:1.16.0"
- dependencies:
- reusify: "npm:^1.0.4"
- checksum: de151543aab9d91900ed5da88860c46987ece925c628df586fac664235f25e020ec20729e1c032edb5fd2520fd4aa5b537d69e39b689e65e82112cfbecb4479e
+"fast-redact@npm:^3.1.1":
+ version: 3.3.0
+ resolution: "fast-redact@npm:3.3.0"
+ checksum: a69c5cb52396eafc4f466f46864406cbd4a6ead6782caf74750ce817794829048baaa933ad98543e744dd54ffb4cddff71f3e75e465a86e3d887894e281ec154
+ languageName: node
+ linkType: hard
+
+"fast-safe-stringify@npm:^2.1.1":
+ version: 2.1.1
+ resolution: "fast-safe-stringify@npm:2.1.1"
+ checksum: dc1f063c2c6ac9533aee14d406441f86783a8984b2ca09b19c2fe281f9ff59d315298bc7bc22fd1f83d26fe19ef2f20e2ddb68e96b15040292e555c5ced0c1e4
+ languageName: node
+ linkType: hard
+
+"fastq@npm:^1.6.0":
+ version: 1.16.0
+ resolution: "fastq@npm:1.16.0"
+ dependencies:
+ reusify: "npm:^1.0.4"
+ checksum: de151543aab9d91900ed5da88860c46987ece925c628df586fac664235f25e020ec20729e1c032edb5fd2520fd4aa5b537d69e39b689e65e82112cfbecb4479e
languageName: node
linkType: hard
@@ -4795,6 +5326,21 @@ __metadata:
languageName: node
linkType: hard
+"finalhandler@npm:1.2.0":
+ version: 1.2.0
+ resolution: "finalhandler@npm:1.2.0"
+ dependencies:
+ debug: "npm:2.6.9"
+ encodeurl: "npm:~1.0.2"
+ escape-html: "npm:~1.0.3"
+ on-finished: "npm:2.4.1"
+ parseurl: "npm:~1.3.3"
+ statuses: "npm:2.0.1"
+ unpipe: "npm:~1.0.0"
+ checksum: 635718cb203c6d18e6b48dfbb6c54ccb08ea470e4f474ddcef38c47edcf3227feec316f886dd701235997d8af35240cae49856721ce18f539ad038665ebbf163
+ languageName: node
+ linkType: hard
+
"find-root@npm:^1.1.0":
version: 1.1.0
resolution: "find-root@npm:1.1.0"
@@ -4874,6 +5420,16 @@ __metadata:
languageName: node
linkType: hard
+"follow-redirects@npm:^1.0.0":
+ version: 1.15.4
+ resolution: "follow-redirects@npm:1.15.4"
+ peerDependenciesMeta:
+ debug:
+ optional: true
+ checksum: 2e8f5f259a6b02dfa8dc199e08431848a7c3beed32eb4c19945966164a52c89f07b86c3afcc32ebe4279cf0a960520e45a63013d6350309c5ec90133c5d9351a
+ languageName: node
+ linkType: hard
+
"for-each@npm:^0.3.3":
version: 0.3.3
resolution: "for-each@npm:0.3.3"
@@ -4893,10 +5449,17 @@ __metadata:
languageName: node
linkType: hard
-"form-data-encoder@npm:^4.0.2":
- version: 4.0.2
- resolution: "form-data-encoder@npm:4.0.2"
- checksum: 71a00a1e954267f8b87d4301936dda7177cfe18714a92930c87ebc132acb8b19ed12e9b9f8ad47af52c1cc582fd45c1771f66f850a6d319147731160f6b9b3fa
+"form-data-encoder@npm:1.7.2":
+ version: 1.7.2
+ resolution: "form-data-encoder@npm:1.7.2"
+ checksum: 227bf2cea083284411fd67472ccc22f5cb354ca92c00690e11ff5ed942d993c13ac99dea365046306200f8bd71e1a7858d2d99e236de694b806b1f374a4ee341
+ languageName: node
+ linkType: hard
+
+"form-data-encoder@npm:^2.1.2":
+ version: 2.1.4
+ resolution: "form-data-encoder@npm:2.1.4"
+ checksum: 3778e7db3c21457296e6fdbc4200642a6c01e8be9297256e845ee275f9ddaecb5f49bfb0364690ad216898c114ec59bf85f01ec823a70670b8067273415d62f6
languageName: node
linkType: hard
@@ -4911,6 +5474,27 @@ __metadata:
languageName: node
linkType: hard
+"form-data@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "form-data@npm:4.0.0"
+ dependencies:
+ asynckit: "npm:^0.4.0"
+ combined-stream: "npm:^1.0.8"
+ mime-types: "npm:^2.1.12"
+ checksum: 7264aa760a8cf09482816d8300f1b6e2423de1b02bba612a136857413fdc96d7178298ced106817655facc6b89036c6e12ae31c9eb5bdc16aabf502ae8a5d805
+ languageName: node
+ linkType: hard
+
+"formdata-node@npm:^4.3.2":
+ version: 4.4.1
+ resolution: "formdata-node@npm:4.4.1"
+ dependencies:
+ node-domexception: "npm:1.0.0"
+ web-streams-polyfill: "npm:4.0.0-beta.3"
+ checksum: 29622f75533107c1bbcbe31fda683e6a55859af7f48ec354a9800591ce7947ed84cd3ef2b2fcb812047a884f17a1bac75ce098ffc17e23402cd373e49c1cd335
+ languageName: node
+ linkType: hard
+
"formdata-polyfill@npm:^4.0.10":
version: 4.0.10
resolution: "formdata-polyfill@npm:4.0.10"
@@ -4920,6 +5504,32 @@ __metadata:
languageName: node
linkType: hard
+"formidable@npm:^2.1.2":
+ version: 2.1.2
+ resolution: "formidable@npm:2.1.2"
+ dependencies:
+ dezalgo: "npm:^1.0.4"
+ hexoid: "npm:^1.0.0"
+ once: "npm:^1.4.0"
+ qs: "npm:^6.11.0"
+ checksum: d385180e0461f65e6f7b70452859fe1c32aa97a290c2ca33f00cdc33145ef44fa68bbc9b93af2c3af73ae726e42c3477c6619c49f3c34b49934e9481275b7b4c
+ languageName: node
+ linkType: hard
+
+"forwarded@npm:0.2.0":
+ version: 0.2.0
+ resolution: "forwarded@npm:0.2.0"
+ checksum: 29ba9fd347117144e97cbb8852baae5e8b2acb7d1b591ef85695ed96f5b933b1804a7fac4a15dd09ca7ac7d0cdc104410e8102aae2dd3faa570a797ba07adb81
+ languageName: node
+ linkType: hard
+
+"fresh@npm:0.5.2":
+ version: 0.5.2
+ resolution: "fresh@npm:0.5.2"
+ checksum: 64c88e489b5d08e2f29664eb3c79c705ff9a8eb15d3e597198ef76546d4ade295897a44abb0abd2700e7ef784b2e3cbf1161e4fbf16f59129193fd1030d16da1
+ languageName: node
+ linkType: hard
+
"from@npm:~0":
version: 0.1.7
resolution: "from@npm:0.1.7"
@@ -5001,6 +5611,13 @@ __metadata:
languageName: node
linkType: hard
+"functional-red-black-tree@npm:^1.0.1":
+ version: 1.0.1
+ resolution: "functional-red-black-tree@npm:1.0.1"
+ checksum: debe73e92204341d1fa5f89614e44284d3add26dee660722978d8c50829170f87d1c74768f68c251d215ae461c11db7bac13101c77f4146ff051da75466f7a12
+ languageName: node
+ linkType: hard
+
"functions-have-names@npm:^1.2.3":
version: 1.2.3
resolution: "functions-have-names@npm:1.2.3"
@@ -5017,7 +5634,7 @@ __metadata:
languageName: node
linkType: hard
-"gaxios@npm:^6.0.0, gaxios@npm:^6.1.1":
+"gaxios@npm:^6.0.0, gaxios@npm:^6.0.3, gaxios@npm:^6.1.1":
version: 6.1.1
resolution: "gaxios@npm:6.1.1"
dependencies:
@@ -5053,6 +5670,13 @@ __metadata:
languageName: node
linkType: hard
+"get-east-asian-width@npm:^1.0.0":
+ version: 1.2.0
+ resolution: "get-east-asian-width@npm:1.2.0"
+ checksum: c9b280e7c7c67fb89fa17e867c4a9d1c9f1321aba2a9ee27bff37fb6ca9552bccda328c70a80c1f83a0e39ba1b7e3427e60f47823402d19e7a41b83417ec047a
+ languageName: node
+ linkType: hard
+
"get-func-name@npm:^2.0.1, get-func-name@npm:^2.0.2":
version: 2.0.2
resolution: "get-func-name@npm:2.0.2"
@@ -5237,7 +5861,7 @@ __metadata:
languageName: node
linkType: hard
-"google-auth-library@npm:^9.0.0":
+"google-auth-library@npm:^9.0.0, google-auth-library@npm:^9.4.1":
version: 9.4.1
resolution: "google-auth-library@npm:9.4.1"
dependencies:
@@ -5251,7 +5875,7 @@ __metadata:
languageName: node
linkType: hard
-"google-gax@npm:^4.0.3":
+"google-gax@npm:^4.0.3, google-gax@npm:^4.0.4":
version: 4.0.5
resolution: "google-gax@npm:4.0.5"
dependencies:
@@ -5270,6 +5894,20 @@ __metadata:
languageName: node
linkType: hard
+"googleapis-common@npm:^7.0.0":
+ version: 7.0.1
+ resolution: "googleapis-common@npm:7.0.1"
+ dependencies:
+ extend: "npm:^3.0.2"
+ gaxios: "npm:^6.0.3"
+ google-auth-library: "npm:^9.0.0"
+ qs: "npm:^6.7.0"
+ url-template: "npm:^2.0.8"
+ uuid: "npm:^9.0.0"
+ checksum: ae44d20c81183d72bf3ce85bfca3915b5370310ce5387b7b8c5b3e9348b1eb14c5f2b8e187aa6d088cd7a64153b3f7b797e0e2ee2894068f0c295287edeaafe3
+ languageName: node
+ linkType: hard
+
"gopd@npm:^1.0.1":
version: 1.0.1
resolution: "gopd@npm:1.0.1"
@@ -5279,22 +5917,22 @@ __metadata:
languageName: node
linkType: hard
-"got@npm:^14.0.0":
- version: 14.0.0
- resolution: "got@npm:14.0.0"
+"got@npm:^13.0.0":
+ version: 13.0.0
+ resolution: "got@npm:13.0.0"
dependencies:
- "@sindresorhus/is": "npm:^6.1.0"
+ "@sindresorhus/is": "npm:^5.2.0"
"@szmarczak/http-timer": "npm:^5.0.1"
cacheable-lookup: "npm:^7.0.0"
- cacheable-request: "npm:^10.2.14"
+ cacheable-request: "npm:^10.2.8"
decompress-response: "npm:^6.0.0"
- form-data-encoder: "npm:^4.0.2"
- get-stream: "npm:^8.0.1"
- http2-wrapper: "npm:^2.2.1"
+ form-data-encoder: "npm:^2.1.2"
+ get-stream: "npm:^6.0.1"
+ http2-wrapper: "npm:^2.1.10"
lowercase-keys: "npm:^3.0.0"
- p-cancelable: "npm:^4.0.1"
+ p-cancelable: "npm:^3.0.0"
responselike: "npm:^3.0.0"
- checksum: 3afcf60c8313cacb3bdc1a153b9b48e6c974241dab09ceb9155bfd4f2aad161a32e9b2f541584c78e8ac2e9615b241e453d06cfa2a4518b7e3899b46948ab9f3
+ checksum: 35ac9fe37daca3d0a4f90305d8e64626268ef5a42584f5bcb42eea3cb9bbeb691cf9041d5ea72133a7295d1291684789a3148ff89a95f3d3ce3d0ebb6fb2f680
languageName: node
linkType: hard
@@ -5419,6 +6057,20 @@ __metadata:
languageName: node
linkType: hard
+"help-me@npm:^5.0.0":
+ version: 5.0.0
+ resolution: "help-me@npm:5.0.0"
+ checksum: 5f99bd91dae93d02867175c3856c561d7e3a24f16999b08f5fc79689044b938d7ed58457f4d8c8744c01403e6e0470b7896baa344d112b2355842fd935a75d69
+ languageName: node
+ linkType: hard
+
+"hexoid@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "hexoid@npm:1.0.0"
+ checksum: f2271b8b6b0e13fb5a1eccf740f53ce8bae689c80b9498b854c447f9dc94f75f44e0de064c0e4660ecdbfa8942bb2b69973fdcb080187b45bbb409a3c71f19d4
+ languageName: node
+ linkType: hard
+
"hoist-non-react-statics@npm:^3.3.1":
version: 3.3.2
resolution: "hoist-non-react-statics@npm:3.3.2"
@@ -5458,6 +6110,19 @@ __metadata:
languageName: node
linkType: hard
+"http-errors@npm:2.0.0, http-errors@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "http-errors@npm:2.0.0"
+ dependencies:
+ depd: "npm:2.0.0"
+ inherits: "npm:2.0.4"
+ setprototypeof: "npm:1.2.0"
+ statuses: "npm:2.0.1"
+ toidentifier: "npm:1.0.1"
+ checksum: 0e7f76ee8ff8a33e58a3281a469815b893c41357378f408be8f6d4aa7d1efafb0da064625518e7078381b6a92325949b119dc38fcb30bdbc4e3a35f78c44c439
+ languageName: node
+ linkType: hard
+
"http-parser-js@npm:>=0.5.1":
version: 0.5.8
resolution: "http-parser-js@npm:0.5.8"
@@ -5486,7 +6151,36 @@ __metadata:
languageName: node
linkType: hard
-"http2-wrapper@npm:^2.2.1":
+"http-proxy-middleware@npm:^2.0.6":
+ version: 2.0.6
+ resolution: "http-proxy-middleware@npm:2.0.6"
+ dependencies:
+ "@types/http-proxy": "npm:^1.17.8"
+ http-proxy: "npm:^1.18.1"
+ is-glob: "npm:^4.0.1"
+ is-plain-obj: "npm:^3.0.0"
+ micromatch: "npm:^4.0.2"
+ peerDependencies:
+ "@types/express": ^4.17.13
+ peerDependenciesMeta:
+ "@types/express":
+ optional: true
+ checksum: 768e7ae5a422bbf4b866b64105b4c2d1f468916b7b0e9c96750551c7732383069b411aa7753eb7b34eab113e4f77fb770122cb7fb9c8ec87d138d5ddaafda891
+ languageName: node
+ linkType: hard
+
+"http-proxy@npm:^1.18.1":
+ version: 1.18.1
+ resolution: "http-proxy@npm:1.18.1"
+ dependencies:
+ eventemitter3: "npm:^4.0.0"
+ follow-redirects: "npm:^1.0.0"
+ requires-port: "npm:^1.0.0"
+ checksum: 2489e98aba70adbfd8b9d41ed1ff43528be4598c88616c558b109a09eaffe4bb35e551b6c75ac42ed7d948bb7530a22a2be6ef4f0cecacb5927be139f4274594
+ languageName: node
+ linkType: hard
+
+"http2-wrapper@npm:^2.1.10":
version: 2.2.1
resolution: "http2-wrapper@npm:2.2.1"
dependencies:
@@ -5530,6 +6224,15 @@ __metadata:
languageName: node
linkType: hard
+"humanize-ms@npm:^1.2.1":
+ version: 1.2.1
+ resolution: "humanize-ms@npm:1.2.1"
+ dependencies:
+ ms: "npm:^2.0.0"
+ checksum: 9c7a74a2827f9294c009266c82031030eae811ca87b0da3dceb8d6071b9bde22c9f3daef0469c3c533cc67a97d8a167cd9fc0389350e5f415f61a79b171ded16
+ languageName: node
+ linkType: hard
+
"husky@npm:^8.0.3":
version: 8.0.3
resolution: "husky@npm:8.0.3"
@@ -5539,6 +6242,15 @@ __metadata:
languageName: node
linkType: hard
+"iconv-lite@npm:0.4.24":
+ version: 0.4.24
+ resolution: "iconv-lite@npm:0.4.24"
+ dependencies:
+ safer-buffer: "npm:>= 2.1.2 < 3"
+ checksum: 6d3a2dac6e5d1fb126d25645c25c3a1209f70cceecc68b8ef51ae0da3cdc078c151fade7524a30b12a3094926336831fca09c666ef55b37e2c69638b5d6bd2e3
+ languageName: node
+ linkType: hard
+
"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2, iconv-lite@npm:^0.6.3":
version: 0.6.3
resolution: "iconv-lite@npm:0.6.3"
@@ -5562,6 +6274,13 @@ __metadata:
languageName: node
linkType: hard
+"ieee754@npm:^1.2.1":
+ version: 1.2.1
+ resolution: "ieee754@npm:1.2.1"
+ checksum: d9f2557a59036f16c282aaeb107832dc957a93d73397d89bbad4eb1130560560eb695060145e8e6b3b498b15ab95510226649a0b8f52ae06583575419fe10fc4
+ languageName: node
+ linkType: hard
+
"ignore@npm:^5.2.0, ignore@npm:^5.2.4":
version: 5.3.0
resolution: "ignore@npm:5.3.0"
@@ -5620,7 +6339,7 @@ __metadata:
languageName: node
linkType: hard
-"inherits@npm:2, inherits@npm:^2.0.3":
+"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.3":
version: 2.0.4
resolution: "inherits@npm:2.0.4"
checksum: cd45e923bee15186c07fa4c89db0aace24824c482fb887b528304694b2aa6ff8a898da8657046a5dcf3e46cd6db6c61629551f9215f208d7c3f157cf9b290521
@@ -5645,6 +6364,13 @@ __metadata:
languageName: node
linkType: hard
+"ipaddr.js@npm:1.9.1":
+ version: 1.9.1
+ resolution: "ipaddr.js@npm:1.9.1"
+ checksum: 864d0cced0c0832700e9621913a6429ccdc67f37c1bd78fb8c6789fff35c9d167cb329134acad2290497a53336813ab4798d2794fd675d5eb33b5fdf0982b9ca
+ languageName: node
+ linkType: hard
+
"is-array-buffer@npm:^3.0.1, is-array-buffer@npm:^3.0.2":
version: 3.0.2
resolution: "is-array-buffer@npm:3.0.2"
@@ -5700,6 +6426,13 @@ __metadata:
languageName: node
linkType: hard
+"is-buffer@npm:~1.1.6":
+ version: 1.1.6
+ resolution: "is-buffer@npm:1.1.6"
+ checksum: f63da109e74bbe8947036ed529d43e4ae0c5fcd0909921dce4917ad3ea212c6a87c29f525ba1d17c0858c18331cf1046d4fc69ef59ed26896b25c8288a627133
+ languageName: node
+ linkType: hard
+
"is-callable@npm:^1.1.3, is-callable@npm:^1.1.4, is-callable@npm:^1.2.7":
version: 1.2.7
resolution: "is-callable@npm:1.2.7"
@@ -5773,6 +6506,13 @@ __metadata:
languageName: node
linkType: hard
+"is-interactive@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "is-interactive@npm:2.0.0"
+ checksum: e8d52ad490bed7ae665032c7675ec07732bbfe25808b0efbc4d5a76b1a1f01c165f332775c63e25e9a03d319ebb6b24f571a9e902669fc1e40b0a60b5be6e26c
+ languageName: node
+ linkType: hard
+
"is-lambda@npm:^1.0.1":
version: 1.0.1
resolution: "is-lambda@npm:1.0.1"
@@ -5817,6 +6557,13 @@ __metadata:
languageName: node
linkType: hard
+"is-plain-obj@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "is-plain-obj@npm:3.0.0"
+ checksum: a6ebdf8e12ab73f33530641972a72a4b8aed6df04f762070d823808303e4f76d87d5ea5bd76f96a7bbe83d93f04ac7764429c29413bd9049853a69cb630fb21c
+ languageName: node
+ linkType: hard
+
"is-regex@npm:^1.1.4":
version: 1.1.4
resolution: "is-regex@npm:1.1.4"
@@ -5884,6 +6631,20 @@ __metadata:
languageName: node
linkType: hard
+"is-unicode-supported@npm:^1.3.0":
+ version: 1.3.0
+ resolution: "is-unicode-supported@npm:1.3.0"
+ checksum: 20a1fc161afafaf49243551a5ac33b6c4cf0bbcce369fcd8f2951fbdd000c30698ce320de3ee6830497310a8f41880f8066d440aa3eb0a853e2aa4836dd89abc
+ languageName: node
+ linkType: hard
+
+"is-unicode-supported@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "is-unicode-supported@npm:2.0.0"
+ checksum: 000b80639dedaf59a385f1c0a57f97a4d1435e0723716f24cc19ad94253a7a0a9f838bdc9ac49b10a29ac93b01f52ae9b2ed358a8876caf1eb74d73b4ede92b2
+ languageName: node
+ linkType: hard
+
"is-weakmap@npm:^2.0.1":
version: 2.0.1
resolution: "is-weakmap@npm:2.0.1"
@@ -5995,6 +6756,13 @@ __metadata:
languageName: node
linkType: hard
+"joycon@npm:^3.1.1":
+ version: 3.1.1
+ resolution: "joycon@npm:3.1.1"
+ checksum: 4b36e3479144ec196425f46b3618f8a96ce7e1b658f091a309cd4906215f5b7a402d7df331a3e0a09681381a658d0c5f039cb3cf6907e0a1e17ed847f5d37775
+ languageName: node
+ linkType: hard
+
"js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0":
version: 4.0.0
resolution: "js-tokens@npm:4.0.0"
@@ -6281,6 +7049,16 @@ __metadata:
languageName: node
linkType: hard
+"log-symbols@npm:^6.0.0":
+ version: 6.0.0
+ resolution: "log-symbols@npm:6.0.0"
+ dependencies:
+ chalk: "npm:^5.3.0"
+ is-unicode-supported: "npm:^1.3.0"
+ checksum: 510cdda36700cbcd87a2a691ea08d310a6c6b449084018f7f2ec4f732ca5e51b301ff1327aadd96f53c08318e616276c65f7fe22f2a16704fb0715d788bc3c33
+ languageName: node
+ linkType: hard
+
"long@npm:^5.0.0":
version: 5.2.3
resolution: "long@npm:5.2.3"
@@ -6384,6 +7162,31 @@ __metadata:
languageName: node
linkType: hard
+"md5@npm:^2.3.0":
+ version: 2.3.0
+ resolution: "md5@npm:2.3.0"
+ dependencies:
+ charenc: "npm:0.0.2"
+ crypt: "npm:0.0.2"
+ is-buffer: "npm:~1.1.6"
+ checksum: 88dce9fb8df1a084c2385726dcc18c7f54e0b64c261b5def7cdfe4928c4ee1cd68695c34108b4fab7ecceb05838c938aa411c6143df9fdc0026c4ddb4e4e72fa
+ languageName: node
+ linkType: hard
+
+"media-typer@npm:0.3.0":
+ version: 0.3.0
+ resolution: "media-typer@npm:0.3.0"
+ checksum: 38e0984db39139604756903a01397e29e17dcb04207bb3e081412ce725ab17338ecc47220c1b186b6bbe79a658aad1b0d41142884f5a481f36290cdefbe6aa46
+ languageName: node
+ linkType: hard
+
+"merge-descriptors@npm:1.0.1":
+ version: 1.0.1
+ resolution: "merge-descriptors@npm:1.0.1"
+ checksum: 5abc259d2ae25bb06d19ce2b94a21632583c74e2a9109ee1ba7fd147aa7362b380d971e0251069f8b3eb7d48c21ac839e21fa177b335e82c76ec172e30c31a26
+ languageName: node
+ linkType: hard
+
"merge-stream@npm:^2.0.0":
version: 2.0.0
resolution: "merge-stream@npm:2.0.0"
@@ -6398,7 +7201,14 @@ __metadata:
languageName: node
linkType: hard
-"micromatch@npm:^4.0.4":
+"methods@npm:^1.1.2, methods@npm:~1.1.2":
+ version: 1.1.2
+ resolution: "methods@npm:1.1.2"
+ checksum: a385dd974faa34b5dd021b2bbf78c722881bf6f003bfe6d391d7da3ea1ed625d1ff10ddd13c57531f628b3e785be38d3eed10ad03cebd90b76932413df9a1820
+ languageName: node
+ linkType: hard
+
+"micromatch@npm:^4.0.2, micromatch@npm:^4.0.4":
version: 4.0.5
resolution: "micromatch@npm:4.0.5"
dependencies:
@@ -6415,7 +7225,7 @@ __metadata:
languageName: node
linkType: hard
-"mime-types@npm:^2.1.12":
+"mime-types@npm:^2.1.12, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34":
version: 2.1.35
resolution: "mime-types@npm:2.1.35"
dependencies:
@@ -6424,6 +7234,24 @@ __metadata:
languageName: node
linkType: hard
+"mime@npm:1.6.0":
+ version: 1.6.0
+ resolution: "mime@npm:1.6.0"
+ bin:
+ mime: cli.js
+ checksum: b7d98bb1e006c0e63e2c91b590fe1163b872abf8f7ef224d53dd31499c2197278a6d3d0864c45239b1a93d22feaf6f9477e9fc847eef945838150b8c02d03170
+ languageName: node
+ linkType: hard
+
+"mime@npm:2.6.0":
+ version: 2.6.0
+ resolution: "mime@npm:2.6.0"
+ bin:
+ mime: cli.js
+ checksum: 7da117808b5cd0203bb1b5e33445c330fe213f4d8ee2402a84d62adbde9716ca4fb90dd6d9ab4e77a4128c6c5c24a9c4c9f6a4d720b095b1b342132d02dba58d
+ languageName: node
+ linkType: hard
+
"mime@npm:^3.0.0":
version: 3.0.0
resolution: "mime@npm:3.0.0"
@@ -6433,6 +7261,13 @@ __metadata:
languageName: node
linkType: hard
+"mimic-fn@npm:^2.1.0":
+ version: 2.1.0
+ resolution: "mimic-fn@npm:2.1.0"
+ checksum: d2421a3444848ce7f84bd49115ddacff29c15745db73f54041edc906c14b131a38d05298dae3081667627a59b2eb1ca4b436ff2e1b80f69679522410418b478a
+ languageName: node
+ linkType: hard
+
"mimic-fn@npm:^4.0.0":
version: 4.0.0
resolution: "mimic-fn@npm:4.0.0"
@@ -6616,6 +7451,13 @@ __metadata:
languageName: node
linkType: hard
+"ms@npm:2.0.0":
+ version: 2.0.0
+ resolution: "ms@npm:2.0.0"
+ checksum: 0e6a22b8b746d2e0b65a430519934fefd41b6db0682e3477c10f60c76e947c4c0ad06f63ffdf1d78d335f83edee8c0aa928aa66a36c7cd95b69b26f468d527f4
+ languageName: node
+ linkType: hard
+
"ms@npm:2.1.2":
version: 2.1.2
resolution: "ms@npm:2.1.2"
@@ -6623,7 +7465,7 @@ __metadata:
languageName: node
linkType: hard
-"ms@npm:^2.1.1":
+"ms@npm:2.1.3, ms@npm:^2.0.0, ms@npm:^2.1.1":
version: 2.1.3
resolution: "ms@npm:2.1.3"
checksum: aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d
@@ -6648,6 +7490,15 @@ __metadata:
languageName: node
linkType: hard
+"nanoid@npm:^5.0.4":
+ version: 5.0.4
+ resolution: "nanoid@npm:5.0.4"
+ bin:
+ nanoid: bin/nanoid.js
+ checksum: cf09cca3774f3147100948f7478f75f4c9ee97a4af65c328dd9abbd83b12f8bb35cf9f89a21c330f3b759d667a4cd0140ed84aa5fdd522c61e0d341aeaa7fb6f
+ languageName: node
+ linkType: hard
+
"natural-compare@npm:^1.4.0":
version: 1.4.0
resolution: "natural-compare@npm:1.4.0"
@@ -6655,14 +7506,14 @@ __metadata:
languageName: node
linkType: hard
-"negotiator@npm:^0.6.3":
+"negotiator@npm:0.6.3, negotiator@npm:^0.6.3":
version: 0.6.3
resolution: "negotiator@npm:0.6.3"
checksum: 2723fb822a17ad55c93a588a4bc44d53b22855bf4be5499916ca0cab1e7165409d0b288ba2577d7b029f10ce18cf2ed8e703e5af31c984e1e2304277ef979837
languageName: node
linkType: hard
-"node-domexception@npm:^1.0.0":
+"node-domexception@npm:1.0.0, node-domexception@npm:^1.0.0":
version: 1.0.0
resolution: "node-domexception@npm:1.0.0"
checksum: e332522f242348c511640c25a6fc7da4f30e09e580c70c6b13cb0be83c78c3e71c8d4665af2527e869fc96848924a4316ae7ec9014c091e2156f41739d4fa233
@@ -6680,7 +7531,7 @@ __metadata:
languageName: node
linkType: hard
-"node-fetch@npm:^2.6.1, node-fetch@npm:^2.6.9":
+"node-fetch@npm:^2.6.1, node-fetch@npm:^2.6.7, node-fetch@npm:^2.6.9":
version: 2.7.0
resolution: "node-fetch@npm:2.7.0"
dependencies:
@@ -6894,7 +7745,23 @@ __metadata:
languageName: node
linkType: hard
-"once@npm:^1.3.0, once@npm:^1.4.0":
+"on-exit-leak-free@npm:^2.1.0":
+ version: 2.1.2
+ resolution: "on-exit-leak-free@npm:2.1.2"
+ checksum: f7b4b7200026a08f6e4a17ba6d72e6c5cbb41789ed9cf7deaf9d9e322872c7dc5a7898549a894651ee0ee9ae635d34a678115bf8acdfba8ebd2ba2af688b563c
+ languageName: node
+ linkType: hard
+
+"on-finished@npm:2.4.1":
+ version: 2.4.1
+ resolution: "on-finished@npm:2.4.1"
+ dependencies:
+ ee-first: "npm:1.1.1"
+ checksum: 8e81472c5028125c8c39044ac4ab8ba51a7cdc19a9fbd4710f5d524a74c6d8c9ded4dd0eed83f28d3d33ac1d7a6a439ba948ccb765ac6ce87f30450a26bfe2ea
+ languageName: node
+ linkType: hard
+
+"once@npm:^1.3.0, once@npm:^1.3.1, once@npm:^1.4.0":
version: 1.4.0
resolution: "once@npm:1.4.0"
dependencies:
@@ -6903,6 +7770,15 @@ __metadata:
languageName: node
linkType: hard
+"onetime@npm:^5.1.0":
+ version: 5.1.2
+ resolution: "onetime@npm:5.1.2"
+ dependencies:
+ mimic-fn: "npm:^2.1.0"
+ checksum: e9fd0695a01cf226652f0385bf16b7a24153dbbb2039f764c8ba6d2306a8506b0e4ce570de6ad99c7a6eb49520743afdb66edd95ee979c1a342554ed49a9aadd
+ languageName: node
+ linkType: hard
+
"onetime@npm:^6.0.0":
version: 6.0.0
resolution: "onetime@npm:6.0.0"
@@ -6912,6 +7788,25 @@ __metadata:
languageName: node
linkType: hard
+"openai@npm:^4.24.1":
+ version: 4.24.1
+ resolution: "openai@npm:4.24.1"
+ dependencies:
+ "@types/node": "npm:^18.11.18"
+ "@types/node-fetch": "npm:^2.6.4"
+ abort-controller: "npm:^3.0.0"
+ agentkeepalive: "npm:^4.2.1"
+ digest-fetch: "npm:^1.3.0"
+ form-data-encoder: "npm:1.7.2"
+ formdata-node: "npm:^4.3.2"
+ node-fetch: "npm:^2.6.7"
+ web-streams-polyfill: "npm:^3.2.1"
+ bin:
+ openai: bin/cli
+ checksum: 30769c66e62129bfe0e5caedb760d9885019cf69bea9d8bcd370e88b6c32311c81a4d895e84ada96da035b6710dd880d67b747a630369c4e3c2b2a08bc8484e9
+ languageName: node
+ linkType: hard
+
"optionator@npm:^0.9.3":
version: 0.9.3
resolution: "optionator@npm:0.9.3"
@@ -6926,10 +7821,27 @@ __metadata:
languageName: node
linkType: hard
-"p-cancelable@npm:^4.0.1":
- version: 4.0.1
- resolution: "p-cancelable@npm:4.0.1"
- checksum: 64de7b0be4c8bacc006488e0e90aa66fbcceb4da4f6fb84584573145f015f9650fe6ac26470897b3e82a3b528f6c60ea276b84cc315e35c45e9f12dec062a295
+"ora@npm:^8.0.1":
+ version: 8.0.1
+ resolution: "ora@npm:8.0.1"
+ dependencies:
+ chalk: "npm:^5.3.0"
+ cli-cursor: "npm:^4.0.0"
+ cli-spinners: "npm:^2.9.2"
+ is-interactive: "npm:^2.0.0"
+ is-unicode-supported: "npm:^2.0.0"
+ log-symbols: "npm:^6.0.0"
+ stdin-discarder: "npm:^0.2.1"
+ string-width: "npm:^7.0.0"
+ strip-ansi: "npm:^7.1.0"
+ checksum: 3d37bb3f53e965e5176004af319f82feef7323ee0b2428db5ee6f689b9b9ba939d7b1e81691d4614333c4fb9e294790eb049db9c1e990b14b9bbe150c6f09993
+ languageName: node
+ linkType: hard
+
+"p-cancelable@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "p-cancelable@npm:3.0.0"
+ checksum: a5eab7cf5ac5de83222a014eccdbfde65ecfb22005ee9bc242041f0b4441e07fac7629432c82f48868aa0f8413fe0df6c6067c16f76bf9217cd8dc651923c93d
languageName: node
linkType: hard
@@ -7047,6 +7959,13 @@ __metadata:
languageName: node
linkType: hard
+"parseurl@npm:~1.3.3":
+ version: 1.3.3
+ resolution: "parseurl@npm:1.3.3"
+ checksum: 407cee8e0a3a4c5cd472559bca8b6a45b82c124e9a4703302326e9ab60fc1081442ada4e02628efef1eb16197ddc7f8822f5a91fd7d7c86b51f530aedb17dfa2
+ languageName: node
+ linkType: hard
+
"path-exists@npm:^4.0.0":
version: 4.0.0
resolution: "path-exists@npm:4.0.0"
@@ -7099,6 +8018,13 @@ __metadata:
languageName: node
linkType: hard
+"path-to-regexp@npm:0.1.7":
+ version: 0.1.7
+ resolution: "path-to-regexp@npm:0.1.7"
+ checksum: 701c99e1f08e3400bea4d701cf6f03517474bb1b608da71c78b1eb261415b645c5670dfae49808c89e12cea2dccd113b069f040a80de012da0400191c6dbd1c8
+ languageName: node
+ linkType: hard
+
"path-to-regexp@npm:^6.2.0":
version: 6.2.1
resolution: "path-to-regexp@npm:6.2.1"
@@ -7150,6 +8076,80 @@ __metadata:
languageName: node
linkType: hard
+"pino-abstract-transport@npm:^1.0.0, pino-abstract-transport@npm:v1.1.0":
+ version: 1.1.0
+ resolution: "pino-abstract-transport@npm:1.1.0"
+ dependencies:
+ readable-stream: "npm:^4.0.0"
+ split2: "npm:^4.0.0"
+ checksum: 39b4496c9e4289e8d44a1d01adfa8dfeebb374e14b7a6451a4f3713561aeb9e181c64ff0272921667abcb95aceb312ab2761b82e253db23a456ab3dd35a42675
+ languageName: node
+ linkType: hard
+
+"pino-http@npm:^9.0.0":
+ version: 9.0.0
+ resolution: "pino-http@npm:9.0.0"
+ dependencies:
+ get-caller-file: "npm:^2.0.5"
+ pino: "npm:^8.17.1"
+ pino-std-serializers: "npm:^6.2.2"
+ process-warning: "npm:^3.0.0"
+ checksum: 12a0b016c62c1f4e7d506f6a690d10b7ccdbb5868fba8156a1bf515143e522087f87ce83a732615773e903271468c308d5f5eb908ca5446208803da119025fdf
+ languageName: node
+ linkType: hard
+
+"pino-pretty@npm:^10.3.1":
+ version: 10.3.1
+ resolution: "pino-pretty@npm:10.3.1"
+ dependencies:
+ colorette: "npm:^2.0.7"
+ dateformat: "npm:^4.6.3"
+ fast-copy: "npm:^3.0.0"
+ fast-safe-stringify: "npm:^2.1.1"
+ help-me: "npm:^5.0.0"
+ joycon: "npm:^3.1.1"
+ minimist: "npm:^1.2.6"
+ on-exit-leak-free: "npm:^2.1.0"
+ pino-abstract-transport: "npm:^1.0.0"
+ pump: "npm:^3.0.0"
+ readable-stream: "npm:^4.0.0"
+ secure-json-parse: "npm:^2.4.0"
+ sonic-boom: "npm:^3.0.0"
+ strip-json-comments: "npm:^3.1.1"
+ bin:
+ pino-pretty: bin.js
+ checksum: 4284f125f7e8a5a10e856c8fd591ba34c30c0a0071a0b265a9eda43c3e447ba11d40b06cc67108675586358a5d1213a6ac3a92f6abd2896abfbab9a5b4c17072
+ languageName: node
+ linkType: hard
+
+"pino-std-serializers@npm:^6.0.0, pino-std-serializers@npm:^6.2.2":
+ version: 6.2.2
+ resolution: "pino-std-serializers@npm:6.2.2"
+ checksum: a00cdff4e1fbc206da9bed047e6dc400b065f43e8b4cef1635b0192feab0e8f932cdeb0faaa38a5d93d2e777ba4cda939c2ed4c1a70f6839ff25f9aef97c27ff
+ languageName: node
+ linkType: hard
+
+"pino@npm:^8.17.1, pino@npm:^8.17.2":
+ version: 8.17.2
+ resolution: "pino@npm:8.17.2"
+ dependencies:
+ atomic-sleep: "npm:^1.0.0"
+ fast-redact: "npm:^3.1.1"
+ on-exit-leak-free: "npm:^2.1.0"
+ pino-abstract-transport: "npm:v1.1.0"
+ pino-std-serializers: "npm:^6.0.0"
+ process-warning: "npm:^3.0.0"
+ quick-format-unescaped: "npm:^4.0.3"
+ real-require: "npm:^0.2.0"
+ safe-stable-stringify: "npm:^2.3.1"
+ sonic-boom: "npm:^3.7.0"
+ thread-stream: "npm:^2.0.0"
+ bin:
+ pino: bin.js
+ checksum: 90b74e4db3b3f8664b13def3eb4e39585a842396fd7a000ef00f2329076c889126f91bdaff0f653b9b5dd5a612dddde6ff87599ad046b47a264e8f7bfabb0ea8
+ languageName: node
+ linkType: hard
+
"pkg-types@npm:^1.0.3":
version: 1.0.3
resolution: "pkg-types@npm:1.0.3"
@@ -7213,6 +8213,20 @@ __metadata:
languageName: node
linkType: hard
+"process-warning@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "process-warning@npm:3.0.0"
+ checksum: 2d82fa641e50a5789eaf0f2b33453760996e373d4591aac576a22d696186ab7e240a0592db86c264d4f28a46c2abbe9b94689752017db7dadc90f169f12b0924
+ languageName: node
+ linkType: hard
+
+"process@npm:^0.11.10":
+ version: 0.11.10
+ resolution: "process@npm:0.11.10"
+ checksum: dbaa7e8d1d5cf375c36963ff43116772a989ef2bb47c9bdee20f38fd8fc061119cf38140631cf90c781aca4d3f0f0d2c834711952b728953f04fd7d238f59f5b
+ languageName: node
+ linkType: hard
+
"promise-retry@npm:^2.0.1":
version: 2.0.1
resolution: "promise-retry@npm:2.0.1"
@@ -7243,7 +8257,7 @@ __metadata:
languageName: node
linkType: hard
-"protobufjs@npm:7.2.5, protobufjs@npm:^7.0.0, protobufjs@npm:^7.2.4":
+"protobufjs@npm:7.2.5, protobufjs@npm:^7.0.0, protobufjs@npm:^7.2.4, protobufjs@npm:^7.2.5":
version: 7.2.5
resolution: "protobufjs@npm:7.2.5"
dependencies:
@@ -7263,6 +8277,16 @@ __metadata:
languageName: node
linkType: hard
+"proxy-addr@npm:~2.0.7":
+ version: 2.0.7
+ resolution: "proxy-addr@npm:2.0.7"
+ dependencies:
+ forwarded: "npm:0.2.0"
+ ipaddr.js: "npm:1.9.1"
+ checksum: f24a0c80af0e75d31e3451398670d73406ec642914da11a2965b80b1898ca6f66a0e3e091a11a4327079b2b268795f6fa06691923fef91887215c3d0e8ea3f68
+ languageName: node
+ linkType: hard
+
"ps-tree@npm:^1.2.0":
version: 1.2.0
resolution: "ps-tree@npm:1.2.0"
@@ -7274,6 +8298,16 @@ __metadata:
languageName: node
linkType: hard
+"pump@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "pump@npm:3.0.0"
+ dependencies:
+ end-of-stream: "npm:^1.1.0"
+ once: "npm:^1.3.1"
+ checksum: e42e9229fba14732593a718b04cb5e1cfef8254544870997e0ecd9732b189a48e1256e4e5478148ecb47c8511dca2b09eae56b4d0aad8009e6fac8072923cfc9
+ languageName: node
+ linkType: hard
+
"punycode@npm:^2.1.0":
version: 2.3.1
resolution: "punycode@npm:2.3.1"
@@ -7281,6 +8315,24 @@ __metadata:
languageName: node
linkType: hard
+"qs@npm:6.11.0":
+ version: 6.11.0
+ resolution: "qs@npm:6.11.0"
+ dependencies:
+ side-channel: "npm:^1.0.4"
+ checksum: 5a3bfea3e2f359ede1bfa5d2f0dbe54001aa55e40e27dc3e60fab814362d83a9b30758db057c2011b6f53a2d4e4e5150194b5bac45372652aecb3e3c0d4b256e
+ languageName: node
+ linkType: hard
+
+"qs@npm:^6.11.0, qs@npm:^6.7.0":
+ version: 6.11.2
+ resolution: "qs@npm:6.11.2"
+ dependencies:
+ side-channel: "npm:^1.0.4"
+ checksum: f2321d0796664d0f94e92447ccd3bdfd6b6f3a50b6b762aa79d7f5b1ea3a7a9f94063ba896b82bc2a877ed6a7426d4081e4f16568fdb04f0ee188cca9d8505b4
+ languageName: node
+ linkType: hard
+
"queue-microtask@npm:^1.2.2":
version: 1.2.3
resolution: "queue-microtask@npm:1.2.3"
@@ -7288,6 +8340,13 @@ __metadata:
languageName: node
linkType: hard
+"quick-format-unescaped@npm:^4.0.3":
+ version: 4.0.4
+ resolution: "quick-format-unescaped@npm:4.0.4"
+ checksum: 591eca457509a99368b623db05248c1193aa3cedafc9a077d7acab09495db1231017ba3ad1b5386e5633271edd0a03b312d8640a59ee585b8516a42e15438aa7
+ languageName: node
+ linkType: hard
+
"quick-lru@npm:^5.1.1":
version: 5.1.1
resolution: "quick-lru@npm:5.1.1"
@@ -7295,6 +8354,25 @@ __metadata:
languageName: node
linkType: hard
+"range-parser@npm:~1.2.1":
+ version: 1.2.1
+ resolution: "range-parser@npm:1.2.1"
+ checksum: ce21ef2a2dd40506893157970dc76e835c78cf56437e26e19189c48d5291e7279314477b06ac38abd6a401b661a6840f7b03bd0b1249da9b691deeaa15872c26
+ languageName: node
+ linkType: hard
+
+"raw-body@npm:2.5.1":
+ version: 2.5.1
+ resolution: "raw-body@npm:2.5.1"
+ dependencies:
+ bytes: "npm:3.1.2"
+ http-errors: "npm:2.0.0"
+ iconv-lite: "npm:0.4.24"
+ unpipe: "npm:1.0.0"
+ checksum: 280bedc12db3490ecd06f740bdcf66093a07535374b51331242382c0e130bb273ebb611b7bc4cba1b4b4e016cc7b1f4b05a6df885a6af39c2bc3b94c02291c84
+ languageName: node
+ linkType: hard
+
"react-dom@npm:^18.2.0":
version: 18.2.0
resolution: "react-dom@npm:18.2.0"
@@ -7410,6 +8488,19 @@ __metadata:
languageName: node
linkType: hard
+"readable-stream@npm:^4.0.0":
+ version: 4.5.2
+ resolution: "readable-stream@npm:4.5.2"
+ dependencies:
+ abort-controller: "npm:^3.0.0"
+ buffer: "npm:^6.0.3"
+ events: "npm:^3.3.0"
+ process: "npm:^0.11.10"
+ string_decoder: "npm:^1.3.0"
+ checksum: 01b128a559c5fd76a898495f858cf0a8839f135e6a69e3409f986e88460134791657eb46a2ff16826f331682a3c4d0c5a75cef5e52ef259711021ba52b1c2e82
+ languageName: node
+ linkType: hard
+
"readdirp@npm:~3.6.0":
version: 3.6.0
resolution: "readdirp@npm:3.6.0"
@@ -7419,6 +8510,13 @@ __metadata:
languageName: node
linkType: hard
+"real-require@npm:^0.2.0":
+ version: 0.2.0
+ resolution: "real-require@npm:0.2.0"
+ checksum: ddf44ee76301c774e9c9f2826da8a3c5c9f8fc87310f4a364e803ef003aa1a43c378b4323051ced212097fff1af459070f4499338b36a7469df1d4f7e8c0ba4c
+ languageName: node
+ linkType: hard
+
"reflect.getprototypeof@npm:^1.0.4":
version: 1.0.4
resolution: "reflect.getprototypeof@npm:1.0.4"
@@ -7467,6 +8565,13 @@ __metadata:
languageName: node
linkType: hard
+"requires-port@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "requires-port@npm:1.0.0"
+ checksum: 878880ee78ccdce372784f62f52a272048e2d0827c29ae31e7f99da18b62a2b9463ea03a75f277352f4697c100183debb0532371ad515a2d49d4bfe596dd4c20
+ languageName: node
+ linkType: hard
+
"resolve-alpn@npm:^1.2.0":
version: 1.2.1
resolution: "resolve-alpn@npm:1.2.1"
@@ -7563,6 +8668,16 @@ __metadata:
languageName: node
linkType: hard
+"restore-cursor@npm:^4.0.0":
+ version: 4.0.0
+ resolution: "restore-cursor@npm:4.0.0"
+ dependencies:
+ onetime: "npm:^5.1.0"
+ signal-exit: "npm:^3.0.2"
+ checksum: 5b675c5a59763bf26e604289eab35711525f11388d77f409453904e1e69c0d37ae5889295706b2c81d23bd780165084d040f9b68fffc32cc921519031c4fa4af
+ languageName: node
+ linkType: hard
+
"retry-request@npm:^7.0.0":
version: 7.0.1
resolution: "retry-request@npm:7.0.1"
@@ -7697,8 +8812,8 @@ __metadata:
"@emotion/babel-plugin": "npm:^11.11.0"
"@emotion/eslint-plugin": "npm:^11.11.0"
"@types/eslint": "npm:^8.56.1"
- "@typescript-eslint/eslint-plugin": "npm:^6.17.0"
- "@typescript-eslint/parser": "npm:^6.17.0"
+ "@typescript-eslint/eslint-plugin": "npm:^6.18.0"
+ "@typescript-eslint/parser": "npm:^6.18.0"
eslint: "npm:^8.56.0"
eslint-config-prettier: "npm:^9.1.0"
eslint-import-resolver-typescript: "npm:^3.6.1"
@@ -7739,7 +8854,7 @@ __metadata:
languageName: node
linkType: hard
-"safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.0.1, safe-buffer@npm:~5.2.0":
+"safe-buffer@npm:5.2.1, safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.0.1, safe-buffer@npm:~5.2.0":
version: 5.2.1
resolution: "safe-buffer@npm:5.2.1"
checksum: 32872cd0ff68a3ddade7a7617b8f4c2ae8764d8b7d884c651b74457967a9e0e886267d3ecc781220629c44a865167b61c375d2da6c720c840ecd73f45d5d9451
@@ -7757,7 +8872,14 @@ __metadata:
languageName: node
linkType: hard
-"safer-buffer@npm:>= 2.1.2 < 3.0.0":
+"safe-stable-stringify@npm:^2.3.1":
+ version: 2.4.3
+ resolution: "safe-stable-stringify@npm:2.4.3"
+ checksum: a6c192bbefe47770a11072b51b500ed29be7b1c15095371c1ee1dc13e45ce48ee3c80330214c56764d006c485b88bd0b24940d868948170dddc16eed312582d8
+ languageName: node
+ linkType: hard
+
+"safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0":
version: 2.1.2
resolution: "safer-buffer@npm:2.1.2"
checksum: 7eaf7a0cf37cc27b42fb3ef6a9b1df6e93a1c6d98c6c6702b02fe262d5fcbd89db63320793b99b21cb5348097d0a53de81bd5f4e8b86e20cc9412e3f1cfb4e83
@@ -7780,7 +8902,7 @@ __metadata:
dotenv: "npm:^16.3.1"
execa: "npm:^8.0.1"
get-port: "npm:^7.0.0"
- got: "npm:^14.0.0"
+ got: "npm:^13.0.0"
graphql: "npm:^16.8.1"
lodash-es: "npm:^4.17.21"
miniflare: "npm:^3.20231218.1"
@@ -7792,6 +8914,13 @@ __metadata:
languageName: unknown
linkType: soft
+"secure-json-parse@npm:^2.4.0":
+ version: 2.7.0
+ resolution: "secure-json-parse@npm:2.7.0"
+ checksum: 974386587060b6fc5b1ac06481b2f9dbbb0d63c860cc73dc7533f27835fdb67b0ef08762dbfef25625c15bc0a0c366899e00076cb0d556af06b71e22f1dede4c
+ languageName: node
+ linkType: hard
+
"selfsigned@npm:^2.0.1":
version: 2.4.1
resolution: "selfsigned@npm:2.4.1"
@@ -7811,7 +8940,7 @@ __metadata:
languageName: node
linkType: hard
-"semver@npm:^7.0.0, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.5.4":
+"semver@npm:^7.0.0, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.4":
version: 7.5.4
resolution: "semver@npm:7.5.4"
dependencies:
@@ -7822,6 +8951,76 @@ __metadata:
languageName: node
linkType: hard
+"send@npm:0.18.0":
+ version: 0.18.0
+ resolution: "send@npm:0.18.0"
+ dependencies:
+ debug: "npm:2.6.9"
+ depd: "npm:2.0.0"
+ destroy: "npm:1.2.0"
+ encodeurl: "npm:~1.0.2"
+ escape-html: "npm:~1.0.3"
+ etag: "npm:~1.8.1"
+ fresh: "npm:0.5.2"
+ http-errors: "npm:2.0.0"
+ mime: "npm:1.6.0"
+ ms: "npm:2.1.3"
+ on-finished: "npm:2.4.1"
+ range-parser: "npm:~1.2.1"
+ statuses: "npm:2.0.1"
+ checksum: ec66c0ad109680ad8141d507677cfd8b4e40b9559de23191871803ed241718e99026faa46c398dcfb9250676076573bd6bfe5d0ec347f88f4b7b8533d1d391cb
+ languageName: node
+ linkType: hard
+
+"serve-static@npm:1.15.0":
+ version: 1.15.0
+ resolution: "serve-static@npm:1.15.0"
+ dependencies:
+ encodeurl: "npm:~1.0.2"
+ escape-html: "npm:~1.0.3"
+ parseurl: "npm:~1.3.3"
+ send: "npm:0.18.0"
+ checksum: 699b2d4c29807a51d9b5e0f24955346911437aebb0178b3c4833ad30d3eca93385ff9927254f5c16da345903cad39d9cd4a532198c95a5129cc4ed43911b15a4
+ languageName: node
+ linkType: hard
+
+"server@workspace:server":
+ version: 0.0.0-use.local
+ resolution: "server@workspace:server"
+ dependencies:
+ "@google-cloud/firestore": "npm:^7.1.0"
+ "@googleapis/identitytoolkit": "npm:^8.0.0"
+ "@trpc/server": "npm:^10.45.0"
+ "@types/express": "npm:^4.17.21"
+ "@types/http-errors": "npm:^2.0.4"
+ "@types/node": "npm:^20.10.7"
+ "@types/supertest": "npm:^6.0.2"
+ "@types/ws": "npm:^8.5.10"
+ db: "workspace:*"
+ envalid: "npm:^8.0.0"
+ envars: "npm:^1.0.2"
+ express: "npm:^4.18.2"
+ get-port: "npm:^7.0.0"
+ google-auth-library: "npm:^9.4.1"
+ got: "npm:^13.0.0"
+ http-errors: "npm:^2.0.0"
+ http-proxy-middleware: "npm:^2.0.6"
+ nanoid: "npm:^5.0.4"
+ openai: "npm:^4.24.1"
+ pino: "npm:^8.17.2"
+ pino-http: "npm:^9.0.0"
+ pino-pretty: "npm:^10.3.1"
+ supertest: "npm:^6.3.3"
+ type-fest: "npm:^4.9.0"
+ typescript: "npm:~5.3.3"
+ vite: "npm:~5.0.11"
+ vite-node: "npm:~1.1.3"
+ vitest: "npm:~1.1.3"
+ ws: "npm:^8.16.0"
+ zod: "npm:^3.22.4"
+ languageName: unknown
+ linkType: soft
+
"set-cookie-parser@npm:^2.4.8":
version: 2.6.0
resolution: "set-cookie-parser@npm:2.6.0"
@@ -7852,6 +9051,13 @@ __metadata:
languageName: node
linkType: hard
+"setprototypeof@npm:1.2.0":
+ version: 1.2.0
+ resolution: "setprototypeof@npm:1.2.0"
+ checksum: fde1630422502fbbc19e6844346778f99d449986b2f9cdcceb8326730d2f3d9964dbcb03c02aaadaefffecd0f2c063315ebea8b3ad895914bf1afc1747fc172e
+ languageName: node
+ linkType: hard
+
"shebang-command@npm:^2.0.0":
version: 2.0.0
resolution: "shebang-command@npm:2.0.0"
@@ -7886,7 +9092,7 @@ __metadata:
languageName: node
linkType: hard
-"signal-exit@npm:^3.0.7":
+"signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.7":
version: 3.0.7
resolution: "signal-exit@npm:3.0.7"
checksum: a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318
@@ -7942,6 +9148,15 @@ __metadata:
languageName: node
linkType: hard
+"sonic-boom@npm:^3.0.0, sonic-boom@npm:^3.7.0":
+ version: 3.8.0
+ resolution: "sonic-boom@npm:3.8.0"
+ dependencies:
+ atomic-sleep: "npm:^1.0.0"
+ checksum: 470a82cb1af3ab99fcd3003bbecb2ce79a6b243d0f6012c59e5f567f71cbe039c8cd810752748b5820ee20d72c8da81aa298e510eec9e41a4ca05c7f419825ff
+ languageName: node
+ linkType: hard
+
"source-map-js@npm:^1.0.2":
version: 1.0.2
resolution: "source-map-js@npm:1.0.2"
@@ -8004,6 +9219,13 @@ __metadata:
languageName: node
linkType: hard
+"split2@npm:^4.0.0":
+ version: 4.2.0
+ resolution: "split2@npm:4.2.0"
+ checksum: 09bbefc11bcf03f044584c9764cd31a252d8e52cea29130950b26161287c11f519807c5e54bd9e5804c713b79c02cefe6a98f4688630993386be353e03f534ab
+ languageName: node
+ linkType: hard
+
"split@npm:0.3":
version: 0.3.3
resolution: "split@npm:0.3.3"
@@ -8046,6 +9268,13 @@ __metadata:
languageName: node
linkType: hard
+"statuses@npm:2.0.1":
+ version: 2.0.1
+ resolution: "statuses@npm:2.0.1"
+ checksum: 18c7623fdb8f646fb213ca4051be4df7efb3484d4ab662937ca6fbef7ced9b9e12842709872eb3020cc3504b93bde88935c9f6417489627a7786f24f8031cbcb
+ languageName: node
+ linkType: hard
+
"std-env@npm:^3.5.0":
version: 3.7.0
resolution: "std-env@npm:3.7.0"
@@ -8053,6 +9282,13 @@ __metadata:
languageName: node
linkType: hard
+"stdin-discarder@npm:^0.2.1":
+ version: 0.2.2
+ resolution: "stdin-discarder@npm:0.2.2"
+ checksum: 642ffd05bd5b100819d6b24a613d83c6e3857c6de74eb02fc51506fa61dc1b0034665163831873868157c4538d71e31762bcf319be86cea04c3aba5336470478
+ languageName: node
+ linkType: hard
+
"stoppable@npm:^1.1.0":
version: 1.1.0
resolution: "stoppable@npm:1.1.0"
@@ -8114,6 +9350,17 @@ __metadata:
languageName: node
linkType: hard
+"string-width@npm:^7.0.0":
+ version: 7.0.0
+ resolution: "string-width@npm:7.0.0"
+ dependencies:
+ emoji-regex: "npm:^10.3.0"
+ get-east-asian-width: "npm:^1.0.0"
+ strip-ansi: "npm:^7.1.0"
+ checksum: bc0de5700a2690895169fce447ec4ed44bc62de80312c2093d5606bfd48319bb88e48a99e97f269dff2bc9577448b91c26b3804c16e7d9b389699795e4655c3b
+ languageName: node
+ linkType: hard
+
"string.prototype.matchall@npm:^4.0.8":
version: 4.0.10
resolution: "string.prototype.matchall@npm:4.0.10"
@@ -8164,7 +9411,7 @@ __metadata:
languageName: node
linkType: hard
-"string_decoder@npm:^1.1.1":
+"string_decoder@npm:^1.1.1, string_decoder@npm:^1.3.0":
version: 1.3.0
resolution: "string_decoder@npm:1.3.0"
dependencies:
@@ -8182,7 +9429,7 @@ __metadata:
languageName: node
linkType: hard
-"strip-ansi@npm:^7.0.1":
+"strip-ansi@npm:^7.0.1, strip-ansi@npm:^7.1.0":
version: 7.1.0
resolution: "strip-ansi@npm:7.1.0"
dependencies:
@@ -8235,6 +9482,34 @@ __metadata:
languageName: node
linkType: hard
+"superagent@npm:^8.0.5":
+ version: 8.1.2
+ resolution: "superagent@npm:8.1.2"
+ dependencies:
+ component-emitter: "npm:^1.3.0"
+ cookiejar: "npm:^2.1.4"
+ debug: "npm:^4.3.4"
+ fast-safe-stringify: "npm:^2.1.1"
+ form-data: "npm:^4.0.0"
+ formidable: "npm:^2.1.2"
+ methods: "npm:^1.1.2"
+ mime: "npm:2.6.0"
+ qs: "npm:^6.11.0"
+ semver: "npm:^7.3.8"
+ checksum: 33d0072e051baf91c7d68131c70682a0650dd1bd0b8dfb6f88e5bdfcb02e18cc2b42a66e44b32fd405ac6bcf5fd57c6e267bf80e2a8ce57a18166a9d3a78f57d
+ languageName: node
+ linkType: hard
+
+"supertest@npm:^6.3.3":
+ version: 6.3.3
+ resolution: "supertest@npm:6.3.3"
+ dependencies:
+ methods: "npm:^1.1.2"
+ superagent: "npm:^8.0.5"
+ checksum: 7a7da05bf0f43bc891fd377f6ee192c6fa115f01034f522d4f53c6305ab8866c760a5b0e7aedb3e422224e35be00a75b283613c446651cc1d9e35f80d9b461b3
+ languageName: node
+ linkType: hard
+
"supports-color@npm:^5.3.0":
version: 5.5.0
resolution: "supports-color@npm:5.5.0"
@@ -8301,6 +9576,15 @@ __metadata:
languageName: node
linkType: hard
+"thread-stream@npm:^2.0.0":
+ version: 2.4.1
+ resolution: "thread-stream@npm:2.4.1"
+ dependencies:
+ real-require: "npm:^0.2.0"
+ checksum: baac5bf555912f216a2494bf3f66377733a843306cddd233b1c5ad63084307266f61af35d6122e3936c657836d5db4a14da34300cd25930e013943b807a29c9b
+ languageName: node
+ linkType: hard
+
"through@npm:2, through@npm:~2.3, through@npm:~2.3.1":
version: 2.3.8
resolution: "through@npm:2.3.8"
@@ -8345,6 +9629,13 @@ __metadata:
languageName: node
linkType: hard
+"toidentifier@npm:1.0.1":
+ version: 1.0.1
+ resolution: "toidentifier@npm:1.0.1"
+ checksum: 952c29e2a85d7123239b5cfdd889a0dde47ab0497f0913d70588f19c53f7e0b5327c95f4651e413c74b785147f9637b17410ac8c846d5d4a20a5a33eb6dc3a45
+ languageName: node
+ linkType: hard
+
"toml@npm:^3.0.0":
version: 3.0.0
resolution: "toml@npm:3.0.0"
@@ -8380,7 +9671,7 @@ __metadata:
languageName: node
linkType: hard
-"tslib@npm:^2.1.0, tslib@npm:^2.2.0":
+"tslib@npm:2.6.2, tslib@npm:^2.1.0, tslib@npm:^2.2.0":
version: 2.6.2
resolution: "tslib@npm:2.6.2"
checksum: bd26c22d36736513980091a1e356378e8b662ded04204453d353a7f34a4c21ed0afc59b5f90719d4ba756e581a162ecbf93118dc9c6be5acf70aa309188166ca
@@ -8417,13 +9708,23 @@ __metadata:
languageName: node
linkType: hard
-"type-fest@npm:^4.2.0":
+"type-fest@npm:^4.2.0, type-fest@npm:^4.9.0":
version: 4.9.0
resolution: "type-fest@npm:4.9.0"
checksum: 49acfb67999566a24d5604435c8cff786dfc26ebea5a2a343e14d437d34f30a55248f8e597b8f64446c344bb68ce14af68899f562cf66ca66c1e1a856b393259
languageName: node
linkType: hard
+"type-is@npm:~1.6.18":
+ version: 1.6.18
+ resolution: "type-is@npm:1.6.18"
+ dependencies:
+ media-typer: "npm:0.3.0"
+ mime-types: "npm:~2.1.24"
+ checksum: 0bd9eeae5efd27d98fd63519f999908c009e148039d8e7179a074f105362d4fcc214c38b24f6cda79c87e563cbd12083a4691381ed28559220d4a10c2047bed4
+ languageName: node
+ linkType: hard
+
"typed-array-buffer@npm:^1.0.0":
version: 1.0.0
resolution: "typed-array-buffer@npm:1.0.0"
@@ -8569,6 +9870,13 @@ __metadata:
languageName: node
linkType: hard
+"unpipe@npm:1.0.0, unpipe@npm:~1.0.0":
+ version: 1.0.0
+ resolution: "unpipe@npm:1.0.0"
+ checksum: 4fa18d8d8d977c55cb09715385c203197105e10a6d220087ec819f50cb68870f02942244f1017565484237f1f8c5d3cd413631b1ae104d3096f24fdfde1b4aa2
+ languageName: node
+ linkType: hard
+
"update-browserslist-db@npm:^1.0.13":
version: 1.0.13
resolution: "update-browserslist-db@npm:1.0.13"
@@ -8592,6 +9900,13 @@ __metadata:
languageName: node
linkType: hard
+"url-template@npm:^2.0.8":
+ version: 2.0.8
+ resolution: "url-template@npm:2.0.8"
+ checksum: fc6a4cf6c3c3c3d7f0a0bb4405c41b81934e583b454e52ace7b2e5d7ed32ec9c2970ff1826d240c5823955fcb13531a1fc4ff6ba4569b1886a2976665353e952
+ languageName: node
+ linkType: hard
+
"urlpattern-polyfill@npm:^4.0.3":
version: 4.0.3
resolution: "urlpattern-polyfill@npm:4.0.3"
@@ -8606,6 +9921,13 @@ __metadata:
languageName: node
linkType: hard
+"utils-merge@npm:1.0.1":
+ version: 1.0.1
+ resolution: "utils-merge@npm:1.0.1"
+ checksum: 5d6949693d58cb2e636a84f3ee1c6e7b2f9c16cb1d42d0ecb386d8c025c69e327205aa1c69e2868cc06a01e5e20681fbba55a4e0ed0cce913d60334024eae798
+ languageName: node
+ linkType: hard
+
"uuid@npm:^9.0.0":
version: 9.0.1
resolution: "uuid@npm:9.0.1"
@@ -8634,7 +9956,14 @@ __metadata:
languageName: node
linkType: hard
-"vite-node@npm:1.1.3":
+"vary@npm:~1.1.2":
+ version: 1.1.2
+ resolution: "vary@npm:1.1.2"
+ checksum: 31389debef15a480849b8331b220782230b9815a8e0dbb7b9a8369559aed2e9a7800cd904d4371ea74f4c3527db456dc8e7ac5befce5f0d289014dbdf47b2242
+ languageName: node
+ linkType: hard
+
+"vite-node@npm:1.1.3, vite-node@npm:~1.1.3":
version: 1.1.3
resolution: "vite-node@npm:1.1.3"
dependencies:
@@ -8765,7 +10094,14 @@ __metadata:
languageName: node
linkType: hard
-"web-streams-polyfill@npm:^3.0.3":
+"web-streams-polyfill@npm:4.0.0-beta.3":
+ version: 4.0.0-beta.3
+ resolution: "web-streams-polyfill@npm:4.0.0-beta.3"
+ checksum: dcdef67de57d83008f9dc330662b65ba4497315555dd0e4e7bcacb132ffdf8a830eaab8f74ad40a4a44f542461f51223f406e2a446ece1cc29927859b1405853
+ languageName: node
+ linkType: hard
+
+"web-streams-polyfill@npm:^3.0.3, web-streams-polyfill@npm:^3.2.1":
version: 3.3.2
resolution: "web-streams-polyfill@npm:3.3.2"
checksum: 0466050f40c3487a96dedb07c60581b07c334daedd1955a7380b9405b77934a5bf9e178411133abca5365f3533543e1876fa5a5b7082382b866d1e5d07385466
@@ -9026,7 +10362,7 @@ __metadata:
languageName: node
linkType: hard
-"ws@npm:^8.11.0, ws@npm:^8.2.2":
+"ws@npm:^8.11.0, ws@npm:^8.16.0, ws@npm:^8.2.2":
version: 8.16.0
resolution: "ws@npm:8.16.0"
peerDependencies: