diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml
index a15950130..44a00d0b5 100644
--- a/.github/workflows/claude-code-review.yml
+++ b/.github/workflows/claude-code-review.yml
@@ -29,7 +29,7 @@ jobs:
- name: Run Claude Code Review
id: claude-review
if: ${{ !contains(github.event.pull_request.title, '[WIP]') }}
- uses: anthropics/claude-code-action@beta
+ uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
@@ -37,7 +37,7 @@ jobs:
# model: "claude-opus-4-20250514"
# Direct prompt for automated review (no @claude mention needed)
- direct_prompt: |
+ prompt: |
Please review this pull request and provide feedback on:
- Code quality and best practices
- Potential bugs or issues
@@ -46,24 +46,3 @@ jobs:
- Test coverage
Be constructive and helpful in your feedback.
-
- # Optional: Use sticky comments to make Claude reuse the same comment on subsequent pushes to the same PR
- # use_sticky_comment: true
-
- # Optional: Customize review based on file types
- # direct_prompt: |
- # Review this PR focusing on:
- # - For TypeScript files: Type safety and proper interface usage
- # - For API endpoints: Security, input validation, and error handling
- # - For React components: Performance, accessibility, and best practices
- # - For tests: Coverage, edge cases, and test quality
-
- # Optional: Different prompts for different authors
- # direct_prompt: |
- # ${{ github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' &&
- # 'Welcome! Please review this PR from a first-time contributor. Be encouraging and provide detailed explanations for any suggestions.' ||
- # 'Please provide a thorough code review focusing on our coding standards and best practices.' }}
-
- # Optional: Add specific tools for running tests or linting
- # allowed_tools: "Bash(npm run test),Bash(npm run lint),Bash(npm run typecheck)"
-
diff --git a/CLAUDE.md b/CLAUDE.md
index c033f44c9..66c279a73 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -58,7 +58,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
- **ORM**: Depends on Kysely, Zod, and various utility libraries
- **CLI**: Depends on language package, Commander.js, and Prisma (for migrations)
- **Language**: Uses Langium for grammar parsing and AST generation
-- **Database Support**: SQLite (better-sqlite3) and PostgreSQL (pg) only
+- **Database Support**: SQLite (better-sqlite3), PostgreSQL (pg), and MySQL
### Testing Strategy
diff --git a/README.md b/README.md
index b30a3f1cf..e1631ee63 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,9 @@
+
+
+
diff --git a/package.json b/package.json
index 8456e81df..a4e71f89d 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "zenstack-v3",
"displayName": "ZenStack",
"description": "ZenStack",
- "version": "3.7.2",
+ "version": "3.8.0",
"type": "module",
"author": {
"name": "ZenStack Team",
@@ -46,7 +46,7 @@
"prettier": "^3.5.3",
"prisma": "catalog:",
"tsdown": "^0.21.8",
- "tsx": "^4.20.3",
+ "tsx": "catalog:",
"turbo": "^2.5.4",
"typescript": "catalog:",
"typescript-eslint": "^8.34.1",
@@ -62,8 +62,7 @@
],
"overrides": {
"cookie@<0.7.0": ">=0.7.0",
- "lodash-es@>=4.0.0 <=4.17.22": ">=4.17.23",
- "lodash@>=4.0.0 <=4.17.22": ">=4.17.23",
+ "lodash@>=4.0.0 <=4.17.23": ">=4.18.0",
"@better-auth/core": "1.4.19"
}
},
diff --git a/packages/auth-adapters/better-auth/package.json b/packages/auth-adapters/better-auth/package.json
index a97ef4a75..b227490d7 100644
--- a/packages/auth-adapters/better-auth/package.json
+++ b/packages/auth-adapters/better-auth/package.json
@@ -2,7 +2,7 @@
"name": "@zenstackhq/better-auth",
"displayName": "ZenStack Better Auth Adapter",
"description": "ZenStack Better Auth Adapter. This adapter is modified from better-auth's Prisma adapter.",
- "version": "3.7.2",
+ "version": "3.8.0",
"type": "module",
"author": {
"name": "ZenStack Team",
diff --git a/packages/auth-adapters/better-auth/src/schema-generator.ts b/packages/auth-adapters/better-auth/src/schema-generator.ts
index dee102dc2..bea59baa8 100644
--- a/packages/auth-adapters/better-auth/src/schema-generator.ts
+++ b/packages/auth-adapters/better-auth/src/schema-generator.ts
@@ -132,7 +132,7 @@ function addDefaultNow(df: DataField) {
} as any;
const nowExpr: InvocationExpr = {
$type: 'InvocationExpr',
- function: { $refText: 'now' },
+ function: { $refText: 'now', ref: undefined },
args: [],
$container: nowArg,
};
@@ -221,6 +221,7 @@ function initializeZmodel(config: AdapterConfig) {
$type: 'InvocationExpr',
function: {
$refText: 'env',
+ ref: undefined,
},
args: [],
$container: urlField,
@@ -391,6 +392,7 @@ function addOrUpdateModel(
$type: 'DataFieldType',
reference: {
$refText: upperCaseFirst(referencedCustomModelName),
+ ref: undefined,
},
array: (field.type as string).endsWith('[]'),
optional: !field.required,
@@ -408,6 +410,7 @@ function addOrUpdateModel(
$type: 'DataFieldAttribute',
decl: {
$refText: '@relation',
+ ref: undefined,
},
args: [],
$container: relationField,
@@ -430,6 +433,7 @@ function addOrUpdateModel(
$container: fieldsExpr,
target: {
$refText: fieldName,
+ ref: undefined,
},
};
fieldsExpr.items.push(fkRefExpr);
@@ -452,6 +456,7 @@ function addOrUpdateModel(
$container: referencesExpr,
target: {
$refText: field.references.field,
+ ref: undefined,
},
};
referencesExpr.items.push(pkRefExpr);
@@ -465,7 +470,7 @@ function addOrUpdateModel(
} as any;
const onDeleteValueExpr: ReferenceExpr = {
$type: 'ReferenceExpr',
- target: { $refText: action },
+ target: { $refText: action, ref: undefined },
args: [],
$container: onDeleteArg,
};
@@ -495,6 +500,7 @@ function addOrUpdateModel(
$type: 'DataFieldType',
reference: {
$refText: relatedModel,
+ ref: undefined,
},
array: true,
optional: false,
@@ -512,7 +518,7 @@ function addOrUpdateModel(
function addModelAttribute(dataModel: DataModel, name: string, args: Omit[] = []) {
const attr: DataModelAttribute = {
$type: 'DataModelAttribute',
- decl: { $refText: name },
+ decl: { $refText: name, ref: undefined },
$container: dataModel,
args: [],
};
@@ -527,7 +533,7 @@ function addModelAttribute(dataModel: DataModel, name: string, args: Omit[] = []) {
const attr: DataFieldAttribute = {
$type: 'DataFieldAttribute',
- decl: { $refText: name },
+ decl: { $refText: name, ref: undefined },
$container: dataField,
args: [],
};
diff --git a/packages/cli/package.json b/packages/cli/package.json
index 5ce77f6cb..886ece525 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -2,7 +2,7 @@
"name": "@zenstackhq/cli",
"displayName": "ZenStack CLI",
"description": "FullStack database toolkit with built-in access control and automatic API generation.",
- "version": "3.7.2",
+ "version": "3.8.0",
"type": "module",
"author": {
"name": "ZenStack Team",
@@ -45,6 +45,7 @@
"@zenstackhq/orm": "workspace:*",
"@zenstackhq/schema": "workspace:*",
"@zenstackhq/sdk": "workspace:*",
+ "@zenstackhq/plugin-policy": "workspace:*",
"@zenstackhq/server": "workspace:*",
"chokidar": "^5.0.0",
"colors": "1.4.0",
@@ -98,4 +99,4 @@
"node": ">=20"
},
"funding": "https://github.com/sponsors/zenstackhq"
-}
+}
\ No newline at end of file
diff --git a/packages/cli/src/actions/check.ts b/packages/cli/src/actions/check.ts
index 61f12c57f..c22e65468 100644
--- a/packages/cli/src/actions/check.ts
+++ b/packages/cli/src/actions/check.ts
@@ -30,7 +30,7 @@ async function checkPluginResolution(schemaFile: string, model: Model) {
const provider = getPluginProvider(plugin);
if (!provider.startsWith('@core/')) {
const pluginSourcePath =
- plugin.$cstNode?.parent?.element.$document?.uri?.fsPath ?? schemaFile;
+ plugin.$cstNode?.container?.astNode.$document?.uri?.fsPath ?? schemaFile;
await loadPluginModule(provider, path.dirname(pluginSourcePath));
}
}
diff --git a/packages/cli/src/actions/db.ts b/packages/cli/src/actions/db.ts
index 592f9888d..1a3325d73 100644
--- a/packages/cli/src/actions/db.ts
+++ b/packages/cli/src/actions/db.ts
@@ -267,7 +267,7 @@ async function runPull(options: PullOptions) {
});
// Add/update models and their fields
newModel.declarations
- .filter((d) => [DataModel, Enum].includes(d.$type))
+ .filter((d) => d.$type === DataModel.$type || d.$type === Enum.$type)
.forEach((_declaration) => {
const newDataModel = _declaration as DataModel | Enum;
const declarations = services.shared.workspace.IndexManager.allElements(newDataModel.$type, docsSet).toArray();
diff --git a/packages/cli/src/actions/generate.ts b/packages/cli/src/actions/generate.ts
index e65747405..8291d4d9d 100644
--- a/packages/cli/src/actions/generate.ts
+++ b/packages/cli/src/actions/generate.ts
@@ -63,10 +63,10 @@ export async function run(options: Options) {
(
model.declarations.filter(
(v) =>
- v.$cstNode?.parent?.element.$type === 'Model' &&
- !!v.$cstNode.parent.element.$document?.uri?.fsPath,
+ v.$cstNode?.container?.astNode.$type === 'Model' &&
+ !!v.$cstNode.container.astNode.$document?.uri?.fsPath,
) as AbstractDeclaration[]
- ).map((v) => v.$cstNode!.parent!.element.$document!.uri!.fsPath),
+ ).map((v) => v.$cstNode!.container!.astNode.$document!.uri!.fsPath),
);
const watchedPaths = getRootModelWatchPaths(model);
@@ -189,7 +189,7 @@ async function runPlugins(schemaFile: string, model: Model, outputPath: string,
// resolve relative plugin paths against the schema file where the plugin is declared,
// not the entry schema file
const pluginSourcePath =
- plugin.$cstNode?.parent?.element.$document?.uri?.fsPath ?? schemaFile;
+ plugin.$cstNode?.container?.astNode.$document?.uri?.fsPath ?? schemaFile;
cliPlugin = await loadPluginModule(provider, path.dirname(pluginSourcePath));
}
diff --git a/packages/cli/src/actions/proxy.ts b/packages/cli/src/actions/proxy.ts
index 54c29c0ab..16c7715d5 100644
--- a/packages/cli/src/actions/proxy.ts
+++ b/packages/cli/src/actions/proxy.ts
@@ -12,6 +12,7 @@ import { MysqlDialect } from '@zenstackhq/orm/dialects/mysql';
import { PostgresDialect } from '@zenstackhq/orm/dialects/postgres';
import { SqliteDialect } from '@zenstackhq/orm/dialects/sqlite';
import type { SchemaDef } from '@zenstackhq/orm/schema';
+import { PolicyPlugin } from '@zenstackhq/plugin-policy';
import { RPCApiHandler } from '@zenstackhq/server/api';
import { ZenStackMiddleware } from '@zenstackhq/server/express';
import type BetterSqlite3 from 'better-sqlite3';
@@ -20,21 +21,72 @@ import cors from 'cors';
import express from 'express';
import { createJiti } from 'jiti';
import type { createPool as MysqlCreatePool } from 'mysql2';
+import { verify } from 'node:crypto';
import path from 'node:path';
import type { Pool as PgPoolType } from 'pg';
import { CliError } from '../cli-error';
import { getVersion } from '../utils/version-utils';
import { getOutputPath, getSchemaFile, loadSchemaDocument } from './action-utils';
+import { z } from 'zod';
type Options = {
output?: string;
schema?: string;
- port?: number;
+ port: number;
logLevel?: string[];
databaseUrl?: string;
+ studioAuthKey?: string;
+ signatureToleranceSecs: number;
};
+export const ProxyAuthError = {
+ MISSING_SIGNATURE_HEADER: 'Missing x-zenstack-signature header',
+ INVALID_TIMESTAMP: 'Request timestamp is expired or invalid',
+ INVALID_SIGNATURE_FORMAT: 'Invalid x-zenstack-signature format',
+} as const;
+
+type ProxyAuthErrorCode = keyof typeof ProxyAuthError;
+
+function rejectAuth(res: express.Response, code: ProxyAuthErrorCode) {
+ return res.status(401).json({ code, message: ProxyAuthError[code] });
+}
+/**
+ * Represents the identity claim embedded in the Authorization header.
+ * The bearer token is a plain base64-encoded JSON string.
+ */
+const UserClaimSchema = z.discriminatedUnion('type', [
+ z.object({ type: z.literal('superUser') }),
+ z.object({ type: z.literal('user'), data: z.record(z.string(), z.unknown()) }),
+]);
+
+type UserClaim = z.infer;
+
+/**
+ * Accepts a public key in either PEM format or as a raw base64 / base64url DER string
+ * (without the `-----BEGIN PUBLIC KEY-----` markers) and always returns a PEM string.
+ */
+function normalizePublicKey(key: string): string {
+ key = key.trim();
+ if (key.startsWith('-----BEGIN PUBLIC KEY-----')) {
+ return key;
+ }
+ // Convert base64url → standard base64, then wrap in PEM markers.
+ const b64 = key.replace(/-/g, '+').replace(/_/g, '/');
+ return `-----BEGIN PUBLIC KEY-----\n${b64}\n-----END PUBLIC KEY-----`;
+}
+
export async function run(options: Options) {
+ // Resolve public key: CLI arg takes precedence, then ZENSTACK_STUDIO_AUTH_KEY env var.
+ options = { ...options, studioAuthKey: options.studioAuthKey ?? process.env['ZENSTACK_STUDIO_AUTH_KEY'] };
+ if (!options.studioAuthKey) {
+ console.warn(
+ colors.yellow(
+ 'Warning: This proxy has no authentication. Do not expose it to the public network.\n' +
+ 'To secure it, get an API key from ZenStack Studio and set it via the ZENSTACK_STUDIO_AUTH_KEY environment variable.',
+ ),
+ );
+ }
+
const allowedLogLevels = ['error', 'query'] as const;
const log = options.logLevel?.filter((level): level is (typeof allowedLogLevels)[number] =>
allowedLogLevels.includes(level as any),
@@ -95,7 +147,7 @@ export async function run(options: Options) {
log: log && log.length > 0 ? log : undefined,
omit: Object.keys(omit).length > 0 ? omit : undefined,
skipValidationForComputedFields: true,
- });
+ }) as ClientContract;
// check whether the database is reachable
try {
@@ -104,7 +156,13 @@ export async function run(options: Options) {
throw new CliError(`Failed to connect to the database: ${err instanceof Error ? err.message : String(err)}`);
}
- startServer(db, schemaModule.schema, options);
+ // If a studioAuthKey is provided, create an authDb with the policy plugin
+ const authDb = db.$use(new PolicyPlugin()) as ClientContract;
+ if (options.studioAuthKey) {
+ console.log(colors.gray('Access policy plugin enabled for authorization.'));
+ }
+
+ startServer(db, schemaModule.schema, options, authDb);
}
function evaluateUrl(schemaUrl: ConfigExpr) {
@@ -198,17 +256,41 @@ async function createDialect(provider: string, databaseUrl: string, outputPath:
}
}
-export function createProxyApp(client: ClientContract, schema: SchemaDef): express.Application {
+export function createProxyApp(
+ client: ClientContract,
+ schema: SchemaDef,
+ authDb: ClientContract,
+ auth?: {
+ studioAuthKey: string;
+ /** Seconds within which a signed request is considered valid. Defaults to 60. */
+ signatureToleranceSecs: number;
+ },
+): express.Application {
const app = express();
app.use(cors());
- app.use(express.json({ limit: '5mb' }));
+ app.use(
+ express.json({
+ limit: '5mb',
+ verify: (req, _res, buf) => {
+ // Capture the raw body string for use in signature verification.
+ (req as express.Request & { rawBody?: string }).rawBody = buf.toString('utf8');
+ },
+ }),
+ );
app.use(express.urlencoded({ extended: true, limit: '5mb' }));
+ if (auth?.studioAuthKey) {
+ // Apply signature-verification middleware to all authenticated endpoints.
+ const toleranceSecs = auth.signatureToleranceSecs;
+ const normalizedKey = normalizePublicKey(auth.studioAuthKey);
+ app.use(['/api/model', '/api/schema'], createSignatureMiddleware(normalizedKey, toleranceSecs));
+ }
+
app.use(
'/api/model',
ZenStackMiddleware({
apiHandler: new RPCApiHandler({ schema }),
- getClient: () => client,
+ getClient: (req) => resolveClient(client, authDb, req, !!auth?.studioAuthKey),
}),
);
@@ -219,8 +301,149 @@ export function createProxyApp(client: ClientContract, schema: Schema
return app;
}
-function startServer(client: ClientContract, schema: any, options: Options) {
- const app = createProxyApp(client, schema);
+/**
+ * Creates an Express middleware that verifies the ed25519 signature on every request.
+ *
+ * The signature header format is: `t=,v1=`
+ *
+ * The signed message is constructed as:
+ * - GET requests: `[]`
+ * - Other methods: `[]`
+ *
+ * `authorizationToken` is the bearer token value from the `Authorization` header (if present).
+ */
+function createSignatureMiddleware(publicKey: string, toleranceSeconds: number) {
+ // Throttle invalid-signature warnings to at most once per 60 seconds.
+ let lastInvalidSigWarnAt = 0;
+ const WARN_THROTTLE_SECS = 60;
+
+ function warnInvalidSignature() {
+ const now = Math.floor(Date.now() / 1000);
+ if (now - lastInvalidSigWarnAt >= WARN_THROTTLE_SECS) {
+ lastInvalidSigWarnAt = now;
+ console.warn(
+ colors.yellow(
+ 'Warning: Received a request with an invalid signature. ' +
+ 'Please double-check whether you have the correct public API key configured.',
+ ),
+ );
+ }
+ }
+
+ return (req: express.Request, res: express.Response, next: express.NextFunction) => {
+ const signatureHeader = req.headers['x-zenstack-signature'];
+ if (!signatureHeader || typeof signatureHeader !== 'string') {
+ return rejectAuth(res, 'MISSING_SIGNATURE_HEADER');
+ }
+
+ const parts = signatureHeader.split(',');
+ const timestampPart = parts.find((p) => p.startsWith('t='));
+ const sigPart = parts.find((p) => p.startsWith('v1='));
+ if (!timestampPart || !sigPart) {
+ return rejectAuth(res, 'INVALID_SIGNATURE_FORMAT');
+ }
+ const timestamp = timestampPart.substring(2);
+ const sig = sigPart.substring(3);
+
+ // Replay-attack prevention: reject requests whose timestamp deviates
+ // from server time by more than the configured tolerance.
+ const requestTime = parseInt(timestamp, 10);
+ const now = Math.floor(Date.now() / 1000);
+ if (isNaN(requestTime) || Math.abs(now - requestTime) > toleranceSeconds) {
+ return rejectAuth(res, 'INVALID_TIMESTAMP');
+ }
+
+ // Payload: raw query string for GET/DELETE, raw body for other methods.
+ let payload: string;
+ if (req.method === 'GET' || req.method === 'DELETE') {
+ const qMark = req.originalUrl.indexOf('?');
+ payload = qMark >= 0 ? req.originalUrl.substring(qMark + 1) : '';
+ } else {
+ payload = (req as express.Request & { rawBody?: string }).rawBody ?? '';
+ }
+
+ // authorizationToken is the bearer token value (if present).
+ const authHeader = req.headers['authorization'];
+ const authorizationToken = authHeader && authHeader.startsWith('Bearer ') ? authHeader.substring(7) : undefined;
+
+ const message = authorizationToken ? `${payload}${timestamp}${authorizationToken}` : `${payload}${timestamp}`;
+
+ try {
+ const isValid = verify(null, Buffer.from(message, 'utf8'), publicKey, Buffer.from(sig, 'base64url'));
+ if (!isValid) {
+ warnInvalidSignature();
+ return rejectAuth(res, 'INVALID_SIGNATURE_FORMAT');
+ }
+ } catch {
+ warnInvalidSignature();
+ return rejectAuth(res, 'INVALID_SIGNATURE_FORMAT');
+ }
+
+ return next();
+ };
+}
+
+/**
+ * Resolves the appropriate client for a request based on the Authorization header.
+ *
+ * - No studioAuthKey configured (authDb is undefined): always return the base client.
+ * - SuperUser claim: return the base client (full access, no policy enforcement).
+ * - Regular user claim: return authDb with the user identity set via $setAuth.
+ * - No / invalid token: return the base client.
+ */
+function resolveClient(
+ client: ClientContract,
+ authDb: ClientContract,
+ req: express.Request,
+ isAuthKeyEnabled: boolean,
+): ClientContract {
+ const authHeader = req.headers['authorization'];
+
+ // If AuthKey is not enabled, and Authorization header is not present, then it is the basic access without auth.
+ if (!isAuthKeyEnabled && !authHeader) {
+ return client;
+ }
+
+ if (!authHeader?.startsWith('Bearer ')) {
+ return authDb;
+ }
+
+ const token = authHeader.substring(7);
+ let claim: UserClaim;
+ try {
+ claim = UserClaimSchema.parse(JSON.parse(Buffer.from(token, 'base64').toString('utf8')));
+ } catch (err) {
+ console.error(
+ colors.red(`Failed to parse user claim from token: ${err instanceof Error ? err.message : String(err)}`),
+ );
+ return authDb;
+ }
+
+ if (claim.type === 'superUser') {
+ // SuperUser has full access without policy enforcement, so we return the base client directly.
+ return client;
+ } else {
+ return authDb.$setAuth(claim.data) as ClientContract;
+ }
+}
+
+function startServer(
+ client: ClientContract,
+ schema: any,
+ options: Options,
+ authDb: ClientContract,
+) {
+ const app = createProxyApp(
+ client,
+ schema,
+ authDb,
+ options.studioAuthKey
+ ? {
+ studioAuthKey: options.studioAuthKey,
+ signatureToleranceSecs: options.signatureToleranceSecs,
+ }
+ : undefined,
+ );
const server = app.listen(options.port, () => {
console.log(`ZenStack proxy server is running on port: ${options.port}`);
diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts
index dd5aea7aa..ba458ded5 100644
--- a/packages/cli/src/index.ts
+++ b/packages/cli/src/index.ts
@@ -263,6 +263,26 @@ Arguments following -- are passed to the seed script. E.g.: "zen db seed -- --us
.addOption(new Option('-o, --output ', 'output directory for `zen generate` command'))
.addOption(new Option('-d, --databaseUrl ', 'database connection URL'))
.addOption(new Option('-l, --logLevel ', 'Query log levels (e.g., query, error)'))
+ .addOption(
+ new Option(
+ '--studioAuthKey ',
+ 'Authentication key from ZenStack Studio. When set, the proxy will only accept requests signed by your Studio project.\nCan also be set via the ZENSTACK_STUDIO_AUTH_KEY environment variable. ',
+ ),
+ )
+ .addOption(
+ new Option(
+ '--signatureToleranceSecs ',
+ 'Maximum age (in seconds) of a signed request before it is rejected as a replay. Defaults to 60.',
+ )
+ .default(60)
+ .argParser((v) => {
+ const parsed = parseInt(v, 10);
+ if (isNaN(parsed) || parsed < 0) {
+ throw new CliError(`--signatureToleranceSecs must be a positive integer, got: ${v}`);
+ }
+ return parsed;
+ }),
+ )
.addOption(noVersionCheckOption)
.action(proxyAction);
diff --git a/packages/cli/src/plugins/typescript.ts b/packages/cli/src/plugins/typescript.ts
index 80576ac35..82fb48937 100644
--- a/packages/cli/src/plugins/typescript.ts
+++ b/packages/cli/src/plugins/typescript.ts
@@ -1,5 +1,5 @@
import type { CliPlugin } from '@zenstackhq/sdk';
-import { TsSchemaGenerator } from '@zenstackhq/sdk';
+import { detectImportFileExtension, TsSchemaGenerator } from '@zenstackhq/sdk';
import fs from 'node:fs';
import path from 'node:path';
@@ -22,9 +22,12 @@ const plugin: CliPlugin = {
// liteOnly mode
const liteOnly = pluginOptions['liteOnly'] === true;
- // add .js extension when importing
- const importWithFileExtension = pluginOptions['importWithFileExtension'];
- if (importWithFileExtension && typeof importWithFileExtension !== 'string') {
+ // file extension to append to relative imports; when not explicitly set,
+ // auto-detect from the project's tsconfig (".js" for node16/nodenext ESM)
+ let importWithFileExtension = pluginOptions['importWithFileExtension'];
+ if (importWithFileExtension === undefined) {
+ importWithFileExtension = detectImportFileExtension(outDir);
+ } else if (typeof importWithFileExtension !== 'string') {
throw new Error('The "importWithFileExtension" option must be a string if specified.');
}
diff --git a/packages/cli/src/telemetry.ts b/packages/cli/src/telemetry.ts
index a078f62d0..abbff92df 100644
--- a/packages/cli/src/telemetry.ts
+++ b/packages/cli/src/telemetry.ts
@@ -1,8 +1,7 @@
-import { init, type Mixpanel } from 'mixpanel';
+import { type Mixpanel } from 'mixpanel';
import { randomUUID } from 'node:crypto';
import fs from 'node:fs';
import * as os from 'os';
-import { TELEMETRY_TRACKING_TOKEN } from './constants';
import { isInCi } from './utils/is-ci';
import { isInContainer } from './utils/is-container';
import isDocker from './utils/is-docker';
@@ -44,11 +43,14 @@ export class Telemetry {
private readonly isCi = isInCi;
constructor() {
- if (process.env['DO_NOT_TRACK'] !== '1' && TELEMETRY_TRACKING_TOKEN) {
- this.mixpanel = init(TELEMETRY_TRACKING_TOKEN, {
- geolocate: true,
- });
- }
+ // if (process.env['DO_NOT_TRACK'] !== '1' && TELEMETRY_TRACKING_TOKEN) {
+ // this.mixpanel = init(TELEMETRY_TRACKING_TOKEN, {
+ // geolocate: true,
+ // });
+ // }
+
+ // Telemetry is currently muted
+ return;
}
get isTracking() {
diff --git a/packages/cli/test/db/pull.test.ts b/packages/cli/test/db/pull.test.ts
index 58649e3da..ec34c66c3 100644
--- a/packages/cli/test/db/pull.test.ts
+++ b/packages/cli/test/db/pull.test.ts
@@ -619,16 +619,18 @@ enum Status {
it('should preserve field-level validation attributes after db pull', async () => {
const { workDir, schema } = await createProject(
`model User {
- id Int @id @default(autoincrement())
- email String @unique @email
- phone String @phone
- name String @length(min: 2, max: 100)
- website String? @url
- code String? @regex('^[A-Z]+$')
- age Int @gt(0)
- score Float @gte(0.0)
- rating Decimal @lt(10)
- rank BigInt @lte(999)
+ id Int @id @default(autoincrement())
+ email String @unique @email
+ phone String @phone
+ birthdate String @date
+ localTime String @time
+ name String @length(min: 2, max: 100)
+ website String? @url
+ code String? @regex('^[A-Z]+$')
+ age Int @gt(0)
+ score Float @gte(0.0)
+ rating Decimal @lt(10)
+ rank BigInt @lte(999)
}`,
);
runCli('db push', workDir);
@@ -1406,7 +1408,7 @@ describe('DB pull - SQL specific features', () => {
return;
}
- const { workDir, schema } = await createProject(
+ const { workDir } = await createProject(
`model User {
id Int @id @default(autoincrement())
email String @unique
diff --git a/packages/cli/test/import-extension.test.ts b/packages/cli/test/import-extension.test.ts
new file mode 100644
index 000000000..033de742c
--- /dev/null
+++ b/packages/cli/test/import-extension.test.ts
@@ -0,0 +1,134 @@
+import { execSync } from 'node:child_process';
+import fs from 'node:fs';
+import path from 'node:path';
+import { describe, expect, it } from 'vitest';
+import { createProject, runCli } from './utils';
+
+const model = `
+model User {
+ id String @id @default(cuid())
+ name String
+ posts Post[]
+}
+
+model Post {
+ id String @id @default(cuid())
+ title String
+ author User @relation(fields: [authorId], references: [id])
+ authorId String
+}
+`;
+
+/**
+ * Overwrites the project's tsconfig.json with the given compiler options
+ * (merged over a sensible default that includes the generated files).
+ */
+function writeTsConfig(workDir: string, compilerOptions: Record) {
+ fs.writeFileSync(
+ path.join(workDir, 'tsconfig.json'),
+ JSON.stringify(
+ {
+ compilerOptions: {
+ target: 'ESNext',
+ esModuleInterop: true,
+ skipLibCheck: true,
+ strict: true,
+ noEmit: true,
+ types: ['node'],
+ ...compilerOptions,
+ },
+ include: ['**/*.ts'],
+ },
+ null,
+ 4,
+ ),
+ );
+}
+
+function readGenerated(workDir: string, file: string) {
+ return fs.readFileSync(path.join(workDir, 'zenstack', file), 'utf8');
+}
+
+function typeCheck(workDir: string) {
+ // throws (non-zero exit) if type checking fails
+ execSync('npx tsc --noEmit', { cwd: workDir, stdio: 'pipe' });
+}
+
+describe('Import file extension generation', () => {
+ it('omits the extension and compiles under bundler resolution', async () => {
+ const { workDir } = await createProject(model);
+ // createTestProject already writes a bundler tsconfig, but set it explicitly here
+ writeTsConfig(workDir, { module: 'ESNext', moduleResolution: 'Bundler' });
+
+ runCli('generate', workDir);
+
+ // relative imports between generated files carry no extension
+ for (const file of ['models.ts', 'input.ts']) {
+ const content = readGenerated(workDir, file);
+ expect(content).toContain(`from "./schema"`);
+ expect(content).not.toContain(`./schema.js`);
+ }
+
+ // and the project type-checks
+ expect(() => typeCheck(workDir)).not.toThrow();
+ });
+
+ it('auto-adds ".js" and compiles under nodenext resolution', async () => {
+ const { workDir } = await createProject(model);
+ writeTsConfig(workDir, { module: 'NodeNext', moduleResolution: 'NodeNext' });
+
+ runCli('generate', workDir);
+
+ // node16/nodenext requires explicit extensions; they must be present
+ for (const file of ['models.ts', 'input.ts']) {
+ const content = readGenerated(workDir, file);
+ expect(content).toContain(`from "./schema.js"`);
+ }
+
+ // the real proof: nodenext would fail to resolve "./schema" without the extension
+ expect(() => typeCheck(workDir)).not.toThrow();
+ });
+
+ it('fails to compile under nodenext if the extension is suppressed', async () => {
+ // negative control proving the auto-detected extension is load-bearing
+ const modelWithoutExtension = `
+plugin typescript {
+ provider = "@core/typescript"
+ importWithFileExtension = ""
+}
+
+${model}`;
+ const { workDir } = await createProject(modelWithoutExtension);
+ writeTsConfig(workDir, { module: 'NodeNext', moduleResolution: 'NodeNext' });
+
+ runCli('generate', workDir);
+
+ const content = readGenerated(workDir, 'input.ts');
+ expect(content).toContain(`from "./schema"`);
+ expect(content).not.toContain(`./schema.js`);
+
+ // missing extension is a hard error under nodenext
+ expect(() => typeCheck(workDir)).toThrow();
+ });
+
+ it('honors an explicit importWithFileExtension over auto-detection', async () => {
+ const modelWithExtension = `
+plugin typescript {
+ provider = "@core/typescript"
+ importWithFileExtension = "js"
+}
+
+${model}`;
+ const { workDir } = await createProject(modelWithExtension);
+ // bundler resolution would auto-detect "no extension"; the explicit option wins
+ writeTsConfig(workDir, { module: 'ESNext', moduleResolution: 'Bundler' });
+
+ runCli('generate', workDir);
+
+ const content = readGenerated(workDir, 'input.ts');
+ expect(content).toContain(`from "./schema.js"`);
+
+ // bundler resolution also accepts the explicit extension
+ expect(() => typeCheck(workDir)).not.toThrow();
+ });
+});
diff --git a/packages/cli/test/proxy.test.ts b/packages/cli/test/proxy.test.ts
index 840412f23..e1f958450 100644
--- a/packages/cli/test/proxy.test.ts
+++ b/packages/cli/test/proxy.test.ts
@@ -1,8 +1,78 @@
+import { PolicyPlugin } from '@zenstackhq/plugin-policy';
import { createTestClient } from '@zenstackhq/testtools';
+import { sign } from 'node:crypto';
import http from 'node:http';
import { afterEach, describe, expect, it } from 'vitest';
import { createProxyApp } from '../src/actions/proxy';
+// ─── Ed25519 key pair for tests ───────────────────────────────────────────────
+const TEST_PRIVATE_KEY = `-----BEGIN PRIVATE KEY-----
+MC4CAQAwBQYDK2VwBCIEIHIlHXhk+zc9ziuvrYAnZZgGL36H1GXwfsYchM9dM8gR
+-----END PRIVATE KEY-----`;
+
+const TEST_PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
+MCowBQYDK2VwAyEAFSJV7wjdFuDz2CqYX7hGnITQvcmJYy7OJQq2Cy2Eiqs=
+-----END PUBLIC KEY-----`;
+
+/** Raw base64 DER — the same key without PEM markers. */
+const TEST_PUBLIC_KEY_DER = 'MCowBQYDK2VwAyEAFSJV7wjdFuDz2CqYX7hGnITQvcmJYy7OJQq2Cy2Eiqs=';
+
+// ─── Helpers ──────────────────────────────────────────────────────────────────
+
+/**
+ * Builds the `x-zenstack-signature` header value for a request.
+ * The payload is:
+ * - GET / DELETE: the raw query string (URL-encoded, after `?`)
+ * - other methods: `JSON.stringify(body)` (the raw request body)
+ */
+function buildSignatureHeader(options: {
+ privateKey: string;
+ method: string;
+ /** Path + optional query string, e.g. `/api/model/user/findMany?q=%7B%7D` */
+ pathWithQuery: string;
+ body?: unknown;
+ authorizationToken?: string;
+ /** Override timestamp (unix seconds as string). Defaults to `now`. */
+ timestamp?: string;
+}): string {
+ const timestamp = options.timestamp ?? String(Math.floor(Date.now() / 1000));
+
+ const method = options.method.toUpperCase();
+ let payload: string;
+ if (method === 'GET' || method === 'DELETE') {
+ const qMark = options.pathWithQuery.indexOf('?');
+ payload = qMark >= 0 ? options.pathWithQuery.substring(qMark + 1) : '';
+ } else {
+ payload = options.body != null ? JSON.stringify(options.body) : '';
+ }
+
+ const message = options.authorizationToken
+ ? `${payload}${timestamp}${options.authorizationToken}`
+ : `${payload}${timestamp}`;
+
+ const sig = sign(null, Buffer.from(message, 'utf8'), options.privateKey).toString('base64url');
+ return `t=${timestamp},v1=${sig}`;
+}
+
+/** Encodes a UserClaim as a plain base64 bearer token. */
+function makeUserToken(claim: { type: 'superUser' } | { type: 'user'; data: Record }): string {
+ return Buffer.from(JSON.stringify(claim)).toString('base64');
+}
+
+async function createPolicyApp(zmodel: string) {
+ const client = await createTestClient(zmodel);
+ const authDb = client.$use(new PolicyPlugin());
+ return {
+ client,
+ app: createProxyApp(client, client.$schema, authDb, {
+ studioAuthKey: TEST_PUBLIC_KEY,
+ signatureToleranceSecs: 60,
+ }),
+ };
+}
+
+// ─── Test suite ───────────────────────────────────────────────────────────────
+
describe('CLI proxy tests', () => {
let server: http.Server | undefined;
@@ -35,7 +105,8 @@ describe('CLI proxy tests', () => {
`;
const client = await createTestClient(zmodel);
- const app = createProxyApp(client, client.$schema);
+ const authDb = client.$use(new PolicyPlugin());
+ const app = createProxyApp(client, client.$schema, authDb);
const baseUrl = await startAt(app);
const r = await fetch(`${baseUrl}/api/schema`);
@@ -69,10 +140,12 @@ describe('CLI proxy tests', () => {
// create the client with skipValidationForComputedFields.
const client = await createTestClient(zmodel, {
skipValidationForComputedFields: true,
- omit: { User: { postCount: true } },
+ // a string schema can't be statically typed, so the omit config is untyped here
+ omit: { User: { postCount: true } } as any,
});
- const app = createProxyApp(client, client.$schema);
+ const authDb = client.$use(new PolicyPlugin());
+ const app = createProxyApp(client, client.$schema, authDb);
const baseUrl = await startAt(app);
// Create a user via the proxy API.
@@ -119,7 +192,8 @@ describe('CLI proxy tests', () => {
`;
const client = await createTestClient(zmodel);
- const app = createProxyApp(client, client.$schema);
+ const authDb = client.$use(new PolicyPlugin());
+ const app = createProxyApp(client, client.$schema, authDb);
const baseUrl = await startAt(app);
const txRes = await fetch(`${baseUrl}/api/model/$transaction/sequential`, {
@@ -167,4 +241,563 @@ describe('CLI proxy tests', () => {
const user = await userRes.json();
expect(user.data).toMatchObject({ id: 'u1', email: 'alice@example.com' });
});
+
+ // ─── AuthN: signature verification ─────────────────────────────────────────
+
+ describe('signature verification (studioAuthKey configured)', async () => {
+ const zmodel = `
+ model User {
+ id String @id @default(cuid())
+ email String @unique
+
+ @@allow('all', true)
+ }
+ `;
+
+ it('should reject requests missing the signature header with 401', async () => {
+ const { app } = await createPolicyApp(zmodel);
+ const baseUrl = await startAt(app);
+ const r = await fetch(`${baseUrl}/api/model/user/findMany`);
+ expect(r.status).toBe(401);
+
+ const schemaR = await fetch(`${baseUrl}/api/schema`);
+ expect(schemaR.status).toBe(401);
+ });
+
+ it('should reject requests with an invalid signature with 401', async () => {
+ const { app } = await createPolicyApp(zmodel);
+ const baseUrl = await startAt(app);
+ const r = await fetch(`${baseUrl}/api/model/user/findMany`, {
+ headers: { 'x-zenstack-signature': 't=1234567890,v1=invalidsignature' },
+ });
+ expect(r.status).toBe(401);
+ });
+
+ it('should allow GET requests with a valid signature', async () => {
+ const { app } = await createPolicyApp(zmodel);
+ const baseUrl = await startAt(app);
+ const path = '/api/model/user/findMany';
+ const sig = buildSignatureHeader({ privateKey: TEST_PRIVATE_KEY, method: 'GET', pathWithQuery: path });
+
+ const r = await fetch(`${baseUrl}${path}`, {
+ headers: { 'x-zenstack-signature': sig },
+ });
+ expect(r.status).toBe(200);
+ const body = await r.json();
+ expect(Array.isArray(body.data)).toBe(true);
+ });
+
+ it('should allow GET request with query params and a valid signature', async () => {
+ const { client, app } = await createPolicyApp(zmodel);
+ const baseUrl = await startAt(app);
+ // Pre-seed a record directly via client
+ await client.user.create({ data: { id: 'u1', email: 'alice@example.com' } });
+
+ const q = encodeURIComponent(JSON.stringify({ where: { id: 'u1' } }));
+ const pathWithQuery = `/api/model/user/findUnique?q=${q}`;
+ const sig = buildSignatureHeader({
+ privateKey: TEST_PRIVATE_KEY,
+ method: 'GET',
+ pathWithQuery,
+ });
+
+ const r = await fetch(`${baseUrl}${pathWithQuery}`, {
+ headers: { 'x-zenstack-signature': sig },
+ });
+ expect(r.status).toBe(200);
+ const body = await r.json();
+ expect(body.data).toMatchObject({ id: 'u1', email: 'alice@example.com' });
+ });
+
+ it('should allow POST (create) requests with a valid signature', async () => {
+ const { app } = await createPolicyApp(zmodel);
+ const baseUrl = await startAt(app);
+ const reqBody = { data: { email: 'bob@example.com' } };
+ const pathWithQuery = '/api/model/user/create';
+ const sig = buildSignatureHeader({
+ privateKey: TEST_PRIVATE_KEY,
+ method: 'POST',
+ pathWithQuery,
+ body: reqBody,
+ });
+
+ const r = await fetch(`${baseUrl}${pathWithQuery}`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json', 'x-zenstack-signature': sig },
+ body: JSON.stringify(reqBody),
+ });
+ expect(r.status).toBe(201);
+ const body = await r.json();
+ expect(body.data).toMatchObject({ email: 'bob@example.com' });
+ });
+
+ it('should allow PUT (update) requests with a valid signature', async () => {
+ const { app, client } = await createPolicyApp(zmodel);
+ const baseUrl = await startAt(app);
+ // Seed a record
+ await client.user.create({ data: { id: 'u1', email: 'old@example.com' } });
+ const reqBody = { where: { id: 'u1' }, data: { email: 'new@example.com' } };
+ const pathWithQuery = '/api/model/user/update';
+ const sig = buildSignatureHeader({
+ privateKey: TEST_PRIVATE_KEY,
+ method: 'PUT',
+ pathWithQuery,
+ body: reqBody,
+ });
+
+ const r = await fetch(`${baseUrl}${pathWithQuery}`, {
+ method: 'PUT',
+ headers: { 'Content-Type': 'application/json', 'x-zenstack-signature': sig },
+ body: JSON.stringify(reqBody),
+ });
+ expect(r.status).toBe(200);
+ const body = await r.json();
+ expect(body.data).toMatchObject({ id: 'u1', email: 'new@example.com' });
+ });
+
+ it('should allow signed schema endpoint', async () => {
+ const { app } = await createPolicyApp(zmodel);
+ const baseUrl = await startAt(app);
+ const pathWithQuery = '/api/schema';
+ const sig = buildSignatureHeader({ privateKey: TEST_PRIVATE_KEY, method: 'GET', pathWithQuery });
+
+ const r = await fetch(`${baseUrl}${pathWithQuery}`, {
+ headers: { 'x-zenstack-signature': sig },
+ });
+ expect(r.status).toBe(200);
+ const body = await r.json();
+ expect(body).toHaveProperty('models');
+ });
+
+ it('should not require signatures when studioAuthKey is not configured', async () => {
+ // No studioAuthKey — backwards-compatible mode
+ const client = await createTestClient(zmodel);
+ const authDb = client.$use(new PolicyPlugin());
+ const app = createProxyApp(client, client.$schema, authDb);
+ const baseUrl = await startAt(app);
+
+ // No signature header — should still work
+ const r = await fetch(`${baseUrl}/api/model/user/findMany`);
+ expect(r.status).toBe(200);
+
+ // Authorization header is silently ignored
+ const withAuthHeader = await fetch(`${baseUrl}/api/model/user/findMany`, {
+ headers: { Authorization: `Bearer ${makeUserToken({ type: 'superUser' })}` },
+ });
+ expect(withAuthHeader.status).toBe(200);
+ });
+ });
+
+ // ─── AuthN: public key format ──────────────────────────────────────────────
+
+ describe('public key format', () => {
+ const zmodel = `
+ model User {
+ id String @id @default(cuid())
+ email String @unique
+ }
+ `;
+
+ it('should accept a raw base64 DER key (without PEM markers)', async () => {
+ const client = await createTestClient(zmodel);
+ const authDb = client.$use(new PolicyPlugin());
+ // Pass the key as raw base64 DER — no PEM markers
+ const app = createProxyApp(client, client.$schema, authDb, {
+ studioAuthKey: TEST_PUBLIC_KEY_DER,
+ signatureToleranceSecs: 60,
+ });
+ const baseUrl = await startAt(app);
+
+ const pathWithQuery = '/api/model/user/findMany';
+ const sig = buildSignatureHeader({ privateKey: TEST_PRIVATE_KEY, method: 'GET', pathWithQuery });
+ const r = await fetch(`${baseUrl}${pathWithQuery}`, {
+ headers: { 'x-zenstack-signature': sig },
+ });
+ expect(r.status).toBe(200);
+ });
+
+ it('should accept a key supplied via ZENSTACK_STUDIO_AUTH_KEY env variable', async () => {
+ const client = await createTestClient(zmodel);
+ // createProxyApp receives the already-resolved key (as run() would pass it),
+ // so we simulate env var resolution by passing the PEM directly.
+ process.env['ZENSTACK_STUDIO_AUTH_KEY'] = TEST_PUBLIC_KEY;
+ try {
+ // No studioAuthKey option — would normally fall back to env var via run();
+ // here we verify the middleware still works when the resolved key is provided.
+ const authDb = client.$use(new PolicyPlugin());
+ const app = createProxyApp(client, client.$schema, authDb, {
+ studioAuthKey: process.env['ZENSTACK_STUDIO_AUTH_KEY'],
+ signatureToleranceSecs: 60,
+ });
+ const baseUrl = await startAt(app);
+
+ const pathWithQuery = '/api/model/user/findMany';
+ const sig = buildSignatureHeader({ privateKey: TEST_PRIVATE_KEY, method: 'GET', pathWithQuery });
+ const r = await fetch(`${baseUrl}${pathWithQuery}`, {
+ headers: { 'x-zenstack-signature': sig },
+ });
+ expect(r.status).toBe(200);
+ } finally {
+ delete process.env['ZENSTACK_STUDIO_AUTH_KEY'];
+ }
+ });
+ });
+
+ // ─── AuthN: timestamp / replay-attack prevention ───────────────────────────
+
+ describe('signature timestamp tolerance', () => {
+ const zmodel = `
+ model User {
+ id String @id @default(cuid())
+ email String @unique
+ }
+ `;
+
+ it('should reject a request whose timestamp is older than the tolerance window', async () => {
+ const client = await createTestClient(zmodel);
+ const authDb = client.$use(new PolicyPlugin());
+ const app = createProxyApp(client, client.$schema, authDb, {
+ studioAuthKey: TEST_PUBLIC_KEY,
+ signatureToleranceSecs: 60,
+ });
+ const baseUrl = await startAt(app);
+
+ // Timestamp 120 seconds ago — exceeds default 60-second tolerance
+ const expiredTimestamp = String(Math.floor(Date.now() / 1000) - 120);
+ const pathWithQuery = '/api/model/user/findMany';
+ const sig = buildSignatureHeader({
+ privateKey: TEST_PRIVATE_KEY,
+ method: 'GET',
+ pathWithQuery,
+ timestamp: expiredTimestamp,
+ });
+
+ const r = await fetch(`${baseUrl}${pathWithQuery}`, {
+ headers: { 'x-zenstack-signature': sig },
+ });
+ expect(r.status).toBe(401);
+ const body = await r.json();
+ expect(body.message).toMatch(/expired/i);
+ });
+
+ it('should reject a request whose timestamp is too far in the future', async () => {
+ const client = await createTestClient(zmodel);
+ const authDb = client.$use(new PolicyPlugin());
+ const app = createProxyApp(client, client.$schema, authDb, {
+ studioAuthKey: TEST_PUBLIC_KEY,
+ signatureToleranceSecs: 60,
+ });
+ const baseUrl = await startAt(app);
+
+ // Timestamp 120 seconds in the future — exceeds default 60-second tolerance
+ const futureTimestamp = String(Math.floor(Date.now() / 1000) + 120);
+ const pathWithQuery = '/api/model/user/findMany';
+ const sig = buildSignatureHeader({
+ privateKey: TEST_PRIVATE_KEY,
+ method: 'GET',
+ pathWithQuery,
+ timestamp: futureTimestamp,
+ });
+
+ const r = await fetch(`${baseUrl}${pathWithQuery}`, {
+ headers: { 'x-zenstack-signature': sig },
+ });
+ expect(r.status).toBe(401);
+ const body = await r.json();
+ expect(body.message).toMatch(/expired/i);
+ });
+
+ it('should accept a request within a custom tolerance window', async () => {
+ const client = await createTestClient(zmodel);
+ // Custom tolerance of 300 seconds
+ const authDb = client.$use(new PolicyPlugin());
+ const app = createProxyApp(client, client.$schema, authDb, {
+ studioAuthKey: TEST_PUBLIC_KEY,
+ signatureToleranceSecs: 300,
+ });
+ const baseUrl = await startAt(app);
+
+ // Timestamp 120 seconds ago — within the 300-second custom tolerance
+ const timestamp = String(Math.floor(Date.now() / 1000) - 120);
+ const pathWithQuery = '/api/model/user/findMany';
+ const sig = buildSignatureHeader({
+ privateKey: TEST_PRIVATE_KEY,
+ method: 'GET',
+ pathWithQuery,
+ timestamp,
+ });
+
+ const r = await fetch(`${baseUrl}${pathWithQuery}`, {
+ headers: { 'x-zenstack-signature': sig },
+ });
+ expect(r.status).toBe(200);
+ });
+
+ it('should reject a request that falls outside a custom tolerance window', async () => {
+ const client = await createTestClient(zmodel);
+ const authDb = client.$use(new PolicyPlugin());
+ // Very tight tolerance of 5 seconds
+ const app = createProxyApp(client, client.$schema, authDb, {
+ studioAuthKey: TEST_PUBLIC_KEY,
+ signatureToleranceSecs: 5,
+ });
+ const baseUrl = await startAt(app);
+
+ // Timestamp 10 seconds ago — exceeds the 5-second custom tolerance
+ const timestamp = String(Math.floor(Date.now() / 1000) - 10);
+ const pathWithQuery = '/api/model/user/findMany';
+ const sig = buildSignatureHeader({
+ privateKey: TEST_PRIVATE_KEY,
+ method: 'GET',
+ pathWithQuery,
+ timestamp,
+ });
+
+ const r = await fetch(`${baseUrl}${pathWithQuery}`, {
+ headers: { 'x-zenstack-signature': sig },
+ });
+ expect(r.status).toBe(401);
+ });
+ });
+
+ // ─── AuthN: signed request also carries Authorization header ──────────────
+
+ describe('signature includes Authorization header in the signed message', () => {
+ const zmodel = `
+ model User {
+ id String @id @default(cuid())
+ email String @unique
+ }
+ `;
+
+ it('should reject a valid signature if it was produced without the Authorization token', async () => {
+ const client = await createTestClient(zmodel);
+ const authDb = client.$use(new PolicyPlugin());
+ const app = createProxyApp(client, client.$schema, authDb, {
+ studioAuthKey: TEST_PUBLIC_KEY,
+ signatureToleranceSecs: 60,
+ });
+ const baseUrl = await startAt(app);
+
+ // Sign without including the auth token
+ const pathWithQuery = '/api/model/user/findMany';
+ const sigWithoutAuth = buildSignatureHeader({
+ privateKey: TEST_PRIVATE_KEY,
+ method: 'GET',
+ pathWithQuery,
+ // authorizationToken intentionally omitted
+ });
+
+ const authToken = makeUserToken({ type: 'superUser' });
+
+ // Send with Authorization header but signature that did NOT cover it
+ const r = await fetch(`${baseUrl}${pathWithQuery}`, {
+ headers: {
+ 'x-zenstack-signature': sigWithoutAuth,
+ Authorization: `Bearer ${authToken}`,
+ },
+ });
+ expect(r.status).toBe(401);
+ });
+
+ it('should accept a request where the signature covers the Authorization token', async () => {
+ const client = await createTestClient(zmodel);
+ const authDb = client.$use(new PolicyPlugin());
+ const app = createProxyApp(client, client.$schema, authDb, {
+ studioAuthKey: TEST_PUBLIC_KEY,
+ signatureToleranceSecs: 60,
+ });
+ const baseUrl = await startAt(app);
+
+ const authToken = makeUserToken({ type: 'superUser' });
+ const pathWithQuery = '/api/model/user/findMany';
+ const sig = buildSignatureHeader({
+ privateKey: TEST_PRIVATE_KEY,
+ method: 'GET',
+ pathWithQuery,
+ authorizationToken: authToken,
+ });
+
+ const r = await fetch(`${baseUrl}${pathWithQuery}`, {
+ headers: {
+ 'x-zenstack-signature': sig,
+ Authorization: `Bearer ${authToken}`,
+ },
+ });
+ expect(r.status).toBe(200);
+ });
+ });
+
+ // ─── AuthZ: user impersonation via PolicyPlugin ─────────────────────────────
+
+ describe('authorization with policy plugin', () => {
+ // Users can only read/write their own record.
+ const zmodel = `
+ model User {
+ id String @id @default(cuid())
+ email String @unique
+
+ @@allow('all', auth() != null && auth().id == id)
+ }
+ `;
+
+ async function signedFetch(baseUrl: string, path: string, init: RequestInit = {}): Promise {
+ const method = (init.method ?? 'GET').toUpperCase();
+ const body = init.body ? JSON.parse(init.body as string) : undefined;
+ const authHeader = (init.headers as Record | undefined)?.['Authorization'];
+ const authorizationToken = authHeader?.startsWith('Bearer ') ? authHeader.substring(7) : undefined;
+
+ const sig = buildSignatureHeader({
+ privateKey: TEST_PRIVATE_KEY,
+ method,
+ pathWithQuery: path,
+ body,
+ authorizationToken,
+ });
+ return fetch(`${baseUrl}${path}`, {
+ ...init,
+ headers: {
+ ...(init.headers as Record),
+ 'x-zenstack-signature': sig,
+ },
+ });
+ }
+
+ it('anonymous request should not bypass access policy', async () => {
+ const { client, app } = await createPolicyApp(zmodel);
+ const baseUrl = await startAt(app);
+ await client.user.create({ data: { id: 'u1', email: 'user1@example.com' } });
+ await client.user.create({ data: { id: 'u2', email: 'user2@example.com' } });
+ const pathWithQuery = '/api/model/user/findMany';
+ const r = await signedFetch(baseUrl, pathWithQuery);
+ expect(r.status).toBe(200);
+ const body = await r.json();
+ expect(body.data).toHaveLength(0);
+ });
+
+ it('superUser can access all records', async () => {
+ const { client, app } = await createPolicyApp(zmodel);
+ const baseUrl = await startAt(app);
+
+ // Seed two users directly via base client (bypasses policy)
+ await client.user.create({ data: { id: 'u1', email: 'user1@example.com' } });
+ await client.user.create({ data: { id: 'u2', email: 'user2@example.com' } });
+
+ const authToken = makeUserToken({ type: 'superUser' });
+ const pathWithQuery = '/api/model/user/findMany';
+ const r = await signedFetch(baseUrl, pathWithQuery, {
+ headers: { Authorization: `Bearer ${authToken}` },
+ });
+ expect(r.status).toBe(200);
+ const body = await r.json();
+ // SuperUser bypasses policy — sees all records
+ expect(body.data).toHaveLength(2);
+ });
+
+ it('regular user can only access their own record', async () => {
+ const { client, app } = await createPolicyApp(zmodel);
+ const baseUrl = await startAt(app);
+
+ // Seed two users
+ await client.user.create({ data: { id: 'u1', email: 'user1@example.com' } });
+ await client.user.create({ data: { id: 'u2', email: 'user2@example.com' } });
+
+ // Authenticated as u1
+ const authToken = makeUserToken({ type: 'user', data: { id: 'u1' } });
+ const pathWithQuery = '/api/model/user/findMany';
+ const r = await signedFetch(baseUrl, pathWithQuery, {
+ headers: { Authorization: `Bearer ${authToken}` },
+ });
+ expect(r.status).toBe(200);
+ const body = await r.json();
+ // Policy restricts to own record only
+ expect(body.data).toHaveLength(1);
+ expect(body.data[0]).toMatchObject({ id: 'u1' });
+ });
+
+ it("regular user cannot update another user's record", async () => {
+ const { client, app } = await createPolicyApp(zmodel);
+ const baseUrl = await startAt(app);
+
+ await client.user.create({ data: { id: 'u1', email: 'user1@example.com' } });
+ await client.user.create({ data: { id: 'u2', email: 'user2@example.com' } });
+
+ // Authenticated as u2 trying to update u1
+ const reqBody = { where: { id: 'u1' }, data: { email: 'hacked@example.com' } };
+ const authToken = makeUserToken({ type: 'user', data: { id: 'u2' } });
+ const pathWithQuery = '/api/model/user/update';
+ const r = await signedFetch(baseUrl, pathWithQuery, {
+ method: 'PUT',
+ headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${authToken}` },
+ body: JSON.stringify(reqBody),
+ });
+ // Policy should reject this — the policy plugin returns 404 (not found)
+ // rather than 403 to avoid leaking that the record exists.
+ expect([403, 404]).toContain(r.status);
+ });
+
+ it('superUser can create records on behalf of others', async () => {
+ const { client: _client, app } = await createPolicyApp(zmodel);
+ const baseUrl = await startAt(app);
+
+ const reqBody = { data: { id: 'u1', email: 'user1@example.com' } };
+ const authToken = makeUserToken({ type: 'superUser' });
+ const pathWithQuery = '/api/model/user/create';
+ const r = await signedFetch(baseUrl, pathWithQuery, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${authToken}` },
+ body: JSON.stringify(reqBody),
+ });
+ expect(r.status).toBe(201);
+ const body = await r.json();
+ expect(body.data).toMatchObject({ id: 'u1', email: 'user1@example.com' });
+ });
+
+ it('sequential transaction respects user-scoped policy', async () => {
+ const fullZModel = `
+ model User {
+ id String @id @default(cuid())
+ email String @unique
+ posts Post[]
+
+ @@allow('all', auth() != null && auth().id == id)
+ }
+ model Post {
+ id String @id @default(cuid())
+ title String
+ author User? @relation(fields: [authorId], references: [id])
+ authorId String?
+
+ @@allow('all', auth() != null && auth().id == authorId)
+ }
+ `;
+ const { client, app } = await createPolicyApp(fullZModel);
+ const baseUrl = await startAt(app);
+
+ // Seed users
+ await client.user.create({ data: { id: 'u1', email: 'user1@example.com' } });
+ await client.user.create({ data: { id: 'u2', email: 'user2@example.com' } });
+
+ // Transaction as u1: create own post and read own posts
+ const txBody = [
+ { model: 'Post', op: 'create', args: { data: { id: 'p1', title: 'Post by u1', authorId: 'u1' } } },
+ { model: 'Post', op: 'findMany', args: {} },
+ ];
+ const authToken = makeUserToken({ type: 'user', data: { id: 'u1' } });
+ const pathWithQuery = '/api/model/$transaction/sequential';
+ const r = await signedFetch(baseUrl, pathWithQuery, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${authToken}` },
+ body: JSON.stringify(txBody),
+ });
+ expect(r.status).toBe(200);
+ const body = await r.json();
+ expect(Array.isArray(body.data)).toBe(true);
+ // Created post
+ expect(body.data[0]).toMatchObject({ id: 'p1', title: 'Post by u1' });
+ // findMany respects policy — u1 sees only their posts
+ expect(body.data[1]).toHaveLength(1);
+ expect(body.data[1][0]).toMatchObject({ id: 'p1' });
+ });
+ });
});
diff --git a/packages/cli/test/ts-schema-gen.test.ts b/packages/cli/test/ts-schema-gen.test.ts
index 29aa7b522..0bf7af48c 100644
--- a/packages/cli/test/ts-schema-gen.test.ts
+++ b/packages/cli/test/ts-schema-gen.test.ts
@@ -462,9 +462,9 @@ model User {
true,
);
- expect(schemaLite!.models.User.attributes).toBeUndefined();
- expect(schemaLite!.models.User.fields.id.attributes).toBeUndefined();
- expect(schemaLite!.models.User.fields.email.attributes).toBeUndefined();
+ expect(schemaLite!.models['User']!.attributes).toBeUndefined();
+ expect(schemaLite!.models['User']!.fields['id']!.attributes).toBeUndefined();
+ expect(schemaLite!.models['User']!.fields['email']!.attributes).toBeUndefined();
});
it('supports ignorable fields for @updatedAt', async () => {
diff --git a/packages/cli/tsconfig.json b/packages/cli/tsconfig.json
index 8ef64682a..e7ce31be8 100644
--- a/packages/cli/tsconfig.json
+++ b/packages/cli/tsconfig.json
@@ -1,4 +1,4 @@
{
"extends": "@zenstackhq/typescript-config/base.json",
- "include": ["src/**/*.ts"]
+ "include": ["src/**/*.ts", "test/**/*.ts"]
}
diff --git a/packages/clients/client-helpers/package.json b/packages/clients/client-helpers/package.json
index 40f5b6fbc..fc4ef18e4 100644
--- a/packages/clients/client-helpers/package.json
+++ b/packages/clients/client-helpers/package.json
@@ -2,7 +2,7 @@
"name": "@zenstackhq/client-helpers",
"displayName": "ZenStack Client Helpers",
"description": "Helpers for implementing clients that consume ZenStack's CRUD service",
- "version": "3.7.2",
+ "version": "3.8.0",
"type": "module",
"author": {
"name": "ZenStack Team",
diff --git a/packages/clients/fetch-client/package.json b/packages/clients/fetch-client/package.json
index 6836ffe1c..af544473c 100644
--- a/packages/clients/fetch-client/package.json
+++ b/packages/clients/fetch-client/package.json
@@ -2,7 +2,7 @@
"name": "@zenstackhq/fetch-client",
"displayName": "ZenStack Fetch Client",
"description": "Simple fetch-based client for consuming ZenStack's RPC-style CRUD API",
- "version": "3.7.2",
+ "version": "3.8.0",
"type": "module",
"author": {
"name": "ZenStack Team",
diff --git a/packages/clients/tanstack-query/package.json b/packages/clients/tanstack-query/package.json
index 90d4add21..3124dfe2e 100644
--- a/packages/clients/tanstack-query/package.json
+++ b/packages/clients/tanstack-query/package.json
@@ -2,7 +2,7 @@
"name": "@zenstackhq/tanstack-query",
"displayName": "ZenStack TanStack Query Integration",
"description": "TanStack Query Client for consuming ZenStack v3's CRUD service",
- "version": "3.7.2",
+ "version": "3.8.0",
"type": "module",
"author": {
"name": "ZenStack Team",
diff --git a/packages/clients/tanstack-query/src/vue.ts b/packages/clients/tanstack-query/src/vue.ts
index 687a43c4d..377da31fb 100644
--- a/packages/clients/tanstack-query/src/vue.ts
+++ b/packages/clients/tanstack-query/src/vue.ts
@@ -651,8 +651,8 @@ export function useInternalInfiniteQuery {
- const reqUrl = makeUrl(endpoint, model, operation, argsValue);
+ queryFn: ({ pageParam, signal }: any) => {
+ const reqUrl = makeUrl(endpoint, model, operation, pageParam ?? argsValue);
return fetcher(reqUrl, { signal }, fetch);
},
initialPageParam: toValue(argsValue) as TPageParam,
diff --git a/packages/common-helpers/package.json b/packages/common-helpers/package.json
index c570e0e58..8f8af7346 100644
--- a/packages/common-helpers/package.json
+++ b/packages/common-helpers/package.json
@@ -2,7 +2,7 @@
"name": "@zenstackhq/common-helpers",
"displayName": "ZenStack Common Helpers",
"description": "ZenStack Common Helpers",
- "version": "3.7.2",
+ "version": "3.8.0",
"type": "module",
"author": {
"name": "ZenStack Team",
diff --git a/packages/config/eslint-config/package.json b/packages/config/eslint-config/package.json
index 560889bd7..b060de766 100644
--- a/packages/config/eslint-config/package.json
+++ b/packages/config/eslint-config/package.json
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/eslint-config",
- "version": "3.7.2",
+ "version": "3.8.0",
"type": "module",
"private": true,
"license": "MIT"
diff --git a/packages/config/tsdown-config/package.json b/packages/config/tsdown-config/package.json
index 477d67c02..a03f35558 100644
--- a/packages/config/tsdown-config/package.json
+++ b/packages/config/tsdown-config/package.json
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/tsdown-config",
- "version": "3.7.2",
+ "version": "3.8.0",
"private": true,
"type": "module",
"license": "MIT",
diff --git a/packages/config/typescript-config/package.json b/packages/config/typescript-config/package.json
index 3f7337055..4b776e08d 100644
--- a/packages/config/typescript-config/package.json
+++ b/packages/config/typescript-config/package.json
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/typescript-config",
- "version": "3.7.2",
+ "version": "3.8.0",
"private": true,
"license": "MIT"
}
diff --git a/packages/config/vitest-config/package.json b/packages/config/vitest-config/package.json
index 058d5ce67..e9a885bff 100644
--- a/packages/config/vitest-config/package.json
+++ b/packages/config/vitest-config/package.json
@@ -1,7 +1,7 @@
{
"name": "@zenstackhq/vitest-config",
"type": "module",
- "version": "3.7.2",
+ "version": "3.8.0",
"private": true,
"license": "MIT",
"exports": {
diff --git a/packages/create-zenstack/package.json b/packages/create-zenstack/package.json
index f20cfed63..3bd4b5925 100644
--- a/packages/create-zenstack/package.json
+++ b/packages/create-zenstack/package.json
@@ -2,7 +2,7 @@
"name": "create-zenstack",
"displayName": "Create ZenStack",
"description": "Create a new ZenStack project",
- "version": "3.7.2",
+ "version": "3.8.0",
"type": "module",
"author": {
"name": "ZenStack Team",
diff --git a/packages/ide/vscode/package.json b/packages/ide/vscode/package.json
index 7931002c9..5355b42de 100644
--- a/packages/ide/vscode/package.json
+++ b/packages/ide/vscode/package.json
@@ -1,7 +1,7 @@
{
"name": "zenstack-v3",
"publisher": "zenstack",
- "version": "3.7.2",
+ "version": "3.8.0",
"displayName": "ZenStack V3 Language Tools",
"description": "VSCode extension for ZenStack (v3) ZModel language",
"private": true,
diff --git a/packages/language/package.json b/packages/language/package.json
index 97d5f2805..f0d3667f4 100644
--- a/packages/language/package.json
+++ b/packages/language/package.json
@@ -2,7 +2,7 @@
"name": "@zenstackhq/language",
"displayName": "ZenStack Language Tooling",
"description": "ZenStack ZModel language specification",
- "version": "3.7.2",
+ "version": "3.8.0",
"type": "module",
"author": {
"name": "ZenStack Team",
@@ -81,6 +81,7 @@
"vscode-languageserver": "^9.0.1"
},
"devDependencies": {
+ "@types/node": "catalog:",
"@types/pluralize": "^0.0.33",
"@types/tmp": "catalog:",
"@zenstackhq/eslint-config": "workspace:*",
diff --git a/packages/language/res/stdlib.zmodel b/packages/language/res/stdlib.zmodel
index 4561da14a..8f009d8ac 100644
--- a/packages/language/res/stdlib.zmodel
+++ b/packages/language/res/stdlib.zmodel
@@ -204,6 +204,12 @@ attribute @@@completionHint(_ values: String[])
*/
attribute @@@once()
+/**
+ * Indicates that a field-level attribute can only be applied to a single field within a model
+ * (including fields inherited from base models and mixins).
+ */
+attribute @@@onceInModel()
+
/**
* Defines a single-field ID on the model.
*
@@ -218,7 +224,7 @@ attribute @id(map: String?, length: Int?, sort: SortOrder?, clustered: Boolean?)
* Defines a default value for a field.
* @param value: An expression (e.g. 5, true, now(), auth()).
*/
-attribute @default(_ value: ContextType, map: String?) @@@prisma
+attribute @default(_ value: ContextType, map: String?) @@@prisma @@@once
/**
* Defines a unique constraint for this field.
@@ -546,6 +552,16 @@ attribute @email(_ message: String?) @@@targetField([StringField]) @@@validation
*/
attribute @datetime(_ message: String?) @@@targetField([StringField]) @@@validation
+/**
+ * Validates a string field value is a valid ISO date.
+ */
+attribute @date(_ message: String?) @@@targetField([StringField]) @@@validation
+
+/**
+ * Validates a string field value is a valid ISO time.
+ */
+attribute @time(_ precision: Int?, _ message: String?) @@@targetField([StringField]) @@@validation
+
/**
* Validates a string field value is a valid url.
*/
@@ -621,6 +637,18 @@ function isEmail(field: String): Boolean {
function isDateTime(field: String): Boolean {
} @@@expressionContext([ValidationRule])
+/**
+ * Validates a string field value is a valid ISO date.
+ */
+function isDate(field: String): Boolean {
+} @@@expressionContext([ValidationRule])
+
+/**
+ * Validates a string field value is a valid ISO time.
+ */
+function isTime(field: String, precision: Int?): Boolean {
+} @@@expressionContext([ValidationRule])
+
/**
* Validates a string field value is a valid url.
*/
diff --git a/packages/language/src/document.ts b/packages/language/src/document.ts
index 87fc48564..dc58f93a7 100644
--- a/packages/language/src/document.ts
+++ b/packages/language/src/document.ts
@@ -251,7 +251,7 @@ function validationAfterImportMerge(model: Model) {
export async function formatDocument(content: string) {
const services = createZModelServices().ZModelLanguage;
const langiumDocuments = services.shared.workspace.LangiumDocuments;
- const document = langiumDocuments.createDocument(URI.parse('memory://schema.zmodel'), content);
+ const document = langiumDocuments.createDocument(URI.parse('memory:///schema.zmodel'), content);
const formatter = services.lsp.Formatter as ZModelFormatter;
const identifier = { uri: document.uri.toString() };
const options = formatter.getFormatOptions() ?? {
diff --git a/packages/language/src/factory/attribute.ts b/packages/language/src/factory/attribute.ts
index b59e35ef1..25bd55bc5 100644
--- a/packages/language/src/factory/attribute.ts
+++ b/packages/language/src/factory/attribute.ts
@@ -18,7 +18,7 @@ export class DataFieldAttributeFactory extends AstFactory {
args: AttributeArgFactory[] = [];
decl?: Reference;
constructor() {
- super({ type: DataFieldAttribute, node: { args: [] } });
+ super({ type: DataFieldAttribute.$type, node: { args: [] } });
}
setDecl(decl: Attribute) {
if (!decl) {
@@ -50,7 +50,7 @@ export class DataModelAttributeFactory extends AstFactory {
args: AttributeArgFactory[] = [];
decl?: Reference;
constructor() {
- super({ type: DataModelAttribute, node: { args: [] } });
+ super({ type: DataModelAttribute.$type, node: { args: [] } });
}
setDecl(decl: Attribute) {
if (!decl) {
@@ -83,7 +83,7 @@ export class AttributeArgFactory extends AstFactory {
value?: AstFactory;
constructor() {
- super({ type: AttributeArg });
+ super({ type: AttributeArg.$type });
}
setName(name: RegularID) {
@@ -108,7 +108,7 @@ export class InternalAttributeFactory extends AstFactory {
args: AttributeArgFactory[] = [];
constructor() {
- super({ type: InternalAttribute, node: { args: [] } });
+ super({ type: InternalAttribute.$type, node: { args: [] } });
}
setDecl(decl: Attribute) {
@@ -144,7 +144,7 @@ export class AttributeParamFactory extends AstFactory {
constructor() {
super({
- type: AttributeParam,
+ type: AttributeParam.$type,
node: {
comments: [],
attributes: [],
@@ -199,7 +199,7 @@ export class AttributeParamTypeFactory extends AstFactory {
reference?: Reference;
type?: AttributeParamType['type'];
constructor() {
- super({ type: AttributeParamType });
+ super({ type: AttributeParamType.$type });
}
setArray(array: boolean) {
this.array = array;
@@ -244,7 +244,7 @@ export class AttributeFactory extends AstFactory {
params: AttributeParamFactory[] = [];
constructor() {
- super({ type: Attribute, node: { comments: [], attributes: [], params: [] } });
+ super({ type: Attribute.$type, node: { comments: [], attributes: [], params: [] } });
}
setName(name: string) {
diff --git a/packages/language/src/factory/declaration.ts b/packages/language/src/factory/declaration.ts
index a6f772a20..3351f9182 100644
--- a/packages/language/src/factory/declaration.ts
+++ b/packages/language/src/factory/declaration.ts
@@ -69,7 +69,7 @@ export class DataModelFactory extends AstFactory {
constructor() {
super({
- type: DataModel,
+ type: DataModel.$type,
node: {
attributes: [],
comments: [],
@@ -151,7 +151,7 @@ export class DataFieldFactory extends AstFactory {
type?: DataFieldTypeFactory;
constructor() {
- super({ type: DataField, node: { attributes: [], comments: [] } });
+ super({ type: DataField.$type, node: { attributes: [], comments: [] } });
}
addAttribute(
@@ -204,7 +204,7 @@ export class DataFieldTypeFactory extends AstFactory {
unsupported?: UnsupportedFieldTypeFactory;
constructor() {
- super({ type: DataFieldType });
+ super({ type: DataFieldType.$type });
}
setArray(array: boolean) {
@@ -254,7 +254,7 @@ export class DataFieldTypeFactory extends AstFactory {
export class UnsupportedFieldTypeFactory extends AstFactory {
value?: AstFactory;
constructor() {
- super({ type: UnsupportedFieldType });
+ super({ type: UnsupportedFieldType.$type });
}
setValue(builder: (value: ExpressionBuilder) => AstFactory) {
this.value = builder(ExpressionBuilder());
@@ -269,7 +269,7 @@ export class ModelFactory extends AstFactory {
declarations: AstFactory[] = [];
imports: ModelImportFactory[] = [];
constructor() {
- super({ type: Model, node: { declarations: [], imports: [] } });
+ super({ type: Model.$type, node: { declarations: [], imports: [] } });
}
addImport(builder: (b: ModelImportFactory) => ModelImportFactory) {
this.imports.push(builder(new ModelImportFactory()).setContainer(this.node));
@@ -291,7 +291,7 @@ export class ModelImportFactory extends AstFactory {
path?: string | undefined;
constructor() {
- super({ type: ModelImport });
+ super({ type: ModelImport.$type });
}
setPath(path: string) {
@@ -310,7 +310,7 @@ export class EnumFactory extends AstFactory {
attributes: DataModelAttributeFactory[] = [];
constructor() {
- super({ type: Enum, node: { comments: [], fields: [], attributes: [] } });
+ super({ type: Enum.$type, node: { comments: [], fields: [], attributes: [] } });
}
addField(builder: (b: EnumFieldFactory) => EnumFieldFactory) {
@@ -344,7 +344,7 @@ export class EnumFieldFactory extends AstFactory {
attributes: DataFieldAttributeFactory[] = [];
constructor() {
- super({ type: EnumField, node: { comments: [], attributes: [] } });
+ super({ type: EnumField.$type, node: { comments: [], attributes: [] } });
}
setName(name: RegularIDWithTypeNames) {
diff --git a/packages/language/src/factory/expression.ts b/packages/language/src/factory/expression.ts
index 19fe16af1..fee479b8b 100644
--- a/packages/language/src/factory/expression.ts
+++ b/packages/language/src/factory/expression.ts
@@ -79,7 +79,7 @@ export class UnaryExprFactory extends AstFactory {
operand?: AstFactory;
constructor() {
- super({ type: UnaryExpr, node: { operator: '!' } });
+ super({ type: UnaryExpr.$type, node: { operator: '!' } });
}
setOperand(builder: (a: ExpressionBuilder) => AstFactory) {
@@ -96,7 +96,7 @@ export class ReferenceExprFactory extends AstFactory {
args: ReferenceArgFactory[] = [];
constructor() {
- super({ type: ReferenceExpr, node: { args: [] } });
+ super({ type: ReferenceExpr.$type, node: { args: [] } });
}
setTarget(target: ReferenceTarget) {
@@ -128,7 +128,7 @@ export class ReferenceArgFactory extends AstFactory {
value?: AstFactory;
constructor() {
- super({ type: ReferenceArg });
+ super({ type: ReferenceArg.$type });
}
setName(name: string) {
@@ -153,7 +153,7 @@ export class MemberAccessExprFactory extends AstFactory {
operand?: AstFactory;
constructor() {
- super({ type: MemberAccessExpr });
+ super({ type: MemberAccessExpr.$type });
}
setMember(target: Reference) {
@@ -177,7 +177,7 @@ export class ObjectExprFactory extends AstFactory {
fields: FieldInitializerFactory[] = [];
constructor() {
- super({ type: ObjectExpr, node: { fields: [] } });
+ super({ type: ObjectExpr.$type, node: { fields: [] } });
}
addField(builder: (b: FieldInitializerFactory) => FieldInitializerFactory) {
@@ -194,7 +194,7 @@ export class FieldInitializerFactory extends AstFactory {
value?: AstFactory;
constructor() {
- super({ type: FieldInitializer });
+ super({ type: FieldInitializer.$type });
}
setName(name: RegularID) {
@@ -219,7 +219,7 @@ export class InvocationExprFactory extends AstFactory {
function?: Reference;
constructor() {
- super({ type: InvocationExpr, node: { args: [] } });
+ super({ type: InvocationExpr.$type, node: { args: [] } });
}
addArg(builder: (arg: ArgumentFactory) => ArgumentFactory) {
@@ -246,7 +246,7 @@ export class ArgumentFactory extends AstFactory {
value?: AstFactory;
constructor() {
- super({ type: Argument });
+ super({ type: Argument.$type });
}
setValue(builder: (a: ExpressionBuilder) => AstFactory) {
@@ -262,7 +262,7 @@ export class ArrayExprFactory extends AstFactory {
items: AstFactory[] = [];
constructor() {
- super({ type: ArrayExpr, node: { items: [] } });
+ super({ type: ArrayExpr.$type, node: { items: [] } });
}
addItem(builder: (a: ExpressionBuilder) => AstFactory) {
@@ -281,7 +281,7 @@ export class BinaryExprFactory extends AstFactory {
// TODO: add support for CollectionPredicateBinding
constructor() {
- super({ type: BinaryExpr });
+ super({ type: BinaryExpr.$type });
}
setOperator(operator: BinaryExpr['operator']) {
diff --git a/packages/language/src/factory/primitives.ts b/packages/language/src/factory/primitives.ts
index e97310d54..276ebaf8e 100644
--- a/packages/language/src/factory/primitives.ts
+++ b/packages/language/src/factory/primitives.ts
@@ -3,13 +3,13 @@ import { BooleanLiteral, NullExpr, NumberLiteral, StringLiteral, ThisExpr } from
export class ThisExprFactory extends AstFactory {
constructor() {
- super({ type: ThisExpr, node: { value: 'this' } });
+ super({ type: ThisExpr.$type, node: { value: 'this' } });
}
}
export class NullExprFactory extends AstFactory {
constructor() {
- super({ type: NullExpr, node: { value: 'null' } });
+ super({ type: NullExpr.$type, node: { value: 'null' } });
}
}
@@ -17,7 +17,7 @@ export class NumberLiteralFactory extends AstFactory {
value?: number | string;
constructor() {
- super({ type: NumberLiteral });
+ super({ type: NumberLiteral.$type });
}
setValue(value: number | string) {
@@ -33,7 +33,7 @@ export class StringLiteralFactory extends AstFactory {
value?: string;
constructor() {
- super({ type: StringLiteral });
+ super({ type: StringLiteral.$type });
}
setValue(value: string) {
@@ -48,7 +48,7 @@ export class BooleanLiteralFactory extends AstFactory {
value?: boolean;
constructor() {
- super({ type: BooleanLiteral });
+ super({ type: BooleanLiteral.$type });
}
setValue(value: boolean) {
diff --git a/packages/language/src/generated/ast.ts b/packages/language/src/generated/ast.ts
index 97431eccf..8609927f4 100644
--- a/packages/language/src/generated/ast.ts
+++ b/packages/language/src/generated/ast.ts
@@ -1,5 +1,5 @@
/******************************************************************************
- * This file was generated by langium-cli 3.5.0.
+ * This file was generated by langium-cli 4.2.1.
* DO NOT EDIT MANUALLY!
******************************************************************************/
@@ -88,88 +88,12 @@ export type ZModelTokenNames = ZModelTerminalNames | ZModelKeywordNames;
export type AbstractDeclaration = Attribute | DataModel | DataSource | Enum | FunctionDecl | GeneratorDecl | Plugin | Procedure | TypeDef;
-export const AbstractDeclaration = 'AbstractDeclaration';
+export const AbstractDeclaration = {
+ $type: 'AbstractDeclaration'
+} as const;
export function isAbstractDeclaration(item: unknown): item is AbstractDeclaration {
- return reflection.isInstance(item, AbstractDeclaration);
-}
-
-export type Boolean = boolean;
-
-export function isBoolean(item: unknown): item is Boolean {
- return typeof item === 'boolean';
-}
-
-export type BuiltinType = 'BigInt' | 'Boolean' | 'Bytes' | 'DateTime' | 'Decimal' | 'Float' | 'Int' | 'Json' | 'String';
-
-export function isBuiltinType(item: unknown): item is BuiltinType {
- return item === 'String' || item === 'Boolean' || item === 'Int' || item === 'BigInt' || item === 'Float' || item === 'Decimal' || item === 'DateTime' || item === 'Json' || item === 'Bytes';
-}
-
-export type ConfigExpr = ConfigArrayExpr | InvocationExpr | LiteralExpr;
-
-export const ConfigExpr = 'ConfigExpr';
-
-export function isConfigExpr(item: unknown): item is ConfigExpr {
- return reflection.isInstance(item, ConfigExpr);
-}
-
-export type Expression = ArrayExpr | BinaryExpr | InvocationExpr | LiteralExpr | MemberAccessExpr | NullExpr | ObjectExpr | ReferenceExpr | ThisExpr | UnaryExpr;
-
-export const Expression = 'Expression';
-
-export function isExpression(item: unknown): item is Expression {
- return reflection.isInstance(item, Expression);
-}
-
-export type ExpressionType = 'Any' | 'BigInt' | 'Boolean' | 'Bytes' | 'DateTime' | 'Decimal' | 'Float' | 'Int' | 'Json' | 'Null' | 'Object' | 'String' | 'Undefined' | 'Unsupported' | 'Void';
-
-export function isExpressionType(item: unknown): item is ExpressionType {
- return item === 'String' || item === 'Int' || item === 'Float' || item === 'Boolean' || item === 'BigInt' || item === 'Decimal' || item === 'DateTime' || item === 'Json' || item === 'Bytes' || item === 'Null' || item === 'Object' || item === 'Any' || item === 'Void' || item === 'Undefined' || item === 'Unsupported';
-}
-
-export type LiteralExpr = BooleanLiteral | NumberLiteral | StringLiteral;
-
-export const LiteralExpr = 'LiteralExpr';
-
-export function isLiteralExpr(item: unknown): item is LiteralExpr {
- return reflection.isInstance(item, LiteralExpr);
-}
-
-export type MemberAccessTarget = DataField;
-
-export const MemberAccessTarget = 'MemberAccessTarget';
-
-export function isMemberAccessTarget(item: unknown): item is MemberAccessTarget {
- return reflection.isInstance(item, MemberAccessTarget);
-}
-
-export type ReferenceTarget = CollectionPredicateBinding | DataField | EnumField | FunctionParam;
-
-export const ReferenceTarget = 'ReferenceTarget';
-
-export function isReferenceTarget(item: unknown): item is ReferenceTarget {
- return reflection.isInstance(item, ReferenceTarget);
-}
-
-export type RegularID = 'abstract' | 'attribute' | 'datasource' | 'enum' | 'import' | 'in' | 'model' | 'plugin' | 'type' | 'view' | string;
-
-export function isRegularID(item: unknown): item is RegularID {
- return item === 'model' || item === 'enum' || item === 'attribute' || item === 'datasource' || item === 'plugin' || item === 'abstract' || item === 'in' || item === 'view' || item === 'import' || item === 'type' || (typeof item === 'string' && (/[_a-zA-Z][\w_]*/.test(item)));
-}
-
-export type RegularIDWithTypeNames = 'Any' | 'BigInt' | 'Boolean' | 'Bytes' | 'DateTime' | 'Decimal' | 'Float' | 'Int' | 'Json' | 'Null' | 'Object' | 'String' | 'Unsupported' | 'Void' | RegularID;
-
-export function isRegularIDWithTypeNames(item: unknown): item is RegularIDWithTypeNames {
- return isRegularID(item) || item === 'String' || item === 'Boolean' || item === 'Int' || item === 'BigInt' || item === 'Float' || item === 'Decimal' || item === 'DateTime' || item === 'Json' || item === 'Bytes' || item === 'Null' || item === 'Object' || item === 'Any' || item === 'Void' || item === 'Unsupported';
-}
-
-export type TypeDeclaration = DataModel | Enum | TypeDef;
-
-export const TypeDeclaration = 'TypeDeclaration';
-
-export function isTypeDeclaration(item: unknown): item is TypeDeclaration {
- return reflection.isInstance(item, TypeDeclaration);
+ return reflection.isInstance(item, AbstractDeclaration.$type);
}
export interface Argument extends langium.AstNode {
@@ -178,10 +102,13 @@ export interface Argument extends langium.AstNode {
value: Expression;
}
-export const Argument = 'Argument';
+export const Argument = {
+ $type: 'Argument',
+ value: 'value'
+} as const;
export function isArgument(item: unknown): item is Argument {
- return reflection.isInstance(item, Argument);
+ return reflection.isInstance(item, Argument.$type);
}
export interface ArrayExpr extends langium.AstNode {
@@ -190,10 +117,13 @@ export interface ArrayExpr extends langium.AstNode {
items: Array;
}
-export const ArrayExpr = 'ArrayExpr';
+export const ArrayExpr = {
+ $type: 'ArrayExpr',
+ items: 'items'
+} as const;
export function isArrayExpr(item: unknown): item is ArrayExpr {
- return reflection.isInstance(item, ArrayExpr);
+ return reflection.isInstance(item, ArrayExpr.$type);
}
export interface Attribute extends langium.AstNode {
@@ -205,10 +135,16 @@ export interface Attribute extends langium.AstNode {
params: Array;
}
-export const Attribute = 'Attribute';
+export const Attribute = {
+ $type: 'Attribute',
+ attributes: 'attributes',
+ comments: 'comments',
+ name: 'name',
+ params: 'params'
+} as const;
export function isAttribute(item: unknown): item is Attribute {
- return reflection.isInstance(item, Attribute);
+ return reflection.isInstance(item, Attribute.$type);
}
export interface AttributeArg extends langium.AstNode {
@@ -220,10 +156,14 @@ export interface AttributeArg extends langium.AstNode {
$resolvedParam?: AttributeParam;
}
-export const AttributeArg = 'AttributeArg';
+export const AttributeArg = {
+ $type: 'AttributeArg',
+ name: 'name',
+ value: 'value'
+} as const;
export function isAttributeArg(item: unknown): item is AttributeArg {
- return reflection.isInstance(item, AttributeArg);
+ return reflection.isInstance(item, AttributeArg.$type);
}
export interface AttributeParam extends langium.AstNode {
@@ -236,10 +176,17 @@ export interface AttributeParam extends langium.AstNode {
type: AttributeParamType;
}
-export const AttributeParam = 'AttributeParam';
+export const AttributeParam = {
+ $type: 'AttributeParam',
+ attributes: 'attributes',
+ comments: 'comments',
+ default: 'default',
+ name: 'name',
+ type: 'type'
+} as const;
export function isAttributeParam(item: unknown): item is AttributeParam {
- return reflection.isInstance(item, AttributeParam);
+ return reflection.isInstance(item, AttributeParam.$type);
}
export interface AttributeParamType extends langium.AstNode {
@@ -251,10 +198,16 @@ export interface AttributeParamType extends langium.AstNode {
type?: 'ContextType' | 'FieldReference' | 'TransitiveFieldReference' | ExpressionType;
}
-export const AttributeParamType = 'AttributeParamType';
+export const AttributeParamType = {
+ $type: 'AttributeParamType',
+ array: 'array',
+ optional: 'optional',
+ reference: 'reference',
+ type: 'type'
+} as const;
export function isAttributeParamType(item: unknown): item is AttributeParamType {
- return reflection.isInstance(item, AttributeParamType);
+ return reflection.isInstance(item, AttributeParamType.$type);
}
export interface BinaryExpr extends langium.AstNode {
@@ -266,10 +219,22 @@ export interface BinaryExpr extends langium.AstNode {
right: Expression;
}
-export const BinaryExpr = 'BinaryExpr';
+export const BinaryExpr = {
+ $type: 'BinaryExpr',
+ binding: 'binding',
+ left: 'left',
+ operator: 'operator',
+ right: 'right'
+} as const;
export function isBinaryExpr(item: unknown): item is BinaryExpr {
- return reflection.isInstance(item, BinaryExpr);
+ return reflection.isInstance(item, BinaryExpr.$type);
+}
+
+export type Boolean = boolean;
+
+export function isBoolean(item: unknown): item is Boolean {
+ return typeof item === 'boolean';
}
export interface BooleanLiteral extends langium.AstNode {
@@ -278,10 +243,19 @@ export interface BooleanLiteral extends langium.AstNode {
value: Boolean;
}
-export const BooleanLiteral = 'BooleanLiteral';
+export const BooleanLiteral = {
+ $type: 'BooleanLiteral',
+ value: 'value'
+} as const;
export function isBooleanLiteral(item: unknown): item is BooleanLiteral {
- return reflection.isInstance(item, BooleanLiteral);
+ return reflection.isInstance(item, BooleanLiteral.$type);
+}
+
+export type BuiltinType = 'BigInt' | 'Boolean' | 'Bytes' | 'DateTime' | 'Decimal' | 'Float' | 'Int' | 'Json' | 'String';
+
+export function isBuiltinType(item: unknown): item is BuiltinType {
+ return item === 'String' || item === 'Boolean' || item === 'Int' || item === 'BigInt' || item === 'Float' || item === 'Decimal' || item === 'DateTime' || item === 'Json' || item === 'Bytes';
}
export interface CollectionPredicateBinding extends langium.AstNode {
@@ -290,10 +264,13 @@ export interface CollectionPredicateBinding extends langium.AstNode {
name: RegularID;
}
-export const CollectionPredicateBinding = 'CollectionPredicateBinding';
+export const CollectionPredicateBinding = {
+ $type: 'CollectionPredicateBinding',
+ name: 'name'
+} as const;
export function isCollectionPredicateBinding(item: unknown): item is CollectionPredicateBinding {
- return reflection.isInstance(item, CollectionPredicateBinding);
+ return reflection.isInstance(item, CollectionPredicateBinding.$type);
}
export interface ConfigArrayExpr extends langium.AstNode {
@@ -302,10 +279,23 @@ export interface ConfigArrayExpr extends langium.AstNode {
items: Array;
}
-export const ConfigArrayExpr = 'ConfigArrayExpr';
+export const ConfigArrayExpr = {
+ $type: 'ConfigArrayExpr',
+ items: 'items'
+} as const;
export function isConfigArrayExpr(item: unknown): item is ConfigArrayExpr {
- return reflection.isInstance(item, ConfigArrayExpr);
+ return reflection.isInstance(item, ConfigArrayExpr.$type);
+}
+
+export type ConfigExpr = ConfigArrayExpr | InvocationExpr | LiteralExpr;
+
+export const ConfigExpr = {
+ $type: 'ConfigExpr'
+} as const;
+
+export function isConfigExpr(item: unknown): item is ConfigExpr {
+ return reflection.isInstance(item, ConfigExpr.$type);
}
export interface ConfigField extends langium.AstNode {
@@ -315,10 +305,14 @@ export interface ConfigField extends langium.AstNode {
value: ConfigExpr;
}
-export const ConfigField = 'ConfigField';
+export const ConfigField = {
+ $type: 'ConfigField',
+ name: 'name',
+ value: 'value'
+} as const;
export function isConfigField(item: unknown): item is ConfigField {
- return reflection.isInstance(item, ConfigField);
+ return reflection.isInstance(item, ConfigField.$type);
}
export interface ConfigInvocationArg extends langium.AstNode {
@@ -328,10 +322,14 @@ export interface ConfigInvocationArg extends langium.AstNode {
value: LiteralExpr;
}
-export const ConfigInvocationArg = 'ConfigInvocationArg';
+export const ConfigInvocationArg = {
+ $type: 'ConfigInvocationArg',
+ name: 'name',
+ value: 'value'
+} as const;
export function isConfigInvocationArg(item: unknown): item is ConfigInvocationArg {
- return reflection.isInstance(item, ConfigInvocationArg);
+ return reflection.isInstance(item, ConfigInvocationArg.$type);
}
export interface ConfigInvocationExpr extends langium.AstNode {
@@ -341,10 +339,14 @@ export interface ConfigInvocationExpr extends langium.AstNode {
name: string;
}
-export const ConfigInvocationExpr = 'ConfigInvocationExpr';
+export const ConfigInvocationExpr = {
+ $type: 'ConfigInvocationExpr',
+ args: 'args',
+ name: 'name'
+} as const;
export function isConfigInvocationExpr(item: unknown): item is ConfigInvocationExpr {
- return reflection.isInstance(item, ConfigInvocationExpr);
+ return reflection.isInstance(item, ConfigInvocationExpr.$type);
}
export interface DataField extends langium.AstNode {
@@ -356,10 +358,16 @@ export interface DataField extends langium.AstNode {
type: DataFieldType;
}
-export const DataField = 'DataField';
+export const DataField = {
+ $type: 'DataField',
+ attributes: 'attributes',
+ comments: 'comments',
+ name: 'name',
+ type: 'type'
+} as const;
export function isDataField(item: unknown): item is DataField {
- return reflection.isInstance(item, DataField);
+ return reflection.isInstance(item, DataField.$type);
}
export interface DataFieldAttribute extends langium.AstNode {
@@ -369,10 +377,14 @@ export interface DataFieldAttribute extends langium.AstNode {
decl: langium.Reference;
}
-export const DataFieldAttribute = 'DataFieldAttribute';
+export const DataFieldAttribute = {
+ $type: 'DataFieldAttribute',
+ args: 'args',
+ decl: 'decl'
+} as const;
export function isDataFieldAttribute(item: unknown): item is DataFieldAttribute {
- return reflection.isInstance(item, DataFieldAttribute);
+ return reflection.isInstance(item, DataFieldAttribute.$type);
}
export interface DataFieldType extends langium.AstNode {
@@ -385,10 +397,17 @@ export interface DataFieldType extends langium.AstNode {
unsupported?: UnsupportedFieldType;
}
-export const DataFieldType = 'DataFieldType';
+export const DataFieldType = {
+ $type: 'DataFieldType',
+ array: 'array',
+ optional: 'optional',
+ reference: 'reference',
+ type: 'type',
+ unsupported: 'unsupported'
+} as const;
export function isDataFieldType(item: unknown): item is DataFieldType {
- return reflection.isInstance(item, DataFieldType);
+ return reflection.isInstance(item, DataFieldType.$type);
}
export interface DataModel extends langium.AstNode {
@@ -405,10 +424,19 @@ export interface DataModel extends langium.AstNode {
$allFields?: DataField[];
}
-export const DataModel = 'DataModel';
+export const DataModel = {
+ $type: 'DataModel',
+ attributes: 'attributes',
+ baseModel: 'baseModel',
+ comments: 'comments',
+ fields: 'fields',
+ isView: 'isView',
+ mixins: 'mixins',
+ name: 'name'
+} as const;
export function isDataModel(item: unknown): item is DataModel {
- return reflection.isInstance(item, DataModel);
+ return reflection.isInstance(item, DataModel.$type);
}
export interface DataModelAttribute extends langium.AstNode {
@@ -418,10 +446,14 @@ export interface DataModelAttribute extends langium.AstNode {
decl: langium.Reference;
}
-export const DataModelAttribute = 'DataModelAttribute';
+export const DataModelAttribute = {
+ $type: 'DataModelAttribute',
+ args: 'args',
+ decl: 'decl'
+} as const;
export function isDataModelAttribute(item: unknown): item is DataModelAttribute {
- return reflection.isInstance(item, DataModelAttribute);
+ return reflection.isInstance(item, DataModelAttribute.$type);
}
export interface DataSource extends langium.AstNode {
@@ -431,10 +463,14 @@ export interface DataSource extends langium.AstNode {
name: RegularID;
}
-export const DataSource = 'DataSource';
+export const DataSource = {
+ $type: 'DataSource',
+ fields: 'fields',
+ name: 'name'
+} as const;
export function isDataSource(item: unknown): item is DataSource {
- return reflection.isInstance(item, DataSource);
+ return reflection.isInstance(item, DataSource.$type);
}
export interface Enum extends langium.AstNode {
@@ -446,10 +482,16 @@ export interface Enum extends langium.AstNode {
name: RegularID;
}
-export const Enum = 'Enum';
+export const Enum = {
+ $type: 'Enum',
+ attributes: 'attributes',
+ comments: 'comments',
+ fields: 'fields',
+ name: 'name'
+} as const;
export function isEnum(item: unknown): item is Enum {
- return reflection.isInstance(item, Enum);
+ return reflection.isInstance(item, Enum.$type);
}
export interface EnumField extends langium.AstNode {
@@ -460,10 +502,31 @@ export interface EnumField extends langium.AstNode {
name: RegularIDWithTypeNames;
}
-export const EnumField = 'EnumField';
+export const EnumField = {
+ $type: 'EnumField',
+ attributes: 'attributes',
+ comments: 'comments',
+ name: 'name'
+} as const;
export function isEnumField(item: unknown): item is EnumField {
- return reflection.isInstance(item, EnumField);
+ return reflection.isInstance(item, EnumField.$type);
+}
+
+export type Expression = ArrayExpr | BinaryExpr | InvocationExpr | LiteralExpr | MemberAccessExpr | NullExpr | ObjectExpr | ReferenceExpr | ThisExpr | UnaryExpr;
+
+export const Expression = {
+ $type: 'Expression'
+} as const;
+
+export function isExpression(item: unknown): item is Expression {
+ return reflection.isInstance(item, Expression.$type);
+}
+
+export type ExpressionType = 'Any' | 'BigInt' | 'Boolean' | 'Bytes' | 'DateTime' | 'Decimal' | 'Float' | 'Int' | 'Json' | 'Null' | 'Object' | 'String' | 'Undefined' | 'Unsupported' | 'Void';
+
+export function isExpressionType(item: unknown): item is ExpressionType {
+ return item === 'String' || item === 'Int' || item === 'Float' || item === 'Boolean' || item === 'BigInt' || item === 'Decimal' || item === 'DateTime' || item === 'Json' || item === 'Bytes' || item === 'Null' || item === 'Object' || item === 'Any' || item === 'Void' || item === 'Undefined' || item === 'Unsupported';
}
export interface FieldInitializer extends langium.AstNode {
@@ -473,10 +536,14 @@ export interface FieldInitializer extends langium.AstNode {
value: Expression;
}
-export const FieldInitializer = 'FieldInitializer';
+export const FieldInitializer = {
+ $type: 'FieldInitializer',
+ name: 'name',
+ value: 'value'
+} as const;
export function isFieldInitializer(item: unknown): item is FieldInitializer {
- return reflection.isInstance(item, FieldInitializer);
+ return reflection.isInstance(item, FieldInitializer.$type);
}
export interface FunctionDecl extends langium.AstNode {
@@ -489,10 +556,17 @@ export interface FunctionDecl extends langium.AstNode {
returnType: FunctionParamType;
}
-export const FunctionDecl = 'FunctionDecl';
+export const FunctionDecl = {
+ $type: 'FunctionDecl',
+ attributes: 'attributes',
+ expression: 'expression',
+ name: 'name',
+ params: 'params',
+ returnType: 'returnType'
+} as const;
export function isFunctionDecl(item: unknown): item is FunctionDecl {
- return reflection.isInstance(item, FunctionDecl);
+ return reflection.isInstance(item, FunctionDecl.$type);
}
export interface FunctionParam extends langium.AstNode {
@@ -503,10 +577,15 @@ export interface FunctionParam extends langium.AstNode {
type: FunctionParamType;
}
-export const FunctionParam = 'FunctionParam';
+export const FunctionParam = {
+ $type: 'FunctionParam',
+ name: 'name',
+ optional: 'optional',
+ type: 'type'
+} as const;
export function isFunctionParam(item: unknown): item is FunctionParam {
- return reflection.isInstance(item, FunctionParam);
+ return reflection.isInstance(item, FunctionParam.$type);
}
export interface FunctionParamType extends langium.AstNode {
@@ -517,10 +596,15 @@ export interface FunctionParamType extends langium.AstNode {
type?: ExpressionType;
}
-export const FunctionParamType = 'FunctionParamType';
+export const FunctionParamType = {
+ $type: 'FunctionParamType',
+ array: 'array',
+ reference: 'reference',
+ type: 'type'
+} as const;
export function isFunctionParamType(item: unknown): item is FunctionParamType {
- return reflection.isInstance(item, FunctionParamType);
+ return reflection.isInstance(item, FunctionParamType.$type);
}
export interface GeneratorDecl extends langium.AstNode {
@@ -530,10 +614,14 @@ export interface GeneratorDecl extends langium.AstNode {
name: RegularID;
}
-export const GeneratorDecl = 'GeneratorDecl';
+export const GeneratorDecl = {
+ $type: 'GeneratorDecl',
+ fields: 'fields',
+ name: 'name'
+} as const;
export function isGeneratorDecl(item: unknown): item is GeneratorDecl {
- return reflection.isInstance(item, GeneratorDecl);
+ return reflection.isInstance(item, GeneratorDecl.$type);
}
export interface InternalAttribute extends langium.AstNode {
@@ -543,10 +631,14 @@ export interface InternalAttribute extends langium.AstNode {
decl: langium.Reference;
}
-export const InternalAttribute = 'InternalAttribute';
+export const InternalAttribute = {
+ $type: 'InternalAttribute',
+ args: 'args',
+ decl: 'decl'
+} as const;
export function isInternalAttribute(item: unknown): item is InternalAttribute {
- return reflection.isInstance(item, InternalAttribute);
+ return reflection.isInstance(item, InternalAttribute.$type);
}
export interface InvocationExpr extends langium.AstNode {
@@ -556,10 +648,24 @@ export interface InvocationExpr extends langium.AstNode {
function: langium.Reference;
}
-export const InvocationExpr = 'InvocationExpr';
+export const InvocationExpr = {
+ $type: 'InvocationExpr',
+ args: 'args',
+ function: 'function'
+} as const;
export function isInvocationExpr(item: unknown): item is InvocationExpr {
- return reflection.isInstance(item, InvocationExpr);
+ return reflection.isInstance(item, InvocationExpr.$type);
+}
+
+export type LiteralExpr = BooleanLiteral | NumberLiteral | StringLiteral;
+
+export const LiteralExpr = {
+ $type: 'LiteralExpr'
+} as const;
+
+export function isLiteralExpr(item: unknown): item is LiteralExpr {
+ return reflection.isInstance(item, LiteralExpr.$type);
}
export interface MemberAccessExpr extends langium.AstNode {
@@ -569,10 +675,24 @@ export interface MemberAccessExpr extends langium.AstNode {
operand: Expression;
}
-export const MemberAccessExpr = 'MemberAccessExpr';
+export const MemberAccessExpr = {
+ $type: 'MemberAccessExpr',
+ member: 'member',
+ operand: 'operand'
+} as const;
export function isMemberAccessExpr(item: unknown): item is MemberAccessExpr {
- return reflection.isInstance(item, MemberAccessExpr);
+ return reflection.isInstance(item, MemberAccessExpr.$type);
+}
+
+export type MemberAccessTarget = DataField;
+
+export const MemberAccessTarget = {
+ $type: 'MemberAccessTarget'
+} as const;
+
+export function isMemberAccessTarget(item: unknown): item is MemberAccessTarget {
+ return reflection.isInstance(item, MemberAccessTarget.$type);
}
export interface Model extends langium.AstNode {
@@ -581,10 +701,14 @@ export interface Model extends langium.AstNode {
imports: Array;
}
-export const Model = 'Model';
+export const Model = {
+ $type: 'Model',
+ declarations: 'declarations',
+ imports: 'imports'
+} as const;
export function isModel(item: unknown): item is Model {
- return reflection.isInstance(item, Model);
+ return reflection.isInstance(item, Model.$type);
}
export interface ModelImport extends langium.AstNode {
@@ -593,10 +717,13 @@ export interface ModelImport extends langium.AstNode {
path: string;
}
-export const ModelImport = 'ModelImport';
+export const ModelImport = {
+ $type: 'ModelImport',
+ path: 'path'
+} as const;
export function isModelImport(item: unknown): item is ModelImport {
- return reflection.isInstance(item, ModelImport);
+ return reflection.isInstance(item, ModelImport.$type);
}
export interface NullExpr extends langium.AstNode {
@@ -605,10 +732,13 @@ export interface NullExpr extends langium.AstNode {
value: 'null';
}
-export const NullExpr = 'NullExpr';
+export const NullExpr = {
+ $type: 'NullExpr',
+ value: 'value'
+} as const;
export function isNullExpr(item: unknown): item is NullExpr {
- return reflection.isInstance(item, NullExpr);
+ return reflection.isInstance(item, NullExpr.$type);
}
export interface NumberLiteral extends langium.AstNode {
@@ -617,10 +747,13 @@ export interface NumberLiteral extends langium.AstNode {
value: string;
}
-export const NumberLiteral = 'NumberLiteral';
+export const NumberLiteral = {
+ $type: 'NumberLiteral',
+ value: 'value'
+} as const;
export function isNumberLiteral(item: unknown): item is NumberLiteral {
- return reflection.isInstance(item, NumberLiteral);
+ return reflection.isInstance(item, NumberLiteral.$type);
}
export interface ObjectExpr extends langium.AstNode {
@@ -629,10 +762,13 @@ export interface ObjectExpr extends langium.AstNode {
fields: Array;
}
-export const ObjectExpr = 'ObjectExpr';
+export const ObjectExpr = {
+ $type: 'ObjectExpr',
+ fields: 'fields'
+} as const;
export function isObjectExpr(item: unknown): item is ObjectExpr {
- return reflection.isInstance(item, ObjectExpr);
+ return reflection.isInstance(item, ObjectExpr.$type);
}
export interface Plugin extends langium.AstNode {
@@ -642,10 +778,14 @@ export interface Plugin extends langium.AstNode {
name: RegularID;
}
-export const Plugin = 'Plugin';
+export const Plugin = {
+ $type: 'Plugin',
+ fields: 'fields',
+ name: 'name'
+} as const;
export function isPlugin(item: unknown): item is Plugin {
- return reflection.isInstance(item, Plugin);
+ return reflection.isInstance(item, Plugin.$type);
}
export interface PluginField extends langium.AstNode {
@@ -655,10 +795,14 @@ export interface PluginField extends langium.AstNode {
value: ArrayExpr | LiteralExpr | ObjectExpr;
}
-export const PluginField = 'PluginField';
+export const PluginField = {
+ $type: 'PluginField',
+ name: 'name',
+ value: 'value'
+} as const;
export function isPluginField(item: unknown): item is PluginField {
- return reflection.isInstance(item, PluginField);
+ return reflection.isInstance(item, PluginField.$type);
}
export interface Procedure extends langium.AstNode {
@@ -671,10 +815,17 @@ export interface Procedure extends langium.AstNode {
returnType: FunctionParamType;
}
-export const Procedure = 'Procedure';
+export const Procedure = {
+ $type: 'Procedure',
+ attributes: 'attributes',
+ mutation: 'mutation',
+ name: 'name',
+ params: 'params',
+ returnType: 'returnType'
+} as const;
export function isProcedure(item: unknown): item is Procedure {
- return reflection.isInstance(item, Procedure);
+ return reflection.isInstance(item, Procedure.$type);
}
export interface ProcedureParam extends langium.AstNode {
@@ -685,10 +836,15 @@ export interface ProcedureParam extends langium.AstNode {
type: FunctionParamType;
}
-export const ProcedureParam = 'ProcedureParam';
+export const ProcedureParam = {
+ $type: 'ProcedureParam',
+ name: 'name',
+ optional: 'optional',
+ type: 'type'
+} as const;
export function isProcedureParam(item: unknown): item is ProcedureParam {
- return reflection.isInstance(item, ProcedureParam);
+ return reflection.isInstance(item, ProcedureParam.$type);
}
export interface ReferenceArg extends langium.AstNode {
@@ -698,10 +854,14 @@ export interface ReferenceArg extends langium.AstNode {
value: Expression;
}
-export const ReferenceArg = 'ReferenceArg';
+export const ReferenceArg = {
+ $type: 'ReferenceArg',
+ name: 'name',
+ value: 'value'
+} as const;
export function isReferenceArg(item: unknown): item is ReferenceArg {
- return reflection.isInstance(item, ReferenceArg);
+ return reflection.isInstance(item, ReferenceArg.$type);
}
export interface ReferenceExpr extends langium.AstNode {
@@ -711,10 +871,36 @@ export interface ReferenceExpr extends langium.AstNode {
target: langium.Reference;
}
-export const ReferenceExpr = 'ReferenceExpr';
+export const ReferenceExpr = {
+ $type: 'ReferenceExpr',
+ args: 'args',
+ target: 'target'
+} as const;
export function isReferenceExpr(item: unknown): item is ReferenceExpr {
- return reflection.isInstance(item, ReferenceExpr);
+ return reflection.isInstance(item, ReferenceExpr.$type);
+}
+
+export type ReferenceTarget = CollectionPredicateBinding | DataField | EnumField | FunctionParam;
+
+export const ReferenceTarget = {
+ $type: 'ReferenceTarget'
+} as const;
+
+export function isReferenceTarget(item: unknown): item is ReferenceTarget {
+ return reflection.isInstance(item, ReferenceTarget.$type);
+}
+
+export type RegularID = 'abstract' | 'attribute' | 'datasource' | 'enum' | 'import' | 'in' | 'model' | 'plugin' | 'type' | 'view' | string;
+
+export function isRegularID(item: unknown): item is RegularID {
+ return item === 'model' || item === 'enum' || item === 'attribute' || item === 'datasource' || item === 'plugin' || item === 'abstract' || item === 'in' || item === 'view' || item === 'import' || item === 'type' || (typeof item === 'string' && (/[_a-zA-Z][\w_]*/.test(item)));
+}
+
+export type RegularIDWithTypeNames = 'Any' | 'BigInt' | 'Boolean' | 'Bytes' | 'DateTime' | 'Decimal' | 'Float' | 'Int' | 'Json' | 'Null' | 'Object' | 'String' | 'Unsupported' | 'Void' | RegularID;
+
+export function isRegularIDWithTypeNames(item: unknown): item is RegularIDWithTypeNames {
+ return isRegularID(item) || item === 'String' || item === 'Boolean' || item === 'Int' || item === 'BigInt' || item === 'Float' || item === 'Decimal' || item === 'DateTime' || item === 'Json' || item === 'Bytes' || item === 'Null' || item === 'Object' || item === 'Any' || item === 'Void' || item === 'Unsupported';
}
export interface StringLiteral extends langium.AstNode {
@@ -723,10 +909,13 @@ export interface StringLiteral extends langium.AstNode {
value: string;
}
-export const StringLiteral = 'StringLiteral';
+export const StringLiteral = {
+ $type: 'StringLiteral',
+ value: 'value'
+} as const;
export function isStringLiteral(item: unknown): item is StringLiteral {
- return reflection.isInstance(item, StringLiteral);
+ return reflection.isInstance(item, StringLiteral.$type);
}
export interface ThisExpr extends langium.AstNode {
@@ -735,10 +924,23 @@ export interface ThisExpr extends langium.AstNode {
value: 'this';
}
-export const ThisExpr = 'ThisExpr';
+export const ThisExpr = {
+ $type: 'ThisExpr',
+ value: 'value'
+} as const;
export function isThisExpr(item: unknown): item is ThisExpr {
- return reflection.isInstance(item, ThisExpr);
+ return reflection.isInstance(item, ThisExpr.$type);
+}
+
+export type TypeDeclaration = DataModel | Enum | TypeDef;
+
+export const TypeDeclaration = {
+ $type: 'TypeDeclaration'
+} as const;
+
+export function isTypeDeclaration(item: unknown): item is TypeDeclaration {
+ return reflection.isInstance(item, TypeDeclaration.$type);
}
export interface TypeDef extends langium.AstNode {
@@ -751,10 +953,17 @@ export interface TypeDef extends langium.AstNode {
name: RegularID;
}
-export const TypeDef = 'TypeDef';
+export const TypeDef = {
+ $type: 'TypeDef',
+ attributes: 'attributes',
+ comments: 'comments',
+ fields: 'fields',
+ mixins: 'mixins',
+ name: 'name'
+} as const;
export function isTypeDef(item: unknown): item is TypeDef {
- return reflection.isInstance(item, TypeDef);
+ return reflection.isInstance(item, TypeDef.$type);
}
export interface UnaryExpr extends langium.AstNode {
@@ -764,10 +973,14 @@ export interface UnaryExpr extends langium.AstNode {
operator: '!';
}
-export const UnaryExpr = 'UnaryExpr';
+export const UnaryExpr = {
+ $type: 'UnaryExpr',
+ operand: 'operand',
+ operator: 'operator'
+} as const;
export function isUnaryExpr(item: unknown): item is UnaryExpr {
- return reflection.isInstance(item, UnaryExpr);
+ return reflection.isInstance(item, UnaryExpr.$type);
}
export interface UnsupportedFieldType extends langium.AstNode {
@@ -776,10 +989,13 @@ export interface UnsupportedFieldType extends langium.AstNode {
value: LiteralExpr;
}
-export const UnsupportedFieldType = 'UnsupportedFieldType';
+export const UnsupportedFieldType = {
+ $type: 'UnsupportedFieldType',
+ value: 'value'
+} as const;
export function isUnsupportedFieldType(item: unknown): item is UnsupportedFieldType {
- return reflection.isInstance(item, UnsupportedFieldType);
+ return reflection.isInstance(item, UnsupportedFieldType.$type);
}
export type ZModelAstType = {
@@ -838,534 +1054,716 @@ export type ZModelAstType = {
}
export class ZModelAstReflection extends langium.AbstractAstReflection {
-
- getAllTypes(): string[] {
- return [AbstractDeclaration, Argument, ArrayExpr, Attribute, AttributeArg, AttributeParam, AttributeParamType, BinaryExpr, BooleanLiteral, CollectionPredicateBinding, ConfigArrayExpr, ConfigExpr, ConfigField, ConfigInvocationArg, ConfigInvocationExpr, DataField, DataFieldAttribute, DataFieldType, DataModel, DataModelAttribute, DataSource, Enum, EnumField, Expression, FieldInitializer, FunctionDecl, FunctionParam, FunctionParamType, GeneratorDecl, InternalAttribute, InvocationExpr, LiteralExpr, MemberAccessExpr, MemberAccessTarget, Model, ModelImport, NullExpr, NumberLiteral, ObjectExpr, Plugin, PluginField, Procedure, ProcedureParam, ReferenceArg, ReferenceExpr, ReferenceTarget, StringLiteral, ThisExpr, TypeDeclaration, TypeDef, UnaryExpr, UnsupportedFieldType];
- }
-
- protected override computeIsSubtype(subtype: string, supertype: string): boolean {
- switch (subtype) {
- case ArrayExpr:
- case BinaryExpr:
- case MemberAccessExpr:
- case NullExpr:
- case ObjectExpr:
- case ReferenceExpr:
- case ThisExpr:
- case UnaryExpr: {
- return this.isSubtype(Expression, supertype);
- }
- case Attribute:
- case DataSource:
- case FunctionDecl:
- case GeneratorDecl:
- case Plugin:
- case Procedure: {
- return this.isSubtype(AbstractDeclaration, supertype);
- }
- case BooleanLiteral:
- case NumberLiteral:
- case StringLiteral: {
- return this.isSubtype(LiteralExpr, supertype);
- }
- case CollectionPredicateBinding:
- case EnumField:
- case FunctionParam: {
- return this.isSubtype(ReferenceTarget, supertype);
- }
- case ConfigArrayExpr: {
- return this.isSubtype(ConfigExpr, supertype);
- }
- case DataField: {
- return this.isSubtype(MemberAccessTarget, supertype) || this.isSubtype(ReferenceTarget, supertype);
- }
- case DataModel:
- case Enum:
- case TypeDef: {
- return this.isSubtype(AbstractDeclaration, supertype) || this.isSubtype(TypeDeclaration, supertype);
- }
- case InvocationExpr:
- case LiteralExpr: {
- return this.isSubtype(ConfigExpr, supertype) || this.isSubtype(Expression, supertype);
- }
- default: {
- return false;
- }
- }
- }
-
- getReferenceType(refInfo: langium.ReferenceInfo): string {
- const referenceId = `${refInfo.container.$type}:${refInfo.property}`;
- switch (referenceId) {
- case 'AttributeParamType:reference':
- case 'DataFieldType:reference':
- case 'FunctionParamType:reference': {
- return TypeDeclaration;
- }
- case 'DataFieldAttribute:decl':
- case 'DataModelAttribute:decl':
- case 'InternalAttribute:decl': {
- return Attribute;
- }
- case 'DataModel:baseModel': {
- return DataModel;
- }
- case 'DataModel:mixins':
- case 'TypeDef:mixins': {
- return TypeDef;
- }
- case 'InvocationExpr:function': {
- return FunctionDecl;
- }
- case 'MemberAccessExpr:member': {
- return MemberAccessTarget;
- }
- case 'ReferenceExpr:target': {
- return ReferenceTarget;
- }
- default: {
- throw new Error(`${referenceId} is not a valid reference id.`);
- }
- }
- }
-
- getTypeMetaData(type: string): langium.TypeMetaData {
- switch (type) {
- case Argument: {
- return {
- name: Argument,
- properties: [
- { name: 'value' }
- ]
- };
- }
- case ArrayExpr: {
- return {
- name: ArrayExpr,
- properties: [
- { name: 'items', defaultValue: [] }
- ]
- };
- }
- case Attribute: {
- return {
- name: Attribute,
- properties: [
- { name: 'attributes', defaultValue: [] },
- { name: 'comments', defaultValue: [] },
- { name: 'name' },
- { name: 'params', defaultValue: [] }
- ]
- };
- }
- case AttributeArg: {
- return {
- name: AttributeArg,
- properties: [
- { name: 'name' },
- { name: 'value' }
- ]
- };
- }
- case AttributeParam: {
- return {
- name: AttributeParam,
- properties: [
- { name: 'attributes', defaultValue: [] },
- { name: 'comments', defaultValue: [] },
- { name: 'default', defaultValue: false },
- { name: 'name' },
- { name: 'type' }
- ]
- };
- }
- case AttributeParamType: {
- return {
- name: AttributeParamType,
- properties: [
- { name: 'array', defaultValue: false },
- { name: 'optional', defaultValue: false },
- { name: 'reference' },
- { name: 'type' }
- ]
- };
- }
- case BinaryExpr: {
- return {
- name: BinaryExpr,
- properties: [
- { name: 'binding' },
- { name: 'left' },
- { name: 'operator' },
- { name: 'right' }
- ]
- };
- }
- case BooleanLiteral: {
- return {
- name: BooleanLiteral,
- properties: [
- { name: 'value' }
- ]
- };
- }
- case CollectionPredicateBinding: {
- return {
- name: CollectionPredicateBinding,
- properties: [
- { name: 'name' }
- ]
- };
- }
- case ConfigArrayExpr: {
- return {
- name: ConfigArrayExpr,
- properties: [
- { name: 'items', defaultValue: [] }
- ]
- };
- }
- case ConfigField: {
- return {
- name: ConfigField,
- properties: [
- { name: 'name' },
- { name: 'value' }
- ]
- };
- }
- case ConfigInvocationArg: {
- return {
- name: ConfigInvocationArg,
- properties: [
- { name: 'name' },
- { name: 'value' }
- ]
- };
- }
- case ConfigInvocationExpr: {
- return {
- name: ConfigInvocationExpr,
- properties: [
- { name: 'args', defaultValue: [] },
- { name: 'name' }
- ]
- };
- }
- case DataField: {
- return {
- name: DataField,
- properties: [
- { name: 'attributes', defaultValue: [] },
- { name: 'comments', defaultValue: [] },
- { name: 'name' },
- { name: 'type' }
- ]
- };
- }
- case DataFieldAttribute: {
- return {
- name: DataFieldAttribute,
- properties: [
- { name: 'args', defaultValue: [] },
- { name: 'decl' }
- ]
- };
- }
- case DataFieldType: {
- return {
- name: DataFieldType,
- properties: [
- { name: 'array', defaultValue: false },
- { name: 'optional', defaultValue: false },
- { name: 'reference' },
- { name: 'type' },
- { name: 'unsupported' }
- ]
- };
- }
- case DataModel: {
- return {
- name: DataModel,
- properties: [
- { name: 'attributes', defaultValue: [] },
- { name: 'baseModel' },
- { name: 'comments', defaultValue: [] },
- { name: 'fields', defaultValue: [] },
- { name: 'isView', defaultValue: false },
- { name: 'mixins', defaultValue: [] },
- { name: 'name' }
- ]
- };
- }
- case DataModelAttribute: {
- return {
- name: DataModelAttribute,
- properties: [
- { name: 'args', defaultValue: [] },
- { name: 'decl' }
- ]
- };
- }
- case DataSource: {
- return {
- name: DataSource,
- properties: [
- { name: 'fields', defaultValue: [] },
- { name: 'name' }
- ]
- };
- }
- case Enum: {
- return {
- name: Enum,
- properties: [
- { name: 'attributes', defaultValue: [] },
- { name: 'comments', defaultValue: [] },
- { name: 'fields', defaultValue: [] },
- { name: 'name' }
- ]
- };
- }
- case EnumField: {
- return {
- name: EnumField,
- properties: [
- { name: 'attributes', defaultValue: [] },
- { name: 'comments', defaultValue: [] },
- { name: 'name' }
- ]
- };
- }
- case FieldInitializer: {
- return {
- name: FieldInitializer,
- properties: [
- { name: 'name' },
- { name: 'value' }
- ]
- };
- }
- case FunctionDecl: {
- return {
- name: FunctionDecl,
- properties: [
- { name: 'attributes', defaultValue: [] },
- { name: 'expression' },
- { name: 'name' },
- { name: 'params', defaultValue: [] },
- { name: 'returnType' }
- ]
- };
- }
- case FunctionParam: {
- return {
- name: FunctionParam,
- properties: [
- { name: 'name' },
- { name: 'optional', defaultValue: false },
- { name: 'type' }
- ]
- };
- }
- case FunctionParamType: {
- return {
- name: FunctionParamType,
- properties: [
- { name: 'array', defaultValue: false },
- { name: 'reference' },
- { name: 'type' }
- ]
- };
- }
- case GeneratorDecl: {
- return {
- name: GeneratorDecl,
- properties: [
- { name: 'fields', defaultValue: [] },
- { name: 'name' }
- ]
- };
- }
- case InternalAttribute: {
- return {
- name: InternalAttribute,
- properties: [
- { name: 'args', defaultValue: [] },
- { name: 'decl' }
- ]
- };
- }
- case InvocationExpr: {
- return {
- name: InvocationExpr,
- properties: [
- { name: 'args', defaultValue: [] },
- { name: 'function' }
- ]
- };
- }
- case MemberAccessExpr: {
- return {
- name: MemberAccessExpr,
- properties: [
- { name: 'member' },
- { name: 'operand' }
- ]
- };
- }
- case Model: {
- return {
- name: Model,
- properties: [
- { name: 'declarations', defaultValue: [] },
- { name: 'imports', defaultValue: [] }
- ]
- };
- }
- case ModelImport: {
- return {
- name: ModelImport,
- properties: [
- { name: 'path' }
- ]
- };
- }
- case NullExpr: {
- return {
- name: NullExpr,
- properties: [
- { name: 'value' }
- ]
- };
- }
- case NumberLiteral: {
- return {
- name: NumberLiteral,
- properties: [
- { name: 'value' }
- ]
- };
- }
- case ObjectExpr: {
- return {
- name: ObjectExpr,
- properties: [
- { name: 'fields', defaultValue: [] }
- ]
- };
- }
- case Plugin: {
- return {
- name: Plugin,
- properties: [
- { name: 'fields', defaultValue: [] },
- { name: 'name' }
- ]
- };
- }
- case PluginField: {
- return {
- name: PluginField,
- properties: [
- { name: 'name' },
- { name: 'value' }
- ]
- };
- }
- case Procedure: {
- return {
- name: Procedure,
- properties: [
- { name: 'attributes', defaultValue: [] },
- { name: 'mutation', defaultValue: false },
- { name: 'name' },
- { name: 'params', defaultValue: [] },
- { name: 'returnType' }
- ]
- };
- }
- case ProcedureParam: {
- return {
- name: ProcedureParam,
- properties: [
- { name: 'name' },
- { name: 'optional', defaultValue: false },
- { name: 'type' }
- ]
- };
- }
- case ReferenceArg: {
- return {
- name: ReferenceArg,
- properties: [
- { name: 'name' },
- { name: 'value' }
- ]
- };
- }
- case ReferenceExpr: {
- return {
- name: ReferenceExpr,
- properties: [
- { name: 'args', defaultValue: [] },
- { name: 'target' }
- ]
- };
- }
- case StringLiteral: {
- return {
- name: StringLiteral,
- properties: [
- { name: 'value' }
- ]
- };
- }
- case ThisExpr: {
- return {
- name: ThisExpr,
- properties: [
- { name: 'value' }
- ]
- };
- }
- case TypeDef: {
- return {
- name: TypeDef,
- properties: [
- { name: 'attributes', defaultValue: [] },
- { name: 'comments', defaultValue: [] },
- { name: 'fields', defaultValue: [] },
- { name: 'mixins', defaultValue: [] },
- { name: 'name' }
- ]
- };
- }
- case UnaryExpr: {
- return {
- name: UnaryExpr,
- properties: [
- { name: 'operand' },
- { name: 'operator' }
- ]
- };
- }
- case UnsupportedFieldType: {
- return {
- name: UnsupportedFieldType,
- properties: [
- { name: 'value' }
- ]
- };
- }
- default: {
- return {
- name: type,
- properties: []
- };
- }
+ override readonly types = {
+ AbstractDeclaration: {
+ name: AbstractDeclaration.$type,
+ properties: {
+ },
+ superTypes: []
+ },
+ Argument: {
+ name: Argument.$type,
+ properties: {
+ value: {
+ name: Argument.value
+ }
+ },
+ superTypes: []
+ },
+ ArrayExpr: {
+ name: ArrayExpr.$type,
+ properties: {
+ items: {
+ name: ArrayExpr.items,
+ defaultValue: []
+ }
+ },
+ superTypes: [Expression.$type]
+ },
+ Attribute: {
+ name: Attribute.$type,
+ properties: {
+ attributes: {
+ name: Attribute.attributes,
+ defaultValue: []
+ },
+ comments: {
+ name: Attribute.comments,
+ defaultValue: []
+ },
+ name: {
+ name: Attribute.name
+ },
+ params: {
+ name: Attribute.params,
+ defaultValue: []
+ }
+ },
+ superTypes: [AbstractDeclaration.$type]
+ },
+ AttributeArg: {
+ name: AttributeArg.$type,
+ properties: {
+ name: {
+ name: AttributeArg.name
+ },
+ value: {
+ name: AttributeArg.value
+ }
+ },
+ superTypes: []
+ },
+ AttributeParam: {
+ name: AttributeParam.$type,
+ properties: {
+ attributes: {
+ name: AttributeParam.attributes,
+ defaultValue: []
+ },
+ comments: {
+ name: AttributeParam.comments,
+ defaultValue: []
+ },
+ default: {
+ name: AttributeParam.default,
+ defaultValue: false
+ },
+ name: {
+ name: AttributeParam.name
+ },
+ type: {
+ name: AttributeParam.type
+ }
+ },
+ superTypes: []
+ },
+ AttributeParamType: {
+ name: AttributeParamType.$type,
+ properties: {
+ array: {
+ name: AttributeParamType.array,
+ defaultValue: false
+ },
+ optional: {
+ name: AttributeParamType.optional,
+ defaultValue: false
+ },
+ reference: {
+ name: AttributeParamType.reference,
+ referenceType: TypeDeclaration.$type
+ },
+ type: {
+ name: AttributeParamType.type
+ }
+ },
+ superTypes: []
+ },
+ BinaryExpr: {
+ name: BinaryExpr.$type,
+ properties: {
+ binding: {
+ name: BinaryExpr.binding
+ },
+ left: {
+ name: BinaryExpr.left
+ },
+ operator: {
+ name: BinaryExpr.operator
+ },
+ right: {
+ name: BinaryExpr.right
+ }
+ },
+ superTypes: [Expression.$type]
+ },
+ BooleanLiteral: {
+ name: BooleanLiteral.$type,
+ properties: {
+ value: {
+ name: BooleanLiteral.value
+ }
+ },
+ superTypes: [LiteralExpr.$type]
+ },
+ CollectionPredicateBinding: {
+ name: CollectionPredicateBinding.$type,
+ properties: {
+ name: {
+ name: CollectionPredicateBinding.name
+ }
+ },
+ superTypes: [ReferenceTarget.$type]
+ },
+ ConfigArrayExpr: {
+ name: ConfigArrayExpr.$type,
+ properties: {
+ items: {
+ name: ConfigArrayExpr.items,
+ defaultValue: []
+ }
+ },
+ superTypes: [ConfigExpr.$type]
+ },
+ ConfigExpr: {
+ name: ConfigExpr.$type,
+ properties: {
+ },
+ superTypes: []
+ },
+ ConfigField: {
+ name: ConfigField.$type,
+ properties: {
+ name: {
+ name: ConfigField.name
+ },
+ value: {
+ name: ConfigField.value
+ }
+ },
+ superTypes: []
+ },
+ ConfigInvocationArg: {
+ name: ConfigInvocationArg.$type,
+ properties: {
+ name: {
+ name: ConfigInvocationArg.name
+ },
+ value: {
+ name: ConfigInvocationArg.value
+ }
+ },
+ superTypes: []
+ },
+ ConfigInvocationExpr: {
+ name: ConfigInvocationExpr.$type,
+ properties: {
+ args: {
+ name: ConfigInvocationExpr.args,
+ defaultValue: []
+ },
+ name: {
+ name: ConfigInvocationExpr.name
+ }
+ },
+ superTypes: []
+ },
+ DataField: {
+ name: DataField.$type,
+ properties: {
+ attributes: {
+ name: DataField.attributes,
+ defaultValue: []
+ },
+ comments: {
+ name: DataField.comments,
+ defaultValue: []
+ },
+ name: {
+ name: DataField.name
+ },
+ type: {
+ name: DataField.type
+ }
+ },
+ superTypes: [MemberAccessTarget.$type, ReferenceTarget.$type]
+ },
+ DataFieldAttribute: {
+ name: DataFieldAttribute.$type,
+ properties: {
+ args: {
+ name: DataFieldAttribute.args,
+ defaultValue: []
+ },
+ decl: {
+ name: DataFieldAttribute.decl,
+ referenceType: Attribute.$type
+ }
+ },
+ superTypes: []
+ },
+ DataFieldType: {
+ name: DataFieldType.$type,
+ properties: {
+ array: {
+ name: DataFieldType.array,
+ defaultValue: false
+ },
+ optional: {
+ name: DataFieldType.optional,
+ defaultValue: false
+ },
+ reference: {
+ name: DataFieldType.reference,
+ referenceType: TypeDeclaration.$type
+ },
+ type: {
+ name: DataFieldType.type
+ },
+ unsupported: {
+ name: DataFieldType.unsupported
+ }
+ },
+ superTypes: []
+ },
+ DataModel: {
+ name: DataModel.$type,
+ properties: {
+ attributes: {
+ name: DataModel.attributes,
+ defaultValue: []
+ },
+ baseModel: {
+ name: DataModel.baseModel,
+ referenceType: DataModel.$type
+ },
+ comments: {
+ name: DataModel.comments,
+ defaultValue: []
+ },
+ fields: {
+ name: DataModel.fields,
+ defaultValue: []
+ },
+ isView: {
+ name: DataModel.isView,
+ defaultValue: false
+ },
+ mixins: {
+ name: DataModel.mixins,
+ defaultValue: [],
+ referenceType: TypeDef.$type
+ },
+ name: {
+ name: DataModel.name
+ }
+ },
+ superTypes: [AbstractDeclaration.$type, TypeDeclaration.$type]
+ },
+ DataModelAttribute: {
+ name: DataModelAttribute.$type,
+ properties: {
+ args: {
+ name: DataModelAttribute.args,
+ defaultValue: []
+ },
+ decl: {
+ name: DataModelAttribute.decl,
+ referenceType: Attribute.$type
+ }
+ },
+ superTypes: []
+ },
+ DataSource: {
+ name: DataSource.$type,
+ properties: {
+ fields: {
+ name: DataSource.fields,
+ defaultValue: []
+ },
+ name: {
+ name: DataSource.name
+ }
+ },
+ superTypes: [AbstractDeclaration.$type]
+ },
+ Enum: {
+ name: Enum.$type,
+ properties: {
+ attributes: {
+ name: Enum.attributes,
+ defaultValue: []
+ },
+ comments: {
+ name: Enum.comments,
+ defaultValue: []
+ },
+ fields: {
+ name: Enum.fields,
+ defaultValue: []
+ },
+ name: {
+ name: Enum.name
+ }
+ },
+ superTypes: [AbstractDeclaration.$type, TypeDeclaration.$type]
+ },
+ EnumField: {
+ name: EnumField.$type,
+ properties: {
+ attributes: {
+ name: EnumField.attributes,
+ defaultValue: []
+ },
+ comments: {
+ name: EnumField.comments,
+ defaultValue: []
+ },
+ name: {
+ name: EnumField.name
+ }
+ },
+ superTypes: [ReferenceTarget.$type]
+ },
+ Expression: {
+ name: Expression.$type,
+ properties: {
+ },
+ superTypes: []
+ },
+ FieldInitializer: {
+ name: FieldInitializer.$type,
+ properties: {
+ name: {
+ name: FieldInitializer.name
+ },
+ value: {
+ name: FieldInitializer.value
+ }
+ },
+ superTypes: []
+ },
+ FunctionDecl: {
+ name: FunctionDecl.$type,
+ properties: {
+ attributes: {
+ name: FunctionDecl.attributes,
+ defaultValue: []
+ },
+ expression: {
+ name: FunctionDecl.expression
+ },
+ name: {
+ name: FunctionDecl.name
+ },
+ params: {
+ name: FunctionDecl.params,
+ defaultValue: []
+ },
+ returnType: {
+ name: FunctionDecl.returnType
+ }
+ },
+ superTypes: [AbstractDeclaration.$type]
+ },
+ FunctionParam: {
+ name: FunctionParam.$type,
+ properties: {
+ name: {
+ name: FunctionParam.name
+ },
+ optional: {
+ name: FunctionParam.optional,
+ defaultValue: false
+ },
+ type: {
+ name: FunctionParam.type
+ }
+ },
+ superTypes: [ReferenceTarget.$type]
+ },
+ FunctionParamType: {
+ name: FunctionParamType.$type,
+ properties: {
+ array: {
+ name: FunctionParamType.array,
+ defaultValue: false
+ },
+ reference: {
+ name: FunctionParamType.reference,
+ referenceType: TypeDeclaration.$type
+ },
+ type: {
+ name: FunctionParamType.type
+ }
+ },
+ superTypes: []
+ },
+ GeneratorDecl: {
+ name: GeneratorDecl.$type,
+ properties: {
+ fields: {
+ name: GeneratorDecl.fields,
+ defaultValue: []
+ },
+ name: {
+ name: GeneratorDecl.name
+ }
+ },
+ superTypes: [AbstractDeclaration.$type]
+ },
+ InternalAttribute: {
+ name: InternalAttribute.$type,
+ properties: {
+ args: {
+ name: InternalAttribute.args,
+ defaultValue: []
+ },
+ decl: {
+ name: InternalAttribute.decl,
+ referenceType: Attribute.$type
+ }
+ },
+ superTypes: []
+ },
+ InvocationExpr: {
+ name: InvocationExpr.$type,
+ properties: {
+ args: {
+ name: InvocationExpr.args,
+ defaultValue: []
+ },
+ function: {
+ name: InvocationExpr.function,
+ referenceType: FunctionDecl.$type
+ }
+ },
+ superTypes: [ConfigExpr.$type, Expression.$type]
+ },
+ LiteralExpr: {
+ name: LiteralExpr.$type,
+ properties: {
+ },
+ superTypes: [ConfigExpr.$type, Expression.$type]
+ },
+ MemberAccessExpr: {
+ name: MemberAccessExpr.$type,
+ properties: {
+ member: {
+ name: MemberAccessExpr.member,
+ referenceType: MemberAccessTarget.$type
+ },
+ operand: {
+ name: MemberAccessExpr.operand
+ }
+ },
+ superTypes: [Expression.$type]
+ },
+ MemberAccessTarget: {
+ name: MemberAccessTarget.$type,
+ properties: {
+ },
+ superTypes: []
+ },
+ Model: {
+ name: Model.$type,
+ properties: {
+ declarations: {
+ name: Model.declarations,
+ defaultValue: []
+ },
+ imports: {
+ name: Model.imports,
+ defaultValue: []
+ }
+ },
+ superTypes: []
+ },
+ ModelImport: {
+ name: ModelImport.$type,
+ properties: {
+ path: {
+ name: ModelImport.path
+ }
+ },
+ superTypes: []
+ },
+ NullExpr: {
+ name: NullExpr.$type,
+ properties: {
+ value: {
+ name: NullExpr.value
+ }
+ },
+ superTypes: [Expression.$type]
+ },
+ NumberLiteral: {
+ name: NumberLiteral.$type,
+ properties: {
+ value: {
+ name: NumberLiteral.value
+ }
+ },
+ superTypes: [LiteralExpr.$type]
+ },
+ ObjectExpr: {
+ name: ObjectExpr.$type,
+ properties: {
+ fields: {
+ name: ObjectExpr.fields,
+ defaultValue: []
+ }
+ },
+ superTypes: [Expression.$type]
+ },
+ Plugin: {
+ name: Plugin.$type,
+ properties: {
+ fields: {
+ name: Plugin.fields,
+ defaultValue: []
+ },
+ name: {
+ name: Plugin.name
+ }
+ },
+ superTypes: [AbstractDeclaration.$type]
+ },
+ PluginField: {
+ name: PluginField.$type,
+ properties: {
+ name: {
+ name: PluginField.name
+ },
+ value: {
+ name: PluginField.value
+ }
+ },
+ superTypes: []
+ },
+ Procedure: {
+ name: Procedure.$type,
+ properties: {
+ attributes: {
+ name: Procedure.attributes,
+ defaultValue: []
+ },
+ mutation: {
+ name: Procedure.mutation,
+ defaultValue: false
+ },
+ name: {
+ name: Procedure.name
+ },
+ params: {
+ name: Procedure.params,
+ defaultValue: []
+ },
+ returnType: {
+ name: Procedure.returnType
+ }
+ },
+ superTypes: [AbstractDeclaration.$type]
+ },
+ ProcedureParam: {
+ name: ProcedureParam.$type,
+ properties: {
+ name: {
+ name: ProcedureParam.name
+ },
+ optional: {
+ name: ProcedureParam.optional,
+ defaultValue: false
+ },
+ type: {
+ name: ProcedureParam.type
+ }
+ },
+ superTypes: []
+ },
+ ReferenceArg: {
+ name: ReferenceArg.$type,
+ properties: {
+ name: {
+ name: ReferenceArg.name
+ },
+ value: {
+ name: ReferenceArg.value
+ }
+ },
+ superTypes: []
+ },
+ ReferenceExpr: {
+ name: ReferenceExpr.$type,
+ properties: {
+ args: {
+ name: ReferenceExpr.args,
+ defaultValue: []
+ },
+ target: {
+ name: ReferenceExpr.target,
+ referenceType: ReferenceTarget.$type
+ }
+ },
+ superTypes: [Expression.$type]
+ },
+ ReferenceTarget: {
+ name: ReferenceTarget.$type,
+ properties: {
+ },
+ superTypes: []
+ },
+ StringLiteral: {
+ name: StringLiteral.$type,
+ properties: {
+ value: {
+ name: StringLiteral.value
+ }
+ },
+ superTypes: [LiteralExpr.$type]
+ },
+ ThisExpr: {
+ name: ThisExpr.$type,
+ properties: {
+ value: {
+ name: ThisExpr.value
+ }
+ },
+ superTypes: [Expression.$type]
+ },
+ TypeDeclaration: {
+ name: TypeDeclaration.$type,
+ properties: {
+ },
+ superTypes: []
+ },
+ TypeDef: {
+ name: TypeDef.$type,
+ properties: {
+ attributes: {
+ name: TypeDef.attributes,
+ defaultValue: []
+ },
+ comments: {
+ name: TypeDef.comments,
+ defaultValue: []
+ },
+ fields: {
+ name: TypeDef.fields,
+ defaultValue: []
+ },
+ mixins: {
+ name: TypeDef.mixins,
+ defaultValue: [],
+ referenceType: TypeDef.$type
+ },
+ name: {
+ name: TypeDef.name
+ }
+ },
+ superTypes: [AbstractDeclaration.$type, TypeDeclaration.$type]
+ },
+ UnaryExpr: {
+ name: UnaryExpr.$type,
+ properties: {
+ operand: {
+ name: UnaryExpr.operand
+ },
+ operator: {
+ name: UnaryExpr.operator
+ }
+ },
+ superTypes: [Expression.$type]
+ },
+ UnsupportedFieldType: {
+ name: UnsupportedFieldType.$type,
+ properties: {
+ value: {
+ name: UnsupportedFieldType.value
+ }
+ },
+ superTypes: []
}
- }
+ } as const satisfies langium.AstMetaData
}
export const reflection = new ZModelAstReflection();
diff --git a/packages/language/src/generated/grammar.ts b/packages/language/src/generated/grammar.ts
index 925d4dcb6..27385931e 100644
--- a/packages/language/src/generated/grammar.ts
+++ b/packages/language/src/generated/grammar.ts
@@ -1,5 +1,5 @@
/******************************************************************************
- * This file was generated by langium-cli 3.5.0.
+ * This file was generated by langium-cli 4.2.1.
* DO NOT EDIT MANUALLY!
******************************************************************************/
@@ -47,11 +47,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -82,12 +79,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -160,12 +154,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -220,12 +211,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -280,12 +268,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -331,12 +316,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -391,12 +373,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -461,12 +440,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -478,12 +454,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
},
"arguments": []
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -500,12 +473,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
"arguments": []
}
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -522,12 +492,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
"arguments": []
}
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -544,12 +511,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
"arguments": []
}
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -580,12 +544,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -643,12 +604,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -692,12 +650,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -742,11 +697,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -784,12 +736,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -871,12 +820,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -907,12 +853,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -926,12 +869,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
"value": "this"
}
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -945,12 +885,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
"value": "null"
}
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -974,7 +911,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
},
"arguments": []
},
- "deprecatedSyntax": false
+ "deprecatedSyntax": false,
+ "isMulti": false
}
},
{
@@ -1000,12 +938,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -1050,11 +985,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -1092,12 +1024,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -1160,12 +1089,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -1215,12 +1141,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -1237,7 +1160,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
"type": {
"$ref": "#/rules@47"
},
- "deprecatedSyntax": false
+ "deprecatedSyntax": false,
+ "isMulti": false
}
},
{
@@ -1258,12 +1182,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -1310,7 +1231,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
"type": {
"$ref": "#/types@1"
},
- "deprecatedSyntax": false
+ "deprecatedSyntax": false,
+ "isMulti": false
}
}
]
@@ -1320,12 +1242,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -1356,12 +1275,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -1461,12 +1377,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -1483,12 +1396,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
"arguments": []
}
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -1545,12 +1455,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -1624,12 +1531,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -1695,12 +1599,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -1766,12 +1667,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -1861,12 +1759,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -1911,11 +1806,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -1932,12 +1824,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
"arguments": []
}
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -2108,12 +1997,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -2135,7 +2021,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
"type": {
"$ref": "#/rules@43"
},
- "deprecatedSyntax": false
+ "deprecatedSyntax": false,
+ "isMulti": false
}
},
{
@@ -2155,7 +2042,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
"type": {
"$ref": "#/rules@43"
},
- "deprecatedSyntax": false
+ "deprecatedSyntax": false,
+ "isMulti": false
}
}
],
@@ -2163,11 +2051,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -2189,16 +2074,14 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
"type": {
"$ref": "#/rules@38"
},
- "deprecatedSyntax": false
+ "deprecatedSyntax": false,
+ "isMulti": false
}
}
]
},
- "definesHiddenTokens": false,
"entry": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -2258,12 +2141,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -2314,7 +2194,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
},
"arguments": []
},
- "deprecatedSyntax": false
+ "deprecatedSyntax": false,
+ "isMulti": false
}
}
]
@@ -2350,12 +2231,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -2440,12 +2318,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -2479,12 +2354,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -2561,12 +2433,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -2614,12 +2483,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -2751,12 +2617,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -2812,12 +2675,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -2856,7 +2716,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
},
"arguments": []
},
- "deprecatedSyntax": false
+ "deprecatedSyntax": false,
+ "isMulti": false
}
}
]
@@ -2882,12 +2743,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -2943,12 +2801,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -3069,12 +2924,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -3132,12 +2984,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -3211,12 +3060,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -3335,12 +3181,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -3414,12 +3257,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -3475,7 +3315,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
},
"arguments": []
},
- "deprecatedSyntax": false
+ "deprecatedSyntax": false,
+ "isMulti": false
}
}
]
@@ -3511,12 +3352,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -3540,7 +3378,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
},
"arguments": []
},
- "deprecatedSyntax": false
+ "deprecatedSyntax": false,
+ "isMulti": false
}
},
{
@@ -3567,12 +3406,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -3604,7 +3440,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
},
"arguments": []
},
- "deprecatedSyntax": false
+ "deprecatedSyntax": false,
+ "isMulti": false
}
},
{
@@ -3631,12 +3468,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -3660,7 +3494,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
},
"arguments": []
},
- "deprecatedSyntax": false
+ "deprecatedSyntax": false,
+ "isMulti": false
}
},
{
@@ -3687,12 +3522,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -3737,11 +3569,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -3785,12 +3614,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -3861,12 +3687,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -3913,12 +3736,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "ParserRule",
@@ -3937,12 +3757,9 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
]
},
- "definesHiddenTokens": false,
"entry": false,
"fragment": false,
- "hiddenTokens": [],
- "parameters": [],
- "wildcard": false
+ "parameters": []
},
{
"$type": "TerminalRule",
@@ -3950,7 +3767,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
"name": "WS",
"definition": {
"$type": "RegexToken",
- "regex": "/\\\\s+/"
+ "regex": "/\\\\s+/",
+ "parenthesized": false
},
"fragment": false
},
@@ -3959,7 +3777,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
"name": "INTERNAL_ATTRIBUTE_NAME",
"definition": {
"$type": "RegexToken",
- "regex": "/@@@([_a-zA-Z][\\\\w_]*\\\\.)*[_a-zA-Z][\\\\w_]*/"
+ "regex": "/@@@([_a-zA-Z][\\\\w_]*\\\\.)*[_a-zA-Z][\\\\w_]*/",
+ "parenthesized": false
},
"fragment": false,
"hidden": false
@@ -3969,7 +3788,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
"name": "MODEL_ATTRIBUTE_NAME",
"definition": {
"$type": "RegexToken",
- "regex": "/@@([_a-zA-Z][\\\\w_]*\\\\.)*[_a-zA-Z][\\\\w_]*/"
+ "regex": "/@@([_a-zA-Z][\\\\w_]*\\\\.)*[_a-zA-Z][\\\\w_]*/",
+ "parenthesized": false
},
"fragment": false,
"hidden": false
@@ -3979,7 +3799,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
"name": "FIELD_ATTRIBUTE_NAME",
"definition": {
"$type": "RegexToken",
- "regex": "/@([_a-zA-Z][\\\\w_]*\\\\.)*[_a-zA-Z][\\\\w_]*/"
+ "regex": "/@([_a-zA-Z][\\\\w_]*\\\\.)*[_a-zA-Z][\\\\w_]*/",
+ "parenthesized": false
},
"fragment": false,
"hidden": false
@@ -3989,7 +3810,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
"name": "ID",
"definition": {
"$type": "RegexToken",
- "regex": "/[_a-zA-Z][\\\\w_]*/"
+ "regex": "/[_a-zA-Z][\\\\w_]*/",
+ "parenthesized": false
},
"fragment": false,
"hidden": false
@@ -3999,7 +3821,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
"name": "STRING",
"definition": {
"$type": "RegexToken",
- "regex": "/\\"(\\\\\\\\.|[^\\"\\\\\\\\])*\\"|'(\\\\\\\\.|[^'\\\\\\\\])*'/"
+ "regex": "/\\"(\\\\\\\\.|[^\\"\\\\\\\\])*\\"|'(\\\\\\\\.|[^'\\\\\\\\])*'/",
+ "parenthesized": false
},
"fragment": false,
"hidden": false
@@ -4009,7 +3832,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
"name": "NUMBER",
"definition": {
"$type": "RegexToken",
- "regex": "/[+-]?[0-9]+(\\\\.[0-9]+)?/"
+ "regex": "/[+-]?[0-9]+(\\\\.[0-9]+)?/",
+ "parenthesized": false
},
"fragment": false,
"hidden": false
@@ -4019,7 +3843,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
"name": "TRIPLE_SLASH_COMMENT",
"definition": {
"$type": "RegexToken",
- "regex": "/\\\\/\\\\/\\\\/[^\\\\n\\\\r]*/"
+ "regex": "/\\\\/\\\\/\\\\/[^\\\\n\\\\r]*/",
+ "parenthesized": false
},
"fragment": false,
"hidden": false
@@ -4030,7 +3855,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
"name": "ML_COMMENT",
"definition": {
"$type": "RegexToken",
- "regex": "/\\\\/\\\\*[\\\\s\\\\S]*?\\\\*\\\\//"
+ "regex": "/\\\\/\\\\*[\\\\s\\\\S]*?\\\\*\\\\//",
+ "parenthesized": false
},
"fragment": false
},
@@ -4040,7 +3866,8 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
"name": "SL_COMMENT",
"definition": {
"$type": "RegexToken",
- "regex": "/\\\\/\\\\/[^\\\\n\\\\r]*/"
+ "regex": "/\\\\/\\\\/[^\\\\n\\\\r]*/",
+ "parenthesized": false
},
"fragment": false
}
@@ -4117,9 +3944,6 @@ export const ZModelGrammar = (): Grammar => loadedZModelGrammar ?? (loadedZModel
}
}
],
- "definesHiddenTokens": false,
- "hiddenTokens": [],
"imports": [],
- "interfaces": [],
- "usedGrammars": []
+ "interfaces": []
}`));
diff --git a/packages/language/src/generated/module.ts b/packages/language/src/generated/module.ts
index 0c621d00c..bc468edcf 100644
--- a/packages/language/src/generated/module.ts
+++ b/packages/language/src/generated/module.ts
@@ -1,5 +1,5 @@
/******************************************************************************
- * This file was generated by langium-cli 3.5.0.
+ * This file was generated by langium-cli 4.2.1.
* DO NOT EDIT MANUALLY!
******************************************************************************/
diff --git a/packages/language/src/validators/datamodel-validator.ts b/packages/language/src/validators/datamodel-validator.ts
index e8ddbe89c..5fc093da1 100644
--- a/packages/language/src/validators/datamodel-validator.ts
+++ b/packages/language/src/validators/datamodel-validator.ts
@@ -3,7 +3,9 @@ import { AstUtils, type AstNode, type DiagnosticInfo, type ValidationAcceptor }
import { IssueCodes, SCALAR_TYPES } from '../constants';
import {
ArrayExpr,
+ Attribute,
DataField,
+ DataFieldAttribute,
DataModel,
DataModelAttribute,
ReferenceExpr,
@@ -38,6 +40,7 @@ export default class DataModelValidator implements AstValidator {
validateDuplicatedDeclarations(dm, getAllFields(dm), accept);
this.validateAttributes(dm, accept);
this.validateFields(dm, accept);
+ this.validateOnceInModelAttributes(dm, accept);
if (dm.mixins.length > 0) {
this.validateMixins(dm, accept);
}
@@ -143,6 +146,40 @@ export default class DataModelValidator implements AstValidator {
getAllAttributes(dm).forEach((attr) => validateAttributeApplication(attr, accept, dm));
}
+ // Validates field-level attributes marked with `@@@onceInModel`, which may be applied to at
+ // most one field per model (including fields inherited from base models and mixins). This must
+ // run at the model level so that duplicates which only co-occur through inheritance are detected
+ // — per-field validation only sees the model that physically declares each field.
+ private validateOnceInModelAttributes(dm: DataModel, accept: ValidationAcceptor) {
+ // group field attributes carrying `@@@onceInModel` by their attribute declaration
+ const occurrences = new Map();
+ for (const field of getAllFields(dm)) {
+ for (const attr of field.attributes) {
+ const decl = attr.decl.ref;
+ if (decl && hasAttribute(decl, '@@@onceInModel')) {
+ const list = occurrences.get(decl) ?? [];
+ list.push(attr);
+ occurrences.set(decl, list);
+ }
+ }
+ }
+
+ for (const [decl, attrs] of occurrences) {
+ if (attrs.length <= 1) {
+ continue;
+ }
+ const message = `Attribute "${decl.name}" can only be applied to one field per model`;
+ // prefer reporting on offending attributes declared on this model's own fields; if all
+ // offending fields are inherited, report on the model declaration itself
+ const local = attrs.filter((attr) => dm.fields.includes(attr.$container as DataField));
+ if (local.length > 0) {
+ local.forEach((attr) => accept('error', message, { node: attr }));
+ } else {
+ accept('error', message, { node: dm });
+ }
+ }
+ }
+
private parseRelation(field: DataField, accept?: ValidationAcceptor) {
const relAttr = field.attributes.find((attr) => attr.decl.ref?.name === '@relation');
diff --git a/packages/language/src/zmodel-code-generator.ts b/packages/language/src/zmodel-code-generator.ts
index e68ba7735..b4f61e9f4 100644
--- a/packages/language/src/zmodel-code-generator.ts
+++ b/packages/language/src/zmodel-code-generator.ts
@@ -57,10 +57,10 @@ export interface ZModelCodeOptions {
const generationHandlers = new Map();
// generation handler decorator
-function gen(name: string) {
+function gen(type: { $type: string }) {
return function (_target: unknown, _propertyKey: string, descriptor: PropertyDescriptor) {
- if (!generationHandlers.get(name)) {
- generationHandlers.set(name, descriptor);
+ if (!generationHandlers.get(type.$type)) {
+ generationHandlers.set(type.$type, descriptor);
}
return descriptor;
};
@@ -407,7 +407,7 @@ ${ast.fields.map((x) => this.indent + this.generate(x)).join('\n')}${
const currentPriority = BinaryExprOperatorPriority[operator];
if (
- ast.left.$type === BinaryExpr &&
+ ast.left.$type === BinaryExpr.$type &&
BinaryExprOperatorPriority[(ast.left as BinaryExpr)['operator']] < currentPriority
) {
result.left = true;
@@ -418,7 +418,7 @@ ${ast.fields.map((x) => this.indent + this.generate(x)).join('\n')}${
**/
if (
!isCollectionPredicate &&
- ast.right.$type === BinaryExpr &&
+ ast.right.$type === BinaryExpr.$type &&
BinaryExprOperatorPriority[(ast.right as BinaryExpr)['operator']] <= currentPriority
) {
result.right = true;
diff --git a/packages/language/src/zmodel-linker.ts b/packages/language/src/zmodel-linker.ts
index fc3a7f0dd..6766a6afc 100644
--- a/packages/language/src/zmodel-linker.ts
+++ b/packages/language/src/zmodel-linker.ts
@@ -101,7 +101,7 @@ export class ZModelLinker extends DefaultLinker {
// already linked
return;
}
- if (this.resolveFromScopeProviders(refInfo.reference, document, extraScopes)) {
+ if (this.resolveFromScopeProviders(defaultRef, document, extraScopes)) {
// resolved from additional scope provider
return;
}
@@ -135,57 +135,57 @@ export class ZModelLinker extends DefaultLinker {
private resolve(node: AstNode, document: LangiumDocument, extraScopes: ScopeProvider[] = []) {
switch (node.$type) {
- case StringLiteral:
- case NumberLiteral:
- case BooleanLiteral:
+ case StringLiteral.$type:
+ case NumberLiteral.$type:
+ case BooleanLiteral.$type:
this.resolveLiteral(node as LiteralExpr);
break;
- case InvocationExpr:
+ case InvocationExpr.$type:
this.resolveInvocation(node as InvocationExpr, document, extraScopes);
break;
- case ArrayExpr:
+ case ArrayExpr.$type:
this.resolveArray(node as ArrayExpr, document, extraScopes);
break;
- case ReferenceExpr:
+ case ReferenceExpr.$type:
this.resolveReference(node as ReferenceExpr, document, extraScopes);
break;
- case MemberAccessExpr:
+ case MemberAccessExpr.$type:
this.resolveMemberAccess(node as MemberAccessExpr, document, extraScopes);
break;
- case UnaryExpr:
+ case UnaryExpr.$type:
this.resolveUnary(node as UnaryExpr, document, extraScopes);
break;
- case BinaryExpr:
+ case BinaryExpr.$type:
this.resolveBinary(node as BinaryExpr, document, extraScopes);
break;
- case ObjectExpr:
+ case ObjectExpr.$type:
this.resolveObject(node as ObjectExpr, document, extraScopes);
break;
- case ThisExpr:
+ case ThisExpr.$type:
this.resolveThis(node as ThisExpr, document, extraScopes);
break;
- case NullExpr:
+ case NullExpr.$type:
this.resolveNull(node as NullExpr, document, extraScopes);
break;
- case AttributeArg:
+ case AttributeArg.$type:
this.resolveAttributeArg(node as AttributeArg, document, extraScopes);
break;
- case DataModel:
+ case DataModel.$type:
this.resolveDataModel(node as DataModel, document, extraScopes);
break;
- case DataField:
+ case DataField.$type:
this.resolveDataField(node as DataField, document, extraScopes);
break;
diff --git a/packages/language/src/zmodel-scope.ts b/packages/language/src/zmodel-scope.ts
index d05a30cfb..8dd3c4dab 100644
--- a/packages/language/src/zmodel-scope.ts
+++ b/packages/language/src/zmodel-scope.ts
@@ -4,6 +4,7 @@ import {
DefaultScopeComputation,
DefaultScopeProvider,
EMPTY_SCOPE,
+ MultiMap,
StreamScope,
UriUtils,
interruptAndCheck,
@@ -11,7 +12,6 @@ import {
type AstNodeDescription,
type LangiumCoreServices,
type LangiumDocument,
- type PrecomputedScopes,
type ReferenceInfo,
type Scope,
} from 'langium';
@@ -52,11 +52,11 @@ export class ZModelScopeComputation extends DefaultScopeComputation {
super(services);
}
- override async computeExports(
+ override async collectExportedSymbols(
document: LangiumDocument,
cancelToken?: Cancellation.CancellationToken | undefined,
): Promise {
- const result = await super.computeExports(document, cancelToken);
+ const result = await super.collectExportedSymbols(document, cancelToken);
// add enum fields so they can be globally resolved across modules
for (const node of AstUtils.streamAllContents(document.parseResult.value)) {
@@ -76,14 +76,18 @@ export class ZModelScopeComputation extends DefaultScopeComputation {
return result;
}
- override processNode(node: AstNode, document: LangiumDocument, scopes: PrecomputedScopes) {
- super.processNode(node, document, scopes);
+ protected override addLocalSymbol(
+ node: AstNode,
+ document: LangiumDocument,
+ symbols: MultiMap,
+ ) {
+ super.addLocalSymbol(node, document, symbols);
if (isDataModel(node) || isTypeDef(node)) {
// add base fields to the scope recursively
const bases = getRecursiveBases(node, true, this.services.shared.workspace.LangiumDocuments);
for (const base of bases) {
for (const field of base.fields) {
- scopes.add(node, this.descriptions.createDescription(field, this.nameProvider.getName(field)));
+ symbols.add(node, this.descriptions.createDescription(field, this.nameProvider.getName(field)));
}
}
}
diff --git a/packages/language/test/attribute-application.test.ts b/packages/language/test/attribute-application.test.ts
index f412d7bec..973c11479 100644
--- a/packages/language/test/attribute-application.test.ts
+++ b/packages/language/test/attribute-application.test.ts
@@ -499,6 +499,95 @@ describe('Attribute application validation tests', () => {
});
});
+ describe('Field-level @@@onceInModel attribute', () => {
+ it('accepts a single field carrying the attribute', async () => {
+ await loadSchema(`
+ datasource db {
+ provider = 'sqlite'
+ url = 'file:./dev.db'
+ }
+
+ attribute @softDelete() @@@targetField([DateTimeField]) @@@onceInModel
+
+ model Foo {
+ id Int @id @default(autoincrement())
+ deletedAt DateTime? @softDelete
+ }
+ `);
+ });
+
+ it('rejects two fields in the same model carrying the attribute', async () => {
+ await loadSchemaWithError(
+ `
+ datasource db {
+ provider = 'sqlite'
+ url = 'file:./dev.db'
+ }
+
+ attribute @softDelete() @@@targetField([DateTimeField]) @@@onceInModel
+
+ model Foo {
+ id Int @id @default(autoincrement())
+ deletedAt DateTime? @softDelete
+ removedAt DateTime? @softDelete
+ }
+ `,
+ /Attribute "@softDelete" can only be applied to one field per model/,
+ );
+ });
+
+ it('rejects when the attribute is inherited from a mixin and also declared locally', async () => {
+ await loadSchemaWithError(
+ `
+ datasource db {
+ provider = 'sqlite'
+ url = 'file:./dev.db'
+ }
+
+ attribute @softDelete() @@@targetField([DateTimeField]) @@@onceInModel
+
+ type Base {
+ deletedAt DateTime? @softDelete
+ }
+
+ model Foo with Base {
+ id Int @id @default(autoincrement())
+ removedAt DateTime? @softDelete
+ }
+ `,
+ /Attribute "@softDelete" can only be applied to one field per model/,
+ );
+ });
+
+ // Duplicates that only co-occur through inheritance (none declared on the leaf model itself)
+ // are detected at the model level via `getAllFields`.
+ it('rejects when the attribute arrives only through inheritance (two mixins)', async () => {
+ await loadSchemaWithError(
+ `
+ datasource db {
+ provider = 'sqlite'
+ url = 'file:./dev.db'
+ }
+
+ attribute @softDelete() @@@targetField([DateTimeField]) @@@onceInModel
+
+ type Base1 {
+ deletedAt DateTime? @softDelete
+ }
+
+ type Base2 {
+ removedAt DateTime? @softDelete
+ }
+
+ model Foo with Base1 Base2 {
+ id Int @id @default(autoincrement())
+ }
+ `,
+ /Attribute "@softDelete" can only be applied to one field per model/,
+ );
+ });
+ });
+
it('requires relation and fk to have consistent optionality', async () => {
await loadSchemaWithError(
`
diff --git a/packages/language/tsconfig.json b/packages/language/tsconfig.json
index accdce5ed..3948382f8 100644
--- a/packages/language/tsconfig.json
+++ b/packages/language/tsconfig.json
@@ -2,6 +2,7 @@
"extends": "@zenstackhq/typescript-config/base.json",
"include": ["src/**/*.ts"],
"compilerOptions": {
- "noUnusedLocals": false
+ "noUnusedLocals": false,
+ "types": ["node"]
}
}
diff --git a/packages/orm/package.json b/packages/orm/package.json
index ce62edc31..5b7bf333f 100644
--- a/packages/orm/package.json
+++ b/packages/orm/package.json
@@ -2,7 +2,7 @@
"name": "@zenstackhq/orm",
"displayName": "ZenStack ORM",
"description": "ZenStack ORM",
- "version": "3.7.2",
+ "version": "3.8.0",
"type": "module",
"author": {
"name": "ZenStack Team",
@@ -158,7 +158,7 @@
"@zenstackhq/tsdown-config": "workspace:*",
"@zenstackhq/typescript-config": "workspace:*",
"@zenstackhq/vitest-config": "workspace:*",
- "tsx": "^4.19.2",
+ "tsx": "catalog:",
"zod": "^4.1.0"
},
"funding": "https://github.com/sponsors/zenstackhq"
diff --git a/packages/orm/src/client/contract.ts b/packages/orm/src/client/contract.ts
index f9a8aeae4..7b5541a54 100644
--- a/packages/orm/src/client/contract.ts
+++ b/packages/orm/src/client/contract.ts
@@ -20,7 +20,7 @@ import type {
TypeDefResult,
} from './crud-types';
import type { Diagnostics } from './diagnostics';
-import type { ClientOptions, QueryOptions } from './options';
+import type { ClientOptions, QueryOptions, QueryRelevantOptions } from './options';
import type {
ExtClientMembersBase,
ExtQueryArgsBase,
@@ -63,6 +63,10 @@ export const ExtResultMarker: unique symbol = Symbol('zenstack.client.extResult'
/**
* ZenStack client interface.
+ *
+ * Note: this alias resolves to an intersection, so it cannot carry variance annotations itself
+ * (TS2637). It doesn't need them - measuring its variance recurses into {@link ModelOperations},
+ * whose annotations short-circuit the expensive cascade. See {@link CommonModelOperations}.
*/
export type ClientContract<
Schema extends SchemaDef,
@@ -257,7 +261,7 @@ export type ClientContract<
/**
* Factory for creating zod schemas to validate query args.
*/
- get $zod(): ZodSchemaFactory;
+ get $zod(): ZodSchemaFactory, ExtQueryArgs>;
/**
* Pushes the schema to the database. For testing purposes only.
@@ -270,10 +274,13 @@ export type ClientContract<
*/
get $diagnostics(): Promise;
} & {
- [Key in GetSlicedModels as Uncapitalize]: ModelOperations<
+ // Project `Options` to its query-relevant subset before fanning out across every model. This
+ // strips the heavy `computedFields`/`procedures` function types (never read by these types) so
+ // the 30+ `ModelOperations` instantiations stay cheap. See {@link QueryRelevantOptions}.
+ [Key in GetSlicedModels> as Uncapitalize]: ModelOperations<
Schema,
Key,
- Options,
+ QueryRelevantOptions,
ExtQueryArgs,
ExtResult
>;
@@ -342,7 +349,7 @@ type SliceOperations<
T extends Record,
Schema extends SchemaDef,
Model extends GetModels,
- Options extends ClientOptions,
+ Options extends QueryOptions,
> = Omit<
{
// keep only operations included by slicing options
@@ -419,12 +426,21 @@ export type AllModelOperations<
): ZenStackPromise>;
});
+// Explicit variance annotations bypass TypeScript's structural variance *measurement* for this
+// large, deeply-recursive generic. Measurement here comes back "unreliable" (the type recurses
+// across related models) and is pure wasted work - it dominated type-check time. The annotations
+// below match the measured variance and let the checker skip that probing entirely.
type CommonModelOperations<
- Schema extends SchemaDef,
- Model extends GetModels,
- Options extends QueryOptions,
- ExtQueryArgs extends ExtQueryArgsBase,
- ExtResult extends ExtResultBase = {},
+ in out Schema extends SchemaDef,
+ in out Model extends GetModels,
+ // `Options` is invariant (it is read for `omit`/`slicing` in both arg and result positions).
+ // Annotating it keeps the variance-measurement skip. Note: a client built with an explicit
+ // `omit`/`slicing` literal is then no longer assignable to the bare `ClientContract`
+ // (default options) - schema-agnostic call sites that take `ClientContract` should
+ // accept the client via a cast. This is a rare pattern and worth the type-check speedup.
+ in out Options extends QueryOptions,
+ in out ExtQueryArgs extends ExtQueryArgsBase,
+ out ExtResult extends ExtResultBase = {},
> = {
/**
* Returns a list of entities.
@@ -955,12 +971,15 @@ type CommonModelOperations<
export type OperationsRequiringCreate = 'create' | 'createMany' | 'createManyAndReturn' | 'upsert';
+// See the note on `CommonModelOperations` - explicit variance annotations skip the expensive,
+// "unreliable" variance measurement of this recursive type.
export type ModelOperations<
- Schema extends SchemaDef,
- Model extends GetModels,
- Options extends ClientOptions = ClientOptions,
- ExtQueryArgs extends ExtQueryArgsBase = {},
- ExtResult extends ExtResultBase = {},
+ in out Schema extends SchemaDef,
+ in out Model extends GetModels,
+ // `Options` is invariant - see the note on {@link CommonModelOperations}.
+ in out Options extends QueryOptions = ClientOptions,
+ in out ExtQueryArgs extends ExtQueryArgsBase = {},
+ out ExtResult extends ExtResultBase = {},
> = SliceOperations, Schema, Model, Options>;
//#endregion
diff --git a/packages/orm/src/client/crud-types.ts b/packages/orm/src/client/crud-types.ts
index 3ed16e8a6..1d6542a99 100644
--- a/packages/orm/src/client/crud-types.ts
+++ b/packages/orm/src/client/crud-types.ts
@@ -1324,9 +1324,9 @@ export type SelectSubset = {
: {});
type ToManyRelationFilter<
- Schema extends SchemaDef,
- Model extends GetModels,
- Field extends RelationFields,
+ in out Schema extends SchemaDef,
+ in out Model extends GetModels,
+ in out Field extends RelationFields,
Options extends QueryOptions,
> = {
every?: WhereInput, Options>;
@@ -1453,7 +1453,7 @@ type OppositeRelationAndFK<
//#region Find args
-type FilterArgs, Options extends QueryOptions> = {
+type FilterArgs, in out Options extends QueryOptions> = {
/**
* Filter conditions
*/
@@ -1461,9 +1461,9 @@ type FilterArgs, Optio
};
type SortAndTakeArgs<
- Schema extends SchemaDef,
- Model extends GetModels,
- Options extends QueryOptions,
+ in out Schema extends SchemaDef,
+ in out Model extends GetModels,
+ in out Options extends QueryOptions,
> = {
/**
* Number of records to skip
@@ -1844,9 +1844,9 @@ export type UpdateManyAndReturnArgs<
ExtractExtQueryArgs;
type UpdateManyPayload<
- Schema extends SchemaDef,
- Model extends GetModels,
- Options extends QueryOptions = QueryOptions,
+ in out Schema extends SchemaDef,
+ in out Model extends GetModels,
+ out Options extends QueryOptions = QueryOptions,
Without extends string = never,
> = {
/**
@@ -2105,11 +2105,15 @@ type ToManyRelationUpdateInput<
: 'create' | 'createMany' | 'connectOrCreate' | 'upsert'
>;
+// Variance-annotated to skip TypeScript's (unreliable, expensive) variance measurement of this
+// recursive arg type. Annotating the parent also short-circuits measurement of its conditional
+// children (`DisconnectInput`/`NestedDeleteInput`), which can't be annotated directly. `Options`
+// is invariant - see the note on `ClientContract`'s `CommonModelOperations`.
type ToOneRelationUpdateInput<
- Schema extends SchemaDef,
- Model extends GetModels,
- Field extends RelationFields,
- Options extends QueryOptions,
+ in out Schema extends SchemaDef,
+ in out Model extends GetModels,
+ in out Field extends RelationFields,
+ in out Options extends QueryOptions,
> = Omit<
{
/**
@@ -2356,9 +2360,9 @@ type AggCommonOutput = Input extends true
// #region GroupBy
type GroupByHaving<
- Schema extends SchemaDef,
- Model extends GetModels,
- Options extends QueryOptions = QueryOptions,
+ in out Schema extends SchemaDef,
+ in out Model extends GetModels,
+ out Options extends QueryOptions = QueryOptions,
> = Omit, '$expr'>;
export type GroupByArgs<
diff --git a/packages/orm/src/client/crud/dialects/lateral-join-dialect-base.ts b/packages/orm/src/client/crud/dialects/lateral-join-dialect-base.ts
index e4c13fe58..cb5035d40 100644
--- a/packages/orm/src/client/crud/dialects/lateral-join-dialect-base.ts
+++ b/packages/orm/src/client/crud/dialects/lateral-join-dialect-base.ts
@@ -301,9 +301,19 @@ export abstract class LateralJoinDialectBase extends B
objArgs,
...Object.entries((payload as any).include)
.filter(([, value]) => value)
- .map(([field]) => ({
- [field]: eb.ref(`${parentResultName}$${field}.$data`),
- })),
+ .map(([field, value]) => {
+ if (field === '_count') {
+ return {
+ [field]: this.buildCountJson(
+ relationModel as GetModels,
+ eb,
+ relationModelAlias,
+ value,
+ ),
+ };
+ }
+ return { [field]: eb.ref(`${parentResultName}$${field}.$data`) };
+ }),
);
}
diff --git a/packages/orm/src/client/crud/dialects/postgresql.ts b/packages/orm/src/client/crud/dialects/postgresql.ts
index 41d9b9006..25345ada0 100644
--- a/packages/orm/src/client/crud/dialects/postgresql.ts
+++ b/packages/orm/src/client/crud/dialects/postgresql.ts
@@ -409,7 +409,7 @@ export class PostgresCrudDialect extends LateralJoinDi
}
override buildArrayLength(array: Expression): AliasableExpression {
- return this.eb.fn('array_length', [array]);
+ return this.eb.fn('array_length', [array, sql.lit(1)]);
}
override buildArrayValue(values: Expression[], elemType: string): AliasableExpression {
diff --git a/packages/orm/src/client/crud/dialects/sqlite.ts b/packages/orm/src/client/crud/dialects/sqlite.ts
index 48418072c..52a0a315d 100644
--- a/packages/orm/src/client/crud/dialects/sqlite.ts
+++ b/packages/orm/src/client/crud/dialects/sqlite.ts
@@ -317,6 +317,15 @@ export class SqliteCrudDialect extends BaseCrudDialect
...Object.entries((payload as any).include)
.filter(([, value]) => value)
.map(([field, value]) => {
+ if (field === '_count') {
+ const subJson = this.buildCountJson(
+ relationModel,
+ eb,
+ tmpAlias(`${parentAlias}$${relationField}`),
+ value,
+ );
+ return [sql.lit(field), subJson];
+ }
const subJson = this.buildRelationJSON(
relationModel,
eb,
diff --git a/packages/orm/src/client/options.ts b/packages/orm/src/client/options.ts
index 136c4928b..d70cc6120 100644
--- a/packages/orm/src/client/options.ts
+++ b/packages/orm/src/client/options.ts
@@ -156,6 +156,21 @@ export type QueryOptions = {
slicing?: SlicingOptions;
};
+/**
+ * Projects a (typically inferred) client options type down to only the members that influence
+ * ORM typing - the {@link QueryOptions} fields (`omit`, `allowQueryTimeOmitOverride`, `slicing`).
+ *
+ * The full options object inferred at `new ZenStackClient(...)` carries heavy function types for
+ * `computedFields` and `procedures`. Those are never read by the model/operation types, but if the
+ * raw options type is fanned out across every model's `ModelOperations` instantiation (30+ for a
+ * typical schema) it inflates type checking dramatically. Projecting to the query-relevant subset
+ * before the fan-out keeps the per-model types cheap while preserving full options on `$options`.
+ */
+export type QueryRelevantOptions = Pick<
+ Options,
+ Extract>
+>;
+
/**
* ZenStack client options.
*/
diff --git a/packages/orm/src/client/zod/factory.ts b/packages/orm/src/client/zod/factory.ts
index 5c39946e6..42b0b8fb3 100644
--- a/packages/orm/src/client/zod/factory.ts
+++ b/packages/orm/src/client/zod/factory.ts
@@ -129,8 +129,11 @@ export type CreateSchemaOptions = {
* Factory class responsible for creating and caching Zod schemas for ORM input validation.
*/
export class ZodSchemaFactory<
- Schema extends SchemaDef,
- Options extends ClientOptions = ClientOptions,
+ in out Schema extends SchemaDef,
+ // Bounded by `QueryOptions` (not `ClientOptions`): only `omit`/`slicing` shape the schema types.
+ // The `$zod` accessor passes the client's *projected* (query-relevant) options, so the heavy
+ // options literal never reaches the (invariant) arg types this factory produces.
+ in out Options extends QueryOptions = ClientOptions,
ExtQueryArgs extends ExtQueryArgsBase = {},
> {
private readonly schemaCache = new Map();
@@ -140,7 +143,10 @@ export class ZodSchemaFactory<
private readonly options: Options;
private readonly extraValidationsEnabled = true;
- constructor(client: ClientContract);
+ // The client's `Options` type arg is intentionally erased here (`any`) - the factory only needs
+ // the schema and the runtime options object; its own `Options` type param is supplied (projected)
+ // by the caller (`$zod`).
+ constructor(client: ClientContract);
constructor(schema: Schema, options?: Options);
constructor(clientOrSchema: any, options?: Options) {
if ('$schema' in clientOrSchema) {
@@ -153,7 +159,9 @@ export class ZodSchemaFactory<
}
private get plugins(): AnyPlugin[] {
- return this.options.plugins ?? [];
+ // `plugins` is a runtime-only field absent from the query-relevant `Options` type;
+ // read it weakly (the concrete options object always carries it at runtime).
+ return (this.options as { plugins?: AnyPlugin[] }).plugins ?? [];
}
/**
@@ -1145,7 +1153,13 @@ export class ZodSchemaFactory<
fields[field] = this.makeRelationSelectIncludeSchema(model, field, options).optional();
}
} else {
- fields[field] = z.boolean().optional();
+ if (this.options.allowQueryTimeOmitOverride === false && this.isFieldOmittedByConfig(model, field)) {
+ // when query-time omit override is disallowed, an omitted field cannot be
+ // un-omitted by explicitly selecting it, so only allow `false`
+ fields[field] = z.literal(false).optional();
+ } else {
+ fields[field] = z.boolean().optional();
+ }
}
}
@@ -1253,6 +1267,24 @@ export class ZodSchemaFactory<
return result;
}
+ /**
+ * Determines whether a field is configured to be omitted at the schema or client-options level
+ * (query-level omit is excluded as it's mutually exclusive with `select`).
+ */
+ private isFieldOmittedByConfig(model: string, field: string): boolean {
+ // options-level omit
+ const omitConfig =
+ (this.options.omit as Record | undefined)?.[lowerCaseFirst(model)] ??
+ (this.options.omit as Record | undefined)?.[model];
+ if (omitConfig && typeof omitConfig[field] === 'boolean') {
+ return omitConfig[field];
+ }
+
+ // schema-level omit
+ const fieldDef = requireField(this.schema, model, field);
+ return !!fieldDef.omit;
+ }
+
@cache()
private makeOmitSchema(model: string) {
const fields: Record = {};
diff --git a/packages/plugins/policy/package.json b/packages/plugins/policy/package.json
index 9cbb28126..535c47f99 100644
--- a/packages/plugins/policy/package.json
+++ b/packages/plugins/policy/package.json
@@ -2,7 +2,7 @@
"name": "@zenstackhq/plugin-policy",
"displayName": "ZenStack Access Policy Plugin",
"description": "ZenStack plugin that enforces access control policies defined in the schema",
- "version": "3.7.2",
+ "version": "3.8.0",
"type": "module",
"author": {
"name": "ZenStack Team",
diff --git a/packages/plugins/policy/src/expression-transformer.ts b/packages/plugins/policy/src/expression-transformer.ts
index 565afe875..27d77432a 100644
--- a/packages/plugins/policy/src/expression-transformer.ts
+++ b/packages/plugins/policy/src/expression-transformer.ts
@@ -254,8 +254,14 @@ export class ExpressionTransformer {
return BinaryOperationNode.create(left, OperatorNode.create('in'), right);
} else {
// array contains
+ const leftFieldDef = this.getFieldDefFromFieldRef(normalizedLeft, context);
+ const comparand =
+ leftFieldDef && QueryUtils.isEnum(this.schema, leftFieldDef.type)
+ ? // cast lhs otherwise dialect like pg can reject due to type mismatch
+ this.dialect.castText(new ExpressionWrapper(left)).toOperationNode()
+ : left;
return BinaryOperationNode.create(
- left,
+ comparand,
OperatorNode.create('='),
FunctionNode.create('any', [right]),
);
diff --git a/packages/plugins/soft-delete/README.md b/packages/plugins/soft-delete/README.md
new file mode 100644
index 000000000..ebd094ab5
--- /dev/null
+++ b/packages/plugins/soft-delete/README.md
@@ -0,0 +1,80 @@
+# @zenstackhq/plugin-soft-delete
+
+A ZenStack runtime plugin that implements **soft delete** by intercepting Kysely queries. Instead of physically removing rows, delete operations mark them with a timestamp, and reads automatically exclude the marked rows.
+
+## How It Works
+
+The plugin works off a single `@deletedAt` marker field on each model that should support soft deletion:
+
+- **Deletes become updates** — a `delete`/`deleteMany` against a soft-delete model is rewritten to set the `@deletedAt` field to the current timestamp instead of issuing a `DELETE`.
+- **Reads are filtered** — `find*` queries (and joined relations) automatically add a ` IS NULL` condition, so soft-deleted rows are invisible.
+- **Updates skip tombstones** — `update`/`updateMany` won't touch rows that are already soft-deleted.
+
+Models without a `@deletedAt` field are left completely untouched.
+
+## Installation
+
+```bash
+npm install @zenstackhq/plugin-soft-delete
+```
+
+## Usage
+
+### 1. Declare the plugin in your ZModel schema
+
+This makes the `@deletedAt` attribute available in your schema.
+
+```zmodel
+plugin softDelete {
+ provider = '@zenstackhq/plugin-soft-delete'
+}
+```
+
+### 2. Mark a nullable `DateTime` field with `@deletedAt`
+
+A model can have at most one `@deletedAt` field, and it must be optional (so that "not deleted" is represented by `null`).
+
+```zmodel
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ posts Post[]
+ deletedAt DateTime? @deletedAt
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ author User @relation(fields: [authorId], references: [id])
+ authorId Int
+ deletedAt DateTime? @deletedAt
+}
+```
+
+### 3. Install the plugin on your client at runtime
+
+```ts
+import { ZenStackClient } from '@zenstackhq/orm';
+import { SoftDeletePlugin } from '@zenstackhq/plugin-soft-delete';
+import { schema } from './schema';
+
+const db = new ZenStackClient(schema, { ... }).$use(new SoftDeletePlugin());
+
+const user = await db.user.create({ data: { email: 'a@example.com' } });
+
+// rewritten to set `deletedAt`, the row is kept in the database
+await db.user.delete({ where: { id: user.id } });
+
+// returns `null` — soft-deleted rows are hidden from reads
+await db.user.findUnique({ where: { id: user.id } });
+```
+
+## Caveats
+
+- **Soft deletes do not cascade.** Children of a soft-deleted parent are left untouched — managing them is up to you. (Note that a *hard* delete on a model without `@deletedAt` still triggers database-level `onDelete: Cascade` as usual.)
+- **Multi-table / joined deletes can't be rewritten.** A joined or multi-table `DELETE` that targets a soft-delete model is rejected rather than silently hard-deleting rows. Use a single-table delete instead.
+- **Unique constraints and tombstones.** Because soft-deleted rows physically remain, a plain `@unique` field will reject reusing a value held by a tombstone. The common mitigation is a partial unique index scoped to live rows (e.g. `... WHERE "deletedAt" IS NULL` on PostgreSQL/SQLite, or a functional index over a `CASE` expression on MySQL).
+
+## Learn More
+
+- [ZenStack Documentation](https://zenstack.dev)
diff --git a/packages/plugins/soft-delete/eslint.config.js b/packages/plugins/soft-delete/eslint.config.js
new file mode 100644
index 000000000..5698b9910
--- /dev/null
+++ b/packages/plugins/soft-delete/eslint.config.js
@@ -0,0 +1,4 @@
+import config from '@zenstackhq/eslint-config/base.js';
+
+/** @type {import("eslint").Linter.Config} */
+export default config;
diff --git a/packages/plugins/soft-delete/package.json b/packages/plugins/soft-delete/package.json
new file mode 100644
index 000000000..3cc7a16c6
--- /dev/null
+++ b/packages/plugins/soft-delete/package.json
@@ -0,0 +1,68 @@
+{
+ "name": "@zenstackhq/plugin-soft-delete",
+ "displayName": "ZenStack Soft Delete Plugin",
+ "description": "ZenStack plugin that implements soft-delete by intercepting Kysely queries",
+ "version": "3.8.0",
+ "type": "module",
+ "author": {
+ "name": "ZenStack Team",
+ "email": "contact@zenstack.dev"
+ },
+ "homepage": "https://zenstack.dev",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/zenstackhq/zenstack"
+ },
+ "license": "MIT",
+ "scripts": {
+ "build": "tsc --noEmit && tsdown",
+ "watch": "tsdown --watch",
+ "lint": "eslint src --ext ts",
+ "test": "vitest run",
+ "pack": "pnpm pack"
+ },
+ "keywords": [],
+ "files": [
+ "dist",
+ "plugin.zmodel"
+ ],
+ "exports": {
+ ".": {
+ "import": {
+ "types": "./dist/index.d.mts",
+ "default": "./dist/index.mjs"
+ },
+ "require": {
+ "types": "./dist/index.d.cts",
+ "default": "./dist/index.cjs"
+ }
+ },
+ "./plugin.zmodel": {
+ "import": "./plugin.zmodel",
+ "require": "./plugin.zmodel"
+ },
+ "./package.json": {
+ "import": "./package.json",
+ "require": "./package.json"
+ }
+ },
+ "dependencies": {
+ "@zenstackhq/common-helpers": "workspace:*",
+ "@zenstackhq/orm": "workspace:*",
+ "ts-pattern": "catalog:"
+ },
+ "peerDependencies": {
+ "kysely": "catalog:"
+ },
+ "devDependencies": {
+ "@types/better-sqlite3": "catalog:",
+ "@types/node": "catalog:",
+ "@zenstackhq/eslint-config": "workspace:*",
+ "@zenstackhq/testtools": "workspace:*",
+ "@zenstackhq/tsdown-config": "workspace:*",
+ "@zenstackhq/typescript-config": "workspace:*",
+ "@zenstackhq/vitest-config": "workspace:*",
+ "better-sqlite3": "catalog:"
+ },
+ "funding": "https://github.com/sponsors/zenstackhq"
+}
diff --git a/packages/plugins/soft-delete/plugin.zmodel b/packages/plugins/soft-delete/plugin.zmodel
new file mode 100644
index 000000000..ba657198b
--- /dev/null
+++ b/packages/plugins/soft-delete/plugin.zmodel
@@ -0,0 +1,10 @@
+/**
+ * Marks a `DateTime` field as the soft-delete indicator for its owning model.
+ *
+ * When the soft-delete plugin is installed, reads against the model are automatically filtered
+ * to exclude rows whose marked field is non-null, and delete operations are rewritten to set
+ * the marked field to the current timestamp instead of physically removing the row.
+ *
+ * A model can have at most one `@deletedAt` field.
+ */
+attribute @deletedAt() @@@targetField([DateTimeField]) @@@once @@@onceInModel
diff --git a/packages/plugins/soft-delete/src/index.ts b/packages/plugins/soft-delete/src/index.ts
new file mode 100644
index 000000000..1110b6451
--- /dev/null
+++ b/packages/plugins/soft-delete/src/index.ts
@@ -0,0 +1 @@
+export * from './plugin';
diff --git a/packages/plugins/soft-delete/src/plugin.ts b/packages/plugins/soft-delete/src/plugin.ts
new file mode 100644
index 000000000..a20cac974
--- /dev/null
+++ b/packages/plugins/soft-delete/src/plugin.ts
@@ -0,0 +1,302 @@
+import {
+ getCrudDialect,
+ ORMError,
+ ORMErrorReason,
+ QueryUtils,
+ type BaseCrudDialect,
+ type ClientContract,
+ type OnKyselyQueryArgs,
+ type ProceedKyselyQueryFunction,
+ type RuntimePlugin,
+} from '@zenstackhq/orm';
+import type { FieldDef, SchemaDef } from '@zenstackhq/orm/schema';
+import {
+ AliasNode,
+ AndNode,
+ BinaryOperationNode,
+ ColumnNode,
+ ColumnUpdateNode,
+ DeleteQueryNode,
+ IdentifierNode,
+ JoinNode,
+ OnNode,
+ OperationNodeTransformer,
+ OperatorNode,
+ OrNode,
+ ParensNode,
+ ReferenceNode,
+ SelectQueryNode,
+ TableNode,
+ UpdateQueryNode,
+ ValueNode,
+ WhereNode,
+ type OperationNode,
+ type RootOperationNode,
+} from 'kysely';
+
+const SOFT_DELETE_ATTRIBUTE = '@deletedAt';
+
+export class SoftDeletePlugin implements RuntimePlugin {
+ get id() {
+ return 'soft-delete' as const;
+ }
+
+ get name() {
+ return 'Soft Delete';
+ }
+
+ get description() {
+ return 'Filters reads against models with @deletedAt and transforms delete operations into updates of the @deletedAt field.';
+ }
+
+ onKyselyQuery({ query, client, proceed }: OnKyselyQueryArgs) {
+ const handler = new SoftDeleteHandler(client);
+ return handler.handle(query, proceed);
+ }
+}
+
+type TableInfo = { model: string; alias?: string };
+
+class SoftDeleteHandler extends OperationNodeTransformer {
+ private readonly dialect: BaseCrudDialect;
+
+ constructor(private readonly client: ClientContract) {
+ super();
+ this.dialect = getCrudDialect(client.$schema, client.$options);
+ }
+
+ async handle(node: RootOperationNode, proceed: ProceedKyselyQueryFunction) {
+ if (DeleteQueryNode.is(node)) {
+ const converted = this.tryConvertDeleteToUpdate(node);
+ if (converted) {
+ // The rewritten UPDATE still flows through `transformUpdateQuery` so the
+ // soft-delete filter is added and already-soft-deleted rows aren't re-touched.
+ return proceed(this.transformNode(converted));
+ }
+ // Not a soft-delete target: let the delete (and any DB-level cascade) proceed naturally.
+ }
+ return proceed(this.transformNode(node));
+ }
+
+ // Inject ` IS NULL` for soft-delete tables in the FROM clause.
+ protected override transformSelectQuery(node: SelectQueryNode): SelectQueryNode {
+ const result = super.transformSelectQuery(node);
+ if (!result.from) {
+ return result;
+ }
+ const filter = this.buildSoftDeleteFilterForTables(result.from.froms);
+ if (!filter) {
+ return result;
+ }
+ return {
+ ...result,
+ where: this.mergeWhere(result.where, filter),
+ };
+ }
+
+ // Inject ` IS NULL` into ON clauses of joins against soft-delete tables.
+ protected override transformJoin(node: JoinNode): JoinNode {
+ const result = super.transformJoin(node);
+ const info = this.extractTableInfo(result.table);
+ if (!info) {
+ return result;
+ }
+ // Any model that participates in a delegate (polymorphic) hierarchy has its `@deletedAt`
+ // handled by `transformSelectQuery`, never here: reconstruction joins are filtered through
+ // the outer WHERE (walking the FROM entity's base chain), and relation reads become subqueries
+ // filtered by their own FROM. The marker may also live on a table that isn't the one under
+ // this join's alias (a base, or a descendant joined for polymorphic packing). So never add an
+ // ON-clause predicate for a hierarchy member — at best it's redundant, and on a LEFT join it
+ // would only null the joined columns and leak the row.
+ if (this.isInDelegateHierarchy(info.model)) {
+ return result;
+ }
+ const deletedAt = this.getDeletedAtField(info.model);
+ if (!deletedAt) {
+ return result;
+ }
+ const filter = this.buildIsNullPredicate(info.alias ?? info.model, deletedAt.name);
+ return {
+ ...result,
+ on: result.on ? OnNode.create(this.andNode(result.on.on, filter)) : OnNode.create(filter),
+ };
+ }
+
+ // Prevent updates from touching already soft-deleted rows.
+ protected override transformUpdateQuery(node: UpdateQueryNode): UpdateQueryNode {
+ const result = super.transformUpdateQuery(node);
+ if (!result.table) {
+ return result;
+ }
+ const info = this.extractTableInfo(result.table);
+ if (!info) {
+ return result;
+ }
+ const deletedAt = this.getDeletedAtField(info.model);
+ if (!deletedAt) {
+ return result;
+ }
+ const filter = this.buildIsNullPredicate(info.alias ?? info.model, deletedAt.name);
+ return {
+ ...result,
+ where: this.mergeWhere(result.where, filter),
+ };
+ }
+
+ private tryConvertDeleteToUpdate(node: DeleteQueryNode): UpdateQueryNode | undefined {
+ // Only single-table deletes can be converted. Multi-table/joined deletes can't be rewritten
+ // into an @deletedAt update — if such a delete targets a soft-delete model, refuse rather
+ // than silently hard-deleting its rows; otherwise let it fall through and cascade naturally.
+ if (node.from.froms.length !== 1 || node.using || node.joins?.length) {
+ for (const fromNode of node.from.froms) {
+ const info = this.extractTableInfo(fromNode);
+ if (info && this.getDeletedAtField(info.model)) {
+ throw new ORMError(
+ ORMErrorReason.NOT_SUPPORTED,
+ `Cannot soft-delete from "${info.model}": multi-table or joined DELETE statements cannot be rewritten into an @deletedAt update. Use a single-table delete instead.`,
+ );
+ }
+ }
+ return undefined;
+ }
+ const fromNode = node.from.froms[0]!;
+ const info = this.extractTableInfo(fromNode);
+ if (!info) {
+ return undefined;
+ }
+ const deletedAt = this.getDeletedAtField(info.model);
+ if (!deletedAt) {
+ return undefined;
+ }
+
+ const now = this.dialect.transformInput(new Date(), 'DateTime', false);
+ const update: UpdateQueryNode = {
+ kind: 'UpdateQueryNode',
+ table: fromNode,
+ updates: [ColumnUpdateNode.create(ColumnNode.create(deletedAt.name), ValueNode.create(now))],
+ where: node.where,
+ with: node.with,
+ returning: node.returning,
+ limit: node.limit,
+ orderBy: node.orderBy,
+ explain: node.explain,
+ };
+ return update;
+ }
+
+ // #region helpers
+
+ private buildSoftDeleteFilterForTables(tables: readonly OperationNode[]): OperationNode | undefined {
+ const filters: OperationNode[] = [];
+ for (const table of tables) {
+ const info = this.extractTableInfo(table);
+ if (!info) {
+ continue;
+ }
+ const target = this.getSoftDeleteTarget(info);
+ if (target) {
+ filters.push(this.buildIsNullPredicate(target.table, target.column));
+ }
+ }
+ if (filters.length === 0) {
+ return undefined;
+ }
+ return filters.reduce((acc, f) => this.andNode(acc, f));
+ }
+
+ // Resolve the single `@deletedAt` column to filter when reading a table. `@@@onceInModel` allows
+ // at most one marker per inheritance hierarchy, so it's either declared on the model itself or
+ // inherited from exactly one delegate base — where the column physically lives on the base's
+ // table (LEFT-joined under its own model name, see buildDelegateJoin), so the filter must key off
+ // that base rather than the queried table.
+ private getSoftDeleteTarget(info: TableInfo): { table: string; column: string } | undefined {
+ const own = this.getDeletedAtField(info.model);
+ if (own) {
+ return { table: info.alias ?? info.model, column: own.name };
+ }
+ let base = QueryUtils.getModel(this.client.$schema, info.model)?.baseModel;
+ while (base) {
+ const marker = this.getDeletedAtField(base);
+ if (marker) {
+ return { table: base, column: marker.name };
+ }
+ base = QueryUtils.getModel(this.client.$schema, base)?.baseModel;
+ }
+ return undefined;
+ }
+
+ private isInDelegateHierarchy(model: string): boolean {
+ const modelDef = QueryUtils.getModel(this.client.$schema, model);
+ return !!modelDef && (!!modelDef.isDelegate || !!modelDef.baseModel);
+ }
+
+ private buildIsNullPredicate(table: string, column: string): OperationNode {
+ return BinaryOperationNode.create(
+ ReferenceNode.create(ColumnNode.create(column), TableNode.create(table)),
+ OperatorNode.create('is'),
+ ValueNode.createImmediate(null),
+ );
+ }
+
+ private andNode(a: OperationNode, b: OperationNode): OperationNode {
+ return AndNode.create(this.wrap(a), this.wrap(b));
+ }
+
+ private wrap(node: OperationNode): OperationNode {
+ return OrNode.is(node) ? ParensNode.create(node) : node;
+ }
+
+ private mergeWhere(existing: WhereNode | undefined, filter: OperationNode): WhereNode {
+ return WhereNode.create(existing ? this.andNode(existing.where, filter) : filter);
+ }
+
+ private extractTableInfo(node: OperationNode): TableInfo | undefined {
+ if (TableNode.is(node)) {
+ return { model: node.table.identifier.name };
+ }
+ if (AliasNode.is(node)) {
+ const inner = this.extractTableInfo(node.node);
+ if (!inner) {
+ return undefined;
+ }
+ return {
+ model: inner.model,
+ alias: IdentifierNode.is(node.alias) ? node.alias.name : inner.alias,
+ };
+ }
+ return undefined;
+ }
+
+ private getDeletedAtField(model: string): FieldDef | undefined {
+ const modelDef = QueryUtils.getModel(this.client.$schema, model);
+ if (!modelDef) {
+ return undefined;
+ }
+ for (const fieldDef of Object.values(modelDef.fields)) {
+ if (fieldDef.attributes?.some((a) => a.name === SOFT_DELETE_ATTRIBUTE)) {
+ if (fieldDef.originModel) {
+ // In a delegate (polymorphic) hierarchy the marker physically lives on the base
+ // table, but it's surfaced on every concrete sub-model's field list (tagged with
+ // `originModel`). Skip it here so we don't reference a non-existent
+ // `.` column — the base model contributes its own FROM/JOIN
+ // node that carries the soft-delete filter on the real column. Likewise, a
+ // concrete delete is rewritten by the ORM into a delete on the base table, so the
+ // delete-to-update conversion also keys off the base model.
+ continue;
+ }
+ if (!fieldDef.optional) {
+ // A non-nullable marker can never be null, so the `IS NULL` read filter would
+ // hide every row. Require the marker to be optional so "not deleted" === null.
+ throw new ORMError(
+ ORMErrorReason.NOT_SUPPORTED,
+ `Field "${model}.${fieldDef.name}" is marked @deletedAt but is not optional. The soft-delete marker must be a nullable field (e.g. "DateTime?").`,
+ );
+ }
+ return fieldDef;
+ }
+ }
+ return undefined;
+ }
+
+ // #endregion
+}
diff --git a/packages/plugins/soft-delete/test/soft-delete.test.ts b/packages/plugins/soft-delete/test/soft-delete.test.ts
new file mode 100644
index 000000000..d4a7eac28
--- /dev/null
+++ b/packages/plugins/soft-delete/test/soft-delete.test.ts
@@ -0,0 +1,434 @@
+import { createTestClient } from '@zenstackhq/testtools';
+import { fileURLToPath } from 'node:url';
+import { describe, expect, it } from 'vitest';
+import { SoftDeletePlugin } from '../src';
+
+// The `@deletedAt` attribute is defined in this plugin's `plugin.zmodel`. We feed it to the
+// test client explicitly so that `@zenstackhq/testtools` doesn't need to depend on this plugin.
+const PLUGIN_MODEL_FILE = fileURLToPath(new URL('../plugin.zmodel', import.meta.url));
+
+function createSoftDeleteTestClient(schema: string, extraOptions: Record = {}) {
+ return createTestClient(schema, { extraPluginModelFiles: [PLUGIN_MODEL_FILE], ...extraOptions });
+}
+
+const schema = `
+model User {
+ id Int @id @default(autoincrement())
+ email String @unique
+ posts Post[]
+ deletedAt DateTime? @deletedAt
+}
+
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ author User @relation(fields: [authorId], references: [id])
+ authorId Int
+ deletedAt DateTime? @deletedAt
+}
+
+model Tag {
+ id Int @id @default(autoincrement())
+ name String
+}
+`;
+
+async function makeClient() {
+ const raw = await createSoftDeleteTestClient(schema);
+ const db = raw.$use(new SoftDeletePlugin());
+ return { db, raw };
+}
+
+describe('soft-delete plugin', () => {
+ it('hides soft-deleted rows from reads', async () => {
+ const { db } = await makeClient();
+
+ const a = await db.user.create({ data: { email: 'a@test.com' } });
+ const b = await db.user.create({ data: { email: 'b@test.com' } });
+
+ await db.user.delete({ where: { id: a.id } });
+
+ await expect(db.user.findMany()).resolves.toEqual([
+ expect.objectContaining({ id: b.id, email: 'b@test.com', deletedAt: null }),
+ ]);
+
+ await expect(db.user.findUnique({ where: { id: a.id } })).resolves.toBeNull();
+ await expect(db.user.findUnique({ where: { id: b.id } })).resolves.toMatchObject({ id: b.id });
+ });
+
+ it('rewrites delete into update on the @deletedAt column', async () => {
+ const { db, raw } = await makeClient();
+ const user = await db.user.create({ data: { email: 'soft@test.com' } });
+
+ // delete returns the affected record (whether its `deletedAt` reflects the new value
+ // depends on the dialect's delete-return strategy — RETURNING vs select-then-mutate —
+ // so we assert the persisted state below instead)
+ const deleted = await db.user.delete({ where: { id: user.id } });
+ expect(deleted).toMatchObject({ id: user.id, email: 'soft@test.com' });
+
+ // the row is still physically present, just marked deleted (peek via plugin-less client)
+ const row = await raw.user.findUniqueOrThrow({ where: { id: user.id } });
+ expect(row.deletedAt).not.toBeNull();
+ expect(row.deletedAt!.getTime()).not.toBeNaN();
+ });
+
+ it('skips already soft-deleted rows on subsequent deletes and updates', async () => {
+ const { db, raw } = await makeClient();
+ const user = await db.user.create({ data: { email: 'one@test.com' } });
+
+ const firstDelete = await db.user.delete({ where: { id: user.id } });
+ expect(firstDelete).toMatchObject({ id: user.id });
+
+ const firstDeletedAt = (await raw.user.findUniqueOrThrow({ where: { id: user.id } })).deletedAt!;
+
+ // a follow-up delete should be a no-op (row already soft-deleted) and report a zero count
+ const secondDelete = await db.user.deleteMany({ where: { id: user.id } });
+ expect(secondDelete).toEqual({ count: 0 });
+ const afterSecondDelete = await raw.user.findUniqueOrThrow({ where: { id: user.id } });
+ expect(afterSecondDelete.deletedAt!.getTime()).toBe(firstDeletedAt.getTime());
+
+ // updateMany should also skip soft-deleted rows
+ await db.user.updateMany({ where: { id: user.id }, data: { email: 'updated@test.com' } });
+ const afterUpdate = await raw.user.findUniqueOrThrow({ where: { id: user.id } });
+ expect(afterUpdate.email).toBe('one@test.com');
+ });
+
+ it('soft-deletes a related row via a nested delete', async () => {
+ const { db, raw } = await makeClient();
+ const user = await db.user.create({
+ data: { email: 'nested@test.com', posts: { create: [{ title: 'a' }, { title: 'b' }] } },
+ include: { posts: true },
+ });
+ // pick by title — `include` has no orderBy, so array position isn't guaranteed
+ const postA = user.posts.find((p: any) => p.title === 'a');
+ const postB = user.posts.find((p: any) => p.title === 'b');
+
+ // nested delete of a soft-delete child runs as a soft delete
+ const updated = await db.user.update({
+ where: { id: user.id },
+ data: { posts: { delete: { id: postA!.id } } },
+ include: { posts: true },
+ });
+
+ // the returned relation only surfaces the surviving post
+ expect(updated.posts).toEqual([expect.objectContaining({ id: postB!.id, title: 'b', deletedAt: null })]);
+
+ // post A is physically present but marked deleted; post B untouched
+ // (read via the plugin-less `raw` client so the soft-delete filter doesn't hide it)
+ const rowA = await raw.post.findUniqueOrThrow({ where: { id: postA!.id } });
+ expect(rowA.deletedAt).not.toBeNull();
+
+ const rowB = await raw.post.findUniqueOrThrow({ where: { id: postB!.id } });
+ expect(rowB.deletedAt).toBeNull();
+ });
+
+ it('soft-deletes matching rows on deleteMany and reports the live count', async () => {
+ const { db, raw } = await makeClient();
+ const keep = await db.user.create({ data: { email: 'keep@x.com' } });
+ const drop1 = await db.user.create({ data: { email: 'drop1@y.com' } });
+ const drop2 = await db.user.create({ data: { email: 'drop2@y.com' } });
+ // pre-soft-deleted row that also matches the filter — must not be re-counted
+ const already = await db.user.create({ data: { email: 'already@y.com' } });
+ await db.user.delete({ where: { id: already.id } });
+
+ // only the two live matching rows are counted
+ const result = await db.user.deleteMany({ where: { email: { endsWith: '@y.com' } } });
+ expect(result).toEqual({ count: 2 });
+
+ // matched rows are soft-deleted (marked, not physically removed)...
+ const droppedRows = await raw.user.findMany({ where: { id: { in: [drop1.id, drop2.id] } } });
+ expect(droppedRows).toHaveLength(2);
+ for (const row of droppedRows) {
+ expect(row.deletedAt).not.toBeNull();
+ }
+
+ // ...and reads only surface the untouched row
+ await expect(db.user.findMany()).resolves.toEqual([
+ expect.objectContaining({ id: keep.id, email: 'keep@x.com', deletedAt: null }),
+ ]);
+ });
+
+ it('filters joined relations against the @deletedAt column', async () => {
+ const { db } = await makeClient();
+ const user = await db.user.create({ data: { email: 'rel@test.com' } });
+ const live = await db.post.create({ data: { title: 'live', authorId: user.id } });
+ const tombstoned = await db.post.create({ data: { title: 'gone', authorId: user.id } });
+
+ await db.post.delete({ where: { id: tombstoned.id } });
+
+ const reloaded = await db.user.findUniqueOrThrow({
+ where: { id: user.id },
+ include: { posts: true },
+ });
+
+ expect(reloaded.posts).toEqual([expect.objectContaining({ id: live.id, title: 'live' })]);
+ });
+
+ it('leaves models without @deletedAt untouched', async () => {
+ const { db, raw } = await makeClient();
+
+ const tag = await db.tag.create({ data: { name: 'keep' } });
+ await db.tag.delete({ where: { id: tag.id } });
+
+ await expect(db.tag.findUnique({ where: { id: tag.id } })).resolves.toBeNull();
+
+ // physically gone (confirm via the plugin-less client)
+ await expect(raw.tag.findUnique({ where: { id: tag.id } })).resolves.toBeNull();
+ });
+
+ it('rejects a non-nullable @deletedAt field', async () => {
+ // A non-optional marker can never be null, so the IS NULL read filter would hide every row.
+ const badSchema = `
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ deletedAt DateTime @default(now()) @deletedAt
+}
+`;
+ const raw = await createSoftDeleteTestClient(badSchema);
+ const db = raw.$use(new SoftDeletePlugin());
+ await expect(db.post.findMany()).rejects.toThrow(/"Post\.deletedAt".*not optional/);
+ });
+
+ it('rejects a model with more than one @deletedAt field', async () => {
+ const twoFieldsSchema = `
+model Post {
+ id Int @id @default(autoincrement())
+ title String
+ deletedAt DateTime? @deletedAt
+ removedAt DateTime? @deletedAt
+}
+`;
+ await expect(createSoftDeleteTestClient(twoFieldsSchema)).rejects.toThrow(
+ /@deletedAt.*can only be applied to one field per model/,
+ );
+ });
+
+ it('rejects a joined/multi-table delete that targets a soft-delete model', async () => {
+ const { db, raw } = await makeClient();
+ const user = await db.user.create({ data: { email: 'spam@test.com' } });
+ const post = await db.post.create({ data: { title: 'spammy', authorId: user.id } });
+
+ // A joined delete on Post (a soft-delete model) can't be rewritten into an @deletedAt update.
+ await expect(
+ db.$qb
+ .deleteFrom('Post')
+ .using('User')
+ .whereRef('Post.authorId', '=', 'User.id')
+ .where('User.email', '=', 'spam@test.com')
+ .execute(),
+ ).rejects.toThrow(/Cannot soft-delete from "Post".*single-table delete/s);
+
+ // the row is untouched — neither hard- nor soft-deleted
+ const row = await raw.post.findUniqueOrThrow({ where: { id: post.id } });
+ expect(row.deletedAt).toBeNull();
+ });
+
+ it('rewrites a single-table $qb delete on a soft-delete model into an update', async () => {
+ const { db, raw } = await makeClient();
+ const user = await db.user.create({ data: { email: 'qb@test.com' } });
+
+ // low-level Kysely delete still flows through the plugin's onKyselyQuery hook;
+ // the rewritten update still reports the affected-row count as a delete result
+ const result = await db.$qb.deleteFrom('User').where('id', '=', user.id).execute();
+ expect(result).toEqual([{ numDeletedRows: 1n }]);
+
+ // physically present, just marked deleted
+ const row = await raw.user.findUniqueOrThrow({ where: { id: user.id } });
+ expect(row.deletedAt).not.toBeNull();
+
+ // and hidden from reads through the plugin
+ await expect(db.user.findUnique({ where: { id: user.id } })).resolves.toBeNull();
+ });
+
+ it('lets a $qb delete on a model without @deletedAt delete physically', async () => {
+ const { db, raw } = await makeClient();
+ const tag = await db.tag.create({ data: { name: 'qb-keep' } });
+
+ const result = await db.$qb.deleteFrom('Tag').where('id', '=', tag.id).execute();
+ expect(result).toEqual([{ numDeletedRows: 1n }]);
+
+ await expect(raw.tag.findUnique({ where: { id: tag.id } })).resolves.toBeNull();
+ });
+
+ it('does not propagate the soft-delete to children (left to the user)', async () => {
+ // The plugin intentionally does not cascade soft-deletes. Children of a soft-deleted
+ // parent are left untouched; managing them is the user's responsibility.
+ const cascadeSchema = `
+model Parent {
+ id Int @id @default(autoincrement())
+ name String
+ children Child[]
+ deletedAt DateTime? @deletedAt
+}
+
+model Child {
+ id Int @id @default(autoincrement())
+ parent Parent @relation(fields: [parentId], references: [id])
+ parentId Int
+ deletedAt DateTime? @deletedAt
+}
+`;
+ const raw = await createSoftDeleteTestClient(cascadeSchema);
+ const db = raw.$use(new SoftDeletePlugin());
+
+ const parent = await db.parent.create({
+ data: { name: 'p', children: { create: [{}, {}] } },
+ });
+
+ await db.parent.delete({ where: { id: parent.id } });
+
+ // parent is soft-deleted...
+ const parentRow = await raw.parent.findUniqueOrThrow({ where: { id: parent.id } });
+ expect(parentRow.deletedAt).not.toBeNull();
+
+ // ...but its children are left untouched
+ const childRows = await raw.child.findMany({ where: { parentId: parent.id } });
+ expect(childRows).toHaveLength(2);
+ for (const row of childRows) {
+ expect(row.deletedAt).toBeNull();
+ }
+ });
+
+ it('lets a hard-delete cascade naturally at the database', async () => {
+ // The parent has no @deletedAt, so its delete is a real DELETE. The plugin does not
+ // interfere, so the DB-level onDelete: Cascade hard-deletes the children too.
+ const cascadeSchema = `
+model Parent {
+ id Int @id @default(autoincrement())
+ name String
+ children Child[]
+}
+
+model Child {
+ id Int @id @default(autoincrement())
+ parent Parent @relation(fields: [parentId], references: [id], onDelete: Cascade)
+ parentId Int
+ deletedAt DateTime? @deletedAt
+}
+`;
+ const raw = await createSoftDeleteTestClient(cascadeSchema);
+ const db = raw.$use(new SoftDeletePlugin());
+
+ const parent = await db.parent.create({
+ data: { name: 'p', children: { create: [{}, {}] } },
+ });
+
+ await db.parent.delete({ where: { id: parent.id } });
+
+ // parent and its children are physically gone
+ await expect(raw.parent.findUnique({ where: { id: parent.id } })).resolves.toBeNull();
+ await expect(raw.child.findMany({ where: { parentId: parent.id } })).resolves.toHaveLength(0);
+ });
+
+ it('soft-deletes a model whose @deletedAt is inherited from a mixin', async () => {
+ // The marker is declared on a `type` mixin and flattened into the model's fields, so the
+ // plugin should treat the composed model exactly like one that declares @deletedAt directly.
+ const mixinSchema = `
+type SoftDeletable {
+ deletedAt DateTime? @deletedAt
+}
+
+model Item with SoftDeletable {
+ id Int @id @default(autoincrement())
+ name String
+}
+`;
+ const raw = await createSoftDeleteTestClient(mixinSchema);
+ const db = raw.$use(new SoftDeletePlugin());
+
+ const a = await db.item.create({ data: { name: 'a' } });
+ const b = await db.item.create({ data: { name: 'b' } });
+
+ await db.item.delete({ where: { id: a.id } });
+
+ // hidden from reads through the plugin
+ await expect(db.item.findMany()).resolves.toEqual([
+ expect.objectContaining({ id: b.id, name: 'b', deletedAt: null }),
+ ]);
+ await expect(db.item.findUnique({ where: { id: a.id } })).resolves.toBeNull();
+
+ // physically present, just marked deleted (peek via the plugin-less client)
+ const row = await raw.item.findUniqueOrThrow({ where: { id: a.id } });
+ expect(row.deletedAt).not.toBeNull();
+ });
+
+ it('soft-deletes a delegate model marked on the base', async () => {
+ // The @deletedAt marker lives on the polymorphic base. Deleting through either the base or a
+ // concrete model should soft-delete the base row, and reads through both should hide it.
+ const delegateSchema = `
+model Content {
+ id Int @id @default(autoincrement())
+ contentType String
+ deletedAt DateTime? @deletedAt
+ @@delegate(contentType)
+}
+
+model Article extends Content {
+ title String
+}
+`;
+ const raw = await createSoftDeleteTestClient(delegateSchema, { usePrismaPush: true });
+ const db = raw.$use(new SoftDeletePlugin());
+
+ const a = await db.article.create({ data: { title: 'a' } });
+ const b = await db.article.create({ data: { title: 'b' } });
+
+ // delete through the concrete model
+ await db.article.delete({ where: { id: a.id } });
+
+ // hidden from reads through both the concrete and base accessors
+ await expect(db.article.findUnique({ where: { id: a.id } })).resolves.toBeNull();
+ await expect(db.content.findUnique({ where: { id: a.id } })).resolves.toBeNull();
+ await expect(db.article.findMany()).resolves.toEqual([expect.objectContaining({ id: b.id, title: 'b' })]);
+
+ // the base row is physically present, just marked deleted (the concrete row survives too)
+ const baseRow = await raw.content.findUniqueOrThrow({ where: { id: a.id } });
+ expect(baseRow.deletedAt).not.toBeNull();
+ await expect(raw.article.findUnique({ where: { id: a.id } })).resolves.not.toBeNull();
+
+ // delete through the base model soft-deletes as well
+ await db.content.delete({ where: { id: b.id } });
+ await expect(db.article.findUnique({ where: { id: b.id } })).resolves.toBeNull();
+ const baseRowB = await raw.content.findUniqueOrThrow({ where: { id: b.id } });
+ expect(baseRowB.deletedAt).not.toBeNull();
+ });
+
+ it('does not update an already soft-deleted delegate row', async () => {
+ // The marker lives on the base, but updates target the concrete sub-table. Updating a
+ // concrete-only field of a soft-deleted row must still be a no-op. The ORM funnels every
+ // delegate update through an `id IN ()` subquery that inherits the soft-delete read
+ // filter, so the soft-deleted row is invisible to the update.
+ const delegateSchema = `
+model Content {
+ id Int @id @default(autoincrement())
+ contentType String
+ deletedAt DateTime? @deletedAt
+ @@delegate(contentType)
+}
+
+model Article extends Content {
+ title String
+}
+`;
+ const raw = await createSoftDeleteTestClient(delegateSchema, { usePrismaPush: true });
+ const db = raw.$use(new SoftDeletePlugin());
+
+ const a = await db.article.create({ data: { title: 'a' } });
+ await db.article.delete({ where: { id: a.id } });
+
+ // updateMany on the concrete field skips the soft-deleted row and reports a zero count
+ await expect(db.article.updateMany({ where: { id: a.id }, data: { title: 'changed' } })).resolves.toEqual({
+ count: 0,
+ });
+
+ // a single update can't find the soft-deleted row at all
+ await expect(db.article.update({ where: { id: a.id }, data: { title: 'changed' } })).rejects.toThrow(
+ /not found/i,
+ );
+
+ // the concrete row is physically untouched (peek via the plugin-less client)
+ const row = await raw.article.findUniqueOrThrow({ where: { id: a.id } });
+ expect(row.title).toBe('a');
+ });
+});
diff --git a/packages/plugins/soft-delete/test/tombstone-unique.test.ts b/packages/plugins/soft-delete/test/tombstone-unique.test.ts
new file mode 100644
index 000000000..1ad2d3f6f
--- /dev/null
+++ b/packages/plugins/soft-delete/test/tombstone-unique.test.ts
@@ -0,0 +1,79 @@
+import { createTestClient, getTestDbProvider } from '@zenstackhq/testtools';
+import { fileURLToPath } from 'node:url';
+import { describe, expect, it } from 'vitest';
+import { SoftDeletePlugin } from '../src';
+
+// The `@deletedAt` attribute is defined in this plugin's `plugin.zmodel`. We feed it to the
+// test client explicitly so that `@zenstackhq/testtools` doesn't need to depend on this plugin.
+const PLUGIN_MODEL_FILE = fileURLToPath(new URL('../plugin.zmodel', import.meta.url));
+
+function createSoftDeleteTestClient(schema: string, provider?: 'sqlite' | 'postgresql' | 'mysql') {
+ return createTestClient(schema, { extraPluginModelFiles: [PLUGIN_MODEL_FILE], provider });
+}
+
+// A column-based soft delete leaves a tombstone behind, so a plain `@unique` would reject reusing
+// the value. The mitigation is a unique index scoped to live (non-deleted) rows. ZModel can't
+// express that condition, so each test below emits the dialect-specific DDL directly (no `@unique`
+// on the model) and asserts the same behavior: live rows are unique, tombstones may share a value.
+describe('tombstone unique conflict mitigation (per-dialect index)', () => {
+ const uniqueSchema = `
+model User {
+ id Int @id @default(autoincrement())
+ email String
+ deletedAt DateTime? @deletedAt
+}
+`;
+
+ async function expectTombstoneUniqueBehavior(db: any) {
+ const a = await db.user.create({ data: { email: 'a@x.com' } });
+
+ // a second *live* row with the same email collides
+ await expect(db.user.create({ data: { email: 'a@x.com' } })).rejects.toThrow();
+
+ // soft-deleting frees the value — the tombstone leaves the index's scope
+ await db.user.delete({ where: { id: a.id } });
+ const b = await db.user.create({ data: { email: 'a@x.com' } });
+ expect(b.id).not.toBe(a.id);
+
+ // uniqueness is still enforced among the remaining live rows
+ await expect(db.user.create({ data: { email: 'a@x.com' } })).rejects.toThrow();
+ }
+
+ it('sqlite: partial unique index scoped to live rows', async ({ skip }) => {
+ if (getTestDbProvider() !== 'sqlite') {
+ skip();
+ }
+ const raw = await createSoftDeleteTestClient(uniqueSchema, 'sqlite');
+ const db = raw.$use(new SoftDeletePlugin());
+ await raw.$executeRawUnsafe(
+ `CREATE UNIQUE INDEX "User_email_active" ON "User" ("email") WHERE "deletedAt" IS NULL`,
+ );
+ await expectTombstoneUniqueBehavior(db);
+ });
+
+ it('postgresql: partial unique index scoped to live rows', async ({ skip }) => {
+ if (getTestDbProvider() !== 'postgresql') {
+ skip();
+ }
+ const raw = await createSoftDeleteTestClient(uniqueSchema, 'postgresql');
+ const db = raw.$use(new SoftDeletePlugin());
+ await raw.$executeRawUnsafe(
+ `CREATE UNIQUE INDEX "User_email_active" ON "User" ("email") WHERE "deletedAt" IS NULL`,
+ );
+ await expectTombstoneUniqueBehavior(db);
+ });
+
+ it('mysql: functional unique index over a CASE expression', async ({ skip }) => {
+ if (getTestDbProvider() !== 'mysql') {
+ skip();
+ }
+ const raw = await createSoftDeleteTestClient(uniqueSchema, 'mysql');
+ const db = raw.$use(new SoftDeletePlugin());
+ // MySQL has no partial indexes; a functional key part over a CASE expr yields NULL for
+ // tombstones (and MySQL allows multiple NULLs in a unique index). Requires MySQL 8.0.13+.
+ await raw.$executeRawUnsafe(
+ 'ALTER TABLE `User` ADD UNIQUE INDEX `User_email_active` ((CASE WHEN `deletedAt` IS NULL THEN `email` END))',
+ );
+ await expectTombstoneUniqueBehavior(db);
+ });
+});
diff --git a/packages/plugins/soft-delete/tsconfig.json b/packages/plugins/soft-delete/tsconfig.json
new file mode 100644
index 000000000..1100998bc
--- /dev/null
+++ b/packages/plugins/soft-delete/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "extends": "@zenstackhq/typescript-config/base.json",
+ "compilerOptions": {
+ "types": ["node"]
+ },
+ "include": ["src/**/*", "test/**/*.ts"]
+}
diff --git a/packages/plugins/soft-delete/tsdown.config.ts b/packages/plugins/soft-delete/tsdown.config.ts
new file mode 100644
index 000000000..e0a6d5624
--- /dev/null
+++ b/packages/plugins/soft-delete/tsdown.config.ts
@@ -0,0 +1,3 @@
+import { createConfig } from '@zenstackhq/tsdown-config';
+
+export default createConfig({ entry: { index: 'src/index.ts' } });
diff --git a/packages/plugins/soft-delete/vitest.config.ts b/packages/plugins/soft-delete/vitest.config.ts
new file mode 100644
index 000000000..75a9f709c
--- /dev/null
+++ b/packages/plugins/soft-delete/vitest.config.ts
@@ -0,0 +1,4 @@
+import base from '@zenstackhq/vitest-config/base';
+import { defineConfig, mergeConfig } from 'vitest/config';
+
+export default mergeConfig(base, defineConfig({}));
diff --git a/packages/schema/package.json b/packages/schema/package.json
index a5e42c1fb..6ddd024d6 100644
--- a/packages/schema/package.json
+++ b/packages/schema/package.json
@@ -2,7 +2,7 @@
"name": "@zenstackhq/schema",
"displayName": "ZenStack Schema Object Model",
"description": "TypeScript representation of ZModel schema",
- "version": "3.7.2",
+ "version": "3.8.0",
"type": "module",
"author": {
"name": "ZenStack Team",
diff --git a/packages/sdk/package.json b/packages/sdk/package.json
index d886d8765..4bef954f7 100644
--- a/packages/sdk/package.json
+++ b/packages/sdk/package.json
@@ -2,7 +2,7 @@
"name": "@zenstackhq/sdk",
"displayName": "ZenStack SDK",
"description": "Utilities for building ZenStack plugins",
- "version": "3.7.2",
+ "version": "3.8.0",
"type": "module",
"author": {
"name": "ZenStack Team",
diff --git a/packages/sdk/src/index.ts b/packages/sdk/src/index.ts
index b213ff89f..c962b626b 100644
--- a/packages/sdk/src/index.ts
+++ b/packages/sdk/src/index.ts
@@ -2,4 +2,5 @@ import * as ModelUtils from './model-utils';
export * from './cli-plugin';
export { PrismaSchemaGenerator } from './prisma/prisma-schema-generator';
export * from './ts-schema-generator';
+export * from './tsconfig-utils';
export { ModelUtils };
diff --git a/packages/sdk/src/prisma/prisma-schema-generator.ts b/packages/sdk/src/prisma/prisma-schema-generator.ts
index 57fd9c6e9..f15422678 100644
--- a/packages/sdk/src/prisma/prisma-schema-generator.ts
+++ b/packages/sdk/src/prisma/prisma-schema-generator.ts
@@ -90,19 +90,19 @@ export class PrismaSchemaGenerator {
for (const decl of this.zmodel.declarations) {
switch (decl.$type) {
- case DataSource:
+ case DataSource.$type:
this.generateDataSource(prisma, decl as DataSource);
break;
- case Enum:
+ case Enum.$type:
this.generateEnum(prisma, decl as Enum);
break;
- case DataModel:
+ case DataModel.$type:
this.generateModel(prisma, decl as DataModel);
break;
- case GeneratorDecl:
+ case GeneratorDecl.$type:
this.generateGenerator(prisma, decl as GeneratorDecl);
break;
}
@@ -351,9 +351,9 @@ export class PrismaSchemaGenerator {
private makeAttributeArgValue(node: Expression): PrismaAttributeArgValue {
if (isLiteralExpr(node)) {
const argType = match(node.$type)
- .with(StringLiteral, () => 'String' as const)
- .with(NumberLiteral, () => 'Number' as const)
- .with(BooleanLiteral, () => 'Boolean' as const)
+ .with(StringLiteral.$type, () => 'String' as const)
+ .with(NumberLiteral.$type, () => 'Number' as const)
+ .with(BooleanLiteral.$type, () => 'Boolean' as const)
.exhaustive();
return new PrismaAttributeArgValue(argType, node.value);
} else if (isArrayExpr(node)) {
diff --git a/packages/sdk/src/tsconfig-utils.ts b/packages/sdk/src/tsconfig-utils.ts
new file mode 100644
index 000000000..c294114c3
--- /dev/null
+++ b/packages/sdk/src/tsconfig-utils.ts
@@ -0,0 +1,54 @@
+import path from 'node:path';
+import * as ts from 'typescript';
+
+/**
+ * Detects the file extension that should be appended to relative imports in
+ * generated TypeScript, by inspecting the nearest `tsconfig.json` to the given
+ * directory.
+ *
+ * Returns `'.js'` when the project uses native ESM module resolution
+ * (`node16`/`nodenext`), which requires explicit extensions on relative imports.
+ * Returns `undefined` for `bundler`/`node` resolution (where extensionless
+ * imports are the idiomatic, maximally-compatible form) or when no tsconfig is
+ * found.
+ */
+export function detectImportFileExtension(fromDir: string): string | undefined {
+ const configPath = ts.findConfigFile(fromDir, ts.sys.fileExists, 'tsconfig.json');
+ if (!configPath) {
+ return undefined;
+ }
+
+ const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
+ if (configFile.error) {
+ return undefined;
+ }
+
+ // resolve `extends` chains and module/moduleResolution defaults
+ const parsed = ts.parseJsonConfigFileContent(configFile.config, ts.sys, path.dirname(configPath));
+
+ // Prefer an explicit `moduleResolution`; when it's omitted, TypeScript derives
+ // it from `module`, so fall back to inspecting the module kind ourselves.
+ let moduleResolution = parsed.options.moduleResolution;
+ if (moduleResolution === undefined) {
+ switch (parsed.options.module) {
+ case ts.ModuleKind.Node16:
+ case ts.ModuleKind.Node18:
+ case ts.ModuleKind.Node20:
+ case ts.ModuleKind.NodeNext:
+ moduleResolution = ts.ModuleResolutionKind.NodeNext;
+ break;
+ default:
+ break;
+ }
+ }
+
+ // node16/nodenext resolution requires explicit extensions on relative imports
+ if (
+ moduleResolution === ts.ModuleResolutionKind.Node16 ||
+ moduleResolution === ts.ModuleResolutionKind.NodeNext
+ ) {
+ return '.js';
+ }
+
+ return undefined;
+}
diff --git a/packages/server/package.json b/packages/server/package.json
index f71f11d6e..b48020437 100644
--- a/packages/server/package.json
+++ b/packages/server/package.json
@@ -2,7 +2,7 @@
"name": "@zenstackhq/server",
"displayName": "ZenStack Automatic CRUD Server",
"description": "ZenStack automatic CRUD API handlers and server adapters for popular frameworks",
- "version": "3.7.2",
+ "version": "3.8.0",
"type": "module",
"author": {
"name": "ZenStack Team",
diff --git a/packages/server/src/api/rpc/openapi.ts b/packages/server/src/api/rpc/openapi.ts
index 6bd6e2c5c..35ff95649 100644
--- a/packages/server/src/api/rpc/openapi.ts
+++ b/packages/server/src/api/rpc/openapi.ts
@@ -9,6 +9,7 @@ import {
DEFAULT_SPEC_VERSION,
getIncludedModels,
getMetaDescription,
+ isModelIncluded,
isOperationIncluded,
isProcedureIncluded,
mayDenyAccess,
@@ -485,6 +486,10 @@ export class RPCApiSpecGenerator {
if (this.isBuiltinType(returnType)) {
base = this.builtinTypeToJsonSchema(returnType as BuiltinType);
+ } else if (this.schema.models?.[returnType] && !isModelIncluded(returnType, this.queryOptions)) {
+ // Return type is a model that's sliced away — its entity schema isn't emitted,
+ // so reference it with a generic schema instead of a dangling `$ref`.
+ base = {};
} else if (
this.schema.enums?.[returnType] ||
this.schema.models?.[returnType] ||
@@ -685,6 +690,10 @@ export class RPCApiSpecGenerator {
if (fieldDef.omit) continue;
if (fieldDef.relation) {
+ // Skip relations pointing to a model that's sliced away — otherwise we'd emit
+ // a dangling `$ref` to a schema that's not in the spec.
+ if (!isModelIncluded(fieldDef.type, this.queryOptions)) continue;
+
// Relation fields appear only with `include` — mark as optional.
// To-one optional relations are nullable (the ORM returns null when not found).
const refSchema: ReferenceObject = { $ref: `#/components/schemas/${fieldDef.type}` };
diff --git a/packages/server/test/openapi/rpc-openapi.test.ts b/packages/server/test/openapi/rpc-openapi.test.ts
index 64d4b1ca4..6e25cb270 100644
--- a/packages/server/test/openapi/rpc-openapi.test.ts
+++ b/packages/server/test/openapi/rpc-openapi.test.ts
@@ -596,6 +596,26 @@ describe('RPC OpenAPI spec generation - queryOptions slicing', () => {
expect(spec.components?.schemas?.['User']).toBeDefined();
});
+ it('drops relation fields pointing to excluded models from entity schemas', async () => {
+ const client = await createTestClient(schema);
+ const handler = new RPCApiHandler({
+ schema: client.$schema,
+ queryOptions: { slicing: { excludedModels: ['Post'] as any } },
+ });
+ // `generateSpec` also validates the document, so a dangling `$ref` to the
+ // excluded `Post` schema would fail here.
+ const spec = await generateSpec(handler);
+
+ // referencing models keep their other fields but lose relations to the excluded model
+ const userProps = (spec.components?.schemas?.['User'] as any)?.properties;
+ expect(userProps?.['email']).toBeDefined();
+ expect(userProps?.['posts']).toBeUndefined();
+
+ const commentProps = (spec.components?.schemas?.['Comment'] as any)?.properties;
+ expect(commentProps?.['content']).toBeDefined();
+ expect(commentProps?.['post']).toBeUndefined();
+ });
+
it('includedModels removes excluded model entity schemas from components', async () => {
const client = await createTestClient(schema);
const handler = new RPCApiHandler({
@@ -858,6 +878,30 @@ mutation procedure softDelete(id: Int?): User
expect(schemaKeys.some((k) => k.startsWith('createUser'))).toBe(true);
});
+ it('procedure returning an excluded model does not emit a dangling ref', async () => {
+ const client = await createTestClient(procSchema);
+ const handler = new RPCApiHandler({
+ schema: client.$schema,
+ queryOptions: { slicing: { excludedModels: ['User'] as any } },
+ });
+ // `getUser`/`createUser`/`optionalSearch` all return `User`, which is excluded.
+ // `generateSpec` validates, so a dangling `$ref` to the absent `User` schema would fail.
+ const spec = await generateSpec(handler);
+
+ expect(spec.components?.schemas?.['User']).toBeUndefined();
+
+ // the procedures themselves are still exposed, but their result shape is generic
+ const dataSchema = (spec.paths?.['/$procs/getUser']?.get as any)?.responses?.['200']?.content?.[
+ 'application/json'
+ ]?.schema?.properties?.data;
+ expect(dataSchema).toEqual({});
+
+ const listDataSchema = (spec.paths?.['/$procs/optionalSearch']?.get as any)?.responses?.['200']?.content?.[
+ 'application/json'
+ ]?.schema?.properties?.data;
+ expect(listDataSchema).toEqual({ type: 'array', items: {} });
+ });
+
it('slicing includedProcedures removes non-listed procedure args from components schemas', async () => {
const client = await createTestClient(procSchema);
const handler = new RPCApiHandler({
diff --git a/packages/testtools/package.json b/packages/testtools/package.json
index 5e9cb76e7..d445bba40 100644
--- a/packages/testtools/package.json
+++ b/packages/testtools/package.json
@@ -2,7 +2,7 @@
"name": "@zenstackhq/testtools",
"displayName": "ZenStack Test Tools",
"description": "ZenStack Test Tools",
- "version": "3.7.2",
+ "version": "3.8.0",
"type": "module",
"author": {
"name": "ZenStack Team",
diff --git a/packages/testtools/src/client.ts b/packages/testtools/src/client.ts
index c9d0ca8b3..6b1bc107c 100644
--- a/packages/testtools/src/client.ts
+++ b/packages/testtools/src/client.ts
@@ -72,6 +72,13 @@ type ExtraTestClientOptions = {
*/
extraZModelFiles?: Record;
+ /**
+ * Extra plugin `plugin.zmodel` files (resolved absolute paths) to merge into the schema
+ * when loading. Use this to make a plugin's custom attributes available without testtools
+ * having to depend on the plugin.
+ */
+ extraPluginModelFiles?: string[];
+
/**
* Extra TypeScript source files to create and compile.
*/
@@ -143,6 +150,7 @@ export async function createTestClient(
options?.extraSourceFiles,
undefined,
options?.extraZModelFiles,
+ options?.extraPluginModelFiles,
);
workDir = generated.workDir;
model = generated.model;
@@ -226,7 +234,10 @@ export async function createTestClient(
'a schema file must be provided when using prisma db push',
);
if (!model) {
- const r = await loadDocumentWithPlugins(path.join(workDir, 'schema.zmodel'));
+ const r = await loadDocumentWithPlugins(
+ path.join(workDir, 'schema.zmodel'),
+ options?.extraPluginModelFiles,
+ );
if (!r.success) {
throw new Error(r.errors.join('\n'));
}
diff --git a/packages/testtools/src/schema.ts b/packages/testtools/src/schema.ts
index ffd016b11..98c836435 100644
--- a/packages/testtools/src/schema.ts
+++ b/packages/testtools/src/schema.ts
@@ -62,6 +62,7 @@ export async function generateTsSchema(
extraSourceFiles?: Record,
withLiteSchema?: boolean,
extraZModelFiles?: Record,
+ extraPluginModelFiles?: string[],
) {
const workDir = createTestProject();
@@ -85,7 +86,7 @@ export async function generateTsSchema(
}
}
- const result = await loadDocumentWithPlugins(zmodelPath);
+ const result = await loadDocumentWithPlugins(zmodelPath, extraPluginModelFiles);
if (!result.success) {
throw new Error(`Failed to load schema from ${zmodelPath}: ${result.errors}`);
}
diff --git a/packages/testtools/src/utils.ts b/packages/testtools/src/utils.ts
index 1f8119fe3..52ec98c40 100644
--- a/packages/testtools/src/utils.ts
+++ b/packages/testtools/src/utils.ts
@@ -1,6 +1,6 @@
import { loadDocument } from '@zenstackhq/language';
-export function loadDocumentWithPlugins(filePath: string) {
- const pluginModelFiles = [require.resolve('@zenstackhq/plugin-policy/plugin.zmodel')];
+export function loadDocumentWithPlugins(filePath: string, extraPluginModelFiles: string[] = []) {
+ const pluginModelFiles = [require.resolve('@zenstackhq/plugin-policy/plugin.zmodel'), ...extraPluginModelFiles];
return loadDocument(filePath, pluginModelFiles);
}
diff --git a/packages/zod/package.json b/packages/zod/package.json
index 4161686f8..417ab942f 100644
--- a/packages/zod/package.json
+++ b/packages/zod/package.json
@@ -2,7 +2,7 @@
"name": "@zenstackhq/zod",
"displayName": "ZenStack Zod Integration",
"description": "Automatically deriving Zod schemas from ZModel schemas",
- "version": "3.7.2",
+ "version": "3.8.0",
"type": "module",
"author": {
"name": "ZenStack Team",
diff --git a/packages/zod/src/utils.ts b/packages/zod/src/utils.ts
index f21d9196f..b048f6abf 100644
--- a/packages/zod/src/utils.ts
+++ b/packages/zod/src/utils.ts
@@ -12,6 +12,16 @@ import Decimal from 'decimal.js';
import { z } from 'zod';
import { SchemaFactoryError } from './error';
+// z.string()[mapped]
+const stringFuncZodMap = {
+ isEmail: 'email',
+ isUrl: 'url',
+ isPhone: 'e164',
+ isDate: 'date',
+ isTime: 'time',
+ isDateTime: 'datetime',
+} as const;
+
function getArgValue(expr: Expression | undefined): T | undefined {
if (!expr || !ExpressionUtils.isLiteral(expr)) {
return undefined;
@@ -75,6 +85,14 @@ export function addStringValidation(
case '@phone':
result = result.e164();
break;
+ case '@date':
+ result = result.date();
+ break;
+ case '@time': {
+ const precision = getArgValue(attr.args?.[0]?.value);
+ result = result.time({ precision });
+ break;
+ }
case '@datetime':
result = result.datetime();
break;
@@ -537,18 +555,19 @@ function evalCall(data: any, expr: CallExpression) {
case 'isEmail':
case 'isUrl':
case 'isPhone':
+ case 'isDate':
+ case 'isTime':
case 'isDateTime': {
if (fieldArg === undefined || fieldArg === null || fieldArg === ABSENT) {
return false;
}
invariant(typeof fieldArg === 'string', `"${f}" first argument must be a string`);
- const fn = f === 'isEmail'
- ? ('email' as const)
- : f === 'isUrl'
- ? ('url' as const)
- : f === 'isPhone'
- ? ('e164' as const)
- : ('datetime' as const);
+ if (f === 'isTime') {
+ const precision = getArgValue(expr.args?.[1]);
+ invariant((precision === null || precision == undefined) || typeof precision === 'number', `"isTime" optional second argument must be a number`);
+ return z.iso.time({ precision }).safeParse(fieldArg).success;
+ }
+ const fn = stringFuncZodMap[f];
return z.string()[fn]().safeParse(fieldArg).success;
}
// list functions
diff --git a/packages/zod/test/factory.test.ts b/packages/zod/test/factory.test.ts
index 8e81b69ea..a0bc7592c 100644
--- a/packages/zod/test/factory.test.ts
+++ b/packages/zod/test/factory.test.ts
@@ -21,6 +21,8 @@ const validUser = {
balance: 10.0,
active: true,
birthdate: null,
+ localTime: null,
+ createdAt: null,
avatar: null,
metadata: null,
status: 'ACTIVE',
@@ -50,6 +52,8 @@ describe('SchemaFactory - makeModelSchema', () => {
expectTypeOf().toEqualTypeOf();
// optional string field (nullable + optional)
expectTypeOf().toEqualTypeOf();
+ expectTypeOf().toEqualTypeOf();
+ expectTypeOf().toEqualTypeOf();
// number fields (Int and Float both map to ZodNumber)
expectTypeOf().toEqualTypeOf();
@@ -65,7 +69,7 @@ describe('SchemaFactory - makeModelSchema', () => {
expectTypeOf().toEqualTypeOf();
// DateTime
- expectTypeOf().toEqualTypeOf();
+ expectTypeOf().toEqualTypeOf();
// optional Bytes
expectTypeOf().toEqualTypeOf();
@@ -144,7 +148,7 @@ describe('SchemaFactory - makeModelSchema', () => {
it('accepts DateTime as a Date object', () => {
const userSchema = factory.makeModelSchema('User');
- const result = userSchema.safeParse({ ...validUser, birthdate: new Date() });
+ const result = userSchema.safeParse({ ...validUser, createdAt: new Date() });
expect(result.success).toBe(true);
});
@@ -152,7 +156,7 @@ describe('SchemaFactory - makeModelSchema', () => {
const userSchema = factory.makeModelSchema('User');
const result = userSchema.safeParse({
...validUser,
- birthdate: '2024-01-15T10:30:00.000Z',
+ createdAt: '2024-01-15T10:30:00.000Z',
});
expect(result.success).toBe(true);
});
@@ -214,7 +218,7 @@ describe('SchemaFactory - makeModelSchema', () => {
it('infers correct input types for fields', () => {
const _userSchema = factory.makeModelSchema('User');
type UserInput = z.input;
- expectTypeOf().toEqualTypeOf();
+ expectTypeOf().toEqualTypeOf();
expectTypeOf().toEqualTypeOf();
expectTypeOf().toEqualTypeOf();
});
@@ -281,6 +285,42 @@ describe('SchemaFactory - makeModelSchema', () => {
expect(result.success).toBe(true);
});
+ it('rejects invalid date for @date field', () => {
+ const userSchema = factory.makeModelSchema('User');
+ const result = userSchema.safeParse({ ...validUser, birthdate: 'not-a-date' });
+ expect(result.success).toBe(false);
+ });
+
+ it('accepts valid date for @date field', () => {
+ const userSchema = factory.makeModelSchema('User');
+ const result = userSchema.safeParse({ ...validUser, birthdate: '2000-01-01' });
+ expect(result.success).toBe(true);
+ });
+
+ it('accepts null for optional @date field', () => {
+ const userSchema = factory.makeModelSchema('User');
+ const result = userSchema.safeParse({ ...validUser, birthdate: null });
+ expect(result.success).toBe(true);
+ });
+
+ it('rejects invalid time for @time field', () => {
+ const userSchema = factory.makeModelSchema('User');
+ const result = userSchema.safeParse({ ...validUser, localTime: 'not-a-time' });
+ expect(result.success).toBe(false);
+ });
+
+ it('accepts valid time for @time field', () => {
+ const userSchema = factory.makeModelSchema('User');
+ const result = userSchema.safeParse({ ...validUser, localTime: '03:15:00' });
+ expect(result.success).toBe(true);
+ });
+
+ it('accepts null for optional @time field', () => {
+ const userSchema = factory.makeModelSchema('User');
+ const result = userSchema.safeParse({ ...validUser, localTime: null });
+ expect(result.success).toBe(true);
+ });
+
it('rejects code that does not start with "USR" for @startsWith', () => {
const userSchema = factory.makeModelSchema('User');
const result = userSchema.safeParse({ ...validUser, code: 'ABC001' });
@@ -608,6 +648,8 @@ describe('SchemaFactory - makeTypeSchema', () => {
balance: 1,
active: true,
birthdate: null,
+ localTime: null,
+ createdAt: null,
avatar: null,
metadata: null,
status: 'ACTIVE',
@@ -1378,6 +1420,8 @@ describe('SchemaFactory - makeModelSchema with options', () => {
expectTypeOf().toEqualTypeOf();
// already-optional nullable field
expectTypeOf().toEqualTypeOf();
+ expectTypeOf().toEqualTypeOf();
+ expectTypeOf().toEqualTypeOf();
});
it('infers omitted field absent even with optionality all', () => {
diff --git a/packages/zod/test/schema/schema.ts b/packages/zod/test/schema/schema.ts
index 3b8dd6eb2..fa7bc045c 100644
--- a/packages/zod/test/schema/schema.ts
+++ b/packages/zod/test/schema/schema.ts
@@ -73,6 +73,18 @@ export class SchemaType implements SchemaDef {
},
birthdate: {
name: "birthdate",
+ type: "String",
+ optional: true,
+ attributes: [{ name: "@date" }] as readonly AttributeApplication[]
+ },
+ localTime: {
+ name: "localTime",
+ type: "String",
+ optional: true,
+ attributes: [{ name: "@time" }] as readonly AttributeApplication[]
+ },
+ createdAt: {
+ name: "createdAt",
type: "DateTime",
optional: true
},
diff --git a/packages/zod/test/schema/schema.zmodel b/packages/zod/test/schema/schema.zmodel
index 0fc3aec88..e7deb27aa 100644
--- a/packages/zod/test/schema/schema.zmodel
+++ b/packages/zod/test/schema/schema.zmodel
@@ -32,7 +32,9 @@ model User {
bigNum BigInt @gte(0)
balance Decimal @gt(0)
active Boolean
- birthdate DateTime?
+ birthdate String? @date
+ localTime String? @time
+ createdAt DateTime?
avatar Bytes?
metadata Json?
status Status
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 6f22e8e26..dd9b6bbc3 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -46,11 +46,11 @@ catalogs:
specifier: ~0.29.0
version: 0.29.0
langium:
- specifier: 3.5.0
- version: 3.5.0
+ specifier: 4.2.4
+ version: 4.2.4
langium-cli:
- specifier: 3.5.0
- version: 3.5.0
+ specifier: 4.2.1
+ version: 4.2.1
mysql2:
specifier: ^3.16.1
version: 3.16.1
@@ -84,6 +84,9 @@ catalogs:
ts-pattern:
specifier: ^5.7.1
version: 5.7.1
+ tsx:
+ specifier: ^4.22.0
+ version: 4.22.4
typescript:
specifier: ^6.0.3
version: 6.0.3
@@ -99,8 +102,7 @@ catalogs:
overrides:
cookie@<0.7.0: '>=0.7.0'
- lodash-es@>=4.0.0 <=4.17.22: '>=4.17.23'
- lodash@>=4.0.0 <=4.17.22: '>=4.17.23'
+ lodash@>=4.0.0 <=4.17.23: '>=4.18.0'
'@better-auth/core': 1.4.19
importers:
@@ -115,7 +117,7 @@ importers:
version: 20.19.24
'@vitest/coverage-v8':
specifier: ^4.0.16
- version: 4.0.16(vitest@4.0.14(@edge-runtime/vm@5.0.0)(@types/node@20.19.24)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0))
+ version: 4.0.16(vitest@4.0.14(@edge-runtime/vm@5.0.0)(@types/node@20.19.24)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.0))
eslint:
specifier: ~9.29.0
version: 9.29.0(jiti@2.6.1)
@@ -135,8 +137,8 @@ importers:
specifier: ^0.21.8
version: 0.21.8(typescript@6.0.3)(vue-tsc@3.2.5(typescript@6.0.3))
tsx:
- specifier: ^4.20.3
- version: 4.20.3
+ specifier: 'catalog:'
+ version: 4.22.4
turbo:
specifier: ^2.5.4
version: 2.5.4
@@ -148,7 +150,7 @@ importers:
version: 8.34.1(eslint@9.29.0(jiti@2.6.1))(typescript@6.0.3)
vitest:
specifier: ^4.0.14
- version: 4.0.14(@edge-runtime/vm@5.0.0)(@types/node@20.19.24)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0)
+ version: 4.0.14(@edge-runtime/vm@5.0.0)(@types/node@20.19.24)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.0)
yaml:
specifier: ^2.8.0
version: 2.8.0
@@ -170,10 +172,10 @@ importers:
devDependencies:
'@better-auth/cli':
specifier: 1.4.19
- version: 1.4.19(@better-fetch/fetch@1.1.21)(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)))(@types/better-sqlite3@7.6.13)(@types/sql.js@1.4.9)(better-call@1.1.8(zod@4.3.6))(bun-types@1.3.3)(jose@6.1.2)(kysely@0.29.0)(magicast@0.5.1)(mysql2@3.16.1)(nanostores@1.0.1)(next@16.1.6(@babel/core@7.29.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sql.js@1.13.0)(svelte@5.53.5)(vitest@4.0.14(@edge-runtime/vm@5.0.0)(@types/node@25.5.2)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))
+ version: 1.4.19(@better-fetch/fetch@1.1.21)(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))(@types/better-sqlite3@7.6.13)(@types/sql.js@1.4.9)(better-call@1.1.8(zod@4.3.6))(bun-types@1.3.3)(jose@6.2.3)(kysely@0.29.0)(magicast@0.5.1)(mysql2@3.16.1)(nanostores@1.3.0)(next@16.1.6(@babel/core@7.29.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sql.js@1.13.0)(svelte@5.53.5)(vitest@4.0.14(@edge-runtime/vm@5.0.0)(@types/node@25.5.2)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))
'@better-auth/core':
specifier: 1.4.19
- version: 1.4.19(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.2)(kysely@0.29.0)(nanostores@1.0.1)
+ version: 1.4.19(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0)
'@types/tmp':
specifier: 'catalog:'
version: 0.2.6
@@ -194,7 +196,7 @@ importers:
version: link:../../config/vitest-config
better-auth:
specifier: 1.4.19
- version: 1.4.19(1495ef1d827113360533150571904e77)
+ version: 1.4.19(aa46c218c2111ba42e6bbb995c1cdf9e)
kysely:
specifier: 'catalog:'
version: 0.29.0
@@ -213,6 +215,9 @@ importers:
'@zenstackhq/orm':
specifier: workspace:*
version: link:../orm
+ '@zenstackhq/plugin-policy':
+ specifier: workspace:*
+ version: link:../plugins/policy
'@zenstackhq/schema':
specifier: workspace:*
version: link:../schema
@@ -251,7 +256,7 @@ importers:
version: 2.6.1
langium:
specifier: 'catalog:'
- version: 3.5.0
+ version: 4.2.4
mixpanel:
specifier: ^0.18.1
version: 0.18.1
@@ -532,7 +537,7 @@ importers:
version: link:../../language
langium:
specifier: 'catalog:'
- version: 3.5.0
+ version: 4.2.4
mixpanel:
specifier: ^0.18.0
version: 0.18.1
@@ -575,7 +580,7 @@ importers:
version: link:../common-helpers
langium:
specifier: 'catalog:'
- version: 3.5.0
+ version: 4.2.4
pluralize:
specifier: ^8.0.0
version: 8.0.0
@@ -586,6 +591,9 @@ importers:
specifier: ^9.0.1
version: 9.0.1
devDependencies:
+ '@types/node':
+ specifier: 'catalog:'
+ version: 20.19.24
'@types/pluralize':
specifier: ^0.0.33
version: 0.0.33
@@ -609,7 +617,7 @@ importers:
version: 11.1.0
langium-cli:
specifier: 'catalog:'
- version: 3.5.0
+ version: 4.2.1
tmp:
specifier: 'catalog:'
version: 0.2.5
@@ -699,8 +707,8 @@ importers:
specifier: workspace:*
version: link:../config/vitest-config
tsx:
- specifier: ^4.19.2
- version: 4.20.3
+ specifier: 'catalog:'
+ version: 4.22.4
zod:
specifier: ^4.1.0
version: 4.1.12
@@ -739,6 +747,46 @@ importers:
specifier: workspace:*
version: link:../../config/vitest-config
+ packages/plugins/soft-delete:
+ dependencies:
+ '@zenstackhq/common-helpers':
+ specifier: workspace:*
+ version: link:../../common-helpers
+ '@zenstackhq/orm':
+ specifier: workspace:*
+ version: link:../../orm
+ kysely:
+ specifier: 'catalog:'
+ version: 0.29.0
+ ts-pattern:
+ specifier: 'catalog:'
+ version: 5.7.1
+ devDependencies:
+ '@types/better-sqlite3':
+ specifier: 'catalog:'
+ version: 7.6.13
+ '@types/node':
+ specifier: 'catalog:'
+ version: 20.19.24
+ '@zenstackhq/eslint-config':
+ specifier: workspace:*
+ version: link:../../config/eslint-config
+ '@zenstackhq/testtools':
+ specifier: workspace:*
+ version: link:../../testtools
+ '@zenstackhq/tsdown-config':
+ specifier: workspace:*
+ version: link:../../config/tsdown-config
+ '@zenstackhq/typescript-config':
+ specifier: workspace:*
+ version: link:../../config/typescript-config
+ '@zenstackhq/vitest-config':
+ specifier: workspace:*
+ version: link:../../config/vitest-config
+ better-sqlite3:
+ specifier: 'catalog:'
+ version: 12.5.0
+
packages/schema:
dependencies:
decimal.js:
@@ -768,7 +816,7 @@ importers:
version: link:../language
langium:
specifier: 'catalog:'
- version: 3.5.0
+ version: 4.2.4
ts-pattern:
specifier: 'catalog:'
version: 5.7.1
@@ -830,7 +878,7 @@ importers:
version: 6.0.0(openapi-types@12.1.3)
'@sveltejs/kit':
specifier: 'catalog:'
- version: 2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))
+ version: 2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
'@types/body-parser':
specifier: ^1.19.6
version: 1.19.6
@@ -881,7 +929,7 @@ importers:
version: 16.1.6(@babel/core@7.29.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
nuxt:
specifier: 'catalog:'
- version: 4.3.1(20bb9c9cac3d4d3ad27d57e07c1eb4f2)
+ version: 4.3.1(526b065509e6a4d54781a1030a9e863f)
supertest:
specifier: ^7.1.4
version: 7.1.4
@@ -1055,7 +1103,7 @@ importers:
dependencies:
'@tailwindcss/vite':
specifier: ^4.1.18
- version: 4.1.18(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))
+ version: 4.1.18(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
'@tanstack/vue-query':
specifier: 'catalog:'
version: 5.90.2(vue@3.5.22(typescript@6.0.3))
@@ -1079,7 +1127,7 @@ importers:
version: 2.0.8
nuxt:
specifier: 'catalog:'
- version: 4.3.1(f6c7dcf4eb9de64f6cb5e0db74766190)
+ version: 4.3.1(95266d6f061a460ce208abe1df07947b)
tailwindcss:
specifier: ^4.1.18
version: 4.1.18
@@ -1163,16 +1211,16 @@ importers:
devDependencies:
'@sveltejs/adapter-auto':
specifier: ^7.0.0
- version: 7.0.0(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)))
+ version: 7.0.0(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))
'@sveltejs/kit':
specifier: 'catalog:'
- version: 2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))
+ version: 2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
'@sveltejs/vite-plugin-svelte':
specifier: ^6.2.1
- version: 6.2.1(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))
+ version: 6.2.1(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
'@tailwindcss/vite':
specifier: ^4.1.17
- version: 4.1.18(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))
+ version: 4.1.18(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
'@types/better-sqlite3':
specifier: 'catalog:'
version: 7.6.13
@@ -1195,14 +1243,48 @@ importers:
specifier: ^4.1.17
version: 4.1.18
tsx:
- specifier: ^4.19.2
- version: 4.20.3
+ specifier: 'catalog:'
+ version: 4.22.4
typescript:
specifier: ^5.9.3
version: 5.9.3
vite:
specifier: ^7.2.6
- version: 7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
+ version: 7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
+
+ samples/taskforge:
+ dependencies:
+ '@zenstackhq/better-auth':
+ specifier: workspace:*
+ version: link:../../packages/auth-adapters/better-auth
+ '@zenstackhq/orm':
+ specifier: workspace:*
+ version: link:../../packages/orm
+ '@zenstackhq/schema':
+ specifier: workspace:*
+ version: link:../../packages/schema
+ better-auth:
+ specifier: ^1.4.21
+ version: 1.6.15(261c4d1149703dc38709f1a99ea83b5c)
+ better-sqlite3:
+ specifier: 'catalog:'
+ version: 12.5.0
+ commander:
+ specifier: ^14.0.2
+ version: 14.0.3
+ devDependencies:
+ '@better-auth/cli':
+ specifier: ^1.4.21
+ version: 1.4.21(@better-fetch/fetch@1.1.21)(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))(@types/better-sqlite3@7.6.13)(@types/sql.js@1.4.9)(better-call@1.1.8(zod@4.3.6))(bun-types@1.3.3)(jose@6.2.3)(kysely@0.29.0)(magicast@0.5.1)(mysql2@3.16.1)(nanostores@1.3.0)(next@16.1.6(@babel/core@7.29.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sql.js@1.13.0)(svelte@5.53.5)(vitest@4.0.14(@edge-runtime/vm@5.0.0)(@types/node@20.19.24)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))
+ '@types/better-sqlite3':
+ specifier: 'catalog:'
+ version: 7.6.13
+ '@types/node':
+ specifier: 'catalog:'
+ version: 20.19.24
+ '@zenstackhq/cli':
+ specifier: workspace:*
+ version: link:../../packages/cli
tests/e2e:
dependencies:
@@ -1675,6 +1757,10 @@ packages:
resolution: {integrity: sha512-kH1e+F8sPwcfEuhyNzFt3rdLo5SBTfw7a9m/hyMv1E7tk/yfsqOZRL0I5GR+Fkm0FJ7SoVA4LJREFV3S0Px8iA==}
hasBin: true
+ '@better-auth/cli@1.4.21':
+ resolution: {integrity: sha512-bKEa8BupnZxNjLk9ZDntvgQGm5jogeE2wHdMbYifhet3GTyxgDi6pXoOK8+aqHYQGg1C3OALi9hVVWnrv7JJWQ==}
+ hasBin: true
+
'@better-auth/core@1.4.19':
resolution: {integrity: sha512-uADLHG1jc5BnEJi7f6ijUN5DmPPRSj++7m/G19z3UqA3MVCo4Y4t1MMa4IIxLCqGDFv22drdfxescgW+HnIowA==}
peerDependencies:
@@ -1685,14 +1771,78 @@ packages:
kysely: ^0.28.5
nanostores: ^1.0.1
+ '@better-auth/drizzle-adapter@1.6.15':
+ resolution: {integrity: sha512-+ho2RozN6cZmCN+6XkZd/ec5iolVlefgInQ7znJ18qRPbgllHxdyu9tGrgKZyEsXSCyqAa6wi5Yb4hd3WZmTNQ==}
+ peerDependencies:
+ '@better-auth/core': 1.4.19
+ '@better-auth/utils': 0.4.1
+ drizzle-orm: ^0.45.2
+ peerDependenciesMeta:
+ drizzle-orm:
+ optional: true
+
+ '@better-auth/kysely-adapter@1.6.15':
+ resolution: {integrity: sha512-E29Sugm+DWRK4oQNBPrjPA4kBYiKy2bBtX1arIlkuyAB9A1BEb4Xn+8t7wlNIF5eFcxpkFZ3F80ceSpWDSYU0Q==}
+ peerDependencies:
+ '@better-auth/core': 1.4.19
+ '@better-auth/utils': 0.4.1
+ kysely: ^0.28.17 || ^0.29.0
+ peerDependenciesMeta:
+ kysely:
+ optional: true
+
+ '@better-auth/memory-adapter@1.6.15':
+ resolution: {integrity: sha512-BRE5Ft0Tn5thOPjCmyXHge7kOI/paLybaKDU+Hzg24DZMU6JvWooYWzvf52r1viDbxq5tz0G97iyaH4bouDyug==}
+ peerDependencies:
+ '@better-auth/core': 1.4.19
+ '@better-auth/utils': 0.4.1
+
+ '@better-auth/mongo-adapter@1.6.15':
+ resolution: {integrity: sha512-r0X9AtFhwDeOU1KMP9kZ5NeV0O3TSFzn8+uidaH+aicy2e1dNUsd9nPYrozEloSxdA2ZOnv5gD4jzH7HPeKkUQ==}
+ peerDependencies:
+ '@better-auth/core': 1.4.19
+ '@better-auth/utils': 0.4.1
+ mongodb: ^6.0.0 || ^7.0.0
+ peerDependenciesMeta:
+ mongodb:
+ optional: true
+
+ '@better-auth/prisma-adapter@1.6.15':
+ resolution: {integrity: sha512-pUOlIUnpMu2l8C2ytgu46+OoOr3LZ+aLpJMFRGIPdnWl1BF2co2YaoZPT3+ZBu1Lzm0FrBN1ZRCAzZbkFoeIAQ==}
+ peerDependencies:
+ '@better-auth/core': 1.4.19
+ '@better-auth/utils': 0.4.1
+ '@prisma/client': ^5.0.0 || ^6.0.0 || ^7.0.0
+ prisma: ^5.0.0 || ^6.0.0 || ^7.0.0
+ peerDependenciesMeta:
+ '@prisma/client':
+ optional: true
+ prisma:
+ optional: true
+
'@better-auth/telemetry@1.4.19':
resolution: {integrity: sha512-ApGNS7olCTtDpKF8Ow3Z+jvFAirOj7c4RyFUpu8axklh3mH57ndpfUAUjhgA8UVoaaH/mnm/Tl884BlqiewLyw==}
peerDependencies:
'@better-auth/core': 1.4.19
+ '@better-auth/telemetry@1.4.21':
+ resolution: {integrity: sha512-LX+FGMZnhR2KQZ0idHH1+UwlXvkOl6P8w3Gne4TtjvUCt3QjG9FKIuP9JD3MAmEEkwGt0SoAPHPJEGTjUl3ydg==}
+ peerDependencies:
+ '@better-auth/core': 1.4.19
+
+ '@better-auth/telemetry@1.6.15':
+ resolution: {integrity: sha512-eoFlUPVrVXLML9saHD11OSKKSRCAYETgRgBW4vQF3Y6pCgmThKD9oehYk3kkb/FsRgfqmsocmvAFqsiyjPIygg==}
+ peerDependencies:
+ '@better-auth/core': 1.4.19
+ '@better-auth/utils': 0.4.1
+ '@better-fetch/fetch': 1.1.21
+
'@better-auth/utils@0.3.0':
resolution: {integrity: sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw==}
+ '@better-auth/utils@0.4.1':
+ resolution: {integrity: sha512-SZBPRPF3z0nBvE5ygOkxae35wnnXPRShmqFo78S+qslLeFoPu/pMgnXAuNKFMMybac3tiLaVg1e3MQW5MC+1iA==}
+
'@better-fetch/fetch@1.1.21':
resolution: {integrity: sha512-/ImESw0sskqlVR94jB+5+Pxjf+xBwDZF/N5+y2/q4EqD7IARUTSpPfIo8uf39SYpCxyOCtbyYpUrZ3F/k0zT4A==}
@@ -1717,29 +1867,29 @@ packages:
'@chevrotain/cst-dts-gen@10.5.0':
resolution: {integrity: sha512-lhmC/FyqQ2o7pGK4Om+hzuDrm9rhFYIJ/AXoQBeongmn870Xeb0L6oGEiuR8nohFNL5sMaQEJWCxr1oIVIVXrw==}
- '@chevrotain/cst-dts-gen@11.0.3':
- resolution: {integrity: sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==}
+ '@chevrotain/cst-dts-gen@12.0.0':
+ resolution: {integrity: sha512-fSL4KXjTl7cDgf0B5Rip9Q05BOrYvkJV/RrBTE/bKDN096E4hN/ySpcBK5B24T76dlQ2i32Zc3PAE27jFnFrKg==}
'@chevrotain/gast@10.5.0':
resolution: {integrity: sha512-pXdMJ9XeDAbgOWKuD1Fldz4ieCs6+nLNmyVhe2gZVqoO7v8HXuHYs5OV2EzUtbuai37TlOAQHrTDvxMnvMJz3A==}
- '@chevrotain/gast@11.0.3':
- resolution: {integrity: sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==}
+ '@chevrotain/gast@12.0.0':
+ resolution: {integrity: sha512-1ne/m3XsIT8aEdrvT33so0GUC+wkctpUPK6zU9IlOyJLUbR0rg4G7ZiApiJbggpgPir9ERy3FRjT6T7lpgetnQ==}
- '@chevrotain/regexp-to-ast@11.0.3':
- resolution: {integrity: sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==}
+ '@chevrotain/regexp-to-ast@12.0.0':
+ resolution: {integrity: sha512-p+EW9MaJwgaHguhoqwOtx/FwuGr+DnNn857sXWOi/mClXIkPGl3rn7hGNWvo31HA3vyeQxjqe+H36yZJwYU8cA==}
'@chevrotain/types@10.5.0':
resolution: {integrity: sha512-f1MAia0x/pAVPWH/T73BJVyO2XU5tI4/iE7cnxb7tqdNTNhQI3Uq3XkqcoteTmD4t1aM0LbHCJOhgIDn07kl2A==}
- '@chevrotain/types@11.0.3':
- resolution: {integrity: sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==}
+ '@chevrotain/types@12.0.0':
+ resolution: {integrity: sha512-S+04vjFQKeuYw0/eW3U52LkAHQsB1ASxsPGsLPUyQgrZ2iNNibQrsidruDzjEX2JYfespXMG0eZmXlhA6z7nWA==}
'@chevrotain/utils@10.5.0':
resolution: {integrity: sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==}
- '@chevrotain/utils@11.0.3':
- resolution: {integrity: sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==}
+ '@chevrotain/utils@12.0.0':
+ resolution: {integrity: sha512-lB59uJoaGIfOOL9knQqQRfhl9g7x8/wqFkp13zTdkRu1huG9kg6IJs1O8hqj9rs6h7orGxHJUKb+mX3rPbWGhA==}
'@clack/core@0.5.0':
resolution: {integrity: sha512-p3y0FIOwaYRUPRcMO7+dlmLh8PSRcrjuTndsiA0WAFbWES0mLZlrjVoBRZ9DzkPFJZG6KGkJmoEAY0ZcVWTkow==}
@@ -1828,12 +1978,6 @@ packages:
'@emnapi/wasi-threads@1.2.1':
resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==}
- '@esbuild/aix-ppc64@0.25.5':
- resolution: {integrity: sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==}
- engines: {node: '>=18'}
- cpu: [ppc64]
- os: [aix]
-
'@esbuild/aix-ppc64@0.27.2':
resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==}
engines: {node: '>=18'}
@@ -1846,11 +1990,11 @@ packages:
cpu: [ppc64]
os: [aix]
- '@esbuild/android-arm64@0.25.5':
- resolution: {integrity: sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==}
+ '@esbuild/aix-ppc64@0.28.0':
+ resolution: {integrity: sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==}
engines: {node: '>=18'}
- cpu: [arm64]
- os: [android]
+ cpu: [ppc64]
+ os: [aix]
'@esbuild/android-arm64@0.27.2':
resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==}
@@ -1864,10 +2008,10 @@ packages:
cpu: [arm64]
os: [android]
- '@esbuild/android-arm@0.25.5':
- resolution: {integrity: sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==}
+ '@esbuild/android-arm64@0.28.0':
+ resolution: {integrity: sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==}
engines: {node: '>=18'}
- cpu: [arm]
+ cpu: [arm64]
os: [android]
'@esbuild/android-arm@0.27.2':
@@ -1882,10 +2026,10 @@ packages:
cpu: [arm]
os: [android]
- '@esbuild/android-x64@0.25.5':
- resolution: {integrity: sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==}
+ '@esbuild/android-arm@0.28.0':
+ resolution: {integrity: sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==}
engines: {node: '>=18'}
- cpu: [x64]
+ cpu: [arm]
os: [android]
'@esbuild/android-x64@0.27.2':
@@ -1900,11 +2044,11 @@ packages:
cpu: [x64]
os: [android]
- '@esbuild/darwin-arm64@0.25.5':
- resolution: {integrity: sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==}
+ '@esbuild/android-x64@0.28.0':
+ resolution: {integrity: sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==}
engines: {node: '>=18'}
- cpu: [arm64]
- os: [darwin]
+ cpu: [x64]
+ os: [android]
'@esbuild/darwin-arm64@0.27.2':
resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==}
@@ -1918,10 +2062,10 @@ packages:
cpu: [arm64]
os: [darwin]
- '@esbuild/darwin-x64@0.25.5':
- resolution: {integrity: sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==}
+ '@esbuild/darwin-arm64@0.28.0':
+ resolution: {integrity: sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==}
engines: {node: '>=18'}
- cpu: [x64]
+ cpu: [arm64]
os: [darwin]
'@esbuild/darwin-x64@0.27.2':
@@ -1936,11 +2080,11 @@ packages:
cpu: [x64]
os: [darwin]
- '@esbuild/freebsd-arm64@0.25.5':
- resolution: {integrity: sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==}
+ '@esbuild/darwin-x64@0.28.0':
+ resolution: {integrity: sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==}
engines: {node: '>=18'}
- cpu: [arm64]
- os: [freebsd]
+ cpu: [x64]
+ os: [darwin]
'@esbuild/freebsd-arm64@0.27.2':
resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==}
@@ -1954,10 +2098,10 @@ packages:
cpu: [arm64]
os: [freebsd]
- '@esbuild/freebsd-x64@0.25.5':
- resolution: {integrity: sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==}
+ '@esbuild/freebsd-arm64@0.28.0':
+ resolution: {integrity: sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==}
engines: {node: '>=18'}
- cpu: [x64]
+ cpu: [arm64]
os: [freebsd]
'@esbuild/freebsd-x64@0.27.2':
@@ -1972,11 +2116,11 @@ packages:
cpu: [x64]
os: [freebsd]
- '@esbuild/linux-arm64@0.25.5':
- resolution: {integrity: sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==}
+ '@esbuild/freebsd-x64@0.28.0':
+ resolution: {integrity: sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==}
engines: {node: '>=18'}
- cpu: [arm64]
- os: [linux]
+ cpu: [x64]
+ os: [freebsd]
'@esbuild/linux-arm64@0.27.2':
resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==}
@@ -1990,10 +2134,10 @@ packages:
cpu: [arm64]
os: [linux]
- '@esbuild/linux-arm@0.25.5':
- resolution: {integrity: sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==}
+ '@esbuild/linux-arm64@0.28.0':
+ resolution: {integrity: sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==}
engines: {node: '>=18'}
- cpu: [arm]
+ cpu: [arm64]
os: [linux]
'@esbuild/linux-arm@0.27.2':
@@ -2008,10 +2152,10 @@ packages:
cpu: [arm]
os: [linux]
- '@esbuild/linux-ia32@0.25.5':
- resolution: {integrity: sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==}
+ '@esbuild/linux-arm@0.28.0':
+ resolution: {integrity: sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==}
engines: {node: '>=18'}
- cpu: [ia32]
+ cpu: [arm]
os: [linux]
'@esbuild/linux-ia32@0.27.2':
@@ -2026,10 +2170,10 @@ packages:
cpu: [ia32]
os: [linux]
- '@esbuild/linux-loong64@0.25.5':
- resolution: {integrity: sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==}
+ '@esbuild/linux-ia32@0.28.0':
+ resolution: {integrity: sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==}
engines: {node: '>=18'}
- cpu: [loong64]
+ cpu: [ia32]
os: [linux]
'@esbuild/linux-loong64@0.27.2':
@@ -2044,10 +2188,10 @@ packages:
cpu: [loong64]
os: [linux]
- '@esbuild/linux-mips64el@0.25.5':
- resolution: {integrity: sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==}
+ '@esbuild/linux-loong64@0.28.0':
+ resolution: {integrity: sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==}
engines: {node: '>=18'}
- cpu: [mips64el]
+ cpu: [loong64]
os: [linux]
'@esbuild/linux-mips64el@0.27.2':
@@ -2062,10 +2206,10 @@ packages:
cpu: [mips64el]
os: [linux]
- '@esbuild/linux-ppc64@0.25.5':
- resolution: {integrity: sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==}
+ '@esbuild/linux-mips64el@0.28.0':
+ resolution: {integrity: sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==}
engines: {node: '>=18'}
- cpu: [ppc64]
+ cpu: [mips64el]
os: [linux]
'@esbuild/linux-ppc64@0.27.2':
@@ -2080,10 +2224,10 @@ packages:
cpu: [ppc64]
os: [linux]
- '@esbuild/linux-riscv64@0.25.5':
- resolution: {integrity: sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==}
+ '@esbuild/linux-ppc64@0.28.0':
+ resolution: {integrity: sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==}
engines: {node: '>=18'}
- cpu: [riscv64]
+ cpu: [ppc64]
os: [linux]
'@esbuild/linux-riscv64@0.27.2':
@@ -2098,10 +2242,10 @@ packages:
cpu: [riscv64]
os: [linux]
- '@esbuild/linux-s390x@0.25.5':
- resolution: {integrity: sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==}
+ '@esbuild/linux-riscv64@0.28.0':
+ resolution: {integrity: sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==}
engines: {node: '>=18'}
- cpu: [s390x]
+ cpu: [riscv64]
os: [linux]
'@esbuild/linux-s390x@0.27.2':
@@ -2116,10 +2260,10 @@ packages:
cpu: [s390x]
os: [linux]
- '@esbuild/linux-x64@0.25.5':
- resolution: {integrity: sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==}
+ '@esbuild/linux-s390x@0.28.0':
+ resolution: {integrity: sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==}
engines: {node: '>=18'}
- cpu: [x64]
+ cpu: [s390x]
os: [linux]
'@esbuild/linux-x64@0.27.2':
@@ -2134,11 +2278,11 @@ packages:
cpu: [x64]
os: [linux]
- '@esbuild/netbsd-arm64@0.25.5':
- resolution: {integrity: sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==}
+ '@esbuild/linux-x64@0.28.0':
+ resolution: {integrity: sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==}
engines: {node: '>=18'}
- cpu: [arm64]
- os: [netbsd]
+ cpu: [x64]
+ os: [linux]
'@esbuild/netbsd-arm64@0.27.2':
resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==}
@@ -2152,10 +2296,10 @@ packages:
cpu: [arm64]
os: [netbsd]
- '@esbuild/netbsd-x64@0.25.5':
- resolution: {integrity: sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==}
+ '@esbuild/netbsd-arm64@0.28.0':
+ resolution: {integrity: sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==}
engines: {node: '>=18'}
- cpu: [x64]
+ cpu: [arm64]
os: [netbsd]
'@esbuild/netbsd-x64@0.27.2':
@@ -2170,11 +2314,11 @@ packages:
cpu: [x64]
os: [netbsd]
- '@esbuild/openbsd-arm64@0.25.5':
- resolution: {integrity: sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==}
+ '@esbuild/netbsd-x64@0.28.0':
+ resolution: {integrity: sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==}
engines: {node: '>=18'}
- cpu: [arm64]
- os: [openbsd]
+ cpu: [x64]
+ os: [netbsd]
'@esbuild/openbsd-arm64@0.27.2':
resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==}
@@ -2188,10 +2332,10 @@ packages:
cpu: [arm64]
os: [openbsd]
- '@esbuild/openbsd-x64@0.25.5':
- resolution: {integrity: sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==}
+ '@esbuild/openbsd-arm64@0.28.0':
+ resolution: {integrity: sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==}
engines: {node: '>=18'}
- cpu: [x64]
+ cpu: [arm64]
os: [openbsd]
'@esbuild/openbsd-x64@0.27.2':
@@ -2206,6 +2350,12 @@ packages:
cpu: [x64]
os: [openbsd]
+ '@esbuild/openbsd-x64@0.28.0':
+ resolution: {integrity: sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [openbsd]
+
'@esbuild/openharmony-arm64@0.27.2':
resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==}
engines: {node: '>=18'}
@@ -2218,11 +2368,11 @@ packages:
cpu: [arm64]
os: [openharmony]
- '@esbuild/sunos-x64@0.25.5':
- resolution: {integrity: sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==}
+ '@esbuild/openharmony-arm64@0.28.0':
+ resolution: {integrity: sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==}
engines: {node: '>=18'}
- cpu: [x64]
- os: [sunos]
+ cpu: [arm64]
+ os: [openharmony]
'@esbuild/sunos-x64@0.27.2':
resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==}
@@ -2236,11 +2386,11 @@ packages:
cpu: [x64]
os: [sunos]
- '@esbuild/win32-arm64@0.25.5':
- resolution: {integrity: sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==}
+ '@esbuild/sunos-x64@0.28.0':
+ resolution: {integrity: sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==}
engines: {node: '>=18'}
- cpu: [arm64]
- os: [win32]
+ cpu: [x64]
+ os: [sunos]
'@esbuild/win32-arm64@0.27.2':
resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==}
@@ -2254,10 +2404,10 @@ packages:
cpu: [arm64]
os: [win32]
- '@esbuild/win32-ia32@0.25.5':
- resolution: {integrity: sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==}
+ '@esbuild/win32-arm64@0.28.0':
+ resolution: {integrity: sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==}
engines: {node: '>=18'}
- cpu: [ia32]
+ cpu: [arm64]
os: [win32]
'@esbuild/win32-ia32@0.27.2':
@@ -2272,10 +2422,10 @@ packages:
cpu: [ia32]
os: [win32]
- '@esbuild/win32-x64@0.25.5':
- resolution: {integrity: sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==}
+ '@esbuild/win32-ia32@0.28.0':
+ resolution: {integrity: sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==}
engines: {node: '>=18'}
- cpu: [x64]
+ cpu: [ia32]
os: [win32]
'@esbuild/win32-x64@0.27.2':
@@ -2290,6 +2440,12 @@ packages:
cpu: [x64]
os: [win32]
+ '@esbuild/win32-x64@0.28.0':
+ resolution: {integrity: sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [win32]
+
'@eslint-community/eslint-utils@4.7.0':
resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -2637,6 +2793,10 @@ packages:
resolution: {integrity: sha512-xHK3XHPUW8DTAobU+G0XT+/w+JLM7/8k1UFdB5xg/zTFPnFCobhftzw8wl4Lw2aq/Rvir5pxfZV5fEazmeCJ2g==}
engines: {node: '>= 20.19.0'}
+ '@noble/ciphers@2.2.0':
+ resolution: {integrity: sha512-Z6pjIZ/8IJcCGzb2S/0Px5J81yij85xASuk1teLNeg75bfT07MV3a/O2Mtn1I2se43k3lkVEcFaR10N4cgQcZA==}
+ engines: {node: '>= 20.19.0'}
+
'@noble/hashes@1.7.1':
resolution: {integrity: sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==}
engines: {node: ^14.21.3 || >=16}
@@ -4772,6 +4932,130 @@ packages:
vue:
optional: true
+ better-auth@1.4.21:
+ resolution: {integrity: sha512-qdrIZS7xnGF2HPBV5wYNPWTkPojhauOOjz1+MhLvwFy+zXpgLofQmWsI5I9DY+ef845NKt93XcgpyAc4RPPT9A==}
+ peerDependencies:
+ '@lynx-js/react': '*'
+ '@prisma/client': ^5.0.0 || ^6.0.0 || ^7.0.0
+ '@sveltejs/kit': ^2.0.0
+ '@tanstack/react-start': ^1.0.0
+ '@tanstack/solid-start': ^1.0.0
+ better-sqlite3: ^12.0.0
+ drizzle-kit: '>=0.31.4'
+ drizzle-orm: '>=0.41.0'
+ mongodb: ^6.0.0 || ^7.0.0
+ mysql2: ^3.0.0
+ next: ^14.0.0 || ^15.0.0 || ^16.0.0
+ pg: ^8.0.0
+ prisma: ^5.0.0 || ^6.0.0 || ^7.0.0
+ react: ^18.0.0 || ^19.0.0
+ react-dom: ^18.0.0 || ^19.0.0
+ solid-js: ^1.0.0
+ svelte: ^4.0.0 || ^5.0.0
+ vitest: ^2.0.0 || ^3.0.0 || ^4.0.0
+ vue: ^3.0.0
+ peerDependenciesMeta:
+ '@lynx-js/react':
+ optional: true
+ '@prisma/client':
+ optional: true
+ '@sveltejs/kit':
+ optional: true
+ '@tanstack/react-start':
+ optional: true
+ '@tanstack/solid-start':
+ optional: true
+ better-sqlite3:
+ optional: true
+ drizzle-kit:
+ optional: true
+ drizzle-orm:
+ optional: true
+ mongodb:
+ optional: true
+ mysql2:
+ optional: true
+ next:
+ optional: true
+ pg:
+ optional: true
+ prisma:
+ optional: true
+ react:
+ optional: true
+ react-dom:
+ optional: true
+ solid-js:
+ optional: true
+ svelte:
+ optional: true
+ vitest:
+ optional: true
+ vue:
+ optional: true
+
+ better-auth@1.6.15:
+ resolution: {integrity: sha512-0nuQuEru3ZrLF+9xFUuN3llAmR+6gHLtLunoXaZxB9lXGjSmfBcc6SZUgYq4DfzugPnLvdnzYazsyprZFSFC4Q==}
+ peerDependencies:
+ '@lynx-js/react': '*'
+ '@prisma/client': ^5.0.0 || ^6.0.0 || ^7.0.0
+ '@sveltejs/kit': ^2.0.0
+ '@tanstack/react-start': ^1.0.0
+ '@tanstack/solid-start': ^1.0.0
+ better-sqlite3: ^12.0.0
+ drizzle-kit: '>=0.31.4'
+ drizzle-orm: ^0.45.2
+ mongodb: ^6.0.0 || ^7.0.0
+ mysql2: ^3.0.0
+ next: ^14.0.0 || ^15.0.0 || ^16.0.0
+ pg: ^8.0.0
+ prisma: ^5.0.0 || ^6.0.0 || ^7.0.0
+ react: ^18.0.0 || ^19.0.0
+ react-dom: ^18.0.0 || ^19.0.0
+ solid-js: ^1.0.0
+ svelte: ^4.0.0 || ^5.0.0
+ vitest: ^2.0.0 || ^3.0.0 || ^4.0.0
+ vue: ^3.0.0
+ peerDependenciesMeta:
+ '@lynx-js/react':
+ optional: true
+ '@prisma/client':
+ optional: true
+ '@sveltejs/kit':
+ optional: true
+ '@tanstack/react-start':
+ optional: true
+ '@tanstack/solid-start':
+ optional: true
+ better-sqlite3:
+ optional: true
+ drizzle-kit:
+ optional: true
+ drizzle-orm:
+ optional: true
+ mongodb:
+ optional: true
+ mysql2:
+ optional: true
+ next:
+ optional: true
+ pg:
+ optional: true
+ prisma:
+ optional: true
+ react:
+ optional: true
+ react-dom:
+ optional: true
+ solid-js:
+ optional: true
+ svelte:
+ optional: true
+ vitest:
+ optional: true
+ vue:
+ optional: true
+
better-call@1.1.8:
resolution: {integrity: sha512-XMQ2rs6FNXasGNfMjzbyroSwKwYbZ/T3IxruSS6U2MJRsSYh3wYtG3o6H00ZlKZ/C/UPOAD97tqgQJNsxyeTXw==}
peerDependencies:
@@ -4780,6 +5064,14 @@ packages:
zod:
optional: true
+ better-call@1.3.5:
+ resolution: {integrity: sha512-kOFJkBP7utAQLEYrobZm3vkTH8mXq5GNgvjc5/XEST1ilVHaxXUXfeDeFlqoETMtyqS4+3/h4ONX2i++ebZrvA==}
+ peerDependencies:
+ zod: ^4.0.0
+ peerDependenciesMeta:
+ zod:
+ optional: true
+
better-sqlite3@12.5.0:
resolution: {integrity: sha512-WwCZ/5Diz7rsF29o27o0Gcc1Du+l7Zsv7SYtVPG0X3G/uUI1LqdxrQI7c9Hs2FWpqXXERjW9hp6g3/tH7DlVKg==}
engines: {node: 20.x || 22.x || 23.x || 24.x || 25.x}
@@ -4915,24 +5207,21 @@ packages:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
- chalk@5.3.0:
- resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==}
- engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
-
chalk@5.6.2:
resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==}
engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
- chevrotain-allstar@0.3.1:
- resolution: {integrity: sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==}
+ chevrotain-allstar@0.4.3:
+ resolution: {integrity: sha512-2X4mkroolSMKqW+H22pyPMUVDqYZzPhephTmg/NODKb1IGYPHfxfhcW0EjS7wcPJNbze2i4vBWT7zT5FKF2lrQ==}
peerDependencies:
- chevrotain: ^11.0.0
+ chevrotain: ^12.0.0
chevrotain@10.5.0:
resolution: {integrity: sha512-Pkv5rBY3+CsHOYfV5g/Vs5JY9WTHHDEKOlohI2XeygaZhUeqhAlldZ8Hz9cRmxu709bvS08YzxHdTPHhffc13A==}
- chevrotain@11.0.3:
- resolution: {integrity: sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==}
+ chevrotain@12.0.0:
+ resolution: {integrity: sha512-csJvb+6kEiQaqo1woTdSAuOWdN0WTLIydkKrBnS+V5gZz0oqBrp4kQ35519QgK6TpBThiG3V1vNSHlIkv4AglQ==}
+ engines: {node: '>=22.0.0'}
chokidar@4.0.3:
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
@@ -5010,10 +5299,6 @@ packages:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'}
- commander@11.0.0:
- resolution: {integrity: sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==}
- engines: {node: '>=16'}
-
commander@11.1.0:
resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==}
engines: {node: '>=16'}
@@ -5022,6 +5307,10 @@ packages:
resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==}
engines: {node: '>=18'}
+ commander@14.0.3:
+ resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==}
+ engines: {node: '>=20'}
+
commander@2.20.3:
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
@@ -5610,11 +5899,6 @@ packages:
resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
engines: {node: '>= 0.4'}
- esbuild@0.25.5:
- resolution: {integrity: sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==}
- engines: {node: '>=18'}
- hasBin: true
-
esbuild@0.27.2:
resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==}
engines: {node: '>=18'}
@@ -5625,6 +5909,11 @@ packages:
engines: {node: '>=18'}
hasBin: true
+ esbuild@0.28.0:
+ resolution: {integrity: sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==}
+ engines: {node: '>=18'}
+ hasBin: true
+
escalade@3.2.0:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'}
@@ -5952,8 +6241,8 @@ packages:
fs-constants@1.0.0:
resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
- fs-extra@11.1.1:
- resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==}
+ fs-extra@11.3.5:
+ resolution: {integrity: sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg==}
engines: {node: '>=14.14'}
fsevents@2.3.3:
@@ -6507,6 +6796,9 @@ packages:
jose@6.1.2:
resolution: {integrity: sha512-MpcPtHLE5EmztuFIqB0vzHAWJPpmN1E6L4oo+kze56LIs3MyXIj9ZHMDxqOvkP38gBR7K1v3jqd4WU2+nrfONQ==}
+ jose@6.2.3:
+ resolution: {integrity: sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==}
+
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
@@ -6575,8 +6867,8 @@ packages:
resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==}
engines: {node: '>=0.10.0'}
- jsonschema@1.4.1:
- resolution: {integrity: sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==}
+ jsonschema@1.5.0:
+ resolution: {integrity: sha512-K+A9hhqbn0f3pJX17Q/7H6yQfD/5OXgdrR5UE12gMXCiN9D5Xq2o5mddV2QEcX/bjla99ASsAAQUyMCCRWAEhw==}
jsx-ast-utils@3.3.5:
resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
@@ -6614,17 +6906,17 @@ packages:
resolution: {integrity: sha512-LrQfPUeTW7MXbMvT62moEMnpMTuj9TO3lqjCeLKjM975PJ4Alrl/43f2tlDX7xOsNptKgH4LSNGwIbXwEkLg4g==}
engines: {node: '>=22.0.0'}
- langium-cli@3.5.0:
- resolution: {integrity: sha512-TPIzIiMAQwTPPphtHGSrFXo4t0orx3aRh0syg9jnOihvBkBDvsQdJP9fBo9hp5Qaosklpc2CfbH0wh/dkgZcJA==}
- engines: {node: '>=18.0.0'}
+ langium-cli@4.2.1:
+ resolution: {integrity: sha512-npo1fSoP/wUf4cxUcKUYph48+jHFPEjeLQJ3pQ1UnA4QRuz8JpOxWsLHB/fdmViZSnI0mb98f06Wo7PKecqoUw==}
+ engines: {node: '>=20.10.0', npm: '>=10.2.3'}
hasBin: true
- langium-railroad@3.5.0:
- resolution: {integrity: sha512-80Enc6bOR6oHZD18IQlVTdfCh07rbrM5SOsPUPc1kyh7n3zQbmLs5P2E9hV4SoWlkhOjGKL1I9Z6uORpgy+jTQ==}
+ langium-railroad@4.2.0:
+ resolution: {integrity: sha512-LYR22GV14iz0GTUtR91pZY6yNImYRk1HbAuHBP8k8GESMcSkCJh+iewJooH9k8H8dJOteXvvI7aFkz6rfU9oLQ==}
- langium@3.5.0:
- resolution: {integrity: sha512-tnqVzWOkUcoiY0bWlyE8diFrZjmGBCF7MesC1bjUaZM+YGQSfdPC+KkhmHM0DWFG+uLcPxidKaPP1SYGtg3J0Q==}
- engines: {node: '>=18.0.0'}
+ langium@4.2.4:
+ resolution: {integrity: sha512-J0M9BkTOZ9Izee2YL0eXkUKFdWhrmTYYVLgiZTz6Z3KvK03ooM+vjVrfphKcdGVPWmM2cFYtDnNyIsIIZPrHNA==}
+ engines: {node: '>=20.10.0', npm: '>=10.2.3'}
language-subtag-registry@0.3.23:
resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==}
@@ -6752,8 +7044,8 @@ packages:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'}
- lodash-es@4.17.23:
- resolution: {integrity: sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==}
+ lodash-es@4.18.1:
+ resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==}
lodash.defaults@4.2.0:
resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==}
@@ -6770,8 +7062,8 @@ packages:
lodash.uniq@4.5.0:
resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==}
- lodash@4.17.23:
- resolution: {integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==}
+ lodash@4.18.1:
+ resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==}
log-symbols@4.1.0:
resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
@@ -7006,6 +7298,10 @@ packages:
resolution: {integrity: sha512-kNZ9xnoJYKg/AfxjrVL4SS0fKX++4awQReGqWnwTRHxeHGZ1FJFVgTqr/eMrNQdp0Tz7M7tG/TDaX8QfHDwVCw==}
engines: {node: ^20.0.0 || >=22.0.0}
+ nanostores@1.3.0:
+ resolution: {integrity: sha512-XPUa/jz+P1oJvN9VBxw4L9MtdFfaH3DAryqPssqhb2kXjmb9npz0dly6rCsgFWOPr4Yg9mTfM3MDZgZZ+7A3lA==}
+ engines: {node: ^20.0.0 || >=22.0.0}
+
nanotar@0.2.0:
resolution: {integrity: sha512-9ca1h0Xjvo9bEkE4UOxgAzLV0jHKe6LMaxo37ND2DAhhAtd0j8pR1Wxz+/goMrZO8AEZTWCmyaOsFI/W5AdpCQ==}
@@ -7342,9 +7638,6 @@ packages:
perfect-debounce@1.0.0:
resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==}
- perfect-debounce@2.0.0:
- resolution: {integrity: sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow==}
-
perfect-debounce@2.1.0:
resolution: {integrity: sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==}
@@ -8598,8 +8891,8 @@ packages:
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
- tsx@4.20.3:
- resolution: {integrity: sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ==}
+ tsx@4.22.4:
+ resolution: {integrity: sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg==}
engines: {node: '>=18.0.0'}
hasBin: true
@@ -9120,9 +9413,6 @@ packages:
resolution: {integrity: sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==}
hasBin: true
- vscode-uri@3.0.8:
- resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==}
-
vscode-uri@3.1.0:
resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==}
@@ -9771,19 +10061,91 @@ snapshots:
'@bcoe/v8-coverage@1.0.2': {}
- '@better-auth/cli@1.4.19(@better-fetch/fetch@1.1.21)(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)))(@types/better-sqlite3@7.6.13)(@types/sql.js@1.4.9)(better-call@1.1.8(zod@4.3.6))(bun-types@1.3.3)(jose@6.1.2)(kysely@0.29.0)(magicast@0.5.1)(mysql2@3.16.1)(nanostores@1.0.1)(next@16.1.6(@babel/core@7.29.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sql.js@1.13.0)(svelte@5.53.5)(vitest@4.0.14(@edge-runtime/vm@5.0.0)(@types/node@25.5.2)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))':
+ '@better-auth/cli@1.4.19(@better-fetch/fetch@1.1.21)(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))(@types/better-sqlite3@7.6.13)(@types/sql.js@1.4.9)(better-call@1.1.8(zod@4.3.6))(bun-types@1.3.3)(jose@6.2.3)(kysely@0.29.0)(magicast@0.5.1)(mysql2@3.16.1)(nanostores@1.3.0)(next@16.1.6(@babel/core@7.29.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sql.js@1.13.0)(svelte@5.53.5)(vitest@4.0.14(@edge-runtime/vm@5.0.0)(@types/node@25.5.2)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))':
+ dependencies:
+ '@babel/core': 7.29.0
+ '@babel/preset-react': 7.28.5(@babel/core@7.29.0)
+ '@babel/preset-typescript': 7.28.5(@babel/core@7.29.0)
+ '@better-auth/core': 1.4.19(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0)
+ '@better-auth/telemetry': 1.4.19(@better-auth/core@1.4.19(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0))
+ '@better-auth/utils': 0.3.0
+ '@clack/prompts': 0.11.0
+ '@mrleebo/prisma-ast': 0.13.1
+ '@prisma/client': 5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))
+ '@types/pg': 8.16.0
+ better-auth: 1.4.19(aa46c218c2111ba42e6bbb995c1cdf9e)
+ better-sqlite3: 12.5.0
+ c12: 3.3.3(magicast@0.5.1)
+ chalk: 5.6.2
+ commander: 12.1.0
+ dotenv: 17.2.3
+ drizzle-orm: 0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))(sql.js@1.13.0)
+ open: 10.2.0
+ pg: 8.16.3
+ prettier: 3.8.1
+ prompts: 2.4.2
+ semver: 7.7.4
+ yocto-spinner: 0.2.3
+ zod: 4.3.6
+ transitivePeerDependencies:
+ - '@aws-sdk/client-rds-data'
+ - '@better-fetch/fetch'
+ - '@cloudflare/workers-types'
+ - '@electric-sql/pglite'
+ - '@libsql/client'
+ - '@libsql/client-wasm'
+ - '@lynx-js/react'
+ - '@neondatabase/serverless'
+ - '@op-engineering/op-sqlite'
+ - '@opentelemetry/api'
+ - '@planetscale/database'
+ - '@sveltejs/kit'
+ - '@tanstack/react-start'
+ - '@tanstack/solid-start'
+ - '@tidbcloud/serverless'
+ - '@types/better-sqlite3'
+ - '@types/sql.js'
+ - '@vercel/postgres'
+ - '@xata.io/client'
+ - better-call
+ - bun-types
+ - drizzle-kit
+ - expo-sqlite
+ - gel
+ - jose
+ - knex
+ - kysely
+ - magicast
+ - mongodb
+ - mysql2
+ - nanostores
+ - next
+ - pg-native
+ - postgres
+ - prisma
+ - react
+ - react-dom
+ - solid-js
+ - sql.js
+ - sqlite3
+ - supports-color
+ - svelte
+ - vitest
+ - vue
+
+ '@better-auth/cli@1.4.21(@better-fetch/fetch@1.1.21)(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))(@types/better-sqlite3@7.6.13)(@types/sql.js@1.4.9)(better-call@1.1.8(zod@4.3.6))(bun-types@1.3.3)(jose@6.2.3)(kysely@0.29.0)(magicast@0.5.1)(mysql2@3.16.1)(nanostores@1.3.0)(next@16.1.6(@babel/core@7.29.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(sql.js@1.13.0)(svelte@5.53.5)(vitest@4.0.14(@edge-runtime/vm@5.0.0)(@types/node@20.19.24)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))':
dependencies:
'@babel/core': 7.29.0
'@babel/preset-react': 7.28.5(@babel/core@7.29.0)
'@babel/preset-typescript': 7.28.5(@babel/core@7.29.0)
- '@better-auth/core': 1.4.19(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.2)(kysely@0.29.0)(nanostores@1.0.1)
- '@better-auth/telemetry': 1.4.19(@better-auth/core@1.4.19(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.2)(kysely@0.29.0)(nanostores@1.0.1))
+ '@better-auth/core': 1.4.19(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0)
+ '@better-auth/telemetry': 1.4.21(@better-auth/core@1.4.19(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0))
'@better-auth/utils': 0.3.0
'@clack/prompts': 0.11.0
'@mrleebo/prisma-ast': 0.13.1
'@prisma/client': 5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))
'@types/pg': 8.16.0
- better-auth: 1.4.19(1495ef1d827113360533150571904e77)
+ better-auth: 1.4.21(261c4d1149703dc38709f1a99ea83b5c)
better-sqlite3: 12.5.0
c12: 3.3.3(magicast@0.5.1)
chalk: 5.6.2
@@ -9854,25 +10216,95 @@ snapshots:
nanostores: 1.0.1
zod: 4.3.6
- '@better-auth/core@1.4.19(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.2)(kysely@0.29.0)(nanostores@1.0.1)':
+ '@better-auth/core@1.4.19(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.2.3)(kysely@0.28.16)(nanostores@1.3.0)':
dependencies:
'@better-auth/utils': 0.3.0
'@better-fetch/fetch': 1.1.21
'@standard-schema/spec': 1.0.0
better-call: 1.1.8(zod@4.3.6)
- jose: 6.1.2
+ jose: 6.2.3
+ kysely: 0.28.16
+ nanostores: 1.3.0
+ zod: 4.3.6
+
+ '@better-auth/core@1.4.19(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0)':
+ dependencies:
+ '@better-auth/utils': 0.3.0
+ '@better-fetch/fetch': 1.1.21
+ '@standard-schema/spec': 1.0.0
+ better-call: 1.1.8(zod@4.3.6)
+ jose: 6.2.3
kysely: 0.29.0
- nanostores: 1.0.1
+ nanostores: 1.3.0
+ zod: 4.3.6
+
+ '@better-auth/core@1.4.19(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0)':
+ dependencies:
+ '@better-auth/utils': 0.4.1
+ '@better-fetch/fetch': 1.1.21
+ '@standard-schema/spec': 1.0.0
+ better-call: 1.1.8(zod@4.3.6)
+ jose: 6.2.3
+ kysely: 0.29.0
+ nanostores: 1.3.0
zod: 4.3.6
- '@better-auth/telemetry@1.4.19(@better-auth/core@1.4.19(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.2)(kysely@0.29.0)(nanostores@1.0.1))':
+ '@better-auth/drizzle-adapter@1.6.15(@better-auth/core@1.4.19(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0))(@better-auth/utils@0.4.1)(drizzle-orm@0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))(sql.js@1.13.0))':
+ dependencies:
+ '@better-auth/core': 1.4.19(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0)
+ '@better-auth/utils': 0.4.1
+ optionalDependencies:
+ drizzle-orm: 0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))(sql.js@1.13.0)
+
+ '@better-auth/kysely-adapter@1.6.15(@better-auth/core@1.4.19(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0))(@better-auth/utils@0.4.1)(kysely@0.29.0)':
+ dependencies:
+ '@better-auth/core': 1.4.19(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0)
+ '@better-auth/utils': 0.4.1
+ optionalDependencies:
+ kysely: 0.29.0
+
+ '@better-auth/memory-adapter@1.6.15(@better-auth/core@1.4.19(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0))(@better-auth/utils@0.4.1)':
+ dependencies:
+ '@better-auth/core': 1.4.19(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0)
+ '@better-auth/utils': 0.4.1
+
+ '@better-auth/mongo-adapter@1.6.15(@better-auth/core@1.4.19(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0))(@better-auth/utils@0.4.1)':
+ dependencies:
+ '@better-auth/core': 1.4.19(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0)
+ '@better-auth/utils': 0.4.1
+
+ '@better-auth/prisma-adapter@1.6.15(@better-auth/core@1.4.19(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0))(@better-auth/utils@0.4.1)(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3)))(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))':
+ dependencies:
+ '@better-auth/core': 1.4.19(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0)
+ '@better-auth/utils': 0.4.1
+ optionalDependencies:
+ '@prisma/client': 5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))
+ prisma: 6.19.0(magicast@0.5.1)(typescript@5.9.3)
+
+ '@better-auth/telemetry@1.4.19(@better-auth/core@1.4.19(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0))':
+ dependencies:
+ '@better-auth/core': 1.4.19(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0)
+ '@better-auth/utils': 0.3.0
+ '@better-fetch/fetch': 1.1.21
+
+ '@better-auth/telemetry@1.4.21(@better-auth/core@1.4.19(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0))':
dependencies:
- '@better-auth/core': 1.4.19(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.2)(kysely@0.29.0)(nanostores@1.0.1)
+ '@better-auth/core': 1.4.19(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0)
'@better-auth/utils': 0.3.0
'@better-fetch/fetch': 1.1.21
+ '@better-auth/telemetry@1.6.15(@better-auth/core@1.4.19(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0))(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)':
+ dependencies:
+ '@better-auth/core': 1.4.19(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0)
+ '@better-auth/utils': 0.4.1
+ '@better-fetch/fetch': 1.1.21
+
'@better-auth/utils@0.3.0': {}
+ '@better-auth/utils@0.4.1':
+ dependencies:
+ '@noble/hashes': 2.0.1
+
'@better-fetch/fetch@1.1.21': {}
'@bomb.sh/tab@0.0.12(cac@6.7.14)(citty@0.2.1)':
@@ -9886,33 +10318,31 @@ snapshots:
dependencies:
'@chevrotain/gast': 10.5.0
'@chevrotain/types': 10.5.0
- lodash: 4.17.23
+ lodash: 4.18.1
- '@chevrotain/cst-dts-gen@11.0.3':
+ '@chevrotain/cst-dts-gen@12.0.0':
dependencies:
- '@chevrotain/gast': 11.0.3
- '@chevrotain/types': 11.0.3
- lodash-es: 4.17.23
+ '@chevrotain/gast': 12.0.0
+ '@chevrotain/types': 12.0.0
'@chevrotain/gast@10.5.0':
dependencies:
'@chevrotain/types': 10.5.0
- lodash: 4.17.23
+ lodash: 4.18.1
- '@chevrotain/gast@11.0.3':
+ '@chevrotain/gast@12.0.0':
dependencies:
- '@chevrotain/types': 11.0.3
- lodash-es: 4.17.23
+ '@chevrotain/types': 12.0.0
- '@chevrotain/regexp-to-ast@11.0.3': {}
+ '@chevrotain/regexp-to-ast@12.0.0': {}
'@chevrotain/types@10.5.0': {}
- '@chevrotain/types@11.0.3': {}
+ '@chevrotain/types@12.0.0': {}
'@chevrotain/utils@10.5.0': {}
- '@chevrotain/utils@11.0.3': {}
+ '@chevrotain/utils@12.0.0': {}
'@clack/core@0.5.0':
dependencies:
@@ -10024,16 +10454,13 @@ snapshots:
tslib: 2.8.1
optional: true
- '@esbuild/aix-ppc64@0.25.5':
- optional: true
-
'@esbuild/aix-ppc64@0.27.2':
optional: true
'@esbuild/aix-ppc64@0.27.3':
optional: true
- '@esbuild/android-arm64@0.25.5':
+ '@esbuild/aix-ppc64@0.28.0':
optional: true
'@esbuild/android-arm64@0.27.2':
@@ -10042,7 +10469,7 @@ snapshots:
'@esbuild/android-arm64@0.27.3':
optional: true
- '@esbuild/android-arm@0.25.5':
+ '@esbuild/android-arm64@0.28.0':
optional: true
'@esbuild/android-arm@0.27.2':
@@ -10051,7 +10478,7 @@ snapshots:
'@esbuild/android-arm@0.27.3':
optional: true
- '@esbuild/android-x64@0.25.5':
+ '@esbuild/android-arm@0.28.0':
optional: true
'@esbuild/android-x64@0.27.2':
@@ -10060,7 +10487,7 @@ snapshots:
'@esbuild/android-x64@0.27.3':
optional: true
- '@esbuild/darwin-arm64@0.25.5':
+ '@esbuild/android-x64@0.28.0':
optional: true
'@esbuild/darwin-arm64@0.27.2':
@@ -10069,7 +10496,7 @@ snapshots:
'@esbuild/darwin-arm64@0.27.3':
optional: true
- '@esbuild/darwin-x64@0.25.5':
+ '@esbuild/darwin-arm64@0.28.0':
optional: true
'@esbuild/darwin-x64@0.27.2':
@@ -10078,7 +10505,7 @@ snapshots:
'@esbuild/darwin-x64@0.27.3':
optional: true
- '@esbuild/freebsd-arm64@0.25.5':
+ '@esbuild/darwin-x64@0.28.0':
optional: true
'@esbuild/freebsd-arm64@0.27.2':
@@ -10087,7 +10514,7 @@ snapshots:
'@esbuild/freebsd-arm64@0.27.3':
optional: true
- '@esbuild/freebsd-x64@0.25.5':
+ '@esbuild/freebsd-arm64@0.28.0':
optional: true
'@esbuild/freebsd-x64@0.27.2':
@@ -10096,7 +10523,7 @@ snapshots:
'@esbuild/freebsd-x64@0.27.3':
optional: true
- '@esbuild/linux-arm64@0.25.5':
+ '@esbuild/freebsd-x64@0.28.0':
optional: true
'@esbuild/linux-arm64@0.27.2':
@@ -10105,7 +10532,7 @@ snapshots:
'@esbuild/linux-arm64@0.27.3':
optional: true
- '@esbuild/linux-arm@0.25.5':
+ '@esbuild/linux-arm64@0.28.0':
optional: true
'@esbuild/linux-arm@0.27.2':
@@ -10114,7 +10541,7 @@ snapshots:
'@esbuild/linux-arm@0.27.3':
optional: true
- '@esbuild/linux-ia32@0.25.5':
+ '@esbuild/linux-arm@0.28.0':
optional: true
'@esbuild/linux-ia32@0.27.2':
@@ -10123,7 +10550,7 @@ snapshots:
'@esbuild/linux-ia32@0.27.3':
optional: true
- '@esbuild/linux-loong64@0.25.5':
+ '@esbuild/linux-ia32@0.28.0':
optional: true
'@esbuild/linux-loong64@0.27.2':
@@ -10132,7 +10559,7 @@ snapshots:
'@esbuild/linux-loong64@0.27.3':
optional: true
- '@esbuild/linux-mips64el@0.25.5':
+ '@esbuild/linux-loong64@0.28.0':
optional: true
'@esbuild/linux-mips64el@0.27.2':
@@ -10141,7 +10568,7 @@ snapshots:
'@esbuild/linux-mips64el@0.27.3':
optional: true
- '@esbuild/linux-ppc64@0.25.5':
+ '@esbuild/linux-mips64el@0.28.0':
optional: true
'@esbuild/linux-ppc64@0.27.2':
@@ -10150,7 +10577,7 @@ snapshots:
'@esbuild/linux-ppc64@0.27.3':
optional: true
- '@esbuild/linux-riscv64@0.25.5':
+ '@esbuild/linux-ppc64@0.28.0':
optional: true
'@esbuild/linux-riscv64@0.27.2':
@@ -10159,7 +10586,7 @@ snapshots:
'@esbuild/linux-riscv64@0.27.3':
optional: true
- '@esbuild/linux-s390x@0.25.5':
+ '@esbuild/linux-riscv64@0.28.0':
optional: true
'@esbuild/linux-s390x@0.27.2':
@@ -10168,7 +10595,7 @@ snapshots:
'@esbuild/linux-s390x@0.27.3':
optional: true
- '@esbuild/linux-x64@0.25.5':
+ '@esbuild/linux-s390x@0.28.0':
optional: true
'@esbuild/linux-x64@0.27.2':
@@ -10177,7 +10604,7 @@ snapshots:
'@esbuild/linux-x64@0.27.3':
optional: true
- '@esbuild/netbsd-arm64@0.25.5':
+ '@esbuild/linux-x64@0.28.0':
optional: true
'@esbuild/netbsd-arm64@0.27.2':
@@ -10186,7 +10613,7 @@ snapshots:
'@esbuild/netbsd-arm64@0.27.3':
optional: true
- '@esbuild/netbsd-x64@0.25.5':
+ '@esbuild/netbsd-arm64@0.28.0':
optional: true
'@esbuild/netbsd-x64@0.27.2':
@@ -10195,7 +10622,7 @@ snapshots:
'@esbuild/netbsd-x64@0.27.3':
optional: true
- '@esbuild/openbsd-arm64@0.25.5':
+ '@esbuild/netbsd-x64@0.28.0':
optional: true
'@esbuild/openbsd-arm64@0.27.2':
@@ -10204,7 +10631,7 @@ snapshots:
'@esbuild/openbsd-arm64@0.27.3':
optional: true
- '@esbuild/openbsd-x64@0.25.5':
+ '@esbuild/openbsd-arm64@0.28.0':
optional: true
'@esbuild/openbsd-x64@0.27.2':
@@ -10213,13 +10640,16 @@ snapshots:
'@esbuild/openbsd-x64@0.27.3':
optional: true
+ '@esbuild/openbsd-x64@0.28.0':
+ optional: true
+
'@esbuild/openharmony-arm64@0.27.2':
optional: true
'@esbuild/openharmony-arm64@0.27.3':
optional: true
- '@esbuild/sunos-x64@0.25.5':
+ '@esbuild/openharmony-arm64@0.28.0':
optional: true
'@esbuild/sunos-x64@0.27.2':
@@ -10228,7 +10658,7 @@ snapshots:
'@esbuild/sunos-x64@0.27.3':
optional: true
- '@esbuild/win32-arm64@0.25.5':
+ '@esbuild/sunos-x64@0.28.0':
optional: true
'@esbuild/win32-arm64@0.27.2':
@@ -10237,7 +10667,7 @@ snapshots:
'@esbuild/win32-arm64@0.27.3':
optional: true
- '@esbuild/win32-ia32@0.25.5':
+ '@esbuild/win32-arm64@0.28.0':
optional: true
'@esbuild/win32-ia32@0.27.2':
@@ -10246,7 +10676,7 @@ snapshots:
'@esbuild/win32-ia32@0.27.3':
optional: true
- '@esbuild/win32-x64@0.25.5':
+ '@esbuild/win32-ia32@0.28.0':
optional: true
'@esbuild/win32-x64@0.27.2':
@@ -10255,6 +10685,9 @@ snapshots:
'@esbuild/win32-x64@0.27.3':
optional: true
+ '@esbuild/win32-x64@0.28.0':
+ optional: true
+
'@eslint-community/eslint-utils@4.7.0(eslint@9.29.0(jiti@2.6.1))':
dependencies:
eslint: 9.29.0(jiti@2.6.1)
@@ -10557,6 +10990,8 @@ snapshots:
'@noble/ciphers@2.0.1': {}
+ '@noble/ciphers@2.2.0': {}
+
'@noble/hashes@1.7.1': {}
'@noble/hashes@2.0.1': {}
@@ -10615,11 +11050,11 @@ snapshots:
'@nuxt/devalue@2.0.2': {}
- '@nuxt/devtools-kit@3.1.1(magicast@0.5.1)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))':
+ '@nuxt/devtools-kit@3.1.1(magicast@0.5.1)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))':
dependencies:
'@nuxt/kit': 4.3.1(magicast@0.5.1)
execa: 8.0.1
- vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
+ vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
transitivePeerDependencies:
- magicast
@@ -10634,12 +11069,12 @@ snapshots:
prompts: 2.4.2
semver: 7.7.4
- '@nuxt/devtools@3.1.1(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))':
+ '@nuxt/devtools@3.1.1(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))':
dependencies:
- '@nuxt/devtools-kit': 3.1.1(magicast@0.5.1)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))
+ '@nuxt/devtools-kit': 3.1.1(magicast@0.5.1)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
'@nuxt/devtools-wizard': 3.1.1
'@nuxt/kit': 4.3.1(magicast@0.5.1)
- '@vue/devtools-core': 8.0.5(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))
+ '@vue/devtools-core': 8.0.5(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))
'@vue/devtools-kit': 8.0.5
birpc: 2.9.0
consola: 3.4.2
@@ -10664,9 +11099,9 @@ snapshots:
sirv: 3.0.2
structured-clone-es: 1.0.0
tinyglobby: 0.2.15
- vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
- vite-plugin-inspect: 11.3.3(@nuxt/kit@4.3.1(magicast@0.5.1))(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))
- vite-plugin-vue-tracer: 1.2.0(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))
+ vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
+ vite-plugin-inspect: 11.3.3(@nuxt/kit@4.3.1(magicast@0.5.1))(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
+ vite-plugin-vue-tracer: 1.2.0(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))
which: 5.0.0
ws: 8.20.0
transitivePeerDependencies:
@@ -10675,12 +11110,12 @@ snapshots:
- utf-8-validate
- vue
- '@nuxt/devtools@3.1.1(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue@3.5.29(typescript@6.0.3))':
+ '@nuxt/devtools@3.1.1(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue@3.5.29(typescript@6.0.3))':
dependencies:
- '@nuxt/devtools-kit': 3.1.1(magicast@0.5.1)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))
+ '@nuxt/devtools-kit': 3.1.1(magicast@0.5.1)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
'@nuxt/devtools-wizard': 3.1.1
'@nuxt/kit': 4.3.1(magicast@0.5.1)
- '@vue/devtools-core': 8.0.5(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue@3.5.29(typescript@6.0.3))
+ '@vue/devtools-core': 8.0.5(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue@3.5.29(typescript@6.0.3))
'@vue/devtools-kit': 8.0.5
birpc: 2.9.0
consola: 3.4.2
@@ -10705,9 +11140,9 @@ snapshots:
sirv: 3.0.2
structured-clone-es: 1.0.0
tinyglobby: 0.2.15
- vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
- vite-plugin-inspect: 11.3.3(@nuxt/kit@4.3.1(magicast@0.5.1))(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))
- vite-plugin-vue-tracer: 1.2.0(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue@3.5.29(typescript@6.0.3))
+ vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
+ vite-plugin-inspect: 11.3.3(@nuxt/kit@4.3.1(magicast@0.5.1))(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
+ vite-plugin-vue-tracer: 1.2.0(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue@3.5.29(typescript@6.0.3))
which: 5.0.0
ws: 8.20.0
transitivePeerDependencies:
@@ -10741,7 +11176,7 @@ snapshots:
transitivePeerDependencies:
- magicast
- '@nuxt/nitro-server@4.3.1(better-sqlite3@12.5.0)(db0@0.3.4(better-sqlite3@12.5.0)(drizzle-orm@0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))(sql.js@1.13.0))(mysql2@3.16.1))(drizzle-orm@0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))(sql.js@1.13.0))(ioredis@5.9.3)(magicast@0.5.1)(mysql2@3.16.1)(nuxt@4.3.1(20bb9c9cac3d4d3ad27d57e07c1eb4f2))(rolldown@1.0.0-rc.15)(typescript@5.9.3)':
+ '@nuxt/nitro-server@4.3.1(better-sqlite3@12.5.0)(db0@0.3.4(better-sqlite3@12.5.0)(drizzle-orm@0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))(sql.js@1.13.0))(mysql2@3.16.1))(drizzle-orm@0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))(sql.js@1.13.0))(ioredis@5.9.3)(magicast@0.5.1)(mysql2@3.16.1)(nuxt@4.3.1(526b065509e6a4d54781a1030a9e863f))(rolldown@1.0.0-rc.15)(typescript@5.9.3)':
dependencies:
'@nuxt/devalue': 2.0.2
'@nuxt/kit': 4.3.1(magicast@0.5.1)
@@ -10759,7 +11194,7 @@ snapshots:
klona: 2.0.6
mocked-exports: 0.1.1
nitropack: 2.13.1(better-sqlite3@12.5.0)(drizzle-orm@0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))(sql.js@1.13.0))(mysql2@3.16.1)(rolldown@1.0.0-rc.15)
- nuxt: 4.3.1(20bb9c9cac3d4d3ad27d57e07c1eb4f2)
+ nuxt: 4.3.1(526b065509e6a4d54781a1030a9e863f)
ohash: 2.0.11
pathe: 2.0.3
pkg-types: 2.3.0
@@ -10806,7 +11241,7 @@ snapshots:
- uploadthing
- xml2js
- '@nuxt/nitro-server@4.3.1(better-sqlite3@12.5.0)(db0@0.3.4(better-sqlite3@12.5.0)(drizzle-orm@0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@6.0.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@6.0.3))(sql.js@1.13.0))(mysql2@3.16.1))(drizzle-orm@0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@6.0.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@6.0.3))(sql.js@1.13.0))(ioredis@5.9.3)(magicast@0.5.1)(mysql2@3.16.1)(nuxt@4.3.1(f6c7dcf4eb9de64f6cb5e0db74766190))(rolldown@1.0.0-rc.15)(typescript@6.0.3)':
+ '@nuxt/nitro-server@4.3.1(better-sqlite3@12.5.0)(db0@0.3.4(better-sqlite3@12.5.0)(drizzle-orm@0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@6.0.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@6.0.3))(sql.js@1.13.0))(mysql2@3.16.1))(drizzle-orm@0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@6.0.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@6.0.3))(sql.js@1.13.0))(ioredis@5.9.3)(magicast@0.5.1)(mysql2@3.16.1)(nuxt@4.3.1(95266d6f061a460ce208abe1df07947b))(rolldown@1.0.0-rc.15)(typescript@6.0.3)':
dependencies:
'@nuxt/devalue': 2.0.2
'@nuxt/kit': 4.3.1(magicast@0.5.1)
@@ -10824,7 +11259,7 @@ snapshots:
klona: 2.0.6
mocked-exports: 0.1.1
nitropack: 2.13.1(better-sqlite3@12.5.0)(drizzle-orm@0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@6.0.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@6.0.3))(sql.js@1.13.0))(mysql2@3.16.1)(rolldown@1.0.0-rc.15)
- nuxt: 4.3.1(f6c7dcf4eb9de64f6cb5e0db74766190)
+ nuxt: 4.3.1(95266d6f061a460ce208abe1df07947b)
ohash: 2.0.11
pathe: 2.0.3
pkg-types: 2.3.0
@@ -10888,12 +11323,12 @@ snapshots:
rc9: 3.0.0
std-env: 3.10.0
- '@nuxt/vite-builder@4.3.1(@types/node@25.5.2)(eslint@9.29.0(jiti@2.6.1))(lightningcss@1.30.2)(magicast@0.5.1)(nuxt@4.3.1(20bb9c9cac3d4d3ad27d57e07c1eb4f2))(optionator@0.9.4)(rolldown@1.0.0-rc.15)(rollup@4.59.0)(terser@5.44.0)(tsx@4.20.3)(typescript@5.9.3)(vue-tsc@3.2.5(typescript@5.9.3))(vue@3.5.29(typescript@5.9.3))(yaml@2.8.2)':
+ '@nuxt/vite-builder@4.3.1(@types/node@25.5.2)(eslint@9.29.0(jiti@2.6.1))(lightningcss@1.30.2)(magicast@0.5.1)(nuxt@4.3.1(526b065509e6a4d54781a1030a9e863f))(optionator@0.9.4)(rolldown@1.0.0-rc.15)(rollup@4.59.0)(terser@5.44.0)(tsx@4.22.4)(typescript@5.9.3)(vue-tsc@3.2.5(typescript@5.9.3))(vue@3.5.29(typescript@5.9.3))(yaml@2.8.2)':
dependencies:
'@nuxt/kit': 4.3.1(magicast@0.5.1)
'@rollup/plugin-replace': 6.0.3(rollup@4.59.0)
- '@vitejs/plugin-vue': 6.0.4(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))
- '@vitejs/plugin-vue-jsx': 5.1.4(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))
+ '@vitejs/plugin-vue': 6.0.4(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))
+ '@vitejs/plugin-vue-jsx': 5.1.4(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))
autoprefixer: 10.4.27(postcss@8.5.6)
consola: 3.4.2
cssnano: 7.1.2(postcss@8.5.6)
@@ -10907,7 +11342,7 @@ snapshots:
magic-string: 0.30.21
mlly: 1.8.0
mocked-exports: 0.1.1
- nuxt: 4.3.1(20bb9c9cac3d4d3ad27d57e07c1eb4f2)
+ nuxt: 4.3.1(526b065509e6a4d54781a1030a9e863f)
pathe: 2.0.3
pkg-types: 2.3.0
postcss: 8.5.6
@@ -10916,9 +11351,9 @@ snapshots:
std-env: 3.10.0
ufo: 1.6.3
unenv: 2.0.0-rc.24
- vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
- vite-node: 5.3.0(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
- vite-plugin-checker: 0.12.0(eslint@9.29.0(jiti@2.6.1))(optionator@0.9.4)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue-tsc@3.2.5(typescript@5.9.3))
+ vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
+ vite-node: 5.3.0(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
+ vite-plugin-checker: 0.12.0(eslint@9.29.0(jiti@2.6.1))(optionator@0.9.4)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue-tsc@3.2.5(typescript@5.9.3))
vue: 3.5.29(typescript@5.9.3)
vue-bundle-renderer: 2.2.0
optionalDependencies:
@@ -10948,12 +11383,12 @@ snapshots:
- vue-tsc
- yaml
- '@nuxt/vite-builder@4.3.1(@types/node@25.5.2)(eslint@9.29.0(jiti@2.6.1))(lightningcss@1.30.2)(magicast@0.5.1)(nuxt@4.3.1(f6c7dcf4eb9de64f6cb5e0db74766190))(optionator@0.9.4)(rolldown@1.0.0-rc.15)(rollup@4.59.0)(terser@5.44.0)(tsx@4.20.3)(typescript@6.0.3)(vue-tsc@3.2.5(typescript@6.0.3))(vue@3.5.29(typescript@6.0.3))(yaml@2.8.2)':
+ '@nuxt/vite-builder@4.3.1(@types/node@25.5.2)(eslint@9.29.0(jiti@2.6.1))(lightningcss@1.30.2)(magicast@0.5.1)(nuxt@4.3.1(95266d6f061a460ce208abe1df07947b))(optionator@0.9.4)(rolldown@1.0.0-rc.15)(rollup@4.59.0)(terser@5.44.0)(tsx@4.22.4)(typescript@6.0.3)(vue-tsc@3.2.5(typescript@6.0.3))(vue@3.5.29(typescript@6.0.3))(yaml@2.8.2)':
dependencies:
'@nuxt/kit': 4.3.1(magicast@0.5.1)
'@rollup/plugin-replace': 6.0.3(rollup@4.59.0)
- '@vitejs/plugin-vue': 6.0.4(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue@3.5.29(typescript@6.0.3))
- '@vitejs/plugin-vue-jsx': 5.1.4(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue@3.5.29(typescript@6.0.3))
+ '@vitejs/plugin-vue': 6.0.4(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue@3.5.29(typescript@6.0.3))
+ '@vitejs/plugin-vue-jsx': 5.1.4(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue@3.5.29(typescript@6.0.3))
autoprefixer: 10.4.27(postcss@8.5.6)
consola: 3.4.2
cssnano: 7.1.2(postcss@8.5.6)
@@ -10967,7 +11402,7 @@ snapshots:
magic-string: 0.30.21
mlly: 1.8.0
mocked-exports: 0.1.1
- nuxt: 4.3.1(f6c7dcf4eb9de64f6cb5e0db74766190)
+ nuxt: 4.3.1(95266d6f061a460ce208abe1df07947b)
pathe: 2.0.3
pkg-types: 2.3.0
postcss: 8.5.6
@@ -10976,9 +11411,9 @@ snapshots:
std-env: 3.10.0
ufo: 1.6.3
unenv: 2.0.0-rc.24
- vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
- vite-node: 5.3.0(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
- vite-plugin-checker: 0.12.0(eslint@9.29.0(jiti@2.6.1))(optionator@0.9.4)(typescript@6.0.3)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue-tsc@3.2.5(typescript@6.0.3))
+ vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
+ vite-node: 5.3.0(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
+ vite-plugin-checker: 0.12.0(eslint@9.29.0(jiti@2.6.1))(optionator@0.9.4)(typescript@6.0.3)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue-tsc@3.2.5(typescript@6.0.3))
vue: 3.5.29(typescript@6.0.3)
vue-bundle-renderer: 2.2.0
optionalDependencies:
@@ -11581,15 +12016,35 @@ snapshots:
dependencies:
acorn: 8.15.0
- '@sveltejs/adapter-auto@7.0.0(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)))':
+ '@sveltejs/adapter-auto@7.0.0(@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))':
+ dependencies:
+ '@sveltejs/kit': 2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
+
+ '@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))':
dependencies:
- '@sveltejs/kit': 2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))
+ '@standard-schema/spec': 1.0.0
+ '@sveltejs/acorn-typescript': 1.0.9(acorn@8.15.0)
+ '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
+ '@types/cookie': 0.6.0
+ acorn: 8.15.0
+ cookie: 1.1.1
+ devalue: 5.6.3
+ esm-env: 1.2.2
+ kleur: 4.1.5
+ magic-string: 0.30.21
+ mrmime: 2.0.1
+ set-cookie-parser: 3.0.1
+ sirv: 3.0.2
+ svelte: 5.53.5
+ vite: 7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
+ optionalDependencies:
+ typescript: 5.9.3
- '@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))':
+ '@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))':
dependencies:
'@standard-schema/spec': 1.0.0
'@sveltejs/acorn-typescript': 1.0.9(acorn@8.15.0)
- '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))
+ '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
'@types/cookie': 0.6.0
acorn: 8.15.0
cookie: 1.1.1
@@ -11601,15 +12056,16 @@ snapshots:
set-cookie-parser: 3.0.1
sirv: 3.0.2
svelte: 5.53.5
- vite: 7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
+ vite: 7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
optionalDependencies:
typescript: 5.9.3
+ optional: true
- '@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))':
+ '@sveltejs/kit@2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))':
dependencies:
'@standard-schema/spec': 1.0.0
'@sveltejs/acorn-typescript': 1.0.9(acorn@8.15.0)
- '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))
+ '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
'@types/cookie': 0.6.0
acorn: 8.15.0
cookie: 1.1.1
@@ -11621,7 +12077,7 @@ snapshots:
set-cookie-parser: 3.0.1
sirv: 3.0.2
svelte: 5.53.5
- vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
+ vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
optionalDependencies:
typescript: 5.9.3
@@ -11636,45 +12092,68 @@ snapshots:
transitivePeerDependencies:
- typescript
- '@sveltejs/vite-plugin-svelte-inspector@5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)))(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))':
+ '@sveltejs/vite-plugin-svelte-inspector@5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))':
+ dependencies:
+ '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
+ debug: 4.4.3
+ svelte: 5.53.5
+ vite: 7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@sveltejs/vite-plugin-svelte-inspector@5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))(svelte@5.53.5)(vite@7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))':
+ dependencies:
+ '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
+ debug: 4.4.3
+ svelte: 5.53.5
+ vite: 7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
+ transitivePeerDependencies:
+ - supports-color
+ optional: true
+
+ '@sveltejs/vite-plugin-svelte-inspector@5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))(svelte@5.53.5)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))':
dependencies:
- '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))
+ '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
debug: 4.4.3
svelte: 5.53.5
- vite: 7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
+ vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
transitivePeerDependencies:
- supports-color
- '@sveltejs/vite-plugin-svelte-inspector@5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)))(svelte@5.53.5)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))':
+ '@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))':
dependencies:
- '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))
+ '@sveltejs/vite-plugin-svelte-inspector': 5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
debug: 4.4.3
+ deepmerge: 4.3.1
+ magic-string: 0.30.21
svelte: 5.53.5
- vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
+ vite: 7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
+ vitefu: 1.1.1(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
transitivePeerDependencies:
- supports-color
- '@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))':
+ '@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))':
dependencies:
- '@sveltejs/vite-plugin-svelte-inspector': 5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)))(svelte@5.53.5)(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))
+ '@sveltejs/vite-plugin-svelte-inspector': 5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))(svelte@5.53.5)(vite@7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
debug: 4.4.3
deepmerge: 4.3.1
magic-string: 0.30.21
svelte: 5.53.5
- vite: 7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
- vitefu: 1.1.1(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))
+ vite: 7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
+ vitefu: 1.1.1(vite@7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
transitivePeerDependencies:
- supports-color
+ optional: true
- '@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))':
+ '@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))':
dependencies:
- '@sveltejs/vite-plugin-svelte-inspector': 5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)))(svelte@5.53.5)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))
+ '@sveltejs/vite-plugin-svelte-inspector': 5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))(svelte@5.53.5)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
debug: 4.4.3
deepmerge: 4.3.1
magic-string: 0.30.21
svelte: 5.53.5
- vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
- vitefu: 1.1.1(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))
+ vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
+ vitefu: 1.1.1(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
transitivePeerDependencies:
- supports-color
@@ -11812,19 +12291,19 @@ snapshots:
postcss: 8.5.6
tailwindcss: 4.1.16
- '@tailwindcss/vite@4.1.18(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))':
+ '@tailwindcss/vite@4.1.18(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))':
dependencies:
'@tailwindcss/node': 4.1.18
'@tailwindcss/oxide': 4.1.18
tailwindcss: 4.1.18
- vite: 7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
+ vite: 7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
- '@tailwindcss/vite@4.1.18(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))':
+ '@tailwindcss/vite@4.1.18(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))':
dependencies:
'@tailwindcss/node': 4.1.18
'@tailwindcss/oxide': 4.1.18
tailwindcss: 4.1.18
- vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
+ vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
'@tanstack/match-sorter-utils@8.19.4':
dependencies:
@@ -11892,7 +12371,7 @@ snapshots:
'@types/better-sqlite3@7.6.13':
dependencies:
- '@types/node': 20.19.24
+ '@types/node': 25.5.2
'@types/body-parser@1.19.6':
dependencies:
@@ -11913,7 +12392,7 @@ snapshots:
'@types/cors@2.8.19':
dependencies:
- '@types/node': 20.19.24
+ '@types/node': 25.5.2
'@types/deep-eql@4.0.2': {}
@@ -11968,7 +12447,7 @@ snapshots:
'@types/pg@8.16.0':
dependencies:
- '@types/node': 20.19.24
+ '@types/node': 25.5.2
pg-protocol: 1.10.3
pg-types: 2.2.0
@@ -12311,43 +12790,43 @@ snapshots:
- rollup
- supports-color
- '@vitejs/plugin-vue-jsx@5.1.4(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))':
+ '@vitejs/plugin-vue-jsx@5.1.4(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))':
dependencies:
'@babel/core': 7.29.0
'@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0)
'@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.29.0)
'@rolldown/pluginutils': 1.0.0-rc.5
'@vue/babel-plugin-jsx': 2.0.1(@babel/core@7.29.0)
- vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
+ vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
vue: 3.5.29(typescript@5.9.3)
transitivePeerDependencies:
- supports-color
- '@vitejs/plugin-vue-jsx@5.1.4(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue@3.5.29(typescript@6.0.3))':
+ '@vitejs/plugin-vue-jsx@5.1.4(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue@3.5.29(typescript@6.0.3))':
dependencies:
'@babel/core': 7.29.0
'@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0)
'@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.29.0)
'@rolldown/pluginutils': 1.0.0-rc.5
'@vue/babel-plugin-jsx': 2.0.1(@babel/core@7.29.0)
- vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
+ vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
vue: 3.5.29(typescript@6.0.3)
transitivePeerDependencies:
- supports-color
- '@vitejs/plugin-vue@6.0.4(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))':
+ '@vitejs/plugin-vue@6.0.4(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))':
dependencies:
'@rolldown/pluginutils': 1.0.0-rc.2
- vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
+ vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
vue: 3.5.29(typescript@5.9.3)
- '@vitejs/plugin-vue@6.0.4(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue@3.5.29(typescript@6.0.3))':
+ '@vitejs/plugin-vue@6.0.4(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue@3.5.29(typescript@6.0.3))':
dependencies:
'@rolldown/pluginutils': 1.0.0-rc.2
- vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
+ vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
vue: 3.5.29(typescript@6.0.3)
- '@vitest/coverage-v8@4.0.16(vitest@4.0.14(@edge-runtime/vm@5.0.0)(@types/node@20.19.24)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0))':
+ '@vitest/coverage-v8@4.0.16(vitest@4.0.14(@edge-runtime/vm@5.0.0)(@types/node@20.19.24)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.0))':
dependencies:
'@bcoe/v8-coverage': 1.0.2
'@vitest/utils': 4.0.16
@@ -12360,7 +12839,7 @@ snapshots:
obug: 2.1.1
std-env: 3.10.0
tinyrainbow: 3.0.3
- vitest: 4.0.14(@edge-runtime/vm@5.0.0)(@types/node@20.19.24)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0)
+ vitest: 4.0.14(@edge-runtime/vm@5.0.0)(@types/node@20.19.24)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.0)
transitivePeerDependencies:
- supports-color
@@ -12373,21 +12852,30 @@ snapshots:
chai: 6.2.1
tinyrainbow: 3.0.3
- '@vitest/mocker@4.0.14(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0))':
+ '@vitest/mocker@4.0.14(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.0))':
+ dependencies:
+ '@vitest/spy': 4.0.14
+ estree-walker: 3.0.3
+ magic-string: 0.30.21
+ optionalDependencies:
+ vite: 7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.0)
+
+ '@vitest/mocker@4.0.14(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))':
dependencies:
'@vitest/spy': 4.0.14
estree-walker: 3.0.3
magic-string: 0.30.21
optionalDependencies:
- vite: 7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0)
+ vite: 7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
+ optional: true
- '@vitest/mocker@4.0.14(vite@7.3.0(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))':
+ '@vitest/mocker@4.0.14(vite@7.3.0(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))':
dependencies:
'@vitest/spy': 4.0.14
estree-walker: 3.0.3
magic-string: 0.30.21
optionalDependencies:
- vite: 7.3.0(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
+ vite: 7.3.0(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
optional: true
'@vitest/pretty-format@4.0.14':
@@ -12574,26 +13062,26 @@ snapshots:
'@vue/devtools-api@6.6.4': {}
- '@vue/devtools-core@8.0.5(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))':
+ '@vue/devtools-core@8.0.5(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))':
dependencies:
'@vue/devtools-kit': 8.0.5
'@vue/devtools-shared': 8.0.5
mitt: 3.0.1
nanoid: 5.1.6
pathe: 2.0.3
- vite-hot-client: 2.1.0(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))
+ vite-hot-client: 2.1.0(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
vue: 3.5.29(typescript@5.9.3)
transitivePeerDependencies:
- vite
- '@vue/devtools-core@8.0.5(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue@3.5.29(typescript@6.0.3))':
+ '@vue/devtools-core@8.0.5(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue@3.5.29(typescript@6.0.3))':
dependencies:
'@vue/devtools-kit': 8.0.5
'@vue/devtools-shared': 8.0.5
mitt: 3.0.1
nanoid: 5.1.6
pathe: 2.0.3
- vite-hot-client: 2.1.0(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))
+ vite-hot-client: 2.1.0(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
vue: 3.5.29(typescript@6.0.3)
transitivePeerDependencies:
- vite
@@ -12766,7 +13254,7 @@ snapshots:
graceful-fs: 4.2.11
is-stream: 2.0.1
lazystream: 1.0.1
- lodash: 4.17.23
+ lodash: 4.18.1
normalize-path: 3.0.0
readable-stream: 4.7.0
@@ -12934,10 +13422,10 @@ snapshots:
baseline-browser-mapping@2.9.11: {}
- better-auth@1.4.19(1495ef1d827113360533150571904e77):
+ better-auth@1.4.19(aa46c218c2111ba42e6bbb995c1cdf9e):
dependencies:
'@better-auth/core': 1.4.19(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.2)(kysely@0.28.16)(nanostores@1.0.1)
- '@better-auth/telemetry': 1.4.19(@better-auth/core@1.4.19(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.2)(kysely@0.29.0)(nanostores@1.0.1))
+ '@better-auth/telemetry': 1.4.19(@better-auth/core@1.4.19(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0))
'@better-auth/utils': 0.3.0
'@better-fetch/fetch': 1.1.21
'@noble/ciphers': 2.0.1
@@ -12950,7 +13438,70 @@ snapshots:
zod: 4.3.6
optionalDependencies:
'@prisma/client': 5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))
- '@sveltejs/kit': 2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))
+ '@sveltejs/kit': 2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
+ better-sqlite3: 12.5.0
+ drizzle-orm: 0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))(sql.js@1.13.0)
+ mysql2: 3.16.1
+ next: 16.1.6(@babel/core@7.29.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
+ pg: 8.16.3
+ prisma: 6.19.0(magicast@0.5.1)(typescript@5.9.3)
+ react: 19.2.0
+ react-dom: 19.2.0(react@19.2.0)
+ svelte: 5.53.5
+ vitest: 4.0.14(@edge-runtime/vm@5.0.0)(@types/node@25.5.2)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
+ vue: 3.5.29(typescript@5.9.3)
+
+ better-auth@1.4.21(261c4d1149703dc38709f1a99ea83b5c):
+ dependencies:
+ '@better-auth/core': 1.4.19(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.2.3)(kysely@0.28.16)(nanostores@1.3.0)
+ '@better-auth/telemetry': 1.4.21(@better-auth/core@1.4.19(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0))
+ '@better-auth/utils': 0.3.0
+ '@better-fetch/fetch': 1.1.21
+ '@noble/ciphers': 2.2.0
+ '@noble/hashes': 2.0.1
+ better-call: 1.1.8(zod@4.3.6)
+ defu: 6.1.7
+ jose: 6.2.3
+ kysely: 0.28.16
+ nanostores: 1.3.0
+ zod: 4.3.6
+ optionalDependencies:
+ '@prisma/client': 5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))
+ '@sveltejs/kit': 2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
+ better-sqlite3: 12.5.0
+ drizzle-orm: 0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))(sql.js@1.13.0)
+ mysql2: 3.16.1
+ next: 16.1.6(@babel/core@7.29.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)
+ pg: 8.16.3
+ prisma: 6.19.0(magicast@0.5.1)(typescript@5.9.3)
+ react: 19.2.0
+ react-dom: 19.2.0(react@19.2.0)
+ svelte: 5.53.5
+ vitest: 4.0.14(@edge-runtime/vm@5.0.0)(@types/node@20.19.24)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
+ vue: 3.5.29(typescript@5.9.3)
+
+ better-auth@1.6.15(261c4d1149703dc38709f1a99ea83b5c):
+ dependencies:
+ '@better-auth/core': 1.4.19(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0)
+ '@better-auth/drizzle-adapter': 1.6.15(@better-auth/core@1.4.19(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0))(@better-auth/utils@0.4.1)(drizzle-orm@0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))(sql.js@1.13.0))
+ '@better-auth/kysely-adapter': 1.6.15(@better-auth/core@1.4.19(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0))(@better-auth/utils@0.4.1)(kysely@0.29.0)
+ '@better-auth/memory-adapter': 1.6.15(@better-auth/core@1.4.19(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0))(@better-auth/utils@0.4.1)
+ '@better-auth/mongo-adapter': 1.6.15(@better-auth/core@1.4.19(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0))(@better-auth/utils@0.4.1)
+ '@better-auth/prisma-adapter': 1.6.15(@better-auth/core@1.4.19(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0))(@better-auth/utils@0.4.1)(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3)))(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))
+ '@better-auth/telemetry': 1.6.15(@better-auth/core@1.4.19(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)(better-call@1.3.5(zod@4.3.6))(jose@6.2.3)(kysely@0.29.0)(nanostores@1.3.0))(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.1.21)
+ '@better-auth/utils': 0.4.1
+ '@better-fetch/fetch': 1.1.21
+ '@noble/ciphers': 2.2.0
+ '@noble/hashes': 2.0.1
+ better-call: 1.3.5(zod@4.3.6)
+ defu: 6.1.7
+ jose: 6.2.3
+ kysely: 0.29.0
+ nanostores: 1.3.0
+ zod: 4.3.6
+ optionalDependencies:
+ '@prisma/client': 5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))
+ '@sveltejs/kit': 2.53.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.53.5)(vite@7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)))(svelte@5.53.5)(typescript@5.9.3)(vite@7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
better-sqlite3: 12.5.0
drizzle-orm: 0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))(sql.js@1.13.0)
mysql2: 3.16.1
@@ -12960,7 +13511,7 @@ snapshots:
react: 19.2.0
react-dom: 19.2.0(react@19.2.0)
svelte: 5.53.5
- vitest: 4.0.14(@edge-runtime/vm@5.0.0)(@types/node@25.5.2)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
+ vitest: 4.0.14(@edge-runtime/vm@5.0.0)(@types/node@20.19.24)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
vue: 3.5.29(typescript@5.9.3)
better-call@1.1.8(zod@4.3.6):
@@ -12972,6 +13523,15 @@ snapshots:
optionalDependencies:
zod: 4.3.6
+ better-call@1.3.5(zod@4.3.6):
+ dependencies:
+ '@better-auth/utils': 0.4.1
+ '@better-fetch/fetch': 1.1.21
+ rou3: 0.7.12
+ set-cookie-parser: 3.0.1
+ optionalDependencies:
+ zod: 4.3.6
+
better-sqlite3@12.5.0:
dependencies:
bindings: 1.5.0
@@ -13073,7 +13633,7 @@ snapshots:
dependencies:
chokidar: 4.0.3
confbox: 0.2.2
- defu: 6.1.4
+ defu: 6.1.7
dotenv: 16.6.1
exsolve: 1.0.7
giget: 2.0.0
@@ -13090,7 +13650,7 @@ snapshots:
dependencies:
chokidar: 4.0.3
confbox: 0.2.2
- defu: 6.1.4
+ defu: 6.1.7
dotenv: 16.6.1
exsolve: 1.0.7
giget: 2.0.0
@@ -13107,15 +13667,15 @@ snapshots:
c12@3.3.3(magicast@0.5.1):
dependencies:
chokidar: 5.0.0
- confbox: 0.2.2
- defu: 6.1.4
+ confbox: 0.2.4
+ defu: 6.1.7
dotenv: 17.2.3
exsolve: 1.0.8
giget: 2.0.0
jiti: 2.6.1
ohash: 2.0.11
pathe: 2.0.3
- perfect-debounce: 2.0.0
+ perfect-debounce: 2.1.0
pkg-types: 2.3.0
rc9: 2.1.2
optionalDependencies:
@@ -13168,14 +13728,12 @@ snapshots:
ansi-styles: 4.3.0
supports-color: 7.2.0
- chalk@5.3.0: {}
-
chalk@5.6.2: {}
- chevrotain-allstar@0.3.1(chevrotain@11.0.3):
+ chevrotain-allstar@0.4.3(chevrotain@12.0.0):
dependencies:
- chevrotain: 11.0.3
- lodash-es: 4.17.23
+ chevrotain: 12.0.0
+ lodash-es: 4.18.1
chevrotain@10.5.0:
dependencies:
@@ -13183,17 +13741,16 @@ snapshots:
'@chevrotain/gast': 10.5.0
'@chevrotain/types': 10.5.0
'@chevrotain/utils': 10.5.0
- lodash: 4.17.23
+ lodash: 4.18.1
regexp-to-ast: 0.5.0
- chevrotain@11.0.3:
+ chevrotain@12.0.0:
dependencies:
- '@chevrotain/cst-dts-gen': 11.0.3
- '@chevrotain/gast': 11.0.3
- '@chevrotain/regexp-to-ast': 11.0.3
- '@chevrotain/types': 11.0.3
- '@chevrotain/utils': 11.0.3
- lodash-es: 4.17.23
+ '@chevrotain/cst-dts-gen': 12.0.0
+ '@chevrotain/gast': 12.0.0
+ '@chevrotain/regexp-to-ast': 12.0.0
+ '@chevrotain/types': 12.0.0
+ '@chevrotain/utils': 12.0.0
chokidar@4.0.3:
dependencies:
@@ -13259,12 +13816,12 @@ snapshots:
dependencies:
delayed-stream: 1.0.0
- commander@11.0.0: {}
-
commander@11.1.0: {}
commander@12.1.0: {}
+ commander@14.0.3: {}
+
commander@2.20.3: {}
commander@8.3.0: {}
@@ -13804,34 +14361,6 @@ snapshots:
is-date-object: 1.1.0
is-symbol: 1.1.1
- esbuild@0.25.5:
- optionalDependencies:
- '@esbuild/aix-ppc64': 0.25.5
- '@esbuild/android-arm': 0.25.5
- '@esbuild/android-arm64': 0.25.5
- '@esbuild/android-x64': 0.25.5
- '@esbuild/darwin-arm64': 0.25.5
- '@esbuild/darwin-x64': 0.25.5
- '@esbuild/freebsd-arm64': 0.25.5
- '@esbuild/freebsd-x64': 0.25.5
- '@esbuild/linux-arm': 0.25.5
- '@esbuild/linux-arm64': 0.25.5
- '@esbuild/linux-ia32': 0.25.5
- '@esbuild/linux-loong64': 0.25.5
- '@esbuild/linux-mips64el': 0.25.5
- '@esbuild/linux-ppc64': 0.25.5
- '@esbuild/linux-riscv64': 0.25.5
- '@esbuild/linux-s390x': 0.25.5
- '@esbuild/linux-x64': 0.25.5
- '@esbuild/netbsd-arm64': 0.25.5
- '@esbuild/netbsd-x64': 0.25.5
- '@esbuild/openbsd-arm64': 0.25.5
- '@esbuild/openbsd-x64': 0.25.5
- '@esbuild/sunos-x64': 0.25.5
- '@esbuild/win32-arm64': 0.25.5
- '@esbuild/win32-ia32': 0.25.5
- '@esbuild/win32-x64': 0.25.5
-
esbuild@0.27.2:
optionalDependencies:
'@esbuild/aix-ppc64': 0.27.2
@@ -13890,6 +14419,35 @@ snapshots:
'@esbuild/win32-ia32': 0.27.3
'@esbuild/win32-x64': 0.27.3
+ esbuild@0.28.0:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.28.0
+ '@esbuild/android-arm': 0.28.0
+ '@esbuild/android-arm64': 0.28.0
+ '@esbuild/android-x64': 0.28.0
+ '@esbuild/darwin-arm64': 0.28.0
+ '@esbuild/darwin-x64': 0.28.0
+ '@esbuild/freebsd-arm64': 0.28.0
+ '@esbuild/freebsd-x64': 0.28.0
+ '@esbuild/linux-arm': 0.28.0
+ '@esbuild/linux-arm64': 0.28.0
+ '@esbuild/linux-ia32': 0.28.0
+ '@esbuild/linux-loong64': 0.28.0
+ '@esbuild/linux-mips64el': 0.28.0
+ '@esbuild/linux-ppc64': 0.28.0
+ '@esbuild/linux-riscv64': 0.28.0
+ '@esbuild/linux-s390x': 0.28.0
+ '@esbuild/linux-x64': 0.28.0
+ '@esbuild/netbsd-arm64': 0.28.0
+ '@esbuild/netbsd-x64': 0.28.0
+ '@esbuild/openbsd-arm64': 0.28.0
+ '@esbuild/openbsd-x64': 0.28.0
+ '@esbuild/openharmony-arm64': 0.28.0
+ '@esbuild/sunos-x64': 0.28.0
+ '@esbuild/win32-arm64': 0.28.0
+ '@esbuild/win32-ia32': 0.28.0
+ '@esbuild/win32-x64': 0.28.0
+
escalade@3.2.0: {}
escape-html@1.0.3: {}
@@ -14365,7 +14923,7 @@ snapshots:
fs-constants@1.0.0: {}
- fs-extra@11.1.1:
+ fs-extra@11.3.5:
dependencies:
graceful-fs: 4.2.11
jsonfile: 6.1.0
@@ -14446,7 +15004,7 @@ snapshots:
dependencies:
citty: 0.1.6
consola: 3.4.2
- defu: 6.1.4
+ defu: 6.1.7
node-fetch-native: 1.6.7
nypm: 0.6.2
pathe: 2.0.3
@@ -14930,6 +15488,8 @@ snapshots:
jose@6.1.2: {}
+ jose@6.2.3: {}
+
js-tokens@4.0.0: {}
js-tokens@9.0.1: {}
@@ -15008,7 +15568,7 @@ snapshots:
jsonpointer@5.0.1: {}
- jsonschema@1.4.1: {}
+ jsonschema@1.5.0: {}
jsx-ast-utils@3.3.5:
dependencies:
@@ -15038,28 +15598,32 @@ snapshots:
kysely@0.29.0: {}
- langium-cli@3.5.0:
+ langium-cli@4.2.1:
dependencies:
- chalk: 5.3.0
- commander: 11.0.0
- fs-extra: 11.1.1
- jsonschema: 1.4.1
- langium: 3.5.0
- langium-railroad: 3.5.0
- lodash: 4.17.23
+ chalk: 5.6.2
+ commander: 14.0.3
+ fs-extra: 11.3.5
+ jsonschema: 1.5.0
+ langium: 4.2.4
+ langium-railroad: 4.2.0
+ lodash: 4.18.1
- langium-railroad@3.5.0:
+ langium-railroad@4.2.0:
dependencies:
- langium: 3.5.0
+ langium: 4.2.4
railroad-diagrams: 1.0.0
- langium@3.5.0:
+ langium@4.2.4:
dependencies:
- chevrotain: 11.0.3
- chevrotain-allstar: 0.3.1(chevrotain@11.0.3)
+ '@chevrotain/regexp-to-ast': 12.0.0
+ chevrotain: 12.0.0
+ chevrotain-allstar: 0.4.3(chevrotain@12.0.0)
+ vscode-jsonrpc: 8.2.0
vscode-languageserver: 9.0.1
+ vscode-languageserver-protocol: 3.17.5
vscode-languageserver-textdocument: 1.0.12
- vscode-uri: 3.0.8
+ vscode-languageserver-types: 3.17.5
+ vscode-uri: 3.1.0
language-subtag-registry@0.3.23: {}
@@ -15150,7 +15714,7 @@ snapshots:
clipboardy: 4.0.0
consola: 3.4.2
crossws: 0.3.5
- defu: 6.1.4
+ defu: 6.1.7
get-port-please: 3.2.0
h3: 1.15.5
http-shutdown: 1.2.2
@@ -15182,7 +15746,7 @@ snapshots:
dependencies:
p-locate: 5.0.0
- lodash-es@4.17.23: {}
+ lodash-es@4.18.1: {}
lodash.defaults@4.2.0: {}
@@ -15194,7 +15758,7 @@ snapshots:
lodash.uniq@4.5.0: {}
- lodash@4.17.23: {}
+ lodash@4.18.1: {}
log-symbols@4.1.0:
dependencies:
@@ -15396,6 +15960,8 @@ snapshots:
nanostores@1.0.1: {}
+ nanostores@1.3.0: {}
+
nanotar@0.2.0: {}
napi-build-utils@2.0.0: {}
@@ -15478,10 +16044,10 @@ snapshots:
croner: 9.1.0
crossws: 0.3.5
db0: 0.3.4(better-sqlite3@12.5.0)(drizzle-orm@0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))(sql.js@1.13.0))(mysql2@3.16.1)
- defu: 6.1.4
+ defu: 6.1.7
destr: 2.0.5
dot-prop: 10.1.0
- esbuild: 0.27.2
+ esbuild: 0.27.3
escape-string-regexp: 5.0.0
etag: 1.8.1
exsolve: 1.0.8
@@ -15580,10 +16146,10 @@ snapshots:
croner: 9.1.0
crossws: 0.3.5
db0: 0.3.4(better-sqlite3@12.5.0)(drizzle-orm@0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@6.0.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@6.0.3))(sql.js@1.13.0))(mysql2@3.16.1)
- defu: 6.1.4
+ defu: 6.1.7
destr: 2.0.5
dot-prop: 10.1.0
- esbuild: 0.27.2
+ esbuild: 0.27.3
escape-string-regexp: 5.0.0
etag: 1.8.1
exsolve: 1.0.8
@@ -15724,16 +16290,16 @@ snapshots:
dependencies:
boolbase: 1.0.0
- nuxt@4.3.1(20bb9c9cac3d4d3ad27d57e07c1eb4f2):
+ nuxt@4.3.1(526b065509e6a4d54781a1030a9e863f):
dependencies:
'@dxup/nuxt': 0.3.2(magicast@0.5.1)
'@nuxt/cli': 3.33.1(@nuxt/schema@4.3.1)(cac@6.7.14)(magicast@0.5.1)
- '@nuxt/devtools': 3.1.1(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))
+ '@nuxt/devtools': 3.1.1(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3))
'@nuxt/kit': 4.3.1(magicast@0.5.1)
- '@nuxt/nitro-server': 4.3.1(better-sqlite3@12.5.0)(db0@0.3.4(better-sqlite3@12.5.0)(drizzle-orm@0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))(sql.js@1.13.0))(mysql2@3.16.1))(drizzle-orm@0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))(sql.js@1.13.0))(ioredis@5.9.3)(magicast@0.5.1)(mysql2@3.16.1)(nuxt@4.3.1(20bb9c9cac3d4d3ad27d57e07c1eb4f2))(rolldown@1.0.0-rc.15)(typescript@5.9.3)
+ '@nuxt/nitro-server': 4.3.1(better-sqlite3@12.5.0)(db0@0.3.4(better-sqlite3@12.5.0)(drizzle-orm@0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))(sql.js@1.13.0))(mysql2@3.16.1))(drizzle-orm@0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@5.9.3))(sql.js@1.13.0))(ioredis@5.9.3)(magicast@0.5.1)(mysql2@3.16.1)(nuxt@4.3.1(526b065509e6a4d54781a1030a9e863f))(rolldown@1.0.0-rc.15)(typescript@5.9.3)
'@nuxt/schema': 4.3.1
'@nuxt/telemetry': 2.7.0(@nuxt/kit@4.3.1(magicast@0.5.1))
- '@nuxt/vite-builder': 4.3.1(@types/node@25.5.2)(eslint@9.29.0(jiti@2.6.1))(lightningcss@1.30.2)(magicast@0.5.1)(nuxt@4.3.1(20bb9c9cac3d4d3ad27d57e07c1eb4f2))(optionator@0.9.4)(rolldown@1.0.0-rc.15)(rollup@4.59.0)(terser@5.44.0)(tsx@4.20.3)(typescript@5.9.3)(vue-tsc@3.2.5(typescript@5.9.3))(vue@3.5.29(typescript@5.9.3))(yaml@2.8.2)
+ '@nuxt/vite-builder': 4.3.1(@types/node@25.5.2)(eslint@9.29.0(jiti@2.6.1))(lightningcss@1.30.2)(magicast@0.5.1)(nuxt@4.3.1(526b065509e6a4d54781a1030a9e863f))(optionator@0.9.4)(rolldown@1.0.0-rc.15)(rollup@4.59.0)(terser@5.44.0)(tsx@4.22.4)(typescript@5.9.3)(vue-tsc@3.2.5(typescript@5.9.3))(vue@3.5.29(typescript@5.9.3))(yaml@2.8.2)
'@unhead/vue': 2.1.7(vue@3.5.29(typescript@5.9.3))
'@vue/shared': 3.5.29
c12: 3.3.3(magicast@0.5.1)
@@ -15847,16 +16413,16 @@ snapshots:
- xml2js
- yaml
- nuxt@4.3.1(f6c7dcf4eb9de64f6cb5e0db74766190):
+ nuxt@4.3.1(95266d6f061a460ce208abe1df07947b):
dependencies:
'@dxup/nuxt': 0.3.2(magicast@0.5.1)
'@nuxt/cli': 3.33.1(@nuxt/schema@4.3.1)(cac@6.7.14)(magicast@0.5.1)
- '@nuxt/devtools': 3.1.1(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue@3.5.29(typescript@6.0.3))
+ '@nuxt/devtools': 3.1.1(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue@3.5.29(typescript@6.0.3))
'@nuxt/kit': 4.3.1(magicast@0.5.1)
- '@nuxt/nitro-server': 4.3.1(better-sqlite3@12.5.0)(db0@0.3.4(better-sqlite3@12.5.0)(drizzle-orm@0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@6.0.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@6.0.3))(sql.js@1.13.0))(mysql2@3.16.1))(drizzle-orm@0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@6.0.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@6.0.3))(sql.js@1.13.0))(ioredis@5.9.3)(magicast@0.5.1)(mysql2@3.16.1)(nuxt@4.3.1(f6c7dcf4eb9de64f6cb5e0db74766190))(rolldown@1.0.0-rc.15)(typescript@6.0.3)
+ '@nuxt/nitro-server': 4.3.1(better-sqlite3@12.5.0)(db0@0.3.4(better-sqlite3@12.5.0)(drizzle-orm@0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@6.0.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@6.0.3))(sql.js@1.13.0))(mysql2@3.16.1))(drizzle-orm@0.41.0(@prisma/client@5.22.0(prisma@6.19.0(magicast@0.5.1)(typescript@6.0.3)))(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.5.0)(bun-types@1.3.3)(kysely@0.29.0)(mysql2@3.16.1)(pg@8.16.3)(prisma@6.19.0(magicast@0.5.1)(typescript@6.0.3))(sql.js@1.13.0))(ioredis@5.9.3)(magicast@0.5.1)(mysql2@3.16.1)(nuxt@4.3.1(95266d6f061a460ce208abe1df07947b))(rolldown@1.0.0-rc.15)(typescript@6.0.3)
'@nuxt/schema': 4.3.1
'@nuxt/telemetry': 2.7.0(@nuxt/kit@4.3.1(magicast@0.5.1))
- '@nuxt/vite-builder': 4.3.1(@types/node@25.5.2)(eslint@9.29.0(jiti@2.6.1))(lightningcss@1.30.2)(magicast@0.5.1)(nuxt@4.3.1(f6c7dcf4eb9de64f6cb5e0db74766190))(optionator@0.9.4)(rolldown@1.0.0-rc.15)(rollup@4.59.0)(terser@5.44.0)(tsx@4.20.3)(typescript@6.0.3)(vue-tsc@3.2.5(typescript@6.0.3))(vue@3.5.29(typescript@6.0.3))(yaml@2.8.2)
+ '@nuxt/vite-builder': 4.3.1(@types/node@25.5.2)(eslint@9.29.0(jiti@2.6.1))(lightningcss@1.30.2)(magicast@0.5.1)(nuxt@4.3.1(95266d6f061a460ce208abe1df07947b))(optionator@0.9.4)(rolldown@1.0.0-rc.15)(rollup@4.59.0)(terser@5.44.0)(tsx@4.22.4)(typescript@6.0.3)(vue-tsc@3.2.5(typescript@6.0.3))(vue@3.5.29(typescript@6.0.3))(yaml@2.8.2)
'@unhead/vue': 2.1.7(vue@3.5.29(typescript@6.0.3))
'@vue/shared': 3.5.29
c12: 3.3.3(magicast@0.5.1)
@@ -16249,8 +16815,6 @@ snapshots:
perfect-debounce@1.0.0: {}
- perfect-debounce@2.0.0: {}
-
perfect-debounce@2.1.0: {}
pg-cloudflare@1.2.7:
@@ -16670,12 +17234,12 @@ snapshots:
rc9@2.1.2:
dependencies:
- defu: 6.1.4
+ defu: 6.1.7
destr: 2.0.5
rc9@3.0.0:
dependencies:
- defu: 6.1.4
+ defu: 6.1.7
destr: 2.0.5
rc@1.2.8:
@@ -16989,7 +17553,7 @@ snapshots:
serve-placeholder@2.0.2:
dependencies:
- defu: 6.1.4
+ defu: 6.1.7
serve-static@2.2.0:
dependencies:
@@ -17598,10 +18162,9 @@ snapshots:
tslib@2.8.1: {}
- tsx@4.20.3:
+ tsx@4.22.4:
dependencies:
- esbuild: 0.25.5
- get-tsconfig: 4.10.1
+ esbuild: 0.28.0
optionalDependencies:
fsevents: 2.3.3
@@ -17963,23 +18526,23 @@ snapshots:
vary@1.1.2: {}
- vite-dev-rpc@1.1.0(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)):
+ vite-dev-rpc@1.1.0(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)):
dependencies:
birpc: 2.9.0
- vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
- vite-hot-client: 2.1.0(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))
+ vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
+ vite-hot-client: 2.1.0(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
- vite-hot-client@2.1.0(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)):
+ vite-hot-client@2.1.0(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)):
dependencies:
- vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
+ vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
- vite-node@5.3.0(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2):
+ vite-node@5.3.0(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2):
dependencies:
cac: 6.7.14
es-module-lexer: 2.0.0
obug: 2.1.1
pathe: 2.0.3
- vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
+ vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
transitivePeerDependencies:
- '@types/node'
- jiti
@@ -17993,7 +18556,7 @@ snapshots:
- tsx
- yaml
- vite-plugin-checker@0.12.0(eslint@9.29.0(jiti@2.6.1))(optionator@0.9.4)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue-tsc@3.2.5(typescript@5.9.3)):
+ vite-plugin-checker@0.12.0(eslint@9.29.0(jiti@2.6.1))(optionator@0.9.4)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue-tsc@3.2.5(typescript@5.9.3)):
dependencies:
'@babel/code-frame': 7.28.6
chokidar: 4.0.3
@@ -18002,7 +18565,7 @@ snapshots:
picomatch: 4.0.3
tiny-invariant: 1.3.3
tinyglobby: 0.2.15
- vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
+ vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
vscode-uri: 3.1.0
optionalDependencies:
eslint: 9.29.0(jiti@2.6.1)
@@ -18010,7 +18573,7 @@ snapshots:
typescript: 5.9.3
vue-tsc: 3.2.5(typescript@5.9.3)
- vite-plugin-checker@0.12.0(eslint@9.29.0(jiti@2.6.1))(optionator@0.9.4)(typescript@6.0.3)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue-tsc@3.2.5(typescript@6.0.3)):
+ vite-plugin-checker@0.12.0(eslint@9.29.0(jiti@2.6.1))(optionator@0.9.4)(typescript@6.0.3)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue-tsc@3.2.5(typescript@6.0.3)):
dependencies:
'@babel/code-frame': 7.28.6
chokidar: 4.0.3
@@ -18019,7 +18582,7 @@ snapshots:
picomatch: 4.0.3
tiny-invariant: 1.3.3
tinyglobby: 0.2.15
- vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
+ vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
vscode-uri: 3.1.0
optionalDependencies:
eslint: 9.29.0(jiti@2.6.1)
@@ -18027,7 +18590,7 @@ snapshots:
typescript: 6.0.3
vue-tsc: 3.2.5(typescript@6.0.3)
- vite-plugin-inspect@11.3.3(@nuxt/kit@4.3.1(magicast@0.5.1))(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)):
+ vite-plugin-inspect@11.3.3(@nuxt/kit@4.3.1(magicast@0.5.1))(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)):
dependencies:
ansis: 4.2.0
debug: 4.4.3
@@ -18037,34 +18600,34 @@ snapshots:
perfect-debounce: 2.1.0
sirv: 3.0.2
unplugin-utils: 0.3.1
- vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
- vite-dev-rpc: 1.1.0(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))
+ vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
+ vite-dev-rpc: 1.1.0(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
optionalDependencies:
'@nuxt/kit': 4.3.1(magicast@0.5.1)
transitivePeerDependencies:
- supports-color
- vite-plugin-vue-tracer@1.2.0(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3)):
+ vite-plugin-vue-tracer@1.2.0(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue@3.5.29(typescript@5.9.3)):
dependencies:
estree-walker: 3.0.3
exsolve: 1.0.8
magic-string: 0.30.21
pathe: 2.0.3
source-map-js: 1.2.1
- vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
+ vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
vue: 3.5.29(typescript@5.9.3)
- vite-plugin-vue-tracer@1.2.0(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))(vue@3.5.29(typescript@6.0.3)):
+ vite-plugin-vue-tracer@1.2.0(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))(vue@3.5.29(typescript@6.0.3)):
dependencies:
estree-walker: 3.0.3
exsolve: 1.0.8
magic-string: 0.30.21
pathe: 2.0.3
source-map-js: 1.2.1
- vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
+ vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
vue: 3.5.29(typescript@6.0.3)
- vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0):
+ vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.0):
dependencies:
esbuild: 0.27.2
fdir: 6.5.0(picomatch@4.0.3)
@@ -18078,10 +18641,10 @@ snapshots:
jiti: 2.6.1
lightningcss: 1.30.2
terser: 5.44.0
- tsx: 4.20.3
+ tsx: 4.22.4
yaml: 2.8.0
- vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2):
+ vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2):
dependencies:
esbuild: 0.27.2
fdir: 6.5.0(picomatch@4.0.3)
@@ -18095,10 +18658,10 @@ snapshots:
jiti: 2.6.1
lightningcss: 1.30.2
terser: 5.44.0
- tsx: 4.20.3
+ tsx: 4.22.4
yaml: 2.8.2
- vite@7.3.0(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2):
+ vite@7.3.0(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2):
dependencies:
esbuild: 0.27.2
fdir: 6.5.0(picomatch@4.0.3)
@@ -18112,11 +18675,29 @@ snapshots:
jiti: 2.6.1
lightningcss: 1.30.2
terser: 5.44.0
- tsx: 4.20.3
+ tsx: 4.22.4
+ yaml: 2.8.2
+ optional: true
+
+ vite@7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2):
+ dependencies:
+ esbuild: 0.27.3
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+ postcss: 8.5.6
+ rollup: 4.59.0
+ tinyglobby: 0.2.15
+ optionalDependencies:
+ '@types/node': 20.19.24
+ fsevents: 2.3.3
+ jiti: 2.6.1
+ lightningcss: 1.30.2
+ terser: 5.44.0
+ tsx: 4.22.4
yaml: 2.8.2
optional: true
- vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2):
+ vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2):
dependencies:
esbuild: 0.27.3
fdir: 6.5.0(picomatch@4.0.3)
@@ -18130,21 +18711,66 @@ snapshots:
jiti: 2.6.1
lightningcss: 1.30.2
terser: 5.44.0
- tsx: 4.20.3
+ tsx: 4.22.4
yaml: 2.8.2
- vitefu@1.1.1(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)):
+ vitefu@1.1.1(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)):
+ optionalDependencies:
+ vite: 7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
+
+ vitefu@1.1.1(vite@7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)):
optionalDependencies:
- vite: 7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
+ vite: 7.3.1(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
+ optional: true
+
+ vitefu@1.1.1(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)):
+ optionalDependencies:
+ vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
- vitefu@1.1.1(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)):
+ vitest@4.0.14(@edge-runtime/vm@5.0.0)(@types/node@20.19.24)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.0):
+ dependencies:
+ '@vitest/expect': 4.0.14
+ '@vitest/mocker': 4.0.14(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.0))
+ '@vitest/pretty-format': 4.0.14
+ '@vitest/runner': 4.0.14
+ '@vitest/snapshot': 4.0.14
+ '@vitest/spy': 4.0.14
+ '@vitest/utils': 4.0.14
+ es-module-lexer: 1.7.0
+ expect-type: 1.2.2
+ magic-string: 0.30.21
+ obug: 2.1.1
+ pathe: 2.0.3
+ picomatch: 4.0.3
+ std-env: 3.10.0
+ tinybench: 2.9.0
+ tinyexec: 0.3.2
+ tinyglobby: 0.2.15
+ tinyrainbow: 3.0.3
+ vite: 7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.0)
+ why-is-node-running: 2.3.0
optionalDependencies:
- vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
+ '@edge-runtime/vm': 5.0.0
+ '@types/node': 20.19.24
+ happy-dom: 20.8.9
+ jsdom: 27.1.0
+ transitivePeerDependencies:
+ - jiti
+ - less
+ - lightningcss
+ - msw
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - terser
+ - tsx
+ - yaml
- vitest@4.0.14(@edge-runtime/vm@5.0.0)(@types/node@20.19.24)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0):
+ vitest@4.0.14(@edge-runtime/vm@5.0.0)(@types/node@20.19.24)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2):
dependencies:
'@vitest/expect': 4.0.14
- '@vitest/mocker': 4.0.14(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0))
+ '@vitest/mocker': 4.0.14(vite@7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
'@vitest/pretty-format': 4.0.14
'@vitest/runner': 4.0.14
'@vitest/snapshot': 4.0.14
@@ -18161,7 +18787,7 @@ snapshots:
tinyexec: 0.3.2
tinyglobby: 0.2.15
tinyrainbow: 3.0.3
- vite: 7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0)
+ vite: 7.3.0(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
why-is-node-running: 2.3.0
optionalDependencies:
'@edge-runtime/vm': 5.0.0
@@ -18180,11 +18806,12 @@ snapshots:
- terser
- tsx
- yaml
+ optional: true
- vitest@4.0.14(@edge-runtime/vm@5.0.0)(@types/node@25.5.2)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2):
+ vitest@4.0.14(@edge-runtime/vm@5.0.0)(@types/node@25.5.2)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2):
dependencies:
'@vitest/expect': 4.0.14
- '@vitest/mocker': 4.0.14(vite@7.3.0(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2))
+ '@vitest/mocker': 4.0.14(vite@7.3.0(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2))
'@vitest/pretty-format': 4.0.14
'@vitest/runner': 4.0.14
'@vitest/snapshot': 4.0.14
@@ -18201,7 +18828,7 @@ snapshots:
tinyexec: 0.3.2
tinyglobby: 0.2.15
tinyrainbow: 3.0.3
- vite: 7.3.0(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.2)
+ vite: 7.3.0(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.22.4)(yaml@2.8.2)
why-is-node-running: 2.3.0
optionalDependencies:
'@edge-runtime/vm': 5.0.0
@@ -18243,8 +18870,6 @@ snapshots:
dependencies:
vscode-languageserver-protocol: 3.17.5
- vscode-uri@3.0.8: {}
-
vscode-uri@3.1.0: {}
vue-bundle-renderer@2.2.0:
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index 20e094cd8..f15d2e997 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -16,8 +16,8 @@ catalog:
better-sqlite3: ^12.5.0
decimal.js: ^10.4.3
kysely: ~0.29.0
- langium: 3.5.0
- langium-cli: 3.5.0
+ langium: 4.2.4
+ langium-cli: 4.2.1
next: 16.1.6
nuxt: 4.3.1
'@sveltejs/kit': 2.53.2
@@ -34,3 +34,4 @@ catalog:
vue: 3.5.22
zod: ^4.0.0
zod-validation-error: ^4.0.1
+ tsx: ^4.22.0
diff --git a/samples/orm/package.json b/samples/orm/package.json
index 0368c8902..f91960e54 100644
--- a/samples/orm/package.json
+++ b/samples/orm/package.json
@@ -1,6 +1,6 @@
{
"name": "sample-orm",
- "version": "3.7.2",
+ "version": "3.8.0",
"description": "",
"main": "index.js",
"private": true,
diff --git a/samples/sveltekit/package.json b/samples/sveltekit/package.json
index 0d1c56779..8782715b8 100644
--- a/samples/sveltekit/package.json
+++ b/samples/sveltekit/package.json
@@ -34,7 +34,7 @@
"svelte": "catalog:",
"svelte-check": "^4.3.4",
"tailwindcss": "^4.1.17",
- "tsx": "^4.19.2",
+ "tsx": "catalog:",
"typescript": "^5.9.3",
"vite": "^7.2.6"
},
diff --git a/samples/taskforge/README.md b/samples/taskforge/README.md
new file mode 100644
index 000000000..92fcffdbc
--- /dev/null
+++ b/samples/taskforge/README.md
@@ -0,0 +1,100 @@
+# TaskForge
+
+A command-line client for a **team collaboration / project-tracking** platform
+(think Linear/Jira), built to demonstrate a complete **[ZenStack v3](https://zenstack.dev)**
+(ORM) + **[Better-Auth](https://better-auth.com)** stack on top of SQLite.
+
+- **34 models** across tenancy, projects/issues, collaboration, automation and billing
+- Every relation flavour: 1-1, 1-many, implicit & explicit many-to-many, self-relations
+- **Polymorphism** (`@@delegate`), **typed JSON** (`@json`), **computed fields** (`@computed`),
+ reusable field **mixins** (`with`), and **enums**
+- Better-Auth wired to the ZenStack ORM via the official adapter (setup only — no HTTP flow)
+
+## Stack
+
+| Concern | Choice |
+| ------------ | ------------------------------------------------------ |
+| ORM / schema | ZenStack v3 (`@zenstackhq/orm`, ZModel schema) |
+| Database | SQLite (via `better-sqlite3`) — zero external services |
+| Auth | Better-Auth + `@zenstackhq/better-auth` adapter |
+| CLI | `commander`, run with `tsx` |
+
+## Quick start
+
+```bash
+pnpm install # native builds (better-sqlite3, prisma) are pre-approved in package.json
+pnpm zen:generate # compile zenstack/schema.zmodel -> zenstack/schema.ts (the typed client)
+pnpm db:push # create/sync the SQLite database (zenstack/taskforge.db)
+pnpm seed # populate a demo workspace (users via Better-Auth, domain via the ORM)
+pnpm cli orgs # try the CLI
+```
+
+## CLI commands
+
+```bash
+pnpm cli orgs # organizations + member/team/project counts
+pnpm cli projects [orgSlug] # projects + open-issue count (computed field)
+pnpm cli issues [--status S] # issues + comment count (computed field)
+pnpm cli issue