Compare commits

...

5 Commits

Author SHA1 Message Date
Matti Nannt
b9b052c102 fix: use correct bcrypt import for runtime 2025-12-22 13:44:28 +01:00
Matti Nannt
9dd604524f feat: implement robust database seeding strategy 2025-12-22 12:46:09 +01:00
Matti Nannt
5cc2a61089 fix: remove internal migration tables from seed clear list 2025-12-22 12:00:56 +01:00
Matti Nannt
520dc1f7b6 feat: improve seeding output with credentials summary 2025-12-22 11:57:57 +01:00
Matti Nannt
6ca21bca5e feat: implement database seeding strategy 2025-12-19 18:00:11 +01:00
7 changed files with 967 additions and 4 deletions

View File

@@ -18,6 +18,8 @@
"db:migrate:deploy": "turbo run db:migrate:deploy",
"db:start": "turbo run db:start",
"db:push": "turbo run db:push",
"db:seed": "turbo run db:seed",
"db:seed:clear": "turbo run db:seed -- -- --clear",
"db:up": "docker compose -f docker-compose.dev.yml up -d",
"db:down": "docker compose -f docker-compose.dev.yml down",
"go": "pnpm db:up && turbo run go --concurrency 20",

View File

@@ -82,6 +82,12 @@ Run these commands from the root directory of the Formbricks monorepo:
- Generates new `migration.sql` in the custom directory
- Copies migration to Prisma's internal directory
- Applies all pending migrations to the database
- **`pnpm db:seed`**: Seed the database with sample data
- Upserts base infrastructure (Organization, Project, Environments)
- Creates multi-role users (Admin, Manager)
- Generates complex surveys and sample responses
- **`pnpm db:seed:clear`**: Clear all seeded data and re-seed
- **WARNING**: This will delete existing data in the database.
### Package Level Commands
@@ -92,6 +98,8 @@ Run these commands from the `packages/database` directory:
- Creates new subdirectory with appropriate timestamp
- Generates `migration.ts` file with pre-configured ID and name
- **Note**: Only use Prisma raw queries in data migrations for better performance and to avoid type errors
- **`pnpm db:seed`**: Run the seeding script
- **`pnpm db:seed:clear`**: Clear data and run the seeding script
### Available Scripts
@@ -102,13 +110,41 @@ Run these commands from the `packages/database` directory:
"db:migrate:deploy": "Apply migrations in production",
"db:migrate:dev": "Apply migrations in development",
"db:push": "prisma db push --accept-data-loss",
"db:setup": "pnpm db:migrate:dev && pnpm db:create-saml-database:dev",
"db:seed": "Seed the database with sample data",
"db:seed:clear": "Clear all data and re-seed",
"db:setup": "pnpm db:migrate:dev && pnpm db:create-saml-database:dev && pnpm db:seed",
"dev": "vite build --watch",
"generate": "prisma generate",
"generate-data-migration": "Create new data migration"
}
```
## Database Seeding
The seeding system provides a quick way to set up a functional environment for development, QA, and testing.
### Safety Guard
To prevent accidental data loss in production, seeding is blocked if `NODE_ENV=production`. If you explicitly need to seed a production-like environment (e.g., staging), you must set:
```bash
ALLOW_SEED=true
```
### Seeding Logic
The `pnpm db:seed` script:
1. **Infrastructure**: Upserts a default organization, project, and environments.
2. **Users**: Creates default users with the following credentials (passwords are hashed):
- **Admin**: `admin@formbricks.com` / `password123`
- **Manager**: `manager@formbricks.com` / `password123`
3. **Surveys**: Creates complex sample surveys (Kitchen Sink, CSAT, Draft, etc.) in the **Production** environment.
4. **Responses**: Generates ~50 realistic responses and displays for each survey.
### Idempotency
By default, the seed script uses `upsert` to ensure it can be run multiple times without creating duplicate infrastructure. To perform a clean reset, use `pnpm db:seed:clear`.
## Migration Workflow
### Adding a Schema Migration

View File

@@ -22,6 +22,9 @@
},
"./zod/*": {
"import": "./zod/*.ts"
},
"./seed/constants": {
"import": "./src/seed/constants.ts"
}
},
"scripts": {
@@ -33,7 +36,9 @@
"db:create-saml-database:deploy": "env SAML_DATABASE_URL=\"${SAML_DATABASE_URL}\" node ./dist/scripts/create-saml-database.js",
"db:create-saml-database:dev": "dotenv -e ../../.env -- node ./dist/scripts/create-saml-database.js",
"db:push": "prisma db push --accept-data-loss",
"db:setup": "pnpm db:migrate:dev && pnpm db:create-saml-database:dev",
"db:seed": "dotenv -e ../../.env -- tsx src/seed.ts",
"db:seed:clear": "dotenv -e ../../.env -- tsx src/seed.ts --clear",
"db:setup": "pnpm db:migrate:dev && pnpm db:create-saml-database:dev && pnpm db:seed",
"db:start": "pnpm db:setup",
"format": "prisma format",
"generate": "prisma generate",
@@ -45,17 +50,20 @@
"@formbricks/logger": "workspace:*",
"@paralleldrive/cuid2": "2.2.2",
"@prisma/client": "6.14.0",
"bcryptjs": "2.4.3",
"zod": "3.24.4",
"zod-openapi": "4.2.4"
},
"devDependencies": {
"@formbricks/config-typescript": "workspace:*",
"@formbricks/eslint-config": "workspace:*",
"@types/bcryptjs": "2.4.6",
"dotenv-cli": "8.0.0",
"glob": "11.1.0",
"prisma": "6.14.0",
"prisma-json-types-generator": "3.5.4",
"ts-node": "10.9.2",
"tsx": "4.19.2",
"vite": "6.4.1",
"vite-plugin-dts": "4.5.3"
}

View File

@@ -0,0 +1,587 @@
import { type Prisma, PrismaClient } from "@prisma/client";
import bcrypt from "bcryptjs";
import { SEED_CREDENTIALS, SEED_IDS } from "./seed/constants";
const prisma = new PrismaClient();
const isProduction = process.env.NODE_ENV === "production";
const allowSeed = process.env.ALLOW_SEED === "true";
if (isProduction && !allowSeed) {
console.error("ERROR: Seeding blocked in production. Set ALLOW_SEED=true to override.");
process.exit(1);
}
const clearData = process.argv.includes("--clear");
// Define local types to avoid resolution issues in seed script
type SurveyElementType =
| "openText"
| "multipleChoiceSingle"
| "multipleChoiceMulti"
| "nps"
| "cta"
| "rating"
| "consent"
| "date"
| "matrix"
| "address"
| "ranking"
| "contactInfo";
interface SurveyQuestion {
id: string;
type: SurveyElementType;
headline: { default: string; [key: string]: string };
subheader?: { default: string; [key: string]: string };
required?: boolean;
placeholder?: { default: string; [key: string]: string };
longAnswer?: boolean;
choices?: { id: string; label: { default: string }; imageUrl?: string }[];
lowerLabel?: { default: string };
upperLabel?: { default: string };
buttonLabel?: { default: string };
buttonUrl?: string;
buttonExternal?: boolean;
dismissButtonLabel?: { default: string };
scale?: string;
range?: number;
label?: { default: string };
allowMulti?: boolean;
format?: string;
rows?: { id: string; label: { default: string } }[];
columns?: { id: string; label: { default: string } }[];
addressLine1?: { show: boolean; required: boolean; placeholder: { default: string } };
addressLine2?: { show: boolean; required: boolean; placeholder: { default: string } };
city?: { show: boolean; required: boolean; placeholder: { default: string } };
state?: { show: boolean; required: boolean; placeholder: { default: string } };
zip?: { show: boolean; required: boolean; placeholder: { default: string } };
country?: { show: boolean; required: boolean; placeholder: { default: string } };
firstName?: { show: boolean; required: boolean; placeholder: { default: string } };
lastName?: { show: boolean; required: boolean; placeholder: { default: string } };
email?: { show: boolean; required: boolean; placeholder: { default: string } };
phone?: { show: boolean; required: boolean; placeholder: { default: string } };
company?: { show: boolean; required: boolean; placeholder: { default: string } };
allowMultipleFiles?: boolean;
maxSizeInMB?: number;
}
async function deleteData(): Promise<void> {
console.log("Clearing existing data...");
const deleteOrder: Prisma.ModelName[] = [
"ResponseQuotaLink",
"SurveyQuota",
"TagsOnResponses",
"Tag",
"SurveyFollowUp",
"Response",
"Display",
"SurveyTrigger",
"SurveyAttributeFilter",
"SurveyLanguage",
"Survey",
"ActionClass",
"ContactAttribute",
"ContactAttributeKey",
"Contact",
"ApiKeyEnvironment",
"ApiKey",
"Segment",
"Webhook",
"Integration",
"ProjectTeam",
"TeamUser",
"Team",
"Project",
"Invite",
"Membership",
"Account",
"User",
"Organization",
];
for (const model of deleteOrder) {
try {
// @ts-expect-error - dynamic model access
const modelClient = prisma[model.charAt(0).toLowerCase() + model.slice(1)] as {
deleteMany: () => Promise<unknown>;
};
await modelClient.deleteMany();
} catch (e: unknown) {
const errorMessage = e instanceof Error ? e.message : String(e);
console.warn(`Could not delete data from ${String(model)}: ${errorMessage}`);
}
}
console.log("Data cleared.");
}
const KITCHEN_SINK_QUESTIONS: SurveyQuestion[] = [
{
id: "q_open_text",
type: "openText",
headline: { default: "What do you think of Formbricks?" },
subheader: { default: "Please be honest!" },
required: true,
placeholder: { default: "Your feedback here..." },
longAnswer: true,
},
{
id: "q_multiple_choice_single",
type: "multipleChoiceSingle",
headline: { default: "How often do you use Formbricks?" },
required: true,
choices: [
{ id: "choice_1", label: { default: "Daily" } },
{ id: "choice_2", label: { default: "Weekly" } },
{ id: "choice_3", label: { default: "Monthly" } },
{ id: "choice_4", label: { default: "Rarely" } },
],
},
{
id: "q_multiple_choice_multi",
type: "multipleChoiceMulti",
headline: { default: "Which features do you use?" },
required: false,
choices: [
{ id: "choice_1", label: { default: "Surveys" } },
{ id: "choice_2", label: { default: "Analytics" } },
{ id: "choice_3", label: { default: "Integrations" } },
{ id: "choice_4", label: { default: "Action Tracking" } },
],
},
{
id: "q_nps",
type: "nps",
headline: { default: "How likely are you to recommend Formbricks?" },
required: true,
lowerLabel: { default: "Not likely" },
upperLabel: { default: "Very likely" },
},
{
id: "q_cta",
type: "cta",
headline: { default: "Check out our documentation!" },
required: true,
buttonLabel: { default: "Go to Docs" },
buttonUrl: "https://formbricks.com/docs",
buttonExternal: true,
dismissButtonLabel: { default: "Skip" },
},
{
id: "q_rating",
type: "rating",
headline: { default: "Rate your overall experience" },
required: true,
scale: "star",
range: 5,
lowerLabel: { default: "Poor" },
upperLabel: { default: "Excellent" },
},
{
id: "q_consent",
type: "consent",
headline: { default: "Do you agree to our terms?" },
required: true,
label: { default: "I agree to the terms and conditions" },
},
{
id: "q_date",
type: "date",
headline: { default: "When did you start using Formbricks?" },
required: true,
format: "M-d-y",
},
{
id: "q_matrix",
type: "matrix",
headline: { default: "How do you feel about these aspects?" },
required: true,
rows: [
{ id: "row_1", label: { default: "UI Design" } },
{ id: "row_2", label: { default: "Performance" } },
{ id: "row_3", label: { default: "Documentation" } },
],
columns: [
{ id: "col_1", label: { default: "Disappointed" } },
{ id: "col_2", label: { default: "Neutral" } },
{ id: "col_3", label: { default: "Satisfied" } },
],
},
{
id: "q_address",
type: "address",
headline: { default: "Where are you located?" },
required: true,
addressLine1: { show: true, required: true, placeholder: { default: "Address Line 1" } },
addressLine2: { show: true, required: false, placeholder: { default: "Address Line 2" } },
city: { show: true, required: true, placeholder: { default: "City" } },
state: { show: true, required: true, placeholder: { default: "State" } },
zip: { show: true, required: true, placeholder: { default: "Zip" } },
country: { show: true, required: true, placeholder: { default: "Country" } },
},
{
id: "q_ranking",
type: "ranking",
headline: { default: "Rank these features" },
required: true,
choices: [
{ id: "rank_1", label: { default: "Feature A" } },
{ id: "rank_2", label: { default: "Feature B" } },
{ id: "rank_3", label: { default: "Feature C" } },
],
},
{
id: "q_contact_info",
type: "contactInfo",
headline: { default: "How can we reach you?" },
required: true,
firstName: { show: true, required: true, placeholder: { default: "First Name" } },
lastName: { show: true, required: true, placeholder: { default: "Last Name" } },
email: { show: true, required: true, placeholder: { default: "Email" } },
phone: { show: true, required: false, placeholder: { default: "Phone" } },
company: { show: true, required: false, placeholder: { default: "Company" } },
},
];
async function generateResponses(surveyId: string, count: number): Promise<void> {
console.log(`Generating ${String(count)} responses for survey ${surveyId}...`);
const survey = await prisma.survey.findUnique({
where: { id: surveyId },
});
if (!survey) return;
const questions = survey.questions as unknown as SurveyQuestion[];
for (let i = 0; i < count; i++) {
const data: Record<string, string | number | string[] | Record<string, string>> = {};
for (const q of questions) {
switch (q.type) {
case "openText":
data[q.id] = `Sample response ${String(i)}`;
break;
case "multipleChoiceSingle":
if (q.choices) {
data[q.id] = q.choices[Math.floor(Math.random() * q.choices.length)].label.default;
}
break;
case "multipleChoiceMulti":
if (q.choices) {
data[q.id] = [q.choices[0].label.default, q.choices[1].label.default];
}
break;
case "nps":
data[q.id] = Math.floor(Math.random() * 11);
break;
case "rating":
if (q.range) {
data[q.id] = Math.floor(Math.random() * q.range) + 1;
}
break;
case "cta":
data[q.id] = "clicked";
break;
case "consent":
data[q.id] = "accepted";
break;
case "date":
data[q.id] = new Date().toISOString().split("T")[0];
break;
case "matrix": {
const matrixData: Record<string, string> = {};
if (q.rows) {
for (const row of q.rows) {
if (q.columns) {
matrixData[row.label.default] =
q.columns[Math.floor(Math.random() * q.columns.length)].label.default;
}
}
}
data[q.id] = matrixData;
break;
}
case "ranking":
if (q.choices) {
data[q.id] = q.choices.map((c) => c.label.default).sort(() => Math.random() - 0.5);
}
break;
case "address":
data[q.id] = {
addressLine1: "Main St 1",
city: "Berlin",
state: "Berlin",
zip: "10115",
country: "Germany",
};
break;
case "contactInfo":
data[q.id] = {
firstName: "John",
lastName: "Doe",
email: `john.doe.${String(i)}@example.com`,
};
break;
default:
data[q.id] = "Sample data";
}
}
await prisma.$transaction(async (tx) => {
const display = await tx.display.create({
data: {
surveyId,
},
});
await tx.response.create({
data: {
surveyId,
finished: true,
data: data as unknown as Prisma.InputJsonValue,
displayId: display.id,
},
});
});
}
// Generate some displays without responses (e.g., 30% more)
const extraDisplays = Math.floor(count * 0.3);
console.log(`Generating ${String(extraDisplays)} extra displays for survey ${surveyId}...`);
for (let i = 0; i < extraDisplays; i++) {
await prisma.display.create({
data: {
surveyId,
},
});
}
}
async function main(): Promise<void> {
if (clearData) {
await deleteData();
}
console.log("Seeding base infrastructure...");
// Organization
const organization = await prisma.organization.upsert({
where: { id: SEED_IDS.ORGANIZATION },
update: {},
create: {
id: SEED_IDS.ORGANIZATION,
name: "Seed Organization",
billing: {
plan: "free",
limits: { projects: 3, monthly: { responses: 1500, miu: 2000 } },
stripeCustomerId: null,
periodStart: new Date(),
period: "monthly",
},
},
});
// Users
const passwordHash = await bcrypt.hash(SEED_CREDENTIALS.ADMIN.password, 10);
await prisma.user.upsert({
where: { id: SEED_IDS.USER_ADMIN },
update: {},
create: {
id: SEED_IDS.USER_ADMIN,
name: "Admin User",
email: SEED_CREDENTIALS.ADMIN.email,
password: passwordHash,
emailVerified: new Date(),
memberships: {
create: {
organizationId: organization.id,
role: "owner",
accepted: true,
},
},
},
});
await prisma.user.upsert({
where: { id: SEED_IDS.USER_MANAGER },
update: {},
create: {
id: SEED_IDS.USER_MANAGER,
name: "Manager User",
email: SEED_CREDENTIALS.MANAGER.email,
password: passwordHash,
emailVerified: new Date(),
memberships: {
create: {
organizationId: organization.id,
role: "manager",
accepted: true,
},
},
},
});
// Project
const project = await prisma.project.upsert({
where: { id: SEED_IDS.PROJECT },
update: {},
create: {
id: SEED_IDS.PROJECT,
name: "Seed Project",
organizationId: organization.id,
},
});
// Environments
await prisma.environment.upsert({
where: { id: SEED_IDS.ENV_DEV },
update: { appSetupCompleted: false },
create: {
id: SEED_IDS.ENV_DEV,
type: "development",
projectId: project.id,
appSetupCompleted: false,
attributeKeys: {
create: [
{ name: "Email", key: "email", isUnique: true, type: "default" },
{ name: "First Name", key: "firstName", isUnique: false, type: "default" },
{ name: "Last Name", key: "lastName", isUnique: false, type: "default" },
{ name: "userId", key: "userId", isUnique: true, type: "default" },
],
},
},
});
const prodEnv = await prisma.environment.upsert({
where: { id: SEED_IDS.ENV_PROD },
update: { appSetupCompleted: false },
create: {
id: SEED_IDS.ENV_PROD,
type: "production",
projectId: project.id,
appSetupCompleted: false,
attributeKeys: {
create: [
{ name: "Email", key: "email", isUnique: true, type: "default" },
{ name: "First Name", key: "firstName", isUnique: false, type: "default" },
{ name: "Last Name", key: "lastName", isUnique: false, type: "default" },
{ name: "userId", key: "userId", isUnique: true, type: "default" },
],
},
},
});
console.log("Seeding surveys...");
const createSurveyWithBlocks = async (
id: string,
name: string,
environmentId: string,
status: "inProgress" | "draft" | "completed",
questions: SurveyQuestion[]
): Promise<void> => {
const blocks = [
{
id: `block_${id}`,
name: "Main Block",
elements: questions,
},
];
await prisma.survey.upsert({
where: { id },
update: {
environmentId,
type: "link",
questions: questions as unknown as Prisma.InputJsonValue,
blocks: blocks as unknown as Prisma.InputJsonValue[],
},
create: {
id,
name,
environmentId,
status,
type: "link",
questions: questions as unknown as Prisma.InputJsonValue,
blocks: blocks as unknown as Prisma.InputJsonValue[],
},
});
};
// Kitchen Sink Survey
await createSurveyWithBlocks(
SEED_IDS.SURVEY_KITCHEN_SINK,
"Kitchen Sink Survey",
prodEnv.id,
"inProgress",
KITCHEN_SINK_QUESTIONS
);
// CSAT Survey
await createSurveyWithBlocks(SEED_IDS.SURVEY_CSAT, "CSAT Survey", prodEnv.id, "inProgress", [
{
id: "csat_rating",
type: "rating",
headline: { default: "How satisfied are you with our product?" },
required: true,
scale: "smiley",
range: 5,
},
]);
// Draft Survey
await createSurveyWithBlocks(SEED_IDS.SURVEY_DRAFT, "Draft Survey", prodEnv.id, "draft", [
{
id: "draft_q1",
type: "openText",
headline: { default: "Coming soon..." },
required: false,
},
]);
// Completed Survey
await createSurveyWithBlocks(SEED_IDS.SURVEY_COMPLETED, "Exit Survey", prodEnv.id, "completed", [
{
id: "exit_q1",
type: "multipleChoiceSingle",
headline: { default: "Why are you leaving?" },
required: true,
choices: [
{ id: "c1", label: { default: "Too expensive" } },
{ id: "c2", label: { default: "Found a better alternative" } },
{ id: "c3", label: { default: "Missing features" } },
],
},
]);
console.log("Generating responses...");
await generateResponses(SEED_IDS.SURVEY_KITCHEN_SINK, 50);
await generateResponses(SEED_IDS.SURVEY_CSAT, 50);
await generateResponses(SEED_IDS.SURVEY_COMPLETED, 50);
console.log(`\n${"=".repeat(50)}`);
console.log("🚀 SEEDING COMPLETED SUCCESSFULLY");
console.log("=".repeat(50));
console.log("\nLog in with the following credentials:");
console.log(`\n Admin (Owner):`);
console.log(` Email: ${SEED_CREDENTIALS.ADMIN.email}`);
console.log(` Password: ${SEED_CREDENTIALS.ADMIN.password}`);
console.log(`\n Manager:`);
console.log(` Email: ${SEED_CREDENTIALS.MANAGER.email}`);
console.log(` Password: ${SEED_CREDENTIALS.MANAGER.password}`);
console.log(`\n Member:`);
console.log(` Email: ${SEED_CREDENTIALS.MEMBER.email}`);
console.log(` Password: ${SEED_CREDENTIALS.MEMBER.password}`);
console.log(`\n${"=".repeat(50)}\n`);
}
main()
.catch((e: unknown) => {
console.error(e);
process.exit(1);
})
.finally(() => {
prisma.$disconnect().catch((e: unknown) => {
console.error("Error disconnecting prisma:", e);
});
});

View File

@@ -0,0 +1,19 @@
export const SEED_IDS = {
USER_ADMIN: "clseedadmin000000000000",
USER_MANAGER: "clseedmanager0000000000",
USER_MEMBER: "clseedmember00000000000",
ORGANIZATION: "clseedorg0000000000000",
PROJECT: "clseedproject000000000",
ENV_DEV: "clseedenvdev0000000000",
ENV_PROD: "clseedenvprod000000000",
SURVEY_KITCHEN_SINK: "clseedsurveykitchen00",
SURVEY_CSAT: "clseedsurveycsat000000",
SURVEY_DRAFT: "clseedsurveydraft00000",
SURVEY_COMPLETED: "clseedsurveycomplete00",
} as const;
export const SEED_CREDENTIALS = {
ADMIN: { email: "admin@formbricks.com", password: "password123" },
MANAGER: { email: "manager@formbricks.com", password: "password123" },
MEMBER: { email: "member@formbricks.com", password: "password123" },
} as const;

314
pnpm-lock.yaml generated
View File

@@ -656,6 +656,9 @@ importers:
'@prisma/client':
specifier: 6.14.0
version: 6.14.0(prisma@6.14.0(magicast@0.3.5)(typescript@5.8.3))(typescript@5.8.3)
bcryptjs:
specifier: 2.4.3
version: 2.4.3
zod:
specifier: 3.24.4
version: 3.24.4
@@ -669,6 +672,9 @@ importers:
'@formbricks/eslint-config':
specifier: workspace:*
version: link:../config-eslint
'@types/bcryptjs':
specifier: 2.4.6
version: 2.4.6
dotenv-cli:
specifier: 8.0.0
version: 8.0.0
@@ -684,12 +690,15 @@ importers:
ts-node:
specifier: 10.9.2
version: 10.9.2(@types/node@22.15.18)(typescript@5.8.3)
tsx:
specifier: 4.19.2
version: 4.19.2
vite:
specifier: 6.4.1
version: 6.4.1(@types/node@22.15.18)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.19.4)(yaml@2.8.1)
version: 6.4.1(@types/node@22.15.18)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.19.2)(yaml@2.8.1)
vite-plugin-dts:
specifier: 4.5.3
version: 4.5.3(@types/node@22.15.18)(rollup@4.52.5)(typescript@5.8.3)(vite@6.4.1(@types/node@22.15.18)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.19.4)(yaml@2.8.1))
version: 4.5.3(@types/node@22.15.18)(rollup@4.52.5)(typescript@5.8.3)(vite@6.4.1(@types/node@22.15.18)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.19.2)(yaml@2.8.1))
packages/i18n-utils:
dependencies:
@@ -1726,6 +1735,12 @@ packages:
'@epic-web/invariant@1.0.0':
resolution: {integrity: sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==}
'@esbuild/aix-ppc64@0.23.1':
resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [aix]
'@esbuild/aix-ppc64@0.25.10':
resolution: {integrity: sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==}
engines: {node: '>=18'}
@@ -1738,6 +1753,12 @@ packages:
cpu: [ppc64]
os: [aix]
'@esbuild/android-arm64@0.23.1':
resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [android]
'@esbuild/android-arm64@0.25.10':
resolution: {integrity: sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==}
engines: {node: '>=18'}
@@ -1750,6 +1771,12 @@ packages:
cpu: [arm64]
os: [android]
'@esbuild/android-arm@0.23.1':
resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==}
engines: {node: '>=18'}
cpu: [arm]
os: [android]
'@esbuild/android-arm@0.25.10':
resolution: {integrity: sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==}
engines: {node: '>=18'}
@@ -1762,6 +1789,12 @@ packages:
cpu: [arm]
os: [android]
'@esbuild/android-x64@0.23.1':
resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==}
engines: {node: '>=18'}
cpu: [x64]
os: [android]
'@esbuild/android-x64@0.25.10':
resolution: {integrity: sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==}
engines: {node: '>=18'}
@@ -1774,6 +1807,12 @@ packages:
cpu: [x64]
os: [android]
'@esbuild/darwin-arm64@0.23.1':
resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==}
engines: {node: '>=18'}
cpu: [arm64]
os: [darwin]
'@esbuild/darwin-arm64@0.25.10':
resolution: {integrity: sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==}
engines: {node: '>=18'}
@@ -1786,6 +1825,12 @@ packages:
cpu: [arm64]
os: [darwin]
'@esbuild/darwin-x64@0.23.1':
resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==}
engines: {node: '>=18'}
cpu: [x64]
os: [darwin]
'@esbuild/darwin-x64@0.25.10':
resolution: {integrity: sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==}
engines: {node: '>=18'}
@@ -1798,6 +1843,12 @@ packages:
cpu: [x64]
os: [darwin]
'@esbuild/freebsd-arm64@0.23.1':
resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==}
engines: {node: '>=18'}
cpu: [arm64]
os: [freebsd]
'@esbuild/freebsd-arm64@0.25.10':
resolution: {integrity: sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==}
engines: {node: '>=18'}
@@ -1810,6 +1861,12 @@ packages:
cpu: [arm64]
os: [freebsd]
'@esbuild/freebsd-x64@0.23.1':
resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==}
engines: {node: '>=18'}
cpu: [x64]
os: [freebsd]
'@esbuild/freebsd-x64@0.25.10':
resolution: {integrity: sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==}
engines: {node: '>=18'}
@@ -1822,6 +1879,12 @@ packages:
cpu: [x64]
os: [freebsd]
'@esbuild/linux-arm64@0.23.1':
resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==}
engines: {node: '>=18'}
cpu: [arm64]
os: [linux]
'@esbuild/linux-arm64@0.25.10':
resolution: {integrity: sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==}
engines: {node: '>=18'}
@@ -1834,6 +1897,12 @@ packages:
cpu: [arm64]
os: [linux]
'@esbuild/linux-arm@0.23.1':
resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==}
engines: {node: '>=18'}
cpu: [arm]
os: [linux]
'@esbuild/linux-arm@0.25.10':
resolution: {integrity: sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==}
engines: {node: '>=18'}
@@ -1846,6 +1915,12 @@ packages:
cpu: [arm]
os: [linux]
'@esbuild/linux-ia32@0.23.1':
resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==}
engines: {node: '>=18'}
cpu: [ia32]
os: [linux]
'@esbuild/linux-ia32@0.25.10':
resolution: {integrity: sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==}
engines: {node: '>=18'}
@@ -1858,6 +1933,12 @@ packages:
cpu: [ia32]
os: [linux]
'@esbuild/linux-loong64@0.23.1':
resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==}
engines: {node: '>=18'}
cpu: [loong64]
os: [linux]
'@esbuild/linux-loong64@0.25.10':
resolution: {integrity: sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==}
engines: {node: '>=18'}
@@ -1870,6 +1951,12 @@ packages:
cpu: [loong64]
os: [linux]
'@esbuild/linux-mips64el@0.23.1':
resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==}
engines: {node: '>=18'}
cpu: [mips64el]
os: [linux]
'@esbuild/linux-mips64el@0.25.10':
resolution: {integrity: sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==}
engines: {node: '>=18'}
@@ -1882,6 +1969,12 @@ packages:
cpu: [mips64el]
os: [linux]
'@esbuild/linux-ppc64@0.23.1':
resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [linux]
'@esbuild/linux-ppc64@0.25.10':
resolution: {integrity: sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==}
engines: {node: '>=18'}
@@ -1894,6 +1987,12 @@ packages:
cpu: [ppc64]
os: [linux]
'@esbuild/linux-riscv64@0.23.1':
resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==}
engines: {node: '>=18'}
cpu: [riscv64]
os: [linux]
'@esbuild/linux-riscv64@0.25.10':
resolution: {integrity: sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==}
engines: {node: '>=18'}
@@ -1906,6 +2005,12 @@ packages:
cpu: [riscv64]
os: [linux]
'@esbuild/linux-s390x@0.23.1':
resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==}
engines: {node: '>=18'}
cpu: [s390x]
os: [linux]
'@esbuild/linux-s390x@0.25.10':
resolution: {integrity: sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==}
engines: {node: '>=18'}
@@ -1918,6 +2023,12 @@ packages:
cpu: [s390x]
os: [linux]
'@esbuild/linux-x64@0.23.1':
resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [linux]
'@esbuild/linux-x64@0.25.10':
resolution: {integrity: sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==}
engines: {node: '>=18'}
@@ -1942,6 +2053,12 @@ packages:
cpu: [arm64]
os: [netbsd]
'@esbuild/netbsd-x64@0.23.1':
resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==}
engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
'@esbuild/netbsd-x64@0.25.10':
resolution: {integrity: sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==}
engines: {node: '>=18'}
@@ -1954,6 +2071,12 @@ packages:
cpu: [x64]
os: [netbsd]
'@esbuild/openbsd-arm64@0.23.1':
resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
'@esbuild/openbsd-arm64@0.25.10':
resolution: {integrity: sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==}
engines: {node: '>=18'}
@@ -1966,6 +2089,12 @@ packages:
cpu: [arm64]
os: [openbsd]
'@esbuild/openbsd-x64@0.23.1':
resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==}
engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
'@esbuild/openbsd-x64@0.25.10':
resolution: {integrity: sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==}
engines: {node: '>=18'}
@@ -1990,6 +2119,12 @@ packages:
cpu: [arm64]
os: [openharmony]
'@esbuild/sunos-x64@0.23.1':
resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==}
engines: {node: '>=18'}
cpu: [x64]
os: [sunos]
'@esbuild/sunos-x64@0.25.10':
resolution: {integrity: sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==}
engines: {node: '>=18'}
@@ -2002,6 +2137,12 @@ packages:
cpu: [x64]
os: [sunos]
'@esbuild/win32-arm64@0.23.1':
resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==}
engines: {node: '>=18'}
cpu: [arm64]
os: [win32]
'@esbuild/win32-arm64@0.25.10':
resolution: {integrity: sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==}
engines: {node: '>=18'}
@@ -2014,6 +2155,12 @@ packages:
cpu: [arm64]
os: [win32]
'@esbuild/win32-ia32@0.23.1':
resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==}
engines: {node: '>=18'}
cpu: [ia32]
os: [win32]
'@esbuild/win32-ia32@0.25.10':
resolution: {integrity: sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==}
engines: {node: '>=18'}
@@ -2026,6 +2173,12 @@ packages:
cpu: [ia32]
os: [win32]
'@esbuild/win32-x64@0.23.1':
resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==}
engines: {node: '>=18'}
cpu: [x64]
os: [win32]
'@esbuild/win32-x64@0.25.10':
resolution: {integrity: sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==}
engines: {node: '>=18'}
@@ -5744,6 +5897,9 @@ packages:
resolution: {integrity: sha512-JU0h5APyQNsHOlAM7HnQnPToSDQoEBZqzu/YBlqDnEeymPnZDREeXJA3KBMQee+dKteAxZ2AtvQEvVYdZf241Q==}
hasBin: true
bcryptjs@2.4.3:
resolution: {integrity: sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==}
bcryptjs@3.0.2:
resolution: {integrity: sha512-k38b3XOZKv60C4E2hVsXTolJWfkGRMbILBIe2IBITXciy5bOsTKot5kDrf3ZfufQtQOUN5mXceUEpU1rTl9Uog==}
hasBin: true
@@ -6472,6 +6628,11 @@ packages:
resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
engines: {node: '>= 0.4'}
esbuild@0.23.1:
resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==}
engines: {node: '>=18'}
hasBin: true
esbuild@0.25.10:
resolution: {integrity: sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==}
engines: {node: '>=18'}
@@ -9880,6 +10041,11 @@ packages:
peerDependencies:
typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta'
tsx@4.19.2:
resolution: {integrity: sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==}
engines: {node: '>=18.0.0'}
hasBin: true
tsx@4.19.4:
resolution: {integrity: sha512-gK5GVzDkJK1SI1zwHf32Mqxf2tSJkNx+eYcNly5+nHvWqXUJYUkWBQtKauoESz3ymezAI++ZwT855x5p5eop+Q==}
engines: {node: '>=18.0.0'}
@@ -12288,102 +12454,153 @@ snapshots:
'@epic-web/invariant@1.0.0': {}
'@esbuild/aix-ppc64@0.23.1':
optional: true
'@esbuild/aix-ppc64@0.25.10':
optional: true
'@esbuild/aix-ppc64@0.27.0':
optional: true
'@esbuild/android-arm64@0.23.1':
optional: true
'@esbuild/android-arm64@0.25.10':
optional: true
'@esbuild/android-arm64@0.27.0':
optional: true
'@esbuild/android-arm@0.23.1':
optional: true
'@esbuild/android-arm@0.25.10':
optional: true
'@esbuild/android-arm@0.27.0':
optional: true
'@esbuild/android-x64@0.23.1':
optional: true
'@esbuild/android-x64@0.25.10':
optional: true
'@esbuild/android-x64@0.27.0':
optional: true
'@esbuild/darwin-arm64@0.23.1':
optional: true
'@esbuild/darwin-arm64@0.25.10':
optional: true
'@esbuild/darwin-arm64@0.27.0':
optional: true
'@esbuild/darwin-x64@0.23.1':
optional: true
'@esbuild/darwin-x64@0.25.10':
optional: true
'@esbuild/darwin-x64@0.27.0':
optional: true
'@esbuild/freebsd-arm64@0.23.1':
optional: true
'@esbuild/freebsd-arm64@0.25.10':
optional: true
'@esbuild/freebsd-arm64@0.27.0':
optional: true
'@esbuild/freebsd-x64@0.23.1':
optional: true
'@esbuild/freebsd-x64@0.25.10':
optional: true
'@esbuild/freebsd-x64@0.27.0':
optional: true
'@esbuild/linux-arm64@0.23.1':
optional: true
'@esbuild/linux-arm64@0.25.10':
optional: true
'@esbuild/linux-arm64@0.27.0':
optional: true
'@esbuild/linux-arm@0.23.1':
optional: true
'@esbuild/linux-arm@0.25.10':
optional: true
'@esbuild/linux-arm@0.27.0':
optional: true
'@esbuild/linux-ia32@0.23.1':
optional: true
'@esbuild/linux-ia32@0.25.10':
optional: true
'@esbuild/linux-ia32@0.27.0':
optional: true
'@esbuild/linux-loong64@0.23.1':
optional: true
'@esbuild/linux-loong64@0.25.10':
optional: true
'@esbuild/linux-loong64@0.27.0':
optional: true
'@esbuild/linux-mips64el@0.23.1':
optional: true
'@esbuild/linux-mips64el@0.25.10':
optional: true
'@esbuild/linux-mips64el@0.27.0':
optional: true
'@esbuild/linux-ppc64@0.23.1':
optional: true
'@esbuild/linux-ppc64@0.25.10':
optional: true
'@esbuild/linux-ppc64@0.27.0':
optional: true
'@esbuild/linux-riscv64@0.23.1':
optional: true
'@esbuild/linux-riscv64@0.25.10':
optional: true
'@esbuild/linux-riscv64@0.27.0':
optional: true
'@esbuild/linux-s390x@0.23.1':
optional: true
'@esbuild/linux-s390x@0.25.10':
optional: true
'@esbuild/linux-s390x@0.27.0':
optional: true
'@esbuild/linux-x64@0.23.1':
optional: true
'@esbuild/linux-x64@0.25.10':
optional: true
@@ -12396,18 +12613,27 @@ snapshots:
'@esbuild/netbsd-arm64@0.27.0':
optional: true
'@esbuild/netbsd-x64@0.23.1':
optional: true
'@esbuild/netbsd-x64@0.25.10':
optional: true
'@esbuild/netbsd-x64@0.27.0':
optional: true
'@esbuild/openbsd-arm64@0.23.1':
optional: true
'@esbuild/openbsd-arm64@0.25.10':
optional: true
'@esbuild/openbsd-arm64@0.27.0':
optional: true
'@esbuild/openbsd-x64@0.23.1':
optional: true
'@esbuild/openbsd-x64@0.25.10':
optional: true
@@ -12420,24 +12646,36 @@ snapshots:
'@esbuild/openharmony-arm64@0.27.0':
optional: true
'@esbuild/sunos-x64@0.23.1':
optional: true
'@esbuild/sunos-x64@0.25.10':
optional: true
'@esbuild/sunos-x64@0.27.0':
optional: true
'@esbuild/win32-arm64@0.23.1':
optional: true
'@esbuild/win32-arm64@0.25.10':
optional: true
'@esbuild/win32-arm64@0.27.0':
optional: true
'@esbuild/win32-ia32@0.23.1':
optional: true
'@esbuild/win32-ia32@0.25.10':
optional: true
'@esbuild/win32-ia32@0.27.0':
optional: true
'@esbuild/win32-x64@0.23.1':
optional: true
'@esbuild/win32-x64@0.25.10':
optional: true
@@ -17007,6 +17245,8 @@ snapshots:
baseline-browser-mapping@2.8.21: {}
bcryptjs@2.4.3: {}
bcryptjs@3.0.2: {}
bidi-js@1.0.3:
@@ -17789,6 +18029,33 @@ snapshots:
is-date-object: 1.1.0
is-symbol: 1.1.1
esbuild@0.23.1:
optionalDependencies:
'@esbuild/aix-ppc64': 0.23.1
'@esbuild/android-arm': 0.23.1
'@esbuild/android-arm64': 0.23.1
'@esbuild/android-x64': 0.23.1
'@esbuild/darwin-arm64': 0.23.1
'@esbuild/darwin-x64': 0.23.1
'@esbuild/freebsd-arm64': 0.23.1
'@esbuild/freebsd-x64': 0.23.1
'@esbuild/linux-arm': 0.23.1
'@esbuild/linux-arm64': 0.23.1
'@esbuild/linux-ia32': 0.23.1
'@esbuild/linux-loong64': 0.23.1
'@esbuild/linux-mips64el': 0.23.1
'@esbuild/linux-ppc64': 0.23.1
'@esbuild/linux-riscv64': 0.23.1
'@esbuild/linux-s390x': 0.23.1
'@esbuild/linux-x64': 0.23.1
'@esbuild/netbsd-x64': 0.23.1
'@esbuild/openbsd-arm64': 0.23.1
'@esbuild/openbsd-x64': 0.23.1
'@esbuild/sunos-x64': 0.23.1
'@esbuild/win32-arm64': 0.23.1
'@esbuild/win32-ia32': 0.23.1
'@esbuild/win32-x64': 0.23.1
esbuild@0.25.10:
optionalDependencies:
'@esbuild/aix-ppc64': 0.25.10
@@ -21640,6 +21907,13 @@ snapshots:
tslib: 1.14.1
typescript: 5.8.3
tsx@4.19.2:
dependencies:
esbuild: 0.23.1
get-tsconfig: 4.13.0
optionalDependencies:
fsevents: 2.3.3
tsx@4.19.4:
dependencies:
esbuild: 0.25.10
@@ -21982,6 +22256,25 @@ snapshots:
- rollup
- supports-color
vite-plugin-dts@4.5.3(@types/node@22.15.18)(rollup@4.52.5)(typescript@5.8.3)(vite@6.4.1(@types/node@22.15.18)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.19.2)(yaml@2.8.1)):
dependencies:
'@microsoft/api-extractor': 7.53.3(@types/node@22.15.18)
'@rollup/pluginutils': 5.3.0(rollup@4.52.5)
'@volar/typescript': 2.4.23
'@vue/language-core': 2.2.0(typescript@5.8.3)
compare-versions: 6.1.1
debug: 4.4.3
kolorist: 1.8.0
local-pkg: 1.1.2
magic-string: 0.30.21
typescript: 5.8.3
optionalDependencies:
vite: 6.4.1(@types/node@22.15.18)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.19.2)(yaml@2.8.1)
transitivePeerDependencies:
- '@types/node'
- rollup
- supports-color
vite-plugin-dts@4.5.3(@types/node@22.15.18)(rollup@4.52.5)(typescript@5.8.3)(vite@6.4.1(@types/node@22.15.18)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.19.4)(yaml@2.8.1)):
dependencies:
'@microsoft/api-extractor': 7.53.3(@types/node@22.15.18)
@@ -22078,6 +22371,23 @@ snapshots:
tsx: 4.19.4
yaml: 2.8.1
vite@6.4.1(@types/node@22.15.18)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.19.2)(yaml@2.8.1):
dependencies:
esbuild: 0.25.10
fdir: 6.5.0(picomatch@4.0.3)
picomatch: 4.0.3
postcss: 8.5.3
rollup: 4.52.5
tinyglobby: 0.2.15
optionalDependencies:
'@types/node': 22.15.18
fsevents: 2.3.3
jiti: 2.6.1
lightningcss: 1.30.2
terser: 5.44.1
tsx: 4.19.2
yaml: 2.8.1
vite@6.4.1(@types/node@22.15.18)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(tsx@4.19.4)(yaml@2.8.1):
dependencies:
esbuild: 0.25.10

View File

@@ -274,6 +274,7 @@
"outputs": []
},
"db:seed": {
"env": ["ALLOW_SEED"],
"outputs": []
},
"db:setup": {