@supacloud/compiler 0.21.1 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -196,10 +196,24 @@ function renderApplication(graph, options) {
196
196
  ""
197
197
  ].join(`
198
198
  `);
199
+ const commandGovernance = graph.modules.flatMap((module) => module.commands.map((command) => ({
200
+ module: module.name,
201
+ className: command.className,
202
+ name: command.name,
203
+ permission: command.permission ?? null,
204
+ rpc: command.rpc ?? null,
205
+ transaction: command.transaction ?? null,
206
+ audit: command.audit ?? null,
207
+ idempotency: command.idempotency ?? null
208
+ }))).sort((left, right) => `${left.module}:${left.name}`.localeCompare(`${right.module}:${right.name}`));
199
209
  const manifest = {
200
210
  version: 1,
201
211
  modules: graph.modules,
202
- externalTokens: graph.externalTokens
212
+ externalTokens: graph.externalTokens,
213
+ commandGovernance: {
214
+ defaults: { authorization: "required", audit: "required", idempotency: "required", transaction: "required" },
215
+ commands: commandGovernance
216
+ }
203
217
  };
204
218
  const clientCode = options.generateClient ? renderClient(graph, options) : undefined;
205
219
  const openApiCode = options.generateOpenApi ? renderOpenApi(graph, options) : undefined;
@@ -354,7 +368,7 @@ class ModuleGenerator {
354
368
  this.imports = imports;
355
369
  this.pascal = pascalName(module.name);
356
370
  if (module.providers.some((provider) => (provider.functionalInjects?.length ?? 0) > 0) || module.controllers.some((controller) => (controller.functionalInjects?.length ?? 0) > 0)) {
357
- imports.add("runInInjectionContext", undefined, "@supacloud/app");
371
+ throw new Error("SC2012: Compiled DI requires constructor injection; property inject() is not supported.");
358
372
  }
359
373
  }
360
374
  renderFactories() {
@@ -388,6 +402,7 @@ class ModuleGenerator {
388
402
  lines.push(` jobs: ${this.renderJobs()},`);
389
403
  if (this.module.aspects && this.module.aspects.length > 0) {
390
404
  lines.push(` aspects: ${this.renderAspects(this.module.aspects)},`);
405
+ lines.push(` aspectPipeline: ${this.renderAspectPipeline(this.module.aspects)},`);
391
406
  }
392
407
  lines.push(`}`);
393
408
  return lines.join(`
@@ -464,6 +479,7 @@ class ModuleGenerator {
464
479
  }
465
480
  if (route.aspects && route.aspects.length > 0) {
466
481
  fields.push(`aspects: ${this.renderAspects(route.aspects)}`);
482
+ fields.push(`aspectPipeline: ${this.renderAspectPipeline(route.aspects)}`);
467
483
  }
468
484
  const invokerArgs = (route.handlerParams ?? []).map((hp) => {
469
485
  if (hp.kind === "param") {
@@ -544,7 +560,7 @@ ${indent(item, 2)}`).join(",")}
544
560
  `idempotency: ${JSON.stringify(command.idempotency)}`,
545
561
  ...command.rpc ? [`rpc: ${JSON.stringify(command.rpc)}`] : [],
546
562
  ...command.standalone ? ["standalone: true"] : [],
547
- ...command.aspects && command.aspects.length > 0 ? [`aspects: ${this.renderAspects(command.aspects)}`] : []
563
+ ...command.aspects && command.aspects.length > 0 ? [`aspects: ${this.renderAspects(command.aspects)}`, `aspectPipeline: ${this.renderAspectPipeline(command.aspects)}`] : []
548
564
  ];
549
565
  return `{ ${fields.join(", ")} }`;
550
566
  }).join(", ")}]`;
@@ -577,6 +593,7 @@ ${indent(item, 2)}`).join(",")}
577
593
  fields.push(`idempotency: ${JSON.stringify(job.idempotency)}`);
578
594
  if (job.aspects && job.aspects.length > 0) {
579
595
  fields.push(`aspects: ${this.renderAspects(job.aspects)}`);
596
+ fields.push(`aspectPipeline: ${this.renderAspectPipeline(job.aspects)}`);
580
597
  }
581
598
  return `{ ${fields.join(", ")}, }`;
582
599
  }).join(", ")}]`;
@@ -584,6 +601,24 @@ ${indent(item, 2)}`).join(",")}
584
601
  renderAspects(aspects) {
585
602
  return `[${aspects.map((aspect) => this.imports.add(aspect.name, aspect.importPath, aspect.importModule)).join(", ")}]`;
586
603
  }
604
+ renderAspectPipeline(aspects) {
605
+ const lines = [
606
+ `async (context, next, observe) => {`,
607
+ ` const state = { active: true };`,
608
+ ` const step${aspects.length} = compiledAspectNext(next, state);`
609
+ ];
610
+ for (let index = aspects.length - 1;index >= 0; index--) {
611
+ const aspect = aspects[index];
612
+ if (!aspect)
613
+ continue;
614
+ const name = this.imports.add(aspect.name, aspect.importPath, aspect.importModule);
615
+ const stage = JSON.stringify(`aspect[${index}]:${aspect.name}`);
616
+ lines.push(` const step${index} = compiledAspectNext(() => observeCompiledAspect(observe, ${stage}, () => ${name}(context, step${index + 1})), state);`);
617
+ }
618
+ lines.push(` try { return await step0(); } finally { state.active = false; }`, `}`);
619
+ return lines.join(`
620
+ `);
621
+ }
587
622
  renderServicesFactory() {
588
623
  return [
589
624
  `function create${this.pascal}Services(`,
@@ -698,7 +733,7 @@ ${indent(item, 2)}`).join(",")}
698
733
  const args = provider.deps.map((dep, index) => this.typedDepExpr(dep, kind, this.depOptions(provider, dep), `ConstructorParameters<typeof ${useClass}>[${index}]`)).join(", ");
699
734
  const local = this.localVar(isMulti ? provider.useClass ?? `${provider.token}Item` : provider.token, kind);
700
735
  return {
701
- constLine: `const ${local} = ${this.instantiate(useClass, args, kind, provider.functionalInjects)};`,
736
+ constLine: `const ${local} = new ${useClass}(${args});`,
702
737
  key,
703
738
  expr: local
704
739
  };
@@ -734,32 +769,11 @@ ${indent(item, 2)}`).join(",")}
734
769
  const key = camelName(controller.className);
735
770
  const local = this.localVar(controller.className, kind);
736
771
  return {
737
- constLine: `const ${local} = ${this.instantiate(className, args, kind, controller.functionalInjects)};`,
772
+ constLine: `const ${local} = new ${className}(${args});`,
738
773
  key,
739
774
  expr: local
740
775
  };
741
776
  }
742
- instantiate(className, args, kind, functionalInjects) {
743
- if (!functionalInjects || functionalInjects.length === 0) {
744
- return `new ${className}(${args})`;
745
- }
746
- const clauses = functionalInjects.map((entry) => {
747
- const token = this.imports.add(entry.expression, entry.importPath, entry.importModule);
748
- const value = this.depExpr(entry.token, kind, entry);
749
- return `if (token === ${token}) return ${value} as T;`;
750
- });
751
- const missing = `if (options?.optional) return undefined; throw new Error("Static inject token not available: " + String(token));`;
752
- const injector = [
753
- `{`,
754
- `get<T>(token: unknown, options?: { optional?: boolean; self?: boolean; skipSelf?: boolean; host?: boolean }): T | undefined {`,
755
- ...clauses,
756
- missing,
757
- `},`,
758
- `}`
759
- ].join(`
760
- `);
761
- return `runInInjectionContext(${injector}, () => new ${className}(${args}))`;
762
- }
763
777
  localVar(token, kind) {
764
778
  const locals = this.locals[kind];
765
779
  const existing = locals.get(token);
@@ -1932,6 +1946,7 @@ var HEADER = "// GENERATED BY @supacloud/compiler — do not edit", INTERFACES =
1932
1946
  title?: string;
1933
1947
  data?: Record<string, unknown>;
1934
1948
  aspects?: CompiledAspect[];
1949
+ aspectPipeline?: CompiledAspectPipeline;
1935
1950
  invoker?: (
1936
1951
  controller: unknown,
1937
1952
  request: {
@@ -1955,6 +1970,7 @@ export interface CompiledCommand {
1955
1970
  idempotency: "required" | "none";
1956
1971
  standalone?: boolean;
1957
1972
  aspects?: CompiledAspect[];
1973
+ aspectPipeline?: CompiledAspectPipeline;
1958
1974
  }
1959
1975
 
1960
1976
  export interface CompiledJob {
@@ -1969,6 +1985,7 @@ export interface CompiledJob {
1969
1985
  maxAttempts?: number;
1970
1986
  idempotency?: "required" | "none";
1971
1987
  aspects?: CompiledAspect[];
1988
+ aspectPipeline?: CompiledAspectPipeline;
1972
1989
  }
1973
1990
 
1974
1991
  export interface CompiledAspectContext {
@@ -2016,7 +2033,24 @@ export interface CompiledModule {
2016
2033
  commands: CompiledCommand[];
2017
2034
  jobs: CompiledJob[];
2018
2035
  aspects?: CompiledAspect[];
2019
- }`, TYPE_GUARDS = `function isRecord(value: unknown): value is Record<string, unknown> {
2036
+ aspectPipeline?: CompiledAspectPipeline;
2037
+ }`, TYPE_GUARDS = `type CompiledAspectObserver = (stage: string, run: () => unknown | Promise<unknown>) => unknown | Promise<unknown>;
2038
+ type CompiledAspectPipeline = (context: CompiledAspectContext, next: () => unknown | Promise<unknown>, observe?: CompiledAspectObserver) => unknown | Promise<unknown>;
2039
+
2040
+ function compiledAspectNext(next: () => unknown | Promise<unknown>, state: { active: boolean }): () => Promise<unknown> {
2041
+ let called = false;
2042
+ return async () => {
2043
+ if (!state.active) throw new Error("Aspect continuation is closed");
2044
+ if (called) throw new Error("Aspect continuation called multiple times");
2045
+ called = true;
2046
+ return await next();
2047
+ };
2048
+ }
2049
+ function observeCompiledAspect(observe: CompiledAspectObserver | undefined, stage: string, run: () => unknown | Promise<unknown>): unknown | Promise<unknown> {
2050
+ return observe ? observe(stage, run) : run();
2051
+ }
2052
+
2053
+ function isRecord(value: unknown): value is Record<string, unknown> {
2020
2054
  return typeof value === "object" && value !== null;
2021
2055
  }
2022
2056
 
@@ -2198,7 +2232,7 @@ var init_graphql_options = __esm(() => {
2198
2232
 
2199
2233
  // src/graphql-inputs.ts
2200
2234
  import { resolve as resolve3 } from "node:path";
2201
- import * as ts5 from "@typescript/typescript6";
2235
+ import * as ts7 from "@typescript/typescript6";
2202
2236
  function graphqlInputPaths(options) {
2203
2237
  if (!options.graphql)
2204
2238
  return [];
@@ -2209,7 +2243,7 @@ function graphqlInputPaths(options) {
2209
2243
  }
2210
2244
  const root = resolve3(options.rootDir);
2211
2245
  const schema = resolve3(root, options.graphql.schema);
2212
- const documents = ts5.sys.readDirectory(root, [".graphql", ".gql"], ["**/node_modules/**", "**/.git/**", resolve3(options.outDir)], options.graphql.documents ?? ["**/*.graphql", "**/*.gql"]).map((path) => resolve3(path)).filter((path) => path !== schema);
2246
+ const documents = ts7.sys.readDirectory(root, [".graphql", ".gql"], ["**/node_modules/**", "**/.git/**", resolve3(options.outDir)], options.graphql.documents ?? ["**/*.graphql", "**/*.gql"]).map((path) => resolve3(path)).filter((path) => path !== schema);
2213
2247
  return [schema, ...[...new Set(documents)].sort()];
2214
2248
  }
2215
2249
  var init_graphql_inputs = __esm(() => {
@@ -2217,7 +2251,7 @@ var init_graphql_inputs = __esm(() => {
2217
2251
  });
2218
2252
 
2219
2253
  // src/graphql-runtime.ts
2220
- import * as ts6 from "@typescript/typescript6";
2254
+ import * as ts8 from "@typescript/typescript6";
2221
2255
  import { resolve as resolve4 } from "node:path";
2222
2256
  function renderGraphqlValidators(source, operationNames) {
2223
2257
  const fileName = resolve4("/__supacloud_graphql__/contracts.ts");
@@ -2229,18 +2263,18 @@ function renderGraphqlValidators(source, operationNames) {
2229
2263
  noPropertyAccessFromIndexSignature: true,
2230
2264
  noFallthroughCasesInSwitch: true,
2231
2265
  skipLibCheck: false,
2232
- target: ts6.ScriptTarget.ES2022,
2266
+ target: ts8.ScriptTarget.ES2022,
2233
2267
  lib: ["lib.es2022.d.ts"],
2234
2268
  types: [],
2235
2269
  noEmit: true
2236
2270
  };
2237
- const host = ts6.createCompilerHost(options);
2271
+ const host = ts8.createCompilerHost(options);
2238
2272
  const getSourceFile = host.getSourceFile.bind(host);
2239
- host.getSourceFile = (path, languageVersion, onError, shouldCreateNewSourceFile) => path === fileName ? ts6.createSourceFile(path, source, languageVersion, true) : getSourceFile(path, languageVersion, onError, shouldCreateNewSourceFile);
2240
- const program = ts6.createProgram([fileName], options, host);
2241
- const diagnostics = ts6.getPreEmitDiagnostics(program);
2273
+ host.getSourceFile = (path, languageVersion, onError, shouldCreateNewSourceFile) => path === fileName ? ts8.createSourceFile(path, source, languageVersion, true) : getSourceFile(path, languageVersion, onError, shouldCreateNewSourceFile);
2274
+ const program = ts8.createProgram([fileName], options, host);
2275
+ const diagnostics = ts8.getPreEmitDiagnostics(program);
2242
2276
  if (diagnostics.length) {
2243
- throw new Error(`Generated GraphQL types cannot be validated: ${diagnostics.map((item) => ts6.flattenDiagnosticMessageText(item.messageText, `
2277
+ throw new Error(`Generated GraphQL types cannot be validated: ${diagnostics.map((item) => ts8.flattenDiagnosticMessageText(item.messageText, `
2244
2278
  `)).join("; ")}`);
2245
2279
  }
2246
2280
  const checker = program.getTypeChecker();
@@ -2270,25 +2304,25 @@ function renderGraphqlValidators(source, operationNames) {
2270
2304
  return name;
2271
2305
  }
2272
2306
  function expression(type) {
2273
- if (type.flags & ts6.TypeFlags.Any)
2307
+ if (type.flags & ts8.TypeFlags.Any)
2274
2308
  return unsupported(type);
2275
- if (type.flags & ts6.TypeFlags.Unknown)
2309
+ if (type.flags & ts8.TypeFlags.Unknown)
2276
2310
  return "true";
2277
- if (type.flags & ts6.TypeFlags.Never)
2311
+ if (type.flags & ts8.TypeFlags.Never)
2278
2312
  return "false";
2279
- if (type.flags & ts6.TypeFlags.Null)
2313
+ if (type.flags & ts8.TypeFlags.Null)
2280
2314
  return "value === null";
2281
- if (type.flags & ts6.TypeFlags.Undefined)
2315
+ if (type.flags & ts8.TypeFlags.Undefined)
2282
2316
  return "value === undefined";
2283
2317
  if (type.isStringLiteral() || type.isNumberLiteral())
2284
2318
  return `value === ${JSON.stringify(type.value)}`;
2285
- if (type.flags & ts6.TypeFlags.BooleanLiteral)
2319
+ if (type.flags & ts8.TypeFlags.BooleanLiteral)
2286
2320
  return `value === ${checker.typeToString(type)}`;
2287
- if (type.flags & ts6.TypeFlags.String)
2321
+ if (type.flags & ts8.TypeFlags.String)
2288
2322
  return 'typeof value === "string"';
2289
- if (type.flags & ts6.TypeFlags.Number)
2323
+ if (type.flags & ts8.TypeFlags.Number)
2290
2324
  return 'typeof value === "number" && Number.isFinite(value)';
2291
- if (type.flags & ts6.TypeFlags.Boolean)
2325
+ if (type.flags & ts8.TypeFlags.Boolean)
2292
2326
  return 'typeof value === "boolean"';
2293
2327
  if (type.isUnion())
2294
2328
  return type.types.map((part) => `${reference(part)}(value)`).join(" || ");
@@ -2297,16 +2331,16 @@ function renderGraphqlValidators(source, operationNames) {
2297
2331
  if (checker.isTupleType(type))
2298
2332
  return unsupported(type);
2299
2333
  if (checker.isArrayType(type)) {
2300
- const item = checker.getIndexTypeOfType(type, ts6.IndexKind.Number);
2334
+ const item = checker.getIndexTypeOfType(type, ts8.IndexKind.Number);
2301
2335
  if (!item)
2302
2336
  return unsupported(type);
2303
2337
  return `isGraphqlArray(value) && Array.from(value).every(${reference(item)})`;
2304
2338
  }
2305
- if (type.flags & ts6.TypeFlags.Object) {
2339
+ if (type.flags & ts8.TypeFlags.Object) {
2306
2340
  if (type.getCallSignatures().length || type.getConstructSignatures().length)
2307
2341
  return unsupported(type);
2308
2342
  const indexes = checker.getIndexInfosOfType(type);
2309
- if (indexes.some((index) => !(index.keyType.flags & ts6.TypeFlags.String)))
2343
+ if (indexes.some((index) => !(index.keyType.flags & ts8.TypeFlags.String)))
2310
2344
  return unsupported(type);
2311
2345
  const properties = checker.getPropertiesOfType(type).map((property) => {
2312
2346
  const declaration = property.valueDeclaration ?? property.declarations?.[0];
@@ -2315,7 +2349,7 @@ function renderGraphqlValidators(source, operationNames) {
2315
2349
  const check = reference(checker.getTypeOfSymbolAtLocation(property, declaration));
2316
2350
  const key = JSON.stringify(property.name);
2317
2351
  const present = `Object.prototype.hasOwnProperty.call(value, ${key})`;
2318
- return property.flags & ts6.SymbolFlags.Optional ? `(!${present} || ${check}(value[${key}]))` : `(${present} && ${check}(value[${key}]))`;
2352
+ return property.flags & ts8.SymbolFlags.Optional ? `(!${present} || ${check}(value[${key}]))` : `(${present} && ${check}(value[${key}]))`;
2319
2353
  });
2320
2354
  const indexedValues = indexes.map((index) => `Object.values(value).every(${reference(index.type)})`);
2321
2355
  return ["isGraphqlRecord(value)", ...properties, ...indexedValues].join(" && ");
@@ -2642,10 +2676,155 @@ var init_graphql_schema = __esm(() => {
2642
2676
  init_graphql_options();
2643
2677
  });
2644
2678
 
2679
+ // src/database-contracts.ts
2680
+ import { createHash as createHash10 } from "node:crypto";
2681
+ import { mkdir as mkdir6, readFile as readFile12 } from "node:fs/promises";
2682
+ import { dirname as dirname11, relative as relative12, resolve as resolve16 } from "node:path";
2683
+ import * as ts13 from "@typescript/typescript6";
2684
+ function hash2(value) {
2685
+ return createHash10("sha256").update(value).digest("hex");
2686
+ }
2687
+ function importPath(out, path) {
2688
+ const value = relative12(out, path).replaceAll("\\", "/").replace(/\.(?:d\.)?[cm]?ts$/, "");
2689
+ return value.startsWith(".") ? value : `./${value}`;
2690
+ }
2691
+ function parseDatabaseContractsOptions(value, directory) {
2692
+ if (!value || typeof value !== "object" || Array.isArray(value))
2693
+ throw new TypeError("Expected database contracts configuration");
2694
+ const allowed = ["rootDir", "outDir", "postgrestTypes", "drizzleSchema", "role", "graphql", "migrations"];
2695
+ if (Object.keys(value).some((name) => !allowed.includes(name)))
2696
+ throw new TypeError("Unknown database contracts option");
2697
+ const field = (name) => {
2698
+ const result = Reflect.get(value, name);
2699
+ if (typeof result !== "string" || !result.trim())
2700
+ throw new TypeError(`Missing database contracts ${name}`);
2701
+ return result;
2702
+ };
2703
+ const graphql = Reflect.get(value, "graphql");
2704
+ assertGraphqlOptions(graphql);
2705
+ const migrations = Reflect.get(value, "migrations");
2706
+ if (!Array.isArray(migrations) || !migrations.every((entry) => typeof entry === "string" && entry.endsWith(".sql"))) {
2707
+ throw new TypeError("migrations must be an ordered list of SQL files");
2708
+ }
2709
+ return {
2710
+ rootDir: resolve16(directory, field("rootDir")),
2711
+ outDir: resolve16(directory, field("outDir")),
2712
+ postgrestTypes: resolve16(directory, field("postgrestTypes")),
2713
+ drizzleSchema: resolve16(directory, field("drizzleSchema")),
2714
+ role: field("role"),
2715
+ graphql: { ...graphql, schema: resolve16(directory, graphql.schema) },
2716
+ migrations: migrations.map((file) => resolve16(directory, file))
2717
+ };
2718
+ }
2719
+ async function generateDatabaseContracts(options, check = false) {
2720
+ const rootDir = resolve16(options.rootDir), outDir = resolve16(options.outDir);
2721
+ const postgrestTypes = resolve16(rootDir, options.postgrestTypes), drizzleSchema = resolve16(rootDir, options.drizzleSchema);
2722
+ const snapshot = await readFile12(postgrestTypes, "utf8");
2723
+ const syntax = ts13.createSourceFile(postgrestTypes, snapshot, ts13.ScriptTarget.Latest, true);
2724
+ const database = syntax.statements.find((node) => (ts13.isTypeAliasDeclaration(node) || ts13.isInterfaceDeclaration(node)) && node.name.text === "Database" && node.modifiers?.some((modifier) => modifier.kind === ts13.SyntaxKind.ExportKeyword));
2725
+ if (!database)
2726
+ throw new Error("PostgREST snapshot must export Database from the official type generator");
2727
+ const program = ts13.createProgram([postgrestTypes], {
2728
+ strict: true,
2729
+ noEmit: true,
2730
+ skipLibCheck: true,
2731
+ types: [],
2732
+ target: ts13.ScriptTarget.ES2022,
2733
+ module: ts13.ModuleKind.ESNext,
2734
+ moduleResolution: ts13.ModuleResolutionKind.Bundler
2735
+ });
2736
+ if (ts13.getPreEmitDiagnostics(program).length)
2737
+ throw new Error("PostgREST snapshot has TypeScript errors");
2738
+ const artifacts = await renderGraphql({
2739
+ rootDir,
2740
+ outDir,
2741
+ graphql: options.graphql
2742
+ });
2743
+ if (artifacts.diagnostics.some((item) => item.severity === "error")) {
2744
+ throw new Error(artifacts.diagnostics.map((item) => item.message).join(`
2745
+ `));
2746
+ }
2747
+ const inputs = {};
2748
+ const addInput = async (path) => {
2749
+ const absolute = resolve16(rootDir, path);
2750
+ inputs[relative12(rootDir, absolute).replaceAll("\\", "/")] = hash2(await readFile12(absolute, "utf8"));
2751
+ };
2752
+ await addInput(postgrestTypes);
2753
+ await addInput(drizzleSchema);
2754
+ const drizzleProgram = ts13.createProgram([drizzleSchema], {
2755
+ noEmit: true,
2756
+ moduleResolution: ts13.ModuleResolutionKind.Bundler,
2757
+ module: ts13.ModuleKind.ESNext,
2758
+ target: ts13.ScriptTarget.ES2022,
2759
+ types: [],
2760
+ skipLibCheck: true
2761
+ });
2762
+ for (const source of drizzleProgram.getSourceFiles()) {
2763
+ if (!source.isDeclarationFile && !source.fileName.includes("/node_modules/"))
2764
+ await addInput(source.fileName);
2765
+ }
2766
+ await addInput(resolve16(rootDir, options.graphql.schema));
2767
+ if (new Set(options.migrations.map((path) => resolve16(rootDir, path))).size !== options.migrations.length) {
2768
+ throw new Error("Duplicate migration in database contracts configuration");
2769
+ }
2770
+ for (const path of options.migrations)
2771
+ await addInput(path);
2772
+ const files = {
2773
+ ...artifacts.files,
2774
+ "database.ts": [
2775
+ "// GENERATED BY @supacloud/compiler database-contracts. Do not edit.",
2776
+ `export type { Database } from ${JSON.stringify(importPath(outDir, postgrestTypes))};`,
2777
+ 'export type { QueryData, QueryResult, QueryError } from "@supabase/supabase-js";',
2778
+ `export type DrizzleSchema = typeof import(${JSON.stringify(importPath(outDir, drizzleSchema))});`,
2779
+ 'export * from "./graphql";',
2780
+ ""
2781
+ ].join(`
2782
+ `)
2783
+ };
2784
+ const manifest = {
2785
+ version: 1,
2786
+ role: options.role,
2787
+ inputs: Object.fromEntries(Object.entries(inputs).sort(([a], [b]) => a.localeCompare(b))),
2788
+ migrationOrder: options.migrations.map((path) => relative12(rootDir, resolve16(rootDir, path)).replaceAll("\\", "/")),
2789
+ outputs: Object.fromEntries(Object.entries(files).sort(([a], [b]) => a.localeCompare(b)).map(([file, text]) => [file, hash2(text)]))
2790
+ };
2791
+ files["database.manifest.json"] = JSON.stringify(manifest, null, 2) + `
2792
+ `;
2793
+ const mismatches = [];
2794
+ for (const [file, content] of Object.entries(files)) {
2795
+ const path = resolve16(outDir, file);
2796
+ let current;
2797
+ try {
2798
+ current = await readFile12(path, "utf8");
2799
+ } catch (error) {
2800
+ if (!(error instanceof Error && ("code" in error) && error.code === "ENOENT"))
2801
+ throw error;
2802
+ }
2803
+ if (current !== content)
2804
+ mismatches.push(file);
2805
+ }
2806
+ if (!check) {
2807
+ await mkdir6(outDir, { recursive: true });
2808
+ for (const [file, content] of Object.entries(files))
2809
+ await writeFileIfChanged(resolve16(outDir, file), content);
2810
+ }
2811
+ return { upToDate: mismatches.length === 0, mismatches, written: check ? [] : mismatches, manifest };
2812
+ }
2813
+ async function runDatabaseContractsFile(path, check = false) {
2814
+ const absolute = resolve16(path);
2815
+ const value = JSON.parse(await readFile12(absolute, "utf8"));
2816
+ return generateDatabaseContracts(parseDatabaseContractsOptions(value, dirname11(absolute)), check);
2817
+ }
2818
+ var init_database_contracts = __esm(() => {
2819
+ init_graphql();
2820
+ init_generate();
2821
+ init_graphql_options();
2822
+ });
2823
+
2645
2824
  // src/analyze.ts
2646
2825
  import { createHash as createHash3 } from "node:crypto";
2647
2826
  import { relative as relative2, resolve as resolvePath, sep as sep2 } from "node:path";
2648
- import * as ts3 from "@typescript/typescript6";
2827
+ import * as ts4 from "@typescript/typescript6";
2649
2828
 
2650
2829
  // src/program.ts
2651
2830
  import { createHash as createHash2 } from "node:crypto";
@@ -3295,6 +3474,7 @@ var COMPILER_DIAGNOSTIC_CODES = {
3295
3474
  "missing-token-factory": { code: "SC2009", docsUrl: "https://supacloud.dev/errors/SC2009" },
3296
3475
  "provider-type-mismatch": { code: "SC2010", docsUrl: "https://supacloud.dev/errors/SC2010" },
3297
3476
  "unsupported-provider-helper": { code: "SC2011", docsUrl: "https://supacloud.dev/errors/SC2011" },
3477
+ "runtime-injection-disallowed": { code: "SC2012", docsUrl: "https://supacloud.dev/errors/SC2012" },
3298
3478
  "command-missing-permission": { code: "SC4001", docsUrl: "https://supacloud.dev/errors/SC4001" },
3299
3479
  "duplicate-command": { code: "SC4002", docsUrl: "https://supacloud.dev/errors/SC4002" },
3300
3480
  "route-command-unresolved": { code: "SC4003", docsUrl: "https://supacloud.dev/errors/SC4003" },
@@ -3341,6 +3521,20 @@ var COMPILER_DIAGNOSTIC_CODES = {
3341
3521
  function validateGraph(graph, options = false) {
3342
3522
  const strict = typeof options === "boolean" ? options : options.strict ?? false;
3343
3523
  const diagnostics = [];
3524
+ for (const module of graph.modules) {
3525
+ for (const owner of [...module.providers, ...module.controllers]) {
3526
+ if (owner.functionalInjects?.length)
3527
+ diagnostics.push({
3528
+ severity: "error",
3529
+ code: "runtime-injection-disallowed",
3530
+ errorCode: "SC2012",
3531
+ docsUrl: "https://supacloud.dev/errors/SC2012",
3532
+ file: owner.file,
3533
+ message: "Property inject() requires runtime token resolution. Compiled applications require constructor injection.",
3534
+ suggestion: "Move injected fields into typed constructor parameters with @Inject(TOKEN) where needed."
3535
+ });
3536
+ }
3537
+ }
3344
3538
  let moduleBoundaries;
3345
3539
  if (typeof options === "object") {
3346
3540
  try {
@@ -3768,7 +3962,7 @@ function validateGraph(graph, options = false) {
3768
3962
  if (typeof options === "object" && options.commandCapabilities) {
3769
3963
  const hostCaps = options.commandCapabilities;
3770
3964
  const rpcCaps = command.rpc && Object.hasOwn(hostCaps.rpc ?? {}, command.rpc) ? hostCaps.rpc?.[command.rpc] : undefined;
3771
- if (hostCaps.requirePersistentAdapters && (!rpcCaps?.boundary || rpcCaps.audit !== true || rpcCaps.idempotency !== true || hostCaps.permission !== true || !command.permission || !command.audit || command.idempotency !== "required" || rpcCaps.boundary === "database" && (rpcCaps.transaction !== true || command.transaction !== "required"))) {
3965
+ if (hostCaps.requirePersistentAdapters && (command.rpc !== undefined && (!rpcCaps?.boundary || rpcCaps.audit !== true || rpcCaps.idempotency !== true) || hostCaps.permission !== true || !command.permission || !command.audit || command.idempotency !== "required" || command.rpc !== undefined && rpcCaps?.boundary === "database" && (rpcCaps.transaction !== true || command.transaction !== "required") || command.rpc === undefined && (hostCaps.audit !== true || hostCaps.idempotency !== true || hostCaps.transaction !== true || command.transaction !== "required"))) {
3772
3966
  error("command-persistence-required", `Command ${command.name} requires an explicit persistent adapter, permission, audit and idempotency policy.`, module.file, module.line, "Register a named database/external adapter, enable permission checks and declare permission, audit and required idempotency on the command.");
3773
3967
  }
3774
3968
  if (rpcCaps?.boundary === "external" && (command.transaction === "required" || rpcCaps.transaction === true)) {
@@ -4121,6 +4315,67 @@ function detectOrphanModules(graph) {
4121
4315
  }
4122
4316
  return diagnostics;
4123
4317
  }
4318
+ // src/static-di.ts
4319
+ import * as ts3 from "@typescript/typescript6";
4320
+ var runtimeApis = new Set([
4321
+ "inject",
4322
+ "createEnvironmentInjector",
4323
+ "runInInjectionContext",
4324
+ "EnvironmentInjector",
4325
+ "bootstrapBun",
4326
+ "runInScope",
4327
+ "runInRequestContext",
4328
+ "runInJobContext",
4329
+ "runInTransactionContext"
4330
+ ]);
4331
+ function scanRuntimeDi(source, file) {
4332
+ const diagnostics = [];
4333
+ const namespaces = new Set;
4334
+ const report = (node) => diagnostics.push({
4335
+ severity: "error",
4336
+ code: "runtime-injection-disallowed",
4337
+ errorCode: "SC2012",
4338
+ docsUrl: "https://supacloud.dev/errors/SC2012",
4339
+ file,
4340
+ line: source.getLineAndCharacterOfPosition(node.getStart()).line + 1,
4341
+ message: "Compiled applications cannot import runtime DI. Use explicit constructors and generated scope factories."
4342
+ });
4343
+ for (const statement of source.statements) {
4344
+ if (!(ts3.isImportDeclaration(statement) || ts3.isExportDeclaration(statement)) || !statement.moduleSpecifier || !ts3.isStringLiteral(statement.moduleSpecifier) || !/^@supacloud\/app(?:\/|$)/.test(statement.moduleSpecifier.text))
4345
+ continue;
4346
+ if (ts3.isImportDeclaration(statement)) {
4347
+ if (statement.importClause?.isTypeOnly)
4348
+ continue;
4349
+ const binding = statement.importClause?.namedBindings;
4350
+ if (binding && ts3.isNamespaceImport(binding))
4351
+ namespaces.add(binding.name.text);
4352
+ if (binding && ts3.isNamedImports(binding))
4353
+ for (const item of binding.elements) {
4354
+ if (!item.isTypeOnly && runtimeApis.has((item.propertyName ?? item.name).text))
4355
+ report(item);
4356
+ }
4357
+ } else if (!statement.isTypeOnly) {
4358
+ if (!statement.exportClause)
4359
+ report(statement);
4360
+ else if (ts3.isNamedExports(statement.exportClause))
4361
+ for (const item of statement.exportClause.elements) {
4362
+ if (!item.isTypeOnly && runtimeApis.has((item.propertyName ?? item.name).text))
4363
+ report(item);
4364
+ }
4365
+ }
4366
+ }
4367
+ const visit = (node) => {
4368
+ if (ts3.isPropertyAccessExpression(node) && ts3.isIdentifier(node.expression) && namespaces.has(node.expression.text) && runtimeApis.has(node.name.text))
4369
+ report(node);
4370
+ if (ts3.isElementAccessExpression(node) && ts3.isIdentifier(node.expression) && namespaces.has(node.expression.text) && (!ts3.isStringLiteral(node.argumentExpression) || runtimeApis.has(node.argumentExpression.text)))
4371
+ report(node);
4372
+ if (ts3.isVariableDeclaration(node) && node.initializer && ts3.isIdentifier(node.initializer) && namespaces.has(node.initializer.text))
4373
+ report(node);
4374
+ ts3.forEachChild(node, visit);
4375
+ };
4376
+ visit(source);
4377
+ return diagnostics;
4378
+ }
4124
4379
 
4125
4380
  // src/analyze.ts
4126
4381
  var DEFAULT_INCLUDE = ["**/*.module.ts", "**/*.ts"];
@@ -4162,26 +4417,26 @@ function lineOf(node) {
4162
4417
  return sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;
4163
4418
  }
4164
4419
  function variableName(decl) {
4165
- return ts3.isIdentifier(decl.name) ? decl.name.text : nodeText(decl.name);
4420
+ return ts4.isIdentifier(decl.name) ? decl.name.text : nodeText(decl.name);
4166
4421
  }
4167
4422
  function propertyName(name) {
4168
- if (ts3.isIdentifier(name) || ts3.isPrivateIdentifier(name))
4423
+ if (ts4.isIdentifier(name) || ts4.isPrivateIdentifier(name))
4169
4424
  return name.text;
4170
- if (ts3.isStringLiteral(name) || ts3.isNumericLiteral(name))
4425
+ if (ts4.isStringLiteral(name) || ts4.isNumericLiteral(name))
4171
4426
  return name.text;
4172
4427
  return nodeText(name);
4173
4428
  }
4174
4429
  function parameterName(param) {
4175
- return ts3.isIdentifier(param.name) ? param.name.text : nodeText(param.name);
4430
+ return ts4.isIdentifier(param.name) ? param.name.text : nodeText(param.name);
4176
4431
  }
4177
4432
  function decoratorsOf(node) {
4178
- return ts3.canHaveDecorators(node) ? ts3.getDecorators(node) ?? [] : [];
4433
+ return ts4.canHaveDecorators(node) ? ts4.getDecorators(node) ?? [] : [];
4179
4434
  }
4180
4435
  function decoratorArguments(dec) {
4181
- return ts3.isCallExpression(dec.expression) ? dec.expression.arguments : [];
4436
+ return ts4.isCallExpression(dec.expression) ? dec.expression.arguments : [];
4182
4437
  }
4183
4438
  function hasMethod(cls, name) {
4184
- return cls.members.some((member) => (ts3.isMethodDeclaration(member) || ts3.isGetAccessorDeclaration(member) || ts3.isSetAccessorDeclaration(member)) && member.name !== undefined && propertyName(member.name) === name);
4439
+ return cls.members.some((member) => (ts4.isMethodDeclaration(member) || ts4.isGetAccessorDeclaration(member) || ts4.isSetAccessorDeclaration(member)) && member.name !== undefined && propertyName(member.name) === name);
4185
4440
  }
4186
4441
  function hasDestroyHook(cls) {
4187
4442
  return hasMethod(cls, "onDestroy") || hasMethod(cls, "ngOnDestroy");
@@ -4191,7 +4446,7 @@ function descendantsOfKind(root, predicate) {
4191
4446
  const visit = (node) => {
4192
4447
  if (predicate(node))
4193
4448
  result.push(node);
4194
- ts3.forEachChild(node, visit);
4449
+ ts4.forEachChild(node, visit);
4195
4450
  };
4196
4451
  visit(root);
4197
4452
  return result;
@@ -4200,7 +4455,7 @@ async function analyzeProject(rootDir, include, cache, changedPaths) {
4200
4455
  const session = cache?.programSession ?? createIncrementalProgramSession(rootDir);
4201
4456
  if (cache)
4202
4457
  cache.programSession = session;
4203
- const rootNames = ts3.sys.readDirectory(rootDir, [".ts", ".tsx"], ["node_modules", "dist"], include ?? DEFAULT_INCLUDE);
4458
+ const rootNames = ts4.sys.readDirectory(rootDir, [".ts", ".tsx"], ["node_modules", "dist"], include ?? DEFAULT_INCLUDE);
4204
4459
  const update = session.update(rootNames, changedPaths);
4205
4460
  const program = update.program;
4206
4461
  const checker = program.getTypeChecker();
@@ -4224,13 +4479,16 @@ async function analyzeProject(rootDir, include, cache, changedPaths) {
4224
4479
  nativeTraitFiles.set(trait.file, kinds);
4225
4480
  }
4226
4481
  for (const sf of sourceFiles) {
4482
+ if (!/\.(?:test|spec)\.[cm]?tsx?$/.test(sf.fileName)) {
4483
+ ctx.diagnostics.push(...scanRuntimeDi(sf, sourcePath(rootDir, sf.fileName)));
4484
+ }
4227
4485
  indexFile(sf, ctx);
4228
4486
  }
4229
4487
  const candidates = [];
4230
4488
  for (const sf of sourceFiles) {
4231
4489
  const traits = nativeTraitFiles.get(sf.fileName);
4232
4490
  if (!cache || traits?.has("module")) {
4233
- for (const cls of sf.statements.filter(ts3.isClassDeclaration)) {
4491
+ for (const cls of sf.statements.filter(ts4.isClassDeclaration)) {
4234
4492
  const moduleDec = findDecorator(cls, "Module");
4235
4493
  if (!moduleDec)
4236
4494
  continue;
@@ -4247,14 +4505,14 @@ async function analyzeProject(rootDir, include, cache, changedPaths) {
4247
4505
  }
4248
4506
  }
4249
4507
  if (!cache || traits?.has("defineModule") || traits?.has("defineFeatureSlice")) {
4250
- for (const call of descendantsOfKind(sf, ts3.isCallExpression)) {
4508
+ for (const call of descendantsOfKind(sf, ts4.isCallExpression)) {
4251
4509
  if (!["defineModule", "defineFeatureSlice"].includes(nodeText(call.expression)))
4252
4510
  continue;
4253
4511
  const parent = call.parent;
4254
- if (!parent || !ts3.isVariableDeclaration(parent))
4512
+ if (!parent || !ts4.isVariableDeclaration(parent))
4255
4513
  continue;
4256
4514
  const arg = call.arguments[0];
4257
- if (!arg || !ts3.isObjectLiteralExpression(arg))
4515
+ if (!arg || !ts4.isObjectLiteralExpression(arg))
4258
4516
  continue;
4259
4517
  candidates.push({
4260
4518
  node: parent,
@@ -4398,7 +4656,7 @@ async function analyzeProject(rootDir, include, cache, changedPaths) {
4398
4656
  const controllerDec = findDecorator(classInfo.decl, "Controller");
4399
4657
  if (controllerDec) {
4400
4658
  const arg = decoratorArguments(controllerDec)[0];
4401
- const isStandalone = arg && ts3.isObjectLiteralExpression(arg) && booleanProp(arg, "standalone");
4659
+ const isStandalone = arg && ts4.isObjectLiteralExpression(arg) && booleanProp(arg, "standalone");
4402
4660
  if (isStandalone) {
4403
4661
  const ctrl = parseController(classInfo.decl, ctx);
4404
4662
  if (ctrl)
@@ -4523,16 +4781,16 @@ function collectModuleSourceClosure(module, ctx) {
4523
4781
  ownedFiles.add(relativeFile);
4524
4782
  for (const statement of sourceFile.statements) {
4525
4783
  let moduleName;
4526
- if (ts3.isImportDeclaration(statement) && ts3.isStringLiteral(statement.moduleSpecifier)) {
4784
+ if (ts4.isImportDeclaration(statement) && ts4.isStringLiteral(statement.moduleSpecifier)) {
4527
4785
  moduleName = statement.moduleSpecifier.text;
4528
- } else if (ts3.isExportDeclaration(statement) && statement.moduleSpecifier && ts3.isStringLiteral(statement.moduleSpecifier)) {
4786
+ } else if (ts4.isExportDeclaration(statement) && statement.moduleSpecifier && ts4.isStringLiteral(statement.moduleSpecifier)) {
4529
4787
  moduleName = statement.moduleSpecifier.text;
4530
- } else if (ts3.isImportEqualsDeclaration(statement) && ts3.isExternalModuleReference(statement.moduleReference) && ts3.isStringLiteral(statement.moduleReference.expression)) {
4788
+ } else if (ts4.isImportEqualsDeclaration(statement) && ts4.isExternalModuleReference(statement.moduleReference) && ts4.isStringLiteral(statement.moduleReference.expression)) {
4531
4789
  moduleName = statement.moduleReference.expression.text;
4532
4790
  }
4533
4791
  if (!moduleName || moduleName.startsWith("node:"))
4534
4792
  continue;
4535
- const resolved = ts3.resolveModuleName(moduleName, sourceFile.fileName, ctx.program.getCompilerOptions(), ts3.sys).resolvedModule?.resolvedFileName;
4793
+ const resolved = ts4.resolveModuleName(moduleName, sourceFile.fileName, ctx.program.getCompilerOptions(), ts4.sys).resolvedModule?.resolvedFileName;
4536
4794
  if (resolved && isProjectSourcePath(resolved, ctx.rootDir) && !enqueued.has(resolved)) {
4537
4795
  enqueued.add(resolved);
4538
4796
  queue.push(resolved);
@@ -4554,15 +4812,15 @@ function isProjectSourceFile(sourceFile, rootDir) {
4554
4812
  return isProjectSourcePath(sourceFile.fileName, rootDir) && /\.(tsx?|mts|cts)$/.test(sourceFile.fileName);
4555
4813
  }
4556
4814
  function indexFile(sf, ctx) {
4557
- for (const cls of sf.statements.filter(ts3.isClassDeclaration)) {
4815
+ for (const cls of sf.statements.filter(ts4.isClassDeclaration)) {
4558
4816
  const name = cls.name?.text;
4559
4817
  if (name && !ctx.classesByName.has(name)) {
4560
4818
  ctx.classesByName.set(name, { name, decl: cls, file: sf.fileName });
4561
4819
  }
4562
4820
  }
4563
- for (const statement of sf.statements.filter(ts3.isVariableStatement)) {
4821
+ for (const statement of sf.statements.filter(ts4.isVariableStatement)) {
4564
4822
  for (const decl of statement.declarationList.declarations) {
4565
- if (ts3.isIdentifier(decl.name) && !ctx.variablesByName.has(decl.name.text)) {
4823
+ if (ts4.isIdentifier(decl.name) && !ctx.variablesByName.has(decl.name.text)) {
4566
4824
  ctx.variablesByName.set(decl.name.text, decl);
4567
4825
  }
4568
4826
  const info = parseTokenVariable(decl, sf.fileName);
@@ -4574,16 +4832,16 @@ function indexFile(sf, ctx) {
4574
4832
  }
4575
4833
  function parseTokenVariable(decl, file) {
4576
4834
  const init = decl.initializer;
4577
- if (!init || !ts3.isNewExpression(init))
4835
+ if (!init || !ts4.isNewExpression(init))
4578
4836
  return;
4579
4837
  if (nodeText(init.expression) !== "InjectionToken")
4580
4838
  return;
4581
4839
  const [nameArg, optionsArg] = init.arguments ?? [];
4582
4840
  const info = { name: variableName(decl), file, line: lineOf(decl) };
4583
- if (nameArg && ts3.isStringLiteral(nameArg)) {
4841
+ if (nameArg && ts4.isStringLiteral(nameArg)) {
4584
4842
  info.stringName = nameArg.text;
4585
4843
  }
4586
- if (optionsArg && ts3.isObjectLiteralExpression(optionsArg)) {
4844
+ if (optionsArg && ts4.isObjectLiteralExpression(optionsArg)) {
4587
4845
  const scope = stringLiteralProp(optionsArg, "scope");
4588
4846
  if (scope && isScope(scope)) {
4589
4847
  info.scope = scope;
@@ -4603,22 +4861,22 @@ function parseModule(candidate, nameByNode, ctx) {
4603
4861
  const { options, className, file, line } = candidate;
4604
4862
  const name = nameByNode.get(candidate.node) ?? className;
4605
4863
  const featureSpec = parseFeatureSpec(getProp(options, "spec"), ctx);
4606
- const tags = arrayProp(options, "tags").map((el) => ts3.isStringLiteral(el) ? el.text : nodeText(el).replace(/['"]/g, "")).filter(Boolean);
4864
+ const tags = arrayProp(options, "tags").map((el) => ts4.isStringLiteral(el) ? el.text : nodeText(el).replace(/['"]/g, "")).filter(Boolean);
4607
4865
  const aspects = parseAspectRefs(getProp(options, "aspects"), ctx, `module ${name}`);
4608
4866
  const imports = arrayProp(options, "imports").map((el) => {
4609
4867
  const unwrapped = unwrapForwardRef(el);
4610
- const decl = ts3.isIdentifier(unwrapped) ? resolveDeclaration(unwrapped, ctx)[0] : undefined;
4868
+ const decl = ts4.isIdentifier(unwrapped) ? resolveDeclaration(unwrapped, ctx)[0] : undefined;
4611
4869
  if (decl) {
4612
4870
  const known = nameByNode.get(decl);
4613
4871
  if (known)
4614
4872
  return known;
4615
- if (ts3.isClassDeclaration(decl)) {
4873
+ if (ts4.isClassDeclaration(decl)) {
4616
4874
  const dec = findDecorator(decl, "Module");
4617
4875
  const decOptions = dec && decoratorObjectArg(dec);
4618
4876
  const decName = decOptions && stringLiteralProp(decOptions, "name");
4619
4877
  return decName ?? decl.name?.text ?? nodeText(el);
4620
4878
  }
4621
- if (ts3.isVariableDeclaration(decl))
4879
+ if (ts4.isVariableDeclaration(decl))
4622
4880
  return variableName(decl);
4623
4881
  }
4624
4882
  return nodeText(el);
@@ -4632,7 +4890,7 @@ function parseModule(candidate, nameByNode, ctx) {
4632
4890
  providers.push(...parsedProviders);
4633
4891
  continue;
4634
4892
  }
4635
- if (ts3.isCallExpression(el)) {
4893
+ if (ts4.isCallExpression(el)) {
4636
4894
  const helper = nodeText(el.expression).split(".").pop() ?? nodeText(el.expression);
4637
4895
  warn(ctx, "unsupported-provider-helper", `无法静态展开 provider helper '${helper}';请改用显式 Provider 或实现编译器支持的 helper`, sourcePath(ctx.rootDir, el.getSourceFile().fileName), lineOf(el));
4638
4896
  continue;
@@ -4642,10 +4900,10 @@ function parseModule(candidate, nameByNode, ctx) {
4642
4900
  providers.push(provider);
4643
4901
  }
4644
4902
  for (const el of arrayProp(options, "jobs")) {
4645
- if (!ts3.isIdentifier(el))
4903
+ if (!ts4.isIdentifier(el))
4646
4904
  continue;
4647
4905
  const decl = resolveDeclaration(el, ctx)[0];
4648
- if (!decl || !ts3.isClassDeclaration(decl))
4906
+ if (!decl || !ts4.isClassDeclaration(decl))
4649
4907
  continue;
4650
4908
  const className = decl.name?.text ?? el.text;
4651
4909
  const registeredProvider = providers.find((provider) => provider.token === className || provider.useClass === className);
@@ -4682,18 +4940,18 @@ function parseModule(candidate, nameByNode, ctx) {
4682
4940
  const handlerClasses = [];
4683
4941
  const seenHandlers = new Set;
4684
4942
  const collectHandler = (expr) => {
4685
- if (!ts3.isIdentifier(expr))
4943
+ if (!ts4.isIdentifier(expr))
4686
4944
  return;
4687
4945
  const decl = resolveDeclaration(expr, ctx)[0];
4688
- if (decl && ts3.isClassDeclaration(decl) && !seenHandlers.has(decl.name?.text ?? "")) {
4946
+ if (decl && ts4.isClassDeclaration(decl) && !seenHandlers.has(decl.name?.text ?? "")) {
4689
4947
  seenHandlers.add(decl.name?.text ?? "");
4690
4948
  handlerClasses.push(decl);
4691
4949
  }
4692
4950
  };
4693
4951
  for (const el of arrayProp(options, "providers")) {
4694
- if (ts3.isIdentifier(el))
4952
+ if (ts4.isIdentifier(el))
4695
4953
  collectHandler(el);
4696
- if (ts3.isObjectLiteralExpression(el)) {
4954
+ if (ts4.isObjectLiteralExpression(el)) {
4697
4955
  const useClass = getProp(el, "useClass");
4698
4956
  if (useClass)
4699
4957
  collectHandler(useClass);
@@ -4793,17 +5051,17 @@ function parseFeatureSpec(input, ctx, seen = new Set) {
4793
5051
  if (seen.has(input))
4794
5052
  return;
4795
5053
  seen.add(input);
4796
- if (ts3.isIdentifier(input)) {
4797
- const local = input.getSourceFile().statements.flatMap((statement) => ts3.isVariableStatement(statement) ? [...statement.declarationList.declarations] : []);
5054
+ if (ts4.isIdentifier(input)) {
5055
+ const local = input.getSourceFile().statements.flatMap((statement) => ts4.isVariableStatement(statement) ? [...statement.declarationList.declarations] : []);
4798
5056
  const resolved = resolveDeclaration(input, ctx)[0];
4799
- const decl = (resolved && ts3.isVariableDeclaration(resolved) ? resolved : undefined) ?? ctx.variablesByName.get(input.text) ?? local.find((candidate) => ts3.isIdentifier(candidate.name) && candidate.name.text === input.text) ?? descendantsOfKind(input.getSourceFile(), ts3.isVariableDeclaration).find((candidate) => ts3.isIdentifier(candidate.name) && candidate.name.text === input.text);
4800
- if (decl && ts3.isVariableDeclaration(decl))
5057
+ const decl = (resolved && ts4.isVariableDeclaration(resolved) ? resolved : undefined) ?? ctx.variablesByName.get(input.text) ?? local.find((candidate) => ts4.isIdentifier(candidate.name) && candidate.name.text === input.text) ?? descendantsOfKind(input.getSourceFile(), ts4.isVariableDeclaration).find((candidate) => ts4.isIdentifier(candidate.name) && candidate.name.text === input.text);
5058
+ if (decl && ts4.isVariableDeclaration(decl))
4801
5059
  return parseFeatureSpec(decl.initializer, ctx, seen);
4802
5060
  }
4803
- if (ts3.isCallExpression(input) && nodeText(input.expression) === "defineFeatureSpec") {
5061
+ if (ts4.isCallExpression(input) && nodeText(input.expression) === "defineFeatureSpec") {
4804
5062
  return parseFeatureSpec(input.arguments[0], ctx, seen);
4805
5063
  }
4806
- if (ts3.isAsExpression(input) || ts3.isSatisfiesExpression(input) || ts3.isParenthesizedExpression(input)) {
5064
+ if (ts4.isAsExpression(input) || ts4.isSatisfiesExpression(input) || ts4.isParenthesizedExpression(input)) {
4807
5065
  return parseFeatureSpec(input.expression, ctx, seen);
4808
5066
  }
4809
5067
  const invalid = () => {
@@ -4816,28 +5074,28 @@ function parseFeatureSpec(input, ctx, seen = new Set) {
4816
5074
  });
4817
5075
  return;
4818
5076
  };
4819
- if (!ts3.isObjectLiteralExpression(input))
5077
+ if (!ts4.isObjectLiteralExpression(input))
4820
5078
  return invalid();
4821
5079
  const name = stringLiteralProp(input, "name");
4822
5080
  const statesExpr = getProp(input, "states");
4823
5081
  const transitionObject = getProp(input, "transitions");
4824
- if (!name || !statesExpr || !ts3.isArrayLiteralExpression(statesExpr) || statesExpr.elements.some((state) => !ts3.isStringLiteral(state)) || !transitionObject || !ts3.isObjectLiteralExpression(transitionObject) || input.properties.some((property) => !ts3.isPropertyAssignment(property))) {
5082
+ if (!name || !statesExpr || !ts4.isArrayLiteralExpression(statesExpr) || statesExpr.elements.some((state) => !ts4.isStringLiteral(state)) || !transitionObject || !ts4.isObjectLiteralExpression(transitionObject) || input.properties.some((property) => !ts4.isPropertyAssignment(property))) {
4825
5083
  return invalid();
4826
5084
  }
4827
5085
  const states = [];
4828
5086
  for (const state of statesExpr.elements) {
4829
- if (!ts3.isStringLiteral(state))
5087
+ if (!ts4.isStringLiteral(state))
4830
5088
  return invalid();
4831
5089
  states.push(state.text);
4832
5090
  }
4833
5091
  const transitions = [];
4834
5092
  for (const property of transitionObject.properties) {
4835
- if (!ts3.isPropertyAssignment(property) || ts3.isComputedPropertyName(property.name) || !ts3.isObjectLiteralExpression(property.initializer))
5093
+ if (!ts4.isPropertyAssignment(property) || ts4.isComputedPropertyName(property.name) || !ts4.isObjectLiteralExpression(property.initializer))
4836
5094
  return invalid();
4837
5095
  const options = property.initializer;
4838
5096
  const from = stringLiteralProp(options, "from");
4839
5097
  const to = stringLiteralProp(options, "to");
4840
- if (!from || !to || options.properties.some((prop) => !ts3.isPropertyAssignment(prop)) || ["permission", "command", "route", "audit"].some((key) => getProp(options, key) && !stringLiteralProp(options, key)) || ["transaction", "idempotency"].some((key) => getProp(options, key) && !commandModeProp(options, key))) {
5098
+ if (!from || !to || options.properties.some((prop) => !ts4.isPropertyAssignment(prop)) || ["permission", "command", "route", "audit"].some((key) => getProp(options, key) && !stringLiteralProp(options, key)) || ["transaction", "idempotency"].some((key) => getProp(options, key) && !commandModeProp(options, key))) {
4841
5099
  return invalid();
4842
5100
  }
4843
5101
  const permission = stringLiteralProp(options, "permission");
@@ -4864,21 +5122,21 @@ function resolveStaticObjectLiteral(input, ctx, seen = new Set) {
4864
5122
  if (!input || seen.has(input))
4865
5123
  return;
4866
5124
  seen.add(input);
4867
- if (ts3.isAsExpression(input) || ts3.isSatisfiesExpression(input) || ts3.isParenthesizedExpression(input)) {
5125
+ if (ts4.isAsExpression(input) || ts4.isSatisfiesExpression(input) || ts4.isParenthesizedExpression(input)) {
4868
5126
  return resolveStaticObjectLiteral(input.expression, ctx, seen);
4869
5127
  }
4870
- if (ts3.isIdentifier(input)) {
4871
- const declaration = resolveDeclaration(input, ctx).find(ts3.isVariableDeclaration);
5128
+ if (ts4.isIdentifier(input)) {
5129
+ const declaration = resolveDeclaration(input, ctx).find(ts4.isVariableDeclaration);
4872
5130
  return declaration?.initializer ? resolveStaticObjectLiteral(declaration.initializer, ctx, seen) : undefined;
4873
5131
  }
4874
- if (ts3.isCallExpression(input)) {
5132
+ if (ts4.isCallExpression(input)) {
4875
5133
  const expressionName = nodeText(input.expression);
4876
5134
  if (expressionName === "defineRouteContract" || expressionName.endsWith(".defineRouteContract")) {
4877
5135
  return resolveStaticObjectLiteral(input.arguments[0], ctx, seen);
4878
5136
  }
4879
5137
  return;
4880
5138
  }
4881
- return ts3.isObjectLiteralExpression(input) ? input : undefined;
5139
+ return ts4.isObjectLiteralExpression(input) ? input : undefined;
4882
5140
  }
4883
5141
  function commandModeProp(object, name) {
4884
5142
  const value = stringLiteralProp(object, name);
@@ -4913,9 +5171,9 @@ function parseProvider(el, exportsSet, ctx) {
4913
5171
  const file = sourcePath(ctx.rootDir, el.getSourceFile().fileName);
4914
5172
  const line = lineOf(el);
4915
5173
  const unwrappedEl = unwrapForwardRef(el);
4916
- if (ts3.isIdentifier(unwrappedEl)) {
5174
+ if (ts4.isIdentifier(unwrappedEl)) {
4917
5175
  const decl = resolveDeclaration(unwrappedEl, ctx)[0];
4918
- const cls = decl && ts3.isClassDeclaration(decl) ? decl : undefined;
5176
+ const cls = decl && ts4.isClassDeclaration(decl) ? decl : undefined;
4919
5177
  const className = cls?.name?.text ?? unwrappedEl.text;
4920
5178
  const { deps, optionalDeps, selfDeps, skipSelfDeps, hostDeps, functionalInjects, missing } = cls ? classDeps(cls, ctx) : { deps: [], optionalDeps: [], selfDeps: [], skipSelfDeps: [], hostDeps: [], functionalInjects: [], missing: false };
4921
5179
  const injectable = cls ? parseInjectableOptions(cls, ctx) : undefined;
@@ -4942,7 +5200,7 @@ function parseProvider(el, exportsSet, ctx) {
4942
5200
  ...cls ? { importPath: modulePath(ctx.rootDir, cls.getSourceFile().fileName) } : {}
4943
5201
  };
4944
5202
  }
4945
- if (!ts3.isObjectLiteralExpression(el))
5203
+ if (!ts4.isObjectLiteralExpression(el))
4946
5204
  return;
4947
5205
  const provideExpr = getProp(el, "provide");
4948
5206
  if (!provideExpr)
@@ -4957,8 +5215,8 @@ function parseProvider(el, exportsSet, ctx) {
4957
5215
  const useExistingExpr = getProp(el, "useExisting");
4958
5216
  if (useClassExpr) {
4959
5217
  const unwrappedClass = unwrapForwardRef(useClassExpr);
4960
- const decl = ts3.isIdentifier(unwrappedClass) ? resolveDeclaration(unwrappedClass, ctx)[0] : undefined;
4961
- const cls = decl && ts3.isClassDeclaration(decl) ? decl : undefined;
5218
+ const decl = ts4.isIdentifier(unwrappedClass) ? resolveDeclaration(unwrappedClass, ctx)[0] : undefined;
5219
+ const cls = decl && ts4.isClassDeclaration(decl) ? decl : undefined;
4962
5220
  const useClass = cls?.name?.text ?? nodeText(unwrappedClass);
4963
5221
  let deps = explicitDeps;
4964
5222
  let optionalDeps = [];
@@ -5014,7 +5272,7 @@ function parseProvider(el, exportsSet, ctx) {
5014
5272
  }
5015
5273
  if (useValueExpr) {
5016
5274
  validateProviderCompatibility(provideExpr, useValueExpr, "value", token, ctx, file, line);
5017
- const importPath = ts3.isIdentifier(useValueExpr) ? importPathOf(useValueExpr, ctx) : undefined;
5275
+ const importPath = ts4.isIdentifier(useValueExpr) ? importPathOf(useValueExpr, ctx) : undefined;
5018
5276
  return {
5019
5277
  token,
5020
5278
  tokenKind,
@@ -5030,12 +5288,12 @@ function parseProvider(el, exportsSet, ctx) {
5030
5288
  };
5031
5289
  }
5032
5290
  if (useFactoryExpr) {
5033
- const factoryName = ts3.isIdentifier(useFactoryExpr) ? (() => {
5291
+ const factoryName = ts4.isIdentifier(useFactoryExpr) ? (() => {
5034
5292
  const decl = resolveDeclaration(useFactoryExpr, ctx)[0];
5035
- return decl && (ts3.isFunctionDeclaration(decl) || ts3.isVariableDeclaration(decl)) ? (ts3.isFunctionDeclaration(decl) ? decl.name?.text : variableName(decl)) ?? useFactoryExpr.text : useFactoryExpr.text;
5293
+ return decl && (ts4.isFunctionDeclaration(decl) || ts4.isVariableDeclaration(decl)) ? (ts4.isFunctionDeclaration(decl) ? decl.name?.text : variableName(decl)) ?? useFactoryExpr.text : useFactoryExpr.text;
5036
5294
  })() : nodeText(useFactoryExpr);
5037
5295
  validateProviderCompatibility(provideExpr, useFactoryExpr, "factory", token, ctx, file, line);
5038
- const importPath = ts3.isIdentifier(useFactoryExpr) ? importPathOf(useFactoryExpr, ctx) : undefined;
5296
+ const importPath = ts4.isIdentifier(useFactoryExpr) ? importPathOf(useFactoryExpr, ctx) : undefined;
5039
5297
  return {
5040
5298
  token,
5041
5299
  tokenKind,
@@ -5071,20 +5329,20 @@ function parseProvider(el, exportsSet, ctx) {
5071
5329
  function expandProviderExpressions(expressions, ctx, seen = new Set) {
5072
5330
  const result = [];
5073
5331
  for (const expression of expressions) {
5074
- if (ts3.isSpreadElement(expression)) {
5332
+ if (ts4.isSpreadElement(expression)) {
5075
5333
  result.push(...expandProviderExpressions([expression.expression], ctx, seen));
5076
5334
  continue;
5077
5335
  }
5078
- if (ts3.isIdentifier(expression)) {
5336
+ if (ts4.isIdentifier(expression)) {
5079
5337
  const declaration = resolveDeclaration(expression, ctx)[0];
5080
- if (declaration && ts3.isVariableDeclaration(declaration) && declaration.initializer) {
5338
+ if (declaration && ts4.isVariableDeclaration(declaration) && declaration.initializer) {
5081
5339
  const key = `${declaration.getSourceFile().fileName}:${declaration.pos}`;
5082
5340
  if (seen.has(key))
5083
5341
  continue;
5084
5342
  const initializer = declaration.initializer;
5085
- if (ts3.isCallExpression(initializer) && isProviderHelper(initializer, "makeEnvironmentProviders")) {
5343
+ if (ts4.isCallExpression(initializer) && isProviderHelper(initializer, "makeEnvironmentProviders")) {
5086
5344
  const nested = initializer.arguments[0];
5087
- if (nested && ts3.isArrayLiteralExpression(nested)) {
5345
+ if (nested && ts4.isArrayLiteralExpression(nested)) {
5088
5346
  seen.add(key);
5089
5347
  result.push(...expandProviderExpressions([...nested.elements], ctx, seen));
5090
5348
  seen.delete(key);
@@ -5093,9 +5351,9 @@ function expandProviderExpressions(expressions, ctx, seen = new Set) {
5093
5351
  }
5094
5352
  }
5095
5353
  }
5096
- if (ts3.isCallExpression(expression) && isProviderHelper(expression, "makeEnvironmentProviders")) {
5354
+ if (ts4.isCallExpression(expression) && isProviderHelper(expression, "makeEnvironmentProviders")) {
5097
5355
  const nested = expression.arguments[0];
5098
- if (nested && ts3.isArrayLiteralExpression(nested)) {
5356
+ if (nested && ts4.isArrayLiteralExpression(nested)) {
5099
5357
  result.push(...expandProviderExpressions([...nested.elements], ctx, seen));
5100
5358
  continue;
5101
5359
  }
@@ -5108,7 +5366,7 @@ function isProviderHelper(expression, name) {
5108
5366
  return nodeText(expression.expression).split(".").pop() === name;
5109
5367
  }
5110
5368
  function parseFunctionalProvider(expression, exportsSet, ctx) {
5111
- if (!ts3.isCallExpression(expression))
5369
+ if (!ts4.isCallExpression(expression))
5112
5370
  return;
5113
5371
  const helper = nodeText(expression.expression).split(".").pop();
5114
5372
  const args = expression.arguments;
@@ -5121,7 +5379,7 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
5121
5379
  return [];
5122
5380
  const { name: token, kind: tokenKind } = tokenNameOf(tokenExpr, ctx);
5123
5381
  validateProviderCompatibility(tokenExpr, valueExpr, "value", token, ctx, file, line);
5124
- const importPath = ts3.isIdentifier(valueExpr) ? importPathOf(valueExpr, ctx) : undefined;
5382
+ const importPath = ts4.isIdentifier(valueExpr) ? importPathOf(valueExpr, ctx) : undefined;
5125
5383
  return [{
5126
5384
  token,
5127
5385
  tokenKind,
@@ -5140,7 +5398,7 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
5140
5398
  if (!initializer)
5141
5399
  return [];
5142
5400
  const token = helper === "provideAppInitializer" ? "APP_INITIALIZER" : "ENVIRONMENT_INITIALIZER";
5143
- const importPath = ts3.isIdentifier(initializer) ? importPathOf(initializer, ctx) : undefined;
5401
+ const importPath = ts4.isIdentifier(initializer) ? importPathOf(initializer, ctx) : undefined;
5144
5402
  return [{
5145
5403
  token,
5146
5404
  tokenKind: "injection-token",
@@ -5159,7 +5417,7 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
5159
5417
  const providers = [];
5160
5418
  const routes = args[0];
5161
5419
  if (routes) {
5162
- const importPath = ts3.isIdentifier(routes) ? importPathOf(routes, ctx) : undefined;
5420
+ const importPath = ts4.isIdentifier(routes) ? importPathOf(routes, ctx) : undefined;
5163
5421
  providers.push({
5164
5422
  token: "ROUTE_CONFIG",
5165
5423
  tokenKind: "injection-token",
@@ -5174,7 +5432,7 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
5174
5432
  });
5175
5433
  }
5176
5434
  for (const feature of args.slice(1)) {
5177
- if (!ts3.isCallExpression(feature))
5435
+ if (!ts4.isCallExpression(feature))
5178
5436
  continue;
5179
5437
  const featureName = nodeText(feature.expression).split(".").pop();
5180
5438
  if (featureName === "withRouterConfig" && feature.arguments[0]) {
@@ -5191,8 +5449,8 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
5191
5449
  });
5192
5450
  } else if (featureName === "withTitleStrategy" && feature.arguments[0]) {
5193
5451
  const strategy = feature.arguments[0];
5194
- const isClass = ts3.isIdentifier(strategy) && Boolean(resolveDeclaration(strategy, ctx).find((declaration) => ts3.isClassDeclaration(declaration)));
5195
- const importPath = ts3.isIdentifier(strategy) ? importPathOf(strategy, ctx) : undefined;
5452
+ const isClass = ts4.isIdentifier(strategy) && Boolean(resolveDeclaration(strategy, ctx).find((declaration) => ts4.isClassDeclaration(declaration)));
5453
+ const importPath = ts4.isIdentifier(strategy) ? importPathOf(strategy, ctx) : undefined;
5196
5454
  providers.push({
5197
5455
  token: "TITLE_STRATEGY",
5198
5456
  tokenKind: "injection-token",
@@ -5224,14 +5482,14 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
5224
5482
  importModule: "@supacloud/app"
5225
5483
  }];
5226
5484
  for (const feature of args) {
5227
- if (!ts3.isCallExpression(feature))
5485
+ if (!ts4.isCallExpression(feature))
5228
5486
  continue;
5229
5487
  const featureName = nodeText(feature.expression).split(".").pop();
5230
5488
  if (featureName === "withInterceptors") {
5231
5489
  for (const interceptorArg of feature.arguments) {
5232
- const values = ts3.isArrayLiteralExpression(interceptorArg) ? [...interceptorArg.elements] : [interceptorArg];
5490
+ const values = ts4.isArrayLiteralExpression(interceptorArg) ? [...interceptorArg.elements] : [interceptorArg];
5233
5491
  for (const value of values) {
5234
- const importPath = ts3.isIdentifier(value) ? importPathOf(value, ctx) : undefined;
5492
+ const importPath = ts4.isIdentifier(value) ? importPathOf(value, ctx) : undefined;
5235
5493
  providers.push({
5236
5494
  token: "HTTP_INTERCEPTORS",
5237
5495
  tokenKind: "injection-token",
@@ -5278,9 +5536,9 @@ function providerTokenValueType(expr, ctx) {
5278
5536
  const typeArguments = typeArgumentsOf(type, ctx);
5279
5537
  if (typeArguments.length > 0)
5280
5538
  return typeArguments[0];
5281
- if (ts3.isIdentifier(expr)) {
5539
+ if (ts4.isIdentifier(expr)) {
5282
5540
  const declaration = resolveDeclaration(expr, ctx)[0];
5283
- if (declaration && ts3.isClassDeclaration(declaration)) {
5541
+ if (declaration && ts4.isClassDeclaration(declaration)) {
5284
5542
  return declaredClassType(declaration, ctx);
5285
5543
  }
5286
5544
  }
@@ -5288,9 +5546,9 @@ function providerTokenValueType(expr, ctx) {
5288
5546
  }
5289
5547
  function providerImplementationType(expr, kind, ctx) {
5290
5548
  if (kind === "class" || kind === "existing") {
5291
- if (ts3.isIdentifier(expr)) {
5549
+ if (ts4.isIdentifier(expr)) {
5292
5550
  const declaration = resolveDeclaration(expr, ctx)[0];
5293
- if (declaration && ts3.isClassDeclaration(declaration)) {
5551
+ if (declaration && ts4.isClassDeclaration(declaration)) {
5294
5552
  return declaredClassType(declaration, ctx);
5295
5553
  }
5296
5554
  }
@@ -5300,7 +5558,7 @@ function providerImplementationType(expr, kind, ctx) {
5300
5558
  }
5301
5559
  if (kind === "factory") {
5302
5560
  const type = ctx.checker.getTypeAtLocation(expr);
5303
- const signature = ctx.checker.getSignaturesOfType(type, ts3.SignatureKind.Call)[0];
5561
+ const signature = ctx.checker.getSignaturesOfType(type, ts4.SignatureKind.Call)[0];
5304
5562
  return signature?.getReturnType();
5305
5563
  }
5306
5564
  return ctx.checker.getTypeAtLocation(expr);
@@ -5319,16 +5577,16 @@ function isTypeReference(type) {
5319
5577
  return "target" in type;
5320
5578
  }
5321
5579
  function isUnknownOrAny(type) {
5322
- return (type.flags & (ts3.TypeFlags.Any | ts3.TypeFlags.Unknown)) !== 0;
5580
+ return (type.flags & (ts4.TypeFlags.Any | ts4.TypeFlags.Unknown)) !== 0;
5323
5581
  }
5324
5582
  function parseController(input, ctx) {
5325
5583
  let decl;
5326
- if (ts3.isClassDeclaration(input)) {
5584
+ if (ts4.isClassDeclaration(input)) {
5327
5585
  decl = input;
5328
5586
  } else {
5329
5587
  const unwrapped = unwrapForwardRef(input);
5330
- const resolved = ts3.isIdentifier(unwrapped) ? resolveDeclaration(unwrapped, ctx)[0] : undefined;
5331
- if (resolved && ts3.isClassDeclaration(resolved)) {
5588
+ const resolved = ts4.isIdentifier(unwrapped) ? resolveDeclaration(unwrapped, ctx)[0] : undefined;
5589
+ if (resolved && ts4.isClassDeclaration(resolved)) {
5332
5590
  decl = resolved;
5333
5591
  }
5334
5592
  }
@@ -5341,9 +5599,9 @@ function parseController(input, ctx) {
5341
5599
  let standalone;
5342
5600
  const pathArg = decoratorArguments(controllerDec)[0];
5343
5601
  if (pathArg) {
5344
- if (ts3.isStringLiteral(pathArg)) {
5602
+ if (ts4.isStringLiteral(pathArg)) {
5345
5603
  path = pathArg.text;
5346
- } else if (ts3.isObjectLiteralExpression(pathArg)) {
5604
+ } else if (ts4.isObjectLiteralExpression(pathArg)) {
5347
5605
  const p = stringLiteralProp(pathArg, "path");
5348
5606
  if (p)
5349
5607
  path = p;
@@ -5366,7 +5624,7 @@ function parseController(input, ctx) {
5366
5624
  }
5367
5625
  }
5368
5626
  }
5369
- for (const method of decl.members.filter(ts3.isMethodDeclaration)) {
5627
+ for (const method of decl.members.filter(ts4.isMethodDeclaration)) {
5370
5628
  for (const dec of decoratorsOf(method)) {
5371
5629
  const name = decoratorName2(dec);
5372
5630
  const httpMethod = name ? ROUTE_DECORATORS[name] : undefined;
@@ -5374,7 +5632,7 @@ function parseController(input, ctx) {
5374
5632
  continue;
5375
5633
  const args = decoratorArguments(dec);
5376
5634
  const pathArg = args[0];
5377
- const routePath = pathArg && ts3.isStringLiteral(pathArg) ? pathArg.text : "/";
5635
+ const routePath = pathArg && ts4.isStringLiteral(pathArg) ? pathArg.text : "/";
5378
5636
  const route = {
5379
5637
  method: httpMethod,
5380
5638
  path: routePath,
@@ -5445,12 +5703,12 @@ function parseController(input, ctx) {
5445
5703
  } else if (dName === "Headers") {
5446
5704
  hasBindingDecorator = true;
5447
5705
  const argument = dArgs[0];
5448
- const bindingName = argument !== undefined && ts3.isStringLiteral(argument) ? argument.text : undefined;
5706
+ const bindingName = argument !== undefined && ts4.isStringLiteral(argument) ? argument.text : undefined;
5449
5707
  paramNode = { name: pName, kind: "headers", ...bindingName === undefined ? {} : { bindingName } };
5450
5708
  } else if (dName === "Cookie") {
5451
5709
  hasBindingDecorator = true;
5452
5710
  const argument = dArgs[0];
5453
- const bindingName = argument !== undefined && ts3.isStringLiteral(argument) ? argument.text : undefined;
5711
+ const bindingName = argument !== undefined && ts4.isStringLiteral(argument) ? argument.text : undefined;
5454
5712
  paramNode = { name: pName, kind: "cookie", ...bindingName === undefined ? {} : { bindingName } };
5455
5713
  }
5456
5714
  }
@@ -5512,20 +5770,20 @@ function parseController(input, ctx) {
5512
5770
  }
5513
5771
  } else if (dName === "Title") {
5514
5772
  const tArg = mArgs[0];
5515
- if (tArg && ts3.isStringLiteral(tArg)) {
5773
+ if (tArg && ts4.isStringLiteral(tArg)) {
5516
5774
  route.title = tArg.text;
5517
5775
  }
5518
5776
  } else if (dName === "Data") {
5519
5777
  const dArg = mArgs[0];
5520
- if (dArg && ts3.isObjectLiteralExpression(dArg)) {
5778
+ if (dArg && ts4.isObjectLiteralExpression(dArg)) {
5521
5779
  route.data = { ...route.data, ...parseObjectLiteralValues(dArg) };
5522
5780
  }
5523
5781
  } else if (dName === "Resolve") {
5524
5782
  const rArg = mArgs[0];
5525
- if (rArg && ts3.isObjectLiteralExpression(rArg)) {
5783
+ if (rArg && ts4.isObjectLiteralExpression(rArg)) {
5526
5784
  const resolvers = route.resolvers ?? {};
5527
5785
  for (const prop of rArg.properties) {
5528
- if (ts3.isPropertyAssignment(prop)) {
5786
+ if (ts4.isPropertyAssignment(prop)) {
5529
5787
  const rName = propertyName(prop.name);
5530
5788
  const init = prop.initializer;
5531
5789
  if (init)
@@ -5556,7 +5814,7 @@ function parseController(input, ctx) {
5556
5814
  });
5557
5815
  }
5558
5816
  const contract = getProp(optionsObject, "contract");
5559
- if (contract && ts3.isObjectLiteralExpression(contract)) {
5817
+ if (contract && ts4.isObjectLiteralExpression(contract)) {
5560
5818
  route.contract = {};
5561
5819
  for (const field of ["body", "response", "evidence"]) {
5562
5820
  const value = stringLiteralProp(contract, field);
@@ -5574,15 +5832,15 @@ function parseController(input, ctx) {
5574
5832
  }
5575
5833
  for (const field of ["body", "params", "query", "headers", "cookie", "response"]) {
5576
5834
  const schemaExpr = getProp(optionsObject, field);
5577
- if (schemaExpr && ts3.isIdentifier(schemaExpr)) {
5835
+ if (schemaExpr && ts4.isIdentifier(schemaExpr)) {
5578
5836
  route[field] = nodeText(schemaExpr);
5579
5837
  const importPath = importPathOf(schemaExpr, ctx);
5580
5838
  if (importPath)
5581
5839
  schemaImports[schemaExpr.text] = importPath;
5582
5840
  const declaration = resolveDeclaration(schemaExpr, ctx)[0];
5583
5841
  const typeName = ctx.checker.typeToString(ctx.checker.getTypeAtLocation(schemaExpr));
5584
- const initializer = declaration && ts3.isVariableDeclaration(declaration) ? declaration.initializer : undefined;
5585
- const opaque = /\bT(?:Unknown|Any)\b/.test(typeName) || initializer && ts3.isCallExpression(initializer) && ts3.isPropertyAccessExpression(initializer.expression) && ["Unknown", "Any"].includes(initializer.expression.name.text);
5842
+ const initializer = declaration && ts4.isVariableDeclaration(declaration) ? declaration.initializer : undefined;
5843
+ const opaque = /\bT(?:Unknown|Any)\b/.test(typeName) || initializer && ts4.isCallExpression(initializer) && ts4.isPropertyAccessExpression(initializer.expression) && ["Unknown", "Any"].includes(initializer.expression.name.text);
5586
5844
  (route.schemaKinds ??= {})[field] = opaque ? "opaque" : "declared";
5587
5845
  }
5588
5846
  }
@@ -5591,7 +5849,7 @@ function parseController(input, ctx) {
5591
5849
  const responses = {};
5592
5850
  const selectors = new Map;
5593
5851
  for (const property of responsesObject.properties) {
5594
- if (!ts3.isPropertyAssignment(property) || ts3.isComputedPropertyName(property.name))
5852
+ if (!ts4.isPropertyAssignment(property) || ts4.isComputedPropertyName(property.name))
5595
5853
  continue;
5596
5854
  const status = propertyName(property.name);
5597
5855
  if (!isRouteResponseSelector(status)) {
@@ -5623,7 +5881,7 @@ function parseController(input, ctx) {
5623
5881
  }
5624
5882
  selectors.set(canonical, status);
5625
5883
  const schemaExpr = property.initializer;
5626
- if (!ts3.isIdentifier(schemaExpr)) {
5884
+ if (!ts4.isIdentifier(schemaExpr)) {
5627
5885
  ctx.diagnostics.push({
5628
5886
  severity: "error",
5629
5887
  code: "invalid-route-response-map",
@@ -5638,8 +5896,8 @@ function parseController(input, ctx) {
5638
5896
  schemaImports[schemaExpr.text] = importPath;
5639
5897
  const declaration = resolveDeclaration(schemaExpr, ctx)[0];
5640
5898
  const typeName = ctx.checker.typeToString(ctx.checker.getTypeAtLocation(schemaExpr));
5641
- const initializer = declaration && ts3.isVariableDeclaration(declaration) ? declaration.initializer : undefined;
5642
- const opaque = /\bT(?:Unknown|Any)\b/.test(typeName) || initializer && ts3.isCallExpression(initializer) && ts3.isPropertyAccessExpression(initializer.expression) && ["Unknown", "Any"].includes(initializer.expression.name.text);
5899
+ const initializer = declaration && ts4.isVariableDeclaration(declaration) ? declaration.initializer : undefined;
5900
+ const opaque = /\bT(?:Unknown|Any)\b/.test(typeName) || initializer && ts4.isCallExpression(initializer) && ts4.isPropertyAccessExpression(initializer.expression) && ["Unknown", "Any"].includes(initializer.expression.name.text);
5643
5901
  const previousKind = route.schemaKinds?.response;
5644
5902
  (route.schemaKinds ??= {}).response = opaque || previousKind === "opaque" ? "opaque" : "declared";
5645
5903
  }
@@ -5647,18 +5905,18 @@ function parseController(input, ctx) {
5647
5905
  route.responses = responses;
5648
5906
  }
5649
5907
  const commandExpr = getProp(optionsObject, "command");
5650
- if (commandExpr && ts3.isIdentifier(commandExpr)) {
5908
+ if (commandExpr && ts4.isIdentifier(commandExpr)) {
5651
5909
  const commandDecl = resolveDeclaration(commandExpr, ctx)[0];
5652
- route.command = commandDecl && ts3.isClassDeclaration(commandDecl) ? commandDecl.name?.text ?? commandExpr.text : commandExpr.text;
5910
+ route.command = commandDecl && ts4.isClassDeclaration(commandDecl) ? commandDecl.name?.text ?? commandExpr.text : commandExpr.text;
5653
5911
  }
5654
5912
  const guardsExpr = getProp(optionsObject, "guards");
5655
- if (guardsExpr && ts3.isArrayLiteralExpression(guardsExpr)) {
5913
+ if (guardsExpr && ts4.isArrayLiteralExpression(guardsExpr)) {
5656
5914
  for (const el of guardsExpr.elements) {
5657
5915
  routeGuards.push(tokenText(el, ctx));
5658
5916
  }
5659
5917
  }
5660
5918
  const canMatchExpr = getProp(optionsObject, "canMatch");
5661
- if (canMatchExpr && ts3.isArrayLiteralExpression(canMatchExpr)) {
5919
+ if (canMatchExpr && ts4.isArrayLiteralExpression(canMatchExpr)) {
5662
5920
  const canMatchList = [];
5663
5921
  for (const el of canMatchExpr.elements) {
5664
5922
  canMatchList.push(tokenText(el, ctx));
@@ -5668,16 +5926,16 @@ function parseController(input, ctx) {
5668
5926
  }
5669
5927
  }
5670
5928
  const canDeactivateExpr = getProp(optionsObject, "canDeactivate");
5671
- if (canDeactivateExpr && ts3.isArrayLiteralExpression(canDeactivateExpr)) {
5929
+ if (canDeactivateExpr && ts4.isArrayLiteralExpression(canDeactivateExpr)) {
5672
5930
  for (const el of canDeactivateExpr.elements) {
5673
5931
  routeCanDeactivate.push(tokenText(el, ctx));
5674
5932
  }
5675
5933
  }
5676
5934
  const resolversExpr = getProp(optionsObject, "resolvers");
5677
- if (resolversExpr && ts3.isObjectLiteralExpression(resolversExpr)) {
5935
+ if (resolversExpr && ts4.isObjectLiteralExpression(resolversExpr)) {
5678
5936
  const resolvers = {};
5679
5937
  for (const prop of resolversExpr.properties) {
5680
- if (ts3.isPropertyAssignment(prop)) {
5938
+ if (ts4.isPropertyAssignment(prop)) {
5681
5939
  const rName = propertyName(prop.name);
5682
5940
  const init = prop.initializer;
5683
5941
  if (init)
@@ -5689,22 +5947,22 @@ function parseController(input, ctx) {
5689
5947
  }
5690
5948
  }
5691
5949
  const redirectToExpr = getProp(optionsObject, "redirectTo");
5692
- if (redirectToExpr && ts3.isStringLiteral(redirectToExpr)) {
5950
+ if (redirectToExpr && ts4.isStringLiteral(redirectToExpr)) {
5693
5951
  route.redirectTo = redirectToExpr.text;
5694
5952
  }
5695
5953
  const pathMatchExpr = getProp(optionsObject, "pathMatch");
5696
- if (pathMatchExpr && ts3.isStringLiteral(pathMatchExpr)) {
5954
+ if (pathMatchExpr && ts4.isStringLiteral(pathMatchExpr)) {
5697
5955
  const val = pathMatchExpr.text;
5698
5956
  if (val === "full" || val === "prefix") {
5699
5957
  route.pathMatch = val;
5700
5958
  }
5701
5959
  }
5702
5960
  const titleExpr = getProp(optionsObject, "title");
5703
- if (titleExpr && ts3.isStringLiteral(titleExpr)) {
5961
+ if (titleExpr && ts4.isStringLiteral(titleExpr)) {
5704
5962
  route.title = titleExpr.text;
5705
5963
  }
5706
5964
  const dataExpr = getProp(optionsObject, "data");
5707
- if (dataExpr && ts3.isObjectLiteralExpression(dataExpr)) {
5965
+ if (dataExpr && ts4.isObjectLiteralExpression(dataExpr)) {
5708
5966
  route.data = { ...route.data, ...parseObjectLiteralValues(dataExpr) };
5709
5967
  }
5710
5968
  const aspects = parseAspectRefs(getProp(optionsObject, "aspects"), ctx, `route ${httpMethod} ${routePath}`);
@@ -5759,7 +6017,7 @@ function parseJobOptions(meta, owner, ctx) {
5759
6017
  const expression = getProp(meta, field);
5760
6018
  if (!expression)
5761
6019
  continue;
5762
- if (!ts3.isIdentifier(expression)) {
6020
+ if (!ts4.isIdentifier(expression)) {
5763
6021
  jobOptionError(ctx, "invalid-job-schema", `${owner} 的 ${field} schema 必须是可静态解析的标识符引用,不能使用内联调用或动态表达式`, expression, "SC4019", `将 schema 提取为命名导出,例如 ${field}: ${field === "input" ? "JobInput" : "JobOutput"}。`);
5764
6022
  continue;
5765
6023
  }
@@ -5783,7 +6041,7 @@ function parseJobEnum(meta, field, allowed, owner, ctx, code, errorCode) {
5783
6041
  const expression = getProp(meta, field);
5784
6042
  if (!expression)
5785
6043
  return;
5786
- if (!ts3.isStringLiteral(expression) || !allowed.includes(expression.text)) {
6044
+ if (!ts4.isStringLiteral(expression) || !allowed.includes(expression.text)) {
5787
6045
  jobOptionError(ctx, code, `${owner} 的 ${field} 必须是 ${allowed.map((value) => JSON.stringify(value)).join(" 或 ")} 字符串字面量`, expression, errorCode);
5788
6046
  return;
5789
6047
  }
@@ -5793,7 +6051,7 @@ function parseJobInteger(meta, field, min, max, owner, ctx, code, errorCode) {
5793
6051
  const expression = getProp(meta, field);
5794
6052
  if (!expression)
5795
6053
  return;
5796
- const value = ts3.isNumericLiteral(expression) ? Number(expression.text) : Number.NaN;
6054
+ const value = ts4.isNumericLiteral(expression) ? Number(expression.text) : Number.NaN;
5797
6055
  if (!Number.isSafeInteger(value) || value < min || value > max) {
5798
6056
  jobOptionError(ctx, code, `${owner} 的 ${field} 必须是 ${min} 到 ${max} 之间的安全整数`, expression, errorCode);
5799
6057
  return;
@@ -5814,8 +6072,8 @@ function jobOptionError(ctx, code, message, node, errorCode, suggestion) {
5814
6072
  }
5815
6073
  function jobSchemaKind(identifier, declaration, ctx) {
5816
6074
  const typeName = ctx.checker.typeToString(ctx.checker.getTypeAtLocation(identifier));
5817
- const initializer = ts3.isVariableDeclaration(declaration) ? declaration.initializer : undefined;
5818
- const opaque = /\bT(?:Unknown|Any)\b/.test(typeName) || initializer && ts3.isCallExpression(initializer) && ts3.isPropertyAccessExpression(initializer.expression) && ["Unknown", "Any"].includes(initializer.expression.name.text);
6075
+ const initializer = ts4.isVariableDeclaration(declaration) ? declaration.initializer : undefined;
6076
+ const opaque = /\bT(?:Unknown|Any)\b/.test(typeName) || initializer && ts4.isCallExpression(initializer) && ts4.isPropertyAccessExpression(initializer.expression) && ["Unknown", "Any"].includes(initializer.expression.name.text);
5819
6077
  return opaque ? "opaque" : "declared";
5820
6078
  }
5821
6079
  function checkedRpc(meta, ctx) {
@@ -5837,7 +6095,7 @@ function checkedRpc(meta, ctx) {
5837
6095
  }
5838
6096
  function classDeps(cls, ctx) {
5839
6097
  const injectable = parseInjectableOptions(cls, ctx);
5840
- const ctor = cls.members.find(ts3.isConstructorDeclaration);
6098
+ const ctor = cls.members.find(ts4.isConstructorDeclaration);
5841
6099
  const deps = injectable?.deps ? [...injectable.deps] : [];
5842
6100
  const optionalDeps = [];
5843
6101
  const selfDeps = [];
@@ -5871,23 +6129,23 @@ function classDeps(cls, ctx) {
5871
6129
  }
5872
6130
  });
5873
6131
  }
5874
- for (const prop of cls.members.filter(ts3.isPropertyDeclaration)) {
6132
+ for (const prop of cls.members.filter(ts4.isPropertyDeclaration)) {
5875
6133
  const init = prop.initializer;
5876
- if (init && ts3.isCallExpression(init)) {
6134
+ if (init && ts4.isCallExpression(init)) {
5877
6135
  const callName = nodeText(init.expression).split(".").pop();
5878
6136
  if (callName === "inject") {
5879
6137
  const [tokenArg, optionsArg] = init.arguments;
5880
6138
  if (tokenArg) {
5881
6139
  const tokenName = tokenText(tokenArg, ctx);
5882
6140
  const unwrappedToken = unwrapForwardRef(tokenArg);
5883
- const known = ts3.isStringLiteral(unwrappedToken) || ts3.isIdentifier(unwrappedToken) && (ctx.tokensByName.has(tokenName) || ctx.classesByName.has(tokenName));
6141
+ const known = ts4.isStringLiteral(unwrappedToken) || ts4.isIdentifier(unwrappedToken) && (ctx.tokensByName.has(tokenName) || ctx.classesByName.has(tokenName));
5884
6142
  if (!known) {
5885
6143
  missing = true;
5886
6144
  continue;
5887
6145
  }
5888
6146
  if (!deps.includes(tokenName))
5889
6147
  deps.push(tokenName);
5890
- const options = optionsArg && ts3.isObjectLiteralExpression(optionsArg) ? {
6148
+ const options = optionsArg && ts4.isObjectLiteralExpression(optionsArg) ? {
5891
6149
  optional: booleanProp(optionsArg, "optional") ?? false,
5892
6150
  self: booleanProp(optionsArg, "self") ?? false,
5893
6151
  skipSelf: booleanProp(optionsArg, "skipSelf") ?? false,
@@ -5902,9 +6160,9 @@ function classDeps(cls, ctx) {
5902
6160
  if (options.host && !hostDeps.includes(tokenName))
5903
6161
  hostDeps.push(tokenName);
5904
6162
  if (!functionalInjects.some((entry) => entry.token === tokenName)) {
5905
- const declaration = ts3.isIdentifier(unwrappedToken) ? resolveDeclaration(unwrappedToken, ctx)[0] : undefined;
6163
+ const declaration = ts4.isIdentifier(unwrappedToken) ? resolveDeclaration(unwrappedToken, ctx)[0] : undefined;
5906
6164
  const localFile = declaration && isProjectSourcePath(declaration.getSourceFile().fileName, ctx.rootDir) ? declaration.getSourceFile().fileName : undefined;
5907
- const importModule = declaration && !localFile && ts3.isIdentifier(unwrappedToken) ? importModuleOf(unwrappedToken, ctx) : undefined;
6165
+ const importModule = declaration && !localFile && ts4.isIdentifier(unwrappedToken) ? importModuleOf(unwrappedToken, ctx) : undefined;
5908
6166
  functionalInjects.push({
5909
6167
  token: tokenName,
5910
6168
  expression: nodeText(unwrappedToken),
@@ -5948,7 +6206,7 @@ function parseInjectableOptions(cls, ctx) {
5948
6206
  }
5949
6207
  function parseInjectParams(cls, ctx) {
5950
6208
  const result = new Map;
5951
- const ctor = cls.members.find(ts3.isConstructorDeclaration);
6209
+ const ctor = cls.members.find(ts4.isConstructorDeclaration);
5952
6210
  if (!ctor)
5953
6211
  return result;
5954
6212
  ctor.parameters.forEach((param, index) => {
@@ -5964,7 +6222,7 @@ function parseInjectParams(cls, ctx) {
5964
6222
  }
5965
6223
  function parseOptionalParams(cls) {
5966
6224
  const result = new Set;
5967
- const ctor = cls.members.find(ts3.isConstructorDeclaration);
6225
+ const ctor = cls.members.find(ts4.isConstructorDeclaration);
5968
6226
  if (!ctor)
5969
6227
  return result;
5970
6228
  ctor.parameters.forEach((param, index) => {
@@ -5979,7 +6237,7 @@ function parseOptionalParams(cls) {
5979
6237
  }
5980
6238
  function parseModifierParams(cls, modifierName) {
5981
6239
  const result = new Set;
5982
- const ctor = cls.members.find(ts3.isConstructorDeclaration);
6240
+ const ctor = cls.members.find(ts4.isConstructorDeclaration);
5983
6241
  if (!ctor)
5984
6242
  return result;
5985
6243
  ctor.parameters.forEach((param, index) => {
@@ -5991,13 +6249,13 @@ function parseModifierParams(cls, modifierName) {
5991
6249
  return result;
5992
6250
  }
5993
6251
  function unwrapForwardRef(expr) {
5994
- if (ts3.isCallExpression(expr)) {
6252
+ if (ts4.isCallExpression(expr)) {
5995
6253
  const exprText = nodeText(expr.expression);
5996
6254
  if (exprText === "forwardRef" || exprText.endsWith(".forwardRef")) {
5997
6255
  const arg = expr.arguments[0];
5998
- if (arg && (ts3.isArrowFunction(arg) || ts3.isFunctionExpression(arg))) {
6256
+ if (arg && (ts4.isArrowFunction(arg) || ts4.isFunctionExpression(arg))) {
5999
6257
  const body = arg.body;
6000
- if (body && ts3.isExpression(body)) {
6258
+ if (body && ts4.isExpression(body)) {
6001
6259
  return unwrapForwardRef(body);
6002
6260
  }
6003
6261
  }
@@ -6007,13 +6265,13 @@ function unwrapForwardRef(expr) {
6007
6265
  }
6008
6266
  function tokenText(expr, ctx) {
6009
6267
  const unwrapped = unwrapForwardRef(expr);
6010
- if (ts3.isStringLiteral(unwrapped))
6268
+ if (ts4.isStringLiteral(unwrapped))
6011
6269
  return unwrapped.text;
6012
- if (ts3.isIdentifier(unwrapped)) {
6270
+ if (ts4.isIdentifier(unwrapped)) {
6013
6271
  const decl = resolveDeclaration(unwrapped, ctx)[0];
6014
- if (decl && ts3.isClassDeclaration(decl))
6272
+ if (decl && ts4.isClassDeclaration(decl))
6015
6273
  return decl.name?.text ?? unwrapped.text;
6016
- if (decl && ts3.isVariableDeclaration(decl))
6274
+ if (decl && ts4.isVariableDeclaration(decl))
6017
6275
  return variableName(decl);
6018
6276
  }
6019
6277
  return nodeText(unwrapped);
@@ -6033,12 +6291,12 @@ function resolveScope(input, ctx) {
6033
6291
  }
6034
6292
  function tokenNameOf(expr, ctx) {
6035
6293
  const unwrapped = unwrapForwardRef(expr);
6036
- if (ts3.isIdentifier(unwrapped)) {
6294
+ if (ts4.isIdentifier(unwrapped)) {
6037
6295
  const decl = resolveDeclaration(unwrapped, ctx)[0];
6038
- if (decl && ts3.isClassDeclaration(decl)) {
6296
+ if (decl && ts4.isClassDeclaration(decl)) {
6039
6297
  return { name: decl.name?.text ?? nodeText(expr), kind: "class" };
6040
6298
  }
6041
- if (decl && ts3.isVariableDeclaration(decl)) {
6299
+ if (decl && ts4.isVariableDeclaration(decl)) {
6042
6300
  const name = variableName(decl);
6043
6301
  return { name, kind: ctx.tokensByName.has(name) ? "injection-token" : "class" };
6044
6302
  }
@@ -6054,10 +6312,10 @@ function resolveDeclaration(id, ctx) {
6054
6312
  return [];
6055
6313
  let declarations = symbol.declarations ?? [];
6056
6314
  for (let guard = 0;guard < 4; guard += 1) {
6057
- const isAlias = declarations.some((d) => ts3.isImportSpecifier(d) || ts3.isImportClause(d) || ts3.isNamespaceImport(d));
6315
+ const isAlias = declarations.some((d) => ts4.isImportSpecifier(d) || ts4.isImportClause(d) || ts4.isNamespaceImport(d));
6058
6316
  if (!isAlias)
6059
6317
  break;
6060
- if (!(symbol.flags & ts3.SymbolFlags.Alias))
6318
+ if (!(symbol.flags & ts4.SymbolFlags.Alias))
6061
6319
  break;
6062
6320
  const aliased = ctx.checker.getAliasedSymbol(symbol);
6063
6321
  symbol = aliased;
@@ -6077,9 +6335,9 @@ function importModuleOf(id, ctx) {
6077
6335
  for (const declaration of declarations) {
6078
6336
  let current = declaration;
6079
6337
  while (current) {
6080
- if (ts3.isImportDeclaration(current)) {
6338
+ if (ts4.isImportDeclaration(current)) {
6081
6339
  const moduleSpecifier = current.moduleSpecifier;
6082
- return ts3.isStringLiteral(moduleSpecifier) ? moduleSpecifier.text : undefined;
6340
+ return ts4.isStringLiteral(moduleSpecifier) ? moduleSpecifier.text : undefined;
6083
6341
  }
6084
6342
  current = current.parent;
6085
6343
  }
@@ -6091,27 +6349,27 @@ function findDecorator(cls, name) {
6091
6349
  }
6092
6350
  function decoratorName2(dec) {
6093
6351
  const expr = dec.expression;
6094
- if (ts3.isCallExpression(expr)) {
6352
+ if (ts4.isCallExpression(expr)) {
6095
6353
  return nodeText(expr.expression).split(".").pop();
6096
6354
  }
6097
- if (ts3.isIdentifier(expr))
6355
+ if (ts4.isIdentifier(expr))
6098
6356
  return expr.text;
6099
6357
  return;
6100
6358
  }
6101
6359
  function decoratorObjectArg(dec) {
6102
6360
  const expr = dec.expression;
6103
- if (!ts3.isCallExpression(expr))
6361
+ if (!ts4.isCallExpression(expr))
6104
6362
  return;
6105
6363
  const arg = expr.arguments[0];
6106
- return arg && ts3.isObjectLiteralExpression(arg) ? arg : undefined;
6364
+ return arg && ts4.isObjectLiteralExpression(arg) ? arg : undefined;
6107
6365
  }
6108
6366
  function getProp(obj, name) {
6109
- const prop = obj.properties.find((item) => (ts3.isPropertyAssignment(item) || ts3.isShorthandPropertyAssignment(item)) && propertyName(item.name) === name);
6367
+ const prop = obj.properties.find((item) => (ts4.isPropertyAssignment(item) || ts4.isShorthandPropertyAssignment(item)) && propertyName(item.name) === name);
6110
6368
  if (!prop)
6111
6369
  return;
6112
- if (ts3.isPropertyAssignment(prop))
6370
+ if (ts4.isPropertyAssignment(prop))
6113
6371
  return prop.initializer;
6114
- if (ts3.isShorthandPropertyAssignment(prop))
6372
+ if (ts4.isShorthandPropertyAssignment(prop))
6115
6373
  return prop.name;
6116
6374
  return;
6117
6375
  }
@@ -6119,10 +6377,10 @@ function toCompilerDiagnostic(diagnostic, rootDir) {
6119
6377
  const file = diagnostic.file;
6120
6378
  const position = file && diagnostic.start !== undefined ? file.getLineAndCharacterOfPosition(diagnostic.start) : undefined;
6121
6379
  return {
6122
- severity: diagnostic.category === ts3.DiagnosticCategory.Error ? "error" : "warn",
6380
+ severity: diagnostic.category === ts4.DiagnosticCategory.Error ? "error" : "warn",
6123
6381
  code: `typescript-${diagnostic.code}`,
6124
6382
  errorCode: `TS${diagnostic.code}`,
6125
- message: ts3.flattenDiagnosticMessageText(diagnostic.messageText, `
6383
+ message: ts4.flattenDiagnosticMessageText(diagnostic.messageText, `
6126
6384
  `),
6127
6385
  ...file ? { file: sourcePath(rootDir, file.fileName) } : {},
6128
6386
  ...position ? { line: position.line + 1 } : {}
@@ -6130,16 +6388,16 @@ function toCompilerDiagnostic(diagnostic, rootDir) {
6130
6388
  }
6131
6389
  function stringLiteralProp(obj, name) {
6132
6390
  const expr = getProp(obj, name);
6133
- return expr && ts3.isStringLiteral(expr) ? expr.text : undefined;
6391
+ return expr && ts4.isStringLiteral(expr) ? expr.text : undefined;
6134
6392
  }
6135
6393
  function arrayProp(obj, name) {
6136
6394
  const expr = getProp(obj, name);
6137
- return expr && ts3.isArrayLiteralExpression(expr) ? [...expr.elements] : [];
6395
+ return expr && ts4.isArrayLiteralExpression(expr) ? [...expr.elements] : [];
6138
6396
  }
6139
6397
  function parseAspectRefs(expression, ctx, owner) {
6140
6398
  if (!expression)
6141
6399
  return [];
6142
- if (!ts3.isArrayLiteralExpression(expression)) {
6400
+ if (!ts4.isArrayLiteralExpression(expression)) {
6143
6401
  ctx.diagnostics.push({
6144
6402
  severity: "error",
6145
6403
  code: "dynamic-aspect-reference",
@@ -6154,7 +6412,7 @@ function parseAspectRefs(expression, ctx, owner) {
6154
6412
  }
6155
6413
  const refs = [];
6156
6414
  for (const element of expression.elements) {
6157
- if (ts3.isSpreadElement(element) || !ts3.isIdentifier(element)) {
6415
+ if (ts4.isSpreadElement(element) || !ts4.isIdentifier(element)) {
6158
6416
  ctx.diagnostics.push({
6159
6417
  severity: "error",
6160
6418
  code: "dynamic-aspect-reference",
@@ -6167,7 +6425,7 @@ function parseAspectRefs(expression, ctx, owner) {
6167
6425
  });
6168
6426
  continue;
6169
6427
  }
6170
- const declaration = resolveDeclaration(element, ctx).find((candidate) => ts3.isFunctionDeclaration(candidate) || ts3.isVariableDeclaration(candidate) && candidate.initializer !== undefined && (ts3.isArrowFunction(candidate.initializer) || ts3.isFunctionExpression(candidate.initializer)));
6428
+ const declaration = resolveDeclaration(element, ctx).find((candidate) => ts4.isFunctionDeclaration(candidate) || ts4.isVariableDeclaration(candidate) && candidate.initializer !== undefined && (ts4.isArrowFunction(candidate.initializer) || ts4.isFunctionExpression(candidate.initializer)));
6171
6429
  if (!declaration) {
6172
6430
  ctx.diagnostics.push({
6173
6431
  severity: "error",
@@ -6181,7 +6439,7 @@ function parseAspectRefs(expression, ctx, owner) {
6181
6439
  });
6182
6440
  continue;
6183
6441
  }
6184
- const name = ts3.isFunctionDeclaration(declaration) ? declaration.name?.text : ts3.isVariableDeclaration(declaration) ? variableName(declaration) : undefined;
6442
+ const name = ts4.isFunctionDeclaration(declaration) ? declaration.name?.text : ts4.isVariableDeclaration(declaration) ? variableName(declaration) : undefined;
6185
6443
  if (!name)
6186
6444
  continue;
6187
6445
  const declaredFile = declaration.getSourceFile().fileName;
@@ -6201,9 +6459,9 @@ function booleanProp(obj, name) {
6201
6459
  const expr = getProp(obj, name);
6202
6460
  if (!expr)
6203
6461
  return;
6204
- if (expr.kind === ts3.SyntaxKind.TrueKeyword)
6462
+ if (expr.kind === ts4.SyntaxKind.TrueKeyword)
6205
6463
  return true;
6206
- if (expr.kind === ts3.SyntaxKind.FalseKeyword)
6464
+ if (expr.kind === ts4.SyntaxKind.FalseKeyword)
6207
6465
  return false;
6208
6466
  return;
6209
6467
  }
@@ -6217,15 +6475,15 @@ function parseBindingOptions(args, defaultName) {
6217
6475
  let defaultValue;
6218
6476
  const first = args[0];
6219
6477
  const second = args[1];
6220
- if (first && ts3.isStringLiteral(first)) {
6478
+ if (first && ts4.isStringLiteral(first)) {
6221
6479
  name = first.text;
6222
- } else if (first && ts3.isObjectLiteralExpression(first)) {
6480
+ } else if (first && ts4.isObjectLiteralExpression(first)) {
6223
6481
  const nameProp = getProp(first, "name");
6224
- if (nameProp && ts3.isStringLiteral(nameProp)) {
6482
+ if (nameProp && ts4.isStringLiteral(nameProp)) {
6225
6483
  name = nameProp.text;
6226
6484
  }
6227
6485
  const trProp = getProp(first, "transform");
6228
- if (trProp && ts3.isStringLiteral(trProp)) {
6486
+ if (trProp && ts4.isStringLiteral(trProp)) {
6229
6487
  const val = trProp.text;
6230
6488
  if (val === "number" || val === "boolean" || val === "string") {
6231
6489
  transform = val;
@@ -6236,9 +6494,9 @@ function parseBindingOptions(args, defaultName) {
6236
6494
  defaultValue = parseLiteralValue(defProp);
6237
6495
  }
6238
6496
  }
6239
- if (second && ts3.isObjectLiteralExpression(second)) {
6497
+ if (second && ts4.isObjectLiteralExpression(second)) {
6240
6498
  const trProp = getProp(second, "transform");
6241
- if (trProp && ts3.isStringLiteral(trProp)) {
6499
+ if (trProp && ts4.isStringLiteral(trProp)) {
6242
6500
  const val = trProp.text;
6243
6501
  if (val === "number" || val === "boolean" || val === "string") {
6244
6502
  transform = val;
@@ -6252,18 +6510,18 @@ function parseBindingOptions(args, defaultName) {
6252
6510
  return { name, ...transform ? { transform } : {}, default: defaultValue };
6253
6511
  }
6254
6512
  function parseLiteralValue(node) {
6255
- if (ts3.isStringLiteral(node))
6513
+ if (ts4.isStringLiteral(node))
6256
6514
  return node.text;
6257
- if (ts3.isNumericLiteral(node))
6515
+ if (ts4.isNumericLiteral(node))
6258
6516
  return Number(node.text);
6259
- if (node.kind === ts3.SyntaxKind.TrueKeyword)
6517
+ if (node.kind === ts4.SyntaxKind.TrueKeyword)
6260
6518
  return true;
6261
- if (node.kind === ts3.SyntaxKind.FalseKeyword)
6519
+ if (node.kind === ts4.SyntaxKind.FalseKeyword)
6262
6520
  return false;
6263
- if (ts3.isArrayLiteralExpression(node)) {
6521
+ if (ts4.isArrayLiteralExpression(node)) {
6264
6522
  return node.elements.map(parseLiteralValue);
6265
6523
  }
6266
- if (ts3.isObjectLiteralExpression(node)) {
6524
+ if (ts4.isObjectLiteralExpression(node)) {
6267
6525
  return parseObjectLiteralValues(node);
6268
6526
  }
6269
6527
  return;
@@ -6271,7 +6529,7 @@ function parseLiteralValue(node) {
6271
6529
  function parseObjectLiteralValues(obj) {
6272
6530
  const result = {};
6273
6531
  for (const prop of obj.properties) {
6274
- if (ts3.isPropertyAssignment(prop)) {
6532
+ if (ts4.isPropertyAssignment(prop)) {
6275
6533
  const name = propertyName(prop.name);
6276
6534
  const init = prop.initializer;
6277
6535
  if (init) {
@@ -6307,7 +6565,50 @@ import { join as join4 } from "node:path";
6307
6565
  // src/type-safety.ts
6308
6566
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
6309
6567
  import { dirname as dirname3, join as join3, relative as relative3, resolve as resolve2, sep as sep3 } from "node:path";
6310
- import * as ts4 from "@typescript/typescript6";
6568
+ import * as ts6 from "@typescript/typescript6";
6569
+
6570
+ // src/sql-safety.ts
6571
+ import * as ts5 from "@typescript/typescript6";
6572
+ var SQL_SAFETY_DIAGNOSTIC_CODES = {
6573
+ "sql-result-assertion": { errorCode: "SC6007", docsUrl: "https://supacloud.dev/errors/SC6007" },
6574
+ "sql-raw-dynamic": { errorCode: "SC6008", docsUrl: "https://supacloud.dev/errors/SC6008" }
6575
+ };
6576
+ function scanDrizzleSql(sourceFile, checker, file, strict) {
6577
+ const diagnostics = [];
6578
+ const importedSql = (expression) => {
6579
+ const symbol = checker.getSymbolAtLocation(ts5.isPropertyAccessExpression(expression) ? expression.name : expression);
6580
+ if (!symbol)
6581
+ return false;
6582
+ const target = symbol.flags & ts5.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
6583
+ return target.name === "sql" && (target.declarations ?? []).some((declaration) => /(?:^|\/)node_modules\/drizzle-orm\//.test(declaration.getSourceFile().fileName.replaceAll("\\", "/")));
6584
+ };
6585
+ const report = (code, node, message) => {
6586
+ diagnostics.push({
6587
+ severity: strict ? "error" : "warn",
6588
+ code,
6589
+ ...SQL_SAFETY_DIAGNOSTIC_CODES[code],
6590
+ message,
6591
+ file,
6592
+ line: sourceFile.getLineAndCharacterOfPosition(node.getStart()).line + 1
6593
+ });
6594
+ };
6595
+ const visit = (node) => {
6596
+ if (ts5.isTaggedTemplateExpression(node) && importedSql(node.tag) && node.typeArguments?.some((type) => type.kind !== ts5.SyntaxKind.UnknownKeyword)) {
6597
+ report("sql-result-assertion", node, "Drizzle sql<T> asserts a result type without checking SQL or decoding rows. Use sql<unknown> and a schema decoder at the result boundary.");
6598
+ }
6599
+ if (ts5.isCallExpression(node) && ts5.isPropertyAccessExpression(node.expression) && node.expression.name.text === "raw" && importedSql(node.expression.expression)) {
6600
+ const argument = node.arguments[0];
6601
+ if (!argument || !ts5.isStringLiteral(argument) && !ts5.isNoSubstitutionTemplateLiteral(argument)) {
6602
+ report("sql-raw-dynamic", node, "Dynamic sql.raw bypasses parameter binding. Interpolate values with sql templates; keep reviewed static DDL in migrations.");
6603
+ }
6604
+ }
6605
+ ts5.forEachChild(node, visit);
6606
+ };
6607
+ visit(sourceFile);
6608
+ return diagnostics;
6609
+ }
6610
+
6611
+ // src/type-safety.ts
6311
6612
  var DEFAULT_EXCLUDES = [
6312
6613
  "**/*.test.ts",
6313
6614
  "**/*.spec.ts",
@@ -6320,6 +6621,7 @@ var DEFAULT_EXCLUDES = [
6320
6621
  "**/*.d.ts"
6321
6622
  ];
6322
6623
  var TYPE_SAFETY_DIAGNOSTIC_CODES = {
6624
+ ...SQL_SAFETY_DIAGNOSTIC_CODES,
6323
6625
  "generated-any": { errorCode: "SC6001", docsUrl: "https://supacloud.dev/errors/SC6001" },
6324
6626
  "source-any": { errorCode: "SC6002", docsUrl: "https://supacloud.dev/errors/SC6002" },
6325
6627
  "source-type-assertion": { errorCode: "SC6003", docsUrl: "https://supacloud.dev/errors/SC6003" },
@@ -6332,7 +6634,7 @@ function scanGeneratedArtifacts(artifacts, strict = true) {
6332
6634
  for (const [file, content] of Object.entries(artifacts)) {
6333
6635
  if (content === undefined)
6334
6636
  continue;
6335
- const sourceFile = ts4.createSourceFile(file, content, ts4.ScriptTarget.Latest, true, ts4.ScriptKind.TS);
6637
+ const sourceFile = ts6.createSourceFile(file, content, ts6.ScriptTarget.Latest, true, ts6.ScriptKind.TS);
6336
6638
  for (const node of descendantsOfKind2(sourceFile, isAnyKeyword)) {
6337
6639
  diagnostics.push(makeDiagnostic("generated-any", `生成产物 ${file} 包含 any;严格生成模式要求使用 unknown、具体接口或泛型约束。`, sourceFile, node, strict));
6338
6640
  }
@@ -6341,30 +6643,30 @@ function scanGeneratedArtifacts(artifacts, strict = true) {
6341
6643
  }
6342
6644
  function scanProductionSource(options) {
6343
6645
  const rootDir = resolve2(options.rootDir);
6344
- const configPath = ts4.findConfigFile(rootDir, ts4.sys.fileExists) ?? join3(rootDir, "tsconfig.json");
6646
+ const configPath = ts6.findConfigFile(rootDir, ts6.sys.fileExists) ?? join3(rootDir, "tsconfig.json");
6345
6647
  const projectConfig = existsSync2(configPath) ? readProjectConfig2(configPath) : {
6346
6648
  options: {
6347
6649
  strict: true,
6348
6650
  skipLibCheck: true,
6349
- target: ts4.ScriptTarget.ES2022,
6350
- module: ts4.ModuleKind.ESNext,
6351
- moduleResolution: ts4.ModuleResolutionKind.Bundler
6651
+ target: ts6.ScriptTarget.ES2022,
6652
+ module: ts6.ModuleKind.ESNext,
6653
+ moduleResolution: ts6.ModuleResolutionKind.Bundler
6352
6654
  },
6353
6655
  errors: []
6354
6656
  };
6355
6657
  const include = options.include ?? ["**/*.ts", "**/*.tsx", "**/*.mts", "**/*.cts"];
6356
- const rootNames = ts4.sys.readDirectory(rootDir, [".ts", ".tsx", ".mts", ".cts"], ["node_modules", "dist"], include).filter((file) => isProductionSourcePath(rootDir, file, [...DEFAULT_EXCLUDES, ...options.exclude ?? []]));
6658
+ const rootNames = ts6.sys.readDirectory(rootDir, [".ts", ".tsx", ".mts", ".cts"], ["node_modules", "dist"], include).filter((file) => isProductionSourcePath(rootDir, file, [...DEFAULT_EXCLUDES, ...options.exclude ?? []]));
6357
6659
  const compilerOptions = { ...projectConfig.options, noEmit: true };
6358
- const host = ts4.createCompilerHost(compilerOptions);
6660
+ const host = ts6.createCompilerHost(compilerOptions);
6359
6661
  host.getCurrentDirectory = () => dirname3(configPath);
6360
- const program = ts4.createProgram(rootNames, compilerOptions, host);
6662
+ const program = ts6.createProgram(rootNames, compilerOptions, host);
6361
6663
  const outDir = options.outDir ? normalizeRelative(rootDir, options.outDir) : undefined;
6362
6664
  const excludes = [...DEFAULT_EXCLUDES, ...options.exclude ?? []];
6363
6665
  const sourceFiles = program.getSourceFiles().filter((sourceFile) => isProductionSource(rootDir, sourceFile, excludes, outDir));
6364
6666
  const diagnostics = [...projectConfig.errors, ...program.getOptionsDiagnostics()].map((diagnostic) => ({
6365
6667
  severity: "error",
6366
6668
  code: "source-config",
6367
- message: ts4.flattenDiagnosticMessageText(diagnostic.messageText, `
6669
+ message: ts6.flattenDiagnosticMessageText(diagnostic.messageText, `
6368
6670
  `),
6369
6671
  file: diagnostic.file ? normalizeRelative(rootDir, diagnostic.file.fileName) : normalizeRelative(rootDir, configPath),
6370
6672
  ...diagnostic.file && diagnostic.start !== undefined ? { line: diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start).line + 1 } : {},
@@ -6381,7 +6683,7 @@ function scanProductionSource(options) {
6381
6683
  diagnostics.push({
6382
6684
  severity: "error",
6383
6685
  code: "source-typescript",
6384
- message: ts4.flattenDiagnosticMessageText(diagnostic.messageText, `
6686
+ message: ts6.flattenDiagnosticMessageText(diagnostic.messageText, `
6385
6687
  `),
6386
6688
  ...diagnostic.file ? { file: normalizeRelative(rootDir, diagnostic.file.fileName) } : {},
6387
6689
  ...diagnostic.file && diagnostic.start !== undefined ? { line: diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start).line + 1 } : {},
@@ -6390,9 +6692,10 @@ function scanProductionSource(options) {
6390
6692
  }
6391
6693
  for (const sourceFile of sourceFiles) {
6392
6694
  scanSourceFile(sourceFile, checker, rootDir, diagnostics, options.strict ?? false);
6393
- const scanner = ts4.createScanner(ts4.ScriptTarget.Latest, false, sourceFile.languageVariant, sourceFile.text);
6394
- for (let kind = scanner.scan();kind !== ts4.SyntaxKind.EndOfFileToken; kind = scanner.scan()) {
6395
- if ((kind === ts4.SyntaxKind.SingleLineCommentTrivia || kind === ts4.SyntaxKind.MultiLineCommentTrivia) && /@ts-(?:ignore|nocheck|expect-error)\b/.test(scanner.getTokenText())) {
6695
+ diagnostics.push(...scanDrizzleSql(sourceFile, checker, normalizeRelative(rootDir, sourceFile.fileName), options.strict ?? false));
6696
+ const scanner = ts6.createScanner(ts6.ScriptTarget.Latest, false, sourceFile.languageVariant, sourceFile.text);
6697
+ for (let kind = scanner.scan();kind !== ts6.SyntaxKind.EndOfFileToken; kind = scanner.scan()) {
6698
+ if ((kind === ts6.SyntaxKind.SingleLineCommentTrivia || kind === ts6.SyntaxKind.MultiLineCommentTrivia) && /@ts-(?:ignore|nocheck|expect-error)\b/.test(scanner.getTokenText())) {
6396
6699
  diagnostics.push({
6397
6700
  severity: "error",
6398
6701
  code: "source-type-suppression",
@@ -6412,22 +6715,22 @@ function scanSourceFile(sourceFile, checker, rootDir, diagnostics, strict) {
6412
6715
  diagnostics.push(makeDiagnostic("source-any", "生产源码使用了显式 any;请改用 unknown、具体接口或泛型约束。", sourceFile, node, strict, rootDir));
6413
6716
  }
6414
6717
  for (const node of descendants(sourceFile)) {
6415
- if (ts4.isAsExpression(node)) {
6416
- if (ts4.isAsExpression(node.parent) || ts4.isTypeAssertionExpression(node.parent))
6718
+ if (ts6.isAsExpression(node)) {
6719
+ if (ts6.isAsExpression(node.parent) || ts6.isTypeAssertionExpression(node.parent))
6417
6720
  continue;
6418
6721
  const assertedType = node.type.getText(sourceFile);
6419
6722
  if (assertedType === "const")
6420
6723
  continue;
6421
6724
  diagnostics.push(makeDiagnostic("source-type-assertion", `生产源码包含类型断言 ${node.getText(sourceFile)};请优先使用类型守卫、satisfies 或显式边界解析。`, sourceFile, node, strict, rootDir));
6422
- } else if (ts4.isTypeAssertionExpression(node)) {
6423
- if (ts4.isAsExpression(node.parent) || ts4.isTypeAssertionExpression(node.parent))
6725
+ } else if (ts6.isTypeAssertionExpression(node)) {
6726
+ if (ts6.isAsExpression(node.parent) || ts6.isTypeAssertionExpression(node.parent))
6424
6727
  continue;
6425
6728
  diagnostics.push(makeDiagnostic("source-type-assertion", `生产源码包含类型断言 ${node.getText(sourceFile)};请优先使用类型守卫、satisfies 或显式边界解析。`, sourceFile, node, strict, rootDir));
6426
- } else if (ts4.isNonNullExpression(node)) {
6729
+ } else if (ts6.isNonNullExpression(node)) {
6427
6730
  diagnostics.push(makeDiagnostic("source-non-null-assertion", `生产源码包含非空断言 ${node.getText(sourceFile)};请显式处理 null/undefined。`, sourceFile, node, strict, rootDir));
6428
6731
  }
6429
6732
  }
6430
- for (const declaration of descendantsOfKind2(sourceFile, ts4.isVariableDeclaration)) {
6733
+ for (const declaration of descendantsOfKind2(sourceFile, ts6.isVariableDeclaration)) {
6431
6734
  const initializer = declaration.initializer;
6432
6735
  if (!initializer || declaration.type)
6433
6736
  continue;
@@ -6443,11 +6746,11 @@ function scanSourceFile(sourceFile, checker, rootDir, diagnostics, strict) {
6443
6746
  if (isLetDeclaration(declaration) && isLiteralSyntax(initializer) && !isLiteralType(declarationType)) {
6444
6747
  diagnostics.push(makeDiagnostic("source-implicit-widening", `变量 ${declaration.name.getText(sourceFile)} 的字面量类型从 ${checker.typeToString(initializerType, initializer)} 隐式宽化为 ${checker.typeToString(declarationType, declaration)};请补充类型或使用 const。`, sourceFile, declaration, strict, rootDir));
6445
6748
  }
6446
- if (ts4.isObjectLiteralExpression(initializer) && isConstDeclaration(declaration) && initializer.getText(sourceFile).length > 0 && initializer.properties.some((property) => ts4.isPropertyAssignment(property) && property.initializer !== undefined && !ts4.isAsExpression(property.initializer) && isLiteralExpression(property.initializer))) {
6749
+ if (ts6.isObjectLiteralExpression(initializer) && isConstDeclaration(declaration) && initializer.getText(sourceFile).length > 0 && initializer.properties.some((property) => ts6.isPropertyAssignment(property) && property.initializer !== undefined && !ts6.isAsExpression(property.initializer) && isLiteralExpression(property.initializer))) {
6447
6750
  diagnostics.push(makeDiagnostic("source-implicit-widening", `常量对象 ${declaration.name.getText(sourceFile)} 的字面量属性会隐式宽化;请补充对象类型或使用 as const。`, sourceFile, declaration, strict, rootDir));
6448
6751
  }
6449
6752
  }
6450
- for (const parameter of descendantsOfKind2(sourceFile, ts4.isParameter)) {
6753
+ for (const parameter of descendantsOfKind2(sourceFile, ts6.isParameter)) {
6451
6754
  if (parameter.type)
6452
6755
  continue;
6453
6756
  for (const name of bindingNames(parameter.name)) {
@@ -6458,10 +6761,10 @@ function scanSourceFile(sourceFile, checker, rootDir, diagnostics, strict) {
6458
6761
  }
6459
6762
  }
6460
6763
  function readProjectConfig2(configPath) {
6461
- const config = ts4.readConfigFile(configPath, (file) => readFileSync2(file, "utf8"));
6764
+ const config = ts6.readConfigFile(configPath, (file) => readFileSync2(file, "utf8"));
6462
6765
  if (config.error)
6463
6766
  return { options: {}, errors: [config.error] };
6464
- const parsed = ts4.parseJsonConfigFileContent(config.config, ts4.sys, dirname3(configPath));
6767
+ const parsed = ts6.parseJsonConfigFileContent(config.config, ts6.sys, dirname3(configPath));
6465
6768
  return { options: parsed.options, errors: parsed.errors };
6466
6769
  }
6467
6770
  function isProductionSource(rootDir, sourceFile, excludes, outDir) {
@@ -6481,42 +6784,42 @@ function globMatches(value, pattern) {
6481
6784
  return new RegExp(`^${escaped}$`).test(value);
6482
6785
  }
6483
6786
  function bindingNames(name) {
6484
- if (ts4.isIdentifier(name))
6787
+ if (ts6.isIdentifier(name))
6485
6788
  return [name];
6486
- return name.elements.flatMap((element) => ts4.isBindingElement(element) ? bindingNames(element.name) : []);
6789
+ return name.elements.flatMap((element) => ts6.isBindingElement(element) ? bindingNames(element.name) : []);
6487
6790
  }
6488
6791
  function isLiteralExpression(node) {
6489
6792
  if (!node)
6490
6793
  return false;
6491
6794
  return [
6492
- ts4.SyntaxKind.StringLiteral,
6493
- ts4.SyntaxKind.NumericLiteral,
6494
- ts4.SyntaxKind.TrueKeyword,
6495
- ts4.SyntaxKind.FalseKeyword
6795
+ ts6.SyntaxKind.StringLiteral,
6796
+ ts6.SyntaxKind.NumericLiteral,
6797
+ ts6.SyntaxKind.TrueKeyword,
6798
+ ts6.SyntaxKind.FalseKeyword
6496
6799
  ].includes(node.kind);
6497
6800
  }
6498
6801
  function isLiteralSyntax(node) {
6499
- return ts4.isStringLiteral(node) || ts4.isNumericLiteral(node) || node.kind === ts4.SyntaxKind.TrueKeyword || node.kind === ts4.SyntaxKind.FalseKeyword;
6802
+ return ts6.isStringLiteral(node) || ts6.isNumericLiteral(node) || node.kind === ts6.SyntaxKind.TrueKeyword || node.kind === ts6.SyntaxKind.FalseKeyword;
6500
6803
  }
6501
6804
  function isLiteralType(type) {
6502
- return (type.flags & (ts4.TypeFlags.StringLiteral | ts4.TypeFlags.NumberLiteral | ts4.TypeFlags.BooleanLiteral | ts4.TypeFlags.BigIntLiteral)) !== 0;
6805
+ return (type.flags & (ts6.TypeFlags.StringLiteral | ts6.TypeFlags.NumberLiteral | ts6.TypeFlags.BooleanLiteral | ts6.TypeFlags.BigIntLiteral)) !== 0;
6503
6806
  }
6504
6807
  function isAnyType(type) {
6505
- return (type.flags & ts4.TypeFlags.Any) !== 0;
6808
+ return (type.flags & ts6.TypeFlags.Any) !== 0;
6506
6809
  }
6507
6810
  function isLetDeclaration(declaration) {
6508
- return ts4.isVariableDeclarationList(declaration.parent) && (declaration.parent.flags & ts4.NodeFlags.Let) !== 0;
6811
+ return ts6.isVariableDeclarationList(declaration.parent) && (declaration.parent.flags & ts6.NodeFlags.Let) !== 0;
6509
6812
  }
6510
6813
  function isConstDeclaration(declaration) {
6511
- return ts4.isVariableDeclarationList(declaration.parent) && (declaration.parent.flags & ts4.NodeFlags.Const) !== 0;
6814
+ return ts6.isVariableDeclarationList(declaration.parent) && (declaration.parent.flags & ts6.NodeFlags.Const) !== 0;
6512
6815
  }
6513
6816
  function descendants(root) {
6514
6817
  const result = [];
6515
6818
  const visit = (node) => {
6516
6819
  result.push(node);
6517
- ts4.forEachChild(node, visit);
6820
+ ts6.forEachChild(node, visit);
6518
6821
  };
6519
- ts4.forEachChild(root, visit);
6822
+ ts6.forEachChild(root, visit);
6520
6823
  return result;
6521
6824
  }
6522
6825
  function descendantsOfKind2(root, predicate) {
@@ -6524,9 +6827,9 @@ function descendantsOfKind2(root, predicate) {
6524
6827
  const visit = (node) => {
6525
6828
  if (predicate(node))
6526
6829
  result.push(node);
6527
- ts4.forEachChild(node, visit);
6830
+ ts6.forEachChild(node, visit);
6528
6831
  };
6529
- ts4.forEachChild(root, visit);
6832
+ ts6.forEachChild(root, visit);
6530
6833
  return result;
6531
6834
  }
6532
6835
  function makeDiagnostic(code, message, fileOrSourceFile, node, strict, rootDir) {
@@ -6547,7 +6850,7 @@ function normalizeRelative(rootDir, filePath) {
6547
6850
  return relative3(rootDir, filePath).split(sep3).join("/").replace(/^\.\//, "");
6548
6851
  }
6549
6852
  function isAnyKeyword(node) {
6550
- return node.kind === ts4.SyntaxKind.AnyKeyword;
6853
+ return node.kind === ts6.SyntaxKind.AnyKeyword;
6551
6854
  }
6552
6855
 
6553
6856
  // src/route-contracts.ts
@@ -6631,15 +6934,28 @@ function validateRouteContracts(graph) {
6631
6934
  }
6632
6935
 
6633
6936
  // src/compile.ts
6937
+ function withDefaultGovernance(options) {
6938
+ return options.commandCapabilities === undefined ? { ...options, commandCapabilities: {
6939
+ requirePersistentAdapters: true,
6940
+ permission: true,
6941
+ audit: true,
6942
+ idempotency: true,
6943
+ transaction: true
6944
+ } } : options;
6945
+ }
6634
6946
  async function renderOptionalGraphql(options) {
6635
6947
  return options.graphql ? (await Promise.resolve().then(() => (init_graphql(), exports_graphql))).renderGraphql(options) : { diagnostics: [], files: {} };
6636
6948
  }
6637
6949
  async function compileProject(options) {
6950
+ options = withDefaultGovernance(options);
6638
6951
  const graph = await analyzeProject(options.rootDir, options.include, options.cache, options.changedPaths);
6639
6952
  const diagnostics = [
6640
6953
  ...graph.diagnostics ?? [],
6641
6954
  ...validateGraph(graph, options)
6642
6955
  ];
6956
+ if (diagnostics.some((item) => item.code === "runtime-injection-disallowed")) {
6957
+ return { diagnostics, graph, written: [] };
6958
+ }
6643
6959
  if (options.strict) {
6644
6960
  for (const diagnostic of diagnostics) {
6645
6961
  if (diagnostic.severity === "warn")
@@ -6693,11 +7009,15 @@ async function compileProject(options) {
6693
7009
  return { diagnostics, graph, written, ...stats ? { stats } : {} };
6694
7010
  }
6695
7011
  async function checkProject(options) {
7012
+ options = withDefaultGovernance(options);
6696
7013
  const graph = await analyzeProject(options.rootDir, options.include, options.cache, options.changedPaths);
6697
7014
  const diagnostics = [
6698
7015
  ...graph.diagnostics ?? [],
6699
7016
  ...validateGraph(graph, options)
6700
7017
  ];
7018
+ if (diagnostics.some((item) => item.code === "runtime-injection-disallowed")) {
7019
+ return { diagnostics, graph, upToDate: false, mismatches: ["Runtime DI must be migrated to constructor injection."] };
7020
+ }
6701
7021
  if (options.strict) {
6702
7022
  for (const diagnostic of diagnostics) {
6703
7023
  if (diagnostic.severity === "warn")
@@ -10248,7 +10568,7 @@ function formatDeliveryPlan(result) {
10248
10568
  import { mkdir as mkdir3, mkdtemp, readFile as readFile5, realpath as realpath2, rename as rename3, rm as rm2 } from "node:fs/promises";
10249
10569
  import { readFileSync as readFileSync3 } from "node:fs";
10250
10570
  import { dirname as dirname5, join as join6, relative as relative6, resolve as resolve7, sep as sep6 } from "node:path";
10251
- import * as ts8 from "@typescript/typescript6";
10571
+ import * as ts10 from "@typescript/typescript6";
10252
10572
 
10253
10573
  // src/delivery-files.ts
10254
10574
  import { createHash as createHash7 } from "node:crypto";
@@ -10482,19 +10802,19 @@ function renderDeliveryTarget(graph, target, options) {
10482
10802
  import { isBuiltin } from "node:module";
10483
10803
  import { readFile as readFile4 } from "node:fs/promises";
10484
10804
  import { resolve as resolve6 } from "node:path";
10485
- import * as ts7 from "@typescript/typescript6";
10805
+ import * as ts9 from "@typescript/typescript6";
10486
10806
  function checkStaticImports(path, contents) {
10487
10807
  if (!/\.[cm]?[jt]sx?$/.test(path))
10488
10808
  return;
10489
- const source = ts7.createSourceFile(path, new TextDecoder().decode(contents), ts7.ScriptTarget.Latest, true);
10809
+ const source = ts9.createSourceFile(path, new TextDecoder().decode(contents), ts9.ScriptTarget.Latest, true);
10490
10810
  function visit(node) {
10491
- if (ts7.isCallExpression(node) && (node.expression.kind === ts7.SyntaxKind.ImportKeyword || ts7.isIdentifier(node.expression) && node.expression.text === "require")) {
10811
+ if (ts9.isCallExpression(node) && (node.expression.kind === ts9.SyntaxKind.ImportKeyword || ts9.isIdentifier(node.expression) && node.expression.text === "require")) {
10492
10812
  const argument = node.arguments[0];
10493
- if (!argument || !ts7.isStringLiteral(argument) && !ts7.isNoSubstitutionTemplateLiteral(argument)) {
10813
+ if (!argument || !ts9.isStringLiteral(argument) && !ts9.isNoSubstitutionTemplateLiteral(argument)) {
10494
10814
  throw new Error("Computed module loading is not supported in independent delivery bundles.");
10495
10815
  }
10496
10816
  }
10497
- ts7.forEachChild(node, visit);
10817
+ ts9.forEachChild(node, visit);
10498
10818
  }
10499
10819
  visit(source);
10500
10820
  }
@@ -10583,7 +10903,7 @@ async function buildDeliveryProject(options, delivery) {
10583
10903
  const settings = parseDeliveryOptions(delivery);
10584
10904
  if (typeof Bun === "undefined")
10585
10905
  throw new Error("Independent delivery builds require Bun.");
10586
- const configPath = ts8.findConfigFile(resolve7(options.rootDir), ts8.sys.fileExists);
10906
+ const configPath = ts10.findConfigFile(resolve7(options.rootDir), ts10.sys.fileExists);
10587
10907
  if (!configPath)
10588
10908
  throw new Error("Independent delivery builds require a project tsconfig.json.");
10589
10909
  const lexicalProject = dirname5(configPath);
@@ -10599,8 +10919,8 @@ async function buildDeliveryProject(options, delivery) {
10599
10919
  if (inside(generatedRoot, sourceRoot))
10600
10920
  throw new Error("Output must not contain the application source root.");
10601
10921
  const configInputs = new Map;
10602
- const parsedConfig = ts8.getParsedCommandLineOfConfigFile(await realpath2(configPath), {}, {
10603
- ...ts8.sys,
10922
+ const parsedConfig = ts10.getParsedCommandLineOfConfigFile(await realpath2(configPath), {}, {
10923
+ ...ts10.sys,
10604
10924
  readFile(path) {
10605
10925
  const contents = readFileSync3(path, "utf8");
10606
10926
  configInputs.set(resolve7(path), digest(contents));
@@ -10686,7 +11006,7 @@ async function buildDeliveryProject(options, delivery) {
10686
11006
  for (const [name, contents] of Object.entries(generated))
10687
11007
  await writeArtifact(stage, `generated/${name}`, contents);
10688
11008
  {
10689
- const program = ts8.createProgram({
11009
+ const program = ts10.createProgram({
10690
11010
  rootNames: [
10691
11011
  ...parsedConfig.fileNames.filter((path) => !inside(generatedRoot, path)),
10692
11012
  ...Object.keys(generated).map((name) => join6(stage, "generated", name))
@@ -10694,12 +11014,12 @@ async function buildDeliveryProject(options, delivery) {
10694
11014
  options: { ...parsedConfig.options, rootDir: project },
10695
11015
  ...parsedConfig.projectReferences ? { projectReferences: parsedConfig.projectReferences } : {}
10696
11016
  });
10697
- const diagnostics = ts8.getPreEmitDiagnostics(program);
10698
- if (diagnostics.some((item) => item.category === ts8.DiagnosticCategory.Error)) {
10699
- return failed(diagnostics.filter((item) => item.category === ts8.DiagnosticCategory.Error).map((item) => ({
11017
+ const diagnostics = ts10.getPreEmitDiagnostics(program);
11018
+ if (diagnostics.some((item) => item.category === ts10.DiagnosticCategory.Error)) {
11019
+ return failed(diagnostics.filter((item) => item.category === ts10.DiagnosticCategory.Error).map((item) => ({
10700
11020
  severity: "error",
10701
11021
  code: "delivery-generated-type-error",
10702
- message: ts8.flattenDiagnosticMessageText(item.messageText, `
11022
+ message: ts10.flattenDiagnosticMessageText(item.messageText, `
10703
11023
  `),
10704
11024
  ...item.file ? { file: item.file.fileName } : {}
10705
11025
  })));
@@ -10831,7 +11151,7 @@ async function buildDeliveryProject(options, delivery) {
10831
11151
  import { randomUUID } from "node:crypto";
10832
11152
  import { lstat as lstat2, readFile as readFile6, realpath as realpath3, rename as rename4, unlink as unlink2, writeFile as writeFile3 } from "node:fs/promises";
10833
11153
  import { dirname as dirname6, isAbsolute as isAbsolute2, relative as relative7, resolve as resolve8, sep as sep7 } from "node:path";
10834
- import * as ts9 from "@typescript/typescript6";
11154
+ import * as ts11 from "@typescript/typescript6";
10835
11155
  async function applyDiagnosticFix(fix, options = {}) {
10836
11156
  if (!fix || typeof fix.targetFile !== "string")
10837
11157
  throw new Error("Invalid DiagnosticFix");
@@ -10856,7 +11176,7 @@ async function applyDiagnosticFix(fix, options = {}) {
10856
11176
  if (!current || current.initializer.getText(source) !== fix.expectedExpression) {
10857
11177
  throw new Error("Command mode changed since diagnosis; analyze the project again");
10858
11178
  }
10859
- content = replaceProperty(source, object, fix.property, ts9.factory.createStringLiteral(fix.value));
11179
+ content = replaceProperty(source, object, fix.property, ts11.factory.createStringLiteral(fix.value));
10860
11180
  break;
10861
11181
  }
10862
11182
  case "add_module_import": {
@@ -10867,15 +11187,15 @@ async function applyDiagnosticFix(fix, options = {}) {
10867
11187
  source = parse3(file, withImport);
10868
11188
  const object = unique(moduleObjects(source).filter((candidate) => !fix.targetModule || stringProperty(candidate, "name") === fix.targetModule), "target module");
10869
11189
  const imports = property(object, "imports");
10870
- if (imports && !ts9.isArrayLiteralExpression(imports.initializer)) {
11190
+ if (imports && !ts11.isArrayLiteralExpression(imports.initializer)) {
10871
11191
  throw new Error("Module imports must be a static array");
10872
11192
  }
10873
- const values = imports && ts9.isArrayLiteralExpression(imports.initializer) ? imports.initializer.elements : [];
10874
- if (values.some(ts9.isSpreadElement))
11193
+ const values = imports && ts11.isArrayLiteralExpression(imports.initializer) ? imports.initializer.elements : [];
11194
+ if (values.some(ts11.isSpreadElement))
10875
11195
  throw new Error("Module imports cannot contain spread elements");
10876
- content = values.some((value) => ts9.isIdentifier(value) && value.text === fix.symbol) ? withImport : replaceProperty(source, object, "imports", ts9.factory.createArrayLiteralExpression([
11196
+ content = values.some((value) => ts11.isIdentifier(value) && value.text === fix.symbol) ? withImport : replaceProperty(source, object, "imports", ts11.factory.createArrayLiteralExpression([
10877
11197
  ...values,
10878
- ts9.factory.createIdentifier(fix.symbol)
11198
+ ts11.factory.createIdentifier(fix.symbol)
10879
11199
  ]));
10880
11200
  break;
10881
11201
  }
@@ -10887,24 +11207,24 @@ async function applyDiagnosticFix(fix, options = {}) {
10887
11207
  const command = findClass(source, fix.command);
10888
11208
  const object = decoratorObject(command, "Command");
10889
11209
  const current = property(object, "permission");
10890
- if (current && (!ts9.isStringLiteral(current.initializer) || current.initializer.text !== permission)) {
11210
+ if (current && (!ts11.isStringLiteral(current.initializer) || current.initializer.text !== permission)) {
10891
11211
  throw new Error("Command permission already exists with a different value");
10892
11212
  }
10893
- content = current ? original : replaceProperty(source, object, "permission", ts9.factory.createStringLiteral(permission));
11213
+ content = current ? original : replaceProperty(source, object, "permission", ts11.factory.createStringLiteral(permission));
10894
11214
  break;
10895
11215
  }
10896
11216
  case "add_route_parameter_binding": {
10897
11217
  const controller = findClass(source, fix.controller);
10898
- const method = unique(controller.members.filter((member) => ts9.isMethodDeclaration(member) && nameOf(member.name) === fix.route), "route handler");
10899
- const parameter = unique(method.parameters.filter((candidate) => ts9.isIdentifier(candidate.name) && candidate.name.text === fix.parameter), "same-named route parameter");
11218
+ const method = unique(controller.members.filter((member) => ts11.isMethodDeclaration(member) && nameOf(member.name) === fix.route), "route handler");
11219
+ const parameter = unique(method.parameters.filter((candidate) => ts11.isIdentifier(candidate.name) && candidate.name.text === fix.parameter), "same-named route parameter");
10900
11220
  const binding = fix.binding === "param" ? "Param" : fix.binding === "query" ? "Query" : undefined;
10901
11221
  if (!binding)
10902
11222
  throw new Error("Invalid route binding");
10903
- const decorators = ts9.getDecorators(parameter) ?? [];
11223
+ const decorators = ts11.getDecorators(parameter) ?? [];
10904
11224
  if (decorators.length > 0)
10905
11225
  throw new Error("Parameter already has a decorator");
10906
- const framework = unique(source.statements.filter((statement) => ts9.isImportDeclaration(statement) && statement.importClause?.namedBindings && ts9.isNamedImports(statement.importClause.namedBindings) && statement.importClause.namedBindings.elements.some((element) => ["Controller", "Get", "Post", "Put", "Patch", "Delete", "Head", "Options"].includes(element.name.text))), "framework import");
10907
- if (!ts9.isImportDeclaration(framework) || !ts9.isStringLiteral(framework.moduleSpecifier)) {
11226
+ const framework = unique(source.statements.filter((statement) => ts11.isImportDeclaration(statement) && statement.importClause?.namedBindings && ts11.isNamedImports(statement.importClause.namedBindings) && statement.importClause.namedBindings.elements.some((element) => ["Controller", "Get", "Post", "Put", "Patch", "Delete", "Head", "Options"].includes(element.name.text))), "framework import");
11227
+ if (!ts11.isImportDeclaration(framework) || !ts11.isStringLiteral(framework.moduleSpecifier)) {
10908
11228
  throw new Error("Framework import must be static");
10909
11229
  }
10910
11230
  const edited = original.slice(0, parameter.getStart(source)) + `@${binding}(${JSON.stringify(fix.parameter)}) ` + original.slice(parameter.getStart(source));
@@ -10930,15 +11250,15 @@ async function applyDiagnosticFix(fix, options = {}) {
10930
11250
  return result;
10931
11251
  }
10932
11252
  function parse3(file, text) {
10933
- const result = ts9.transpileModule(text, {
11253
+ const result = ts11.transpileModule(text, {
10934
11254
  fileName: file,
10935
11255
  reportDiagnostics: true,
10936
- compilerOptions: { target: ts9.ScriptTarget.ESNext, experimentalDecorators: true }
11256
+ compilerOptions: { target: ts11.ScriptTarget.ESNext, experimentalDecorators: true }
10937
11257
  });
10938
- if (result.diagnostics?.some((item) => item.category === ts9.DiagnosticCategory.Error)) {
11258
+ if (result.diagnostics?.some((item) => item.category === ts11.DiagnosticCategory.Error)) {
10939
11259
  throw new Error("Cannot fix syntactically invalid TypeScript");
10940
11260
  }
10941
- return ts9.createSourceFile(file, text, ts9.ScriptTarget.Latest, true, ts9.ScriptKind.TS);
11261
+ return ts11.createSourceFile(file, text, ts11.ScriptTarget.Latest, true, ts11.ScriptKind.TS);
10942
11262
  }
10943
11263
  function unique(items, description) {
10944
11264
  if (items.length !== 1)
@@ -10952,50 +11272,50 @@ function identifier(value) {
10952
11272
  function nameOf(name) {
10953
11273
  if (!name)
10954
11274
  return "";
10955
- return ts9.isIdentifier(name) || ts9.isStringLiteral(name) || ts9.isNumericLiteral(name) ? name.text : "";
11275
+ return ts11.isIdentifier(name) || ts11.isStringLiteral(name) || ts11.isNumericLiteral(name) ? name.text : "";
10956
11276
  }
10957
11277
  function property(object, key) {
10958
- if (object.properties.some((item) => !ts9.isPropertyAssignment(item) || ts9.isComputedPropertyName(item.name))) {
11278
+ if (object.properties.some((item) => !ts11.isPropertyAssignment(item) || ts11.isComputedPropertyName(item.name))) {
10959
11279
  throw new Error("Fix requires explicit static object properties");
10960
11280
  }
10961
- const values = object.properties.filter((item) => ts9.isPropertyAssignment(item) && nameOf(item.name) === key);
11281
+ const values = object.properties.filter((item) => ts11.isPropertyAssignment(item) && nameOf(item.name) === key);
10962
11282
  if (values.length > 1)
10963
11283
  throw new Error(`Duplicate '${key}' property`);
10964
11284
  return values[0];
10965
11285
  }
10966
11286
  function stringProperty(object, key) {
10967
11287
  const value = property(object, key)?.initializer;
10968
- return value && ts9.isStringLiteral(value) ? value.text : undefined;
11288
+ return value && ts11.isStringLiteral(value) ? value.text : undefined;
10969
11289
  }
10970
11290
  function replaceProperty(source, object, key, value) {
10971
11291
  const previous = property(object, key);
10972
- const replacement = ts9.factory.createPropertyAssignment(key, value);
11292
+ const replacement = ts11.factory.createPropertyAssignment(key, value);
10973
11293
  const properties = object.properties.map((item) => item === previous ? replacement : item);
10974
11294
  if (!previous)
10975
11295
  properties.push(replacement);
10976
- const updated = ts9.factory.updateObjectLiteralExpression(object, properties);
10977
- return source.text.slice(0, object.getStart(source)) + ts9.createPrinter().printNode(ts9.EmitHint.Expression, updated, source) + source.text.slice(object.end);
11296
+ const updated = ts11.factory.updateObjectLiteralExpression(object, properties);
11297
+ return source.text.slice(0, object.getStart(source)) + ts11.createPrinter().printNode(ts11.EmitHint.Expression, updated, source) + source.text.slice(object.end);
10978
11298
  }
10979
11299
  function findClass(source, name) {
10980
- return unique(source.statements.filter((statement) => ts9.isClassDeclaration(statement) && statement.name?.text === name), `class '${name}'`);
11300
+ return unique(source.statements.filter((statement) => ts11.isClassDeclaration(statement) && statement.name?.text === name), `class '${name}'`);
10981
11301
  }
10982
11302
  function decoratorObject(node, name) {
10983
- const decorator = unique((ts9.getDecorators(node) ?? []).filter((item) => ts9.isCallExpression(item.expression) && item.expression.expression.getText() === name), `@${name} decorator`);
10984
- const argument = ts9.isCallExpression(decorator.expression) ? decorator.expression.arguments[0] : undefined;
10985
- if (!argument || !ts9.isObjectLiteralExpression(argument))
11303
+ const decorator = unique((ts11.getDecorators(node) ?? []).filter((item) => ts11.isCallExpression(item.expression) && item.expression.expression.getText() === name), `@${name} decorator`);
11304
+ const argument = ts11.isCallExpression(decorator.expression) ? decorator.expression.arguments[0] : undefined;
11305
+ if (!argument || !ts11.isObjectLiteralExpression(argument))
10986
11306
  throw new Error(`@${name} requires a static object`);
10987
11307
  return argument;
10988
11308
  }
10989
11309
  function moduleObjects(source) {
10990
11310
  const result = [];
10991
11311
  for (const statement of source.statements) {
10992
- if (ts9.isClassDeclaration(statement) && (ts9.getDecorators(statement) ?? []).some((item) => ts9.isCallExpression(item.expression) && item.expression.expression.getText() === "Module")) {
11312
+ if (ts11.isClassDeclaration(statement) && (ts11.getDecorators(statement) ?? []).some((item) => ts11.isCallExpression(item.expression) && item.expression.expression.getText() === "Module")) {
10993
11313
  result.push(decoratorObject(statement, "Module"));
10994
11314
  }
10995
- if (ts9.isVariableStatement(statement)) {
11315
+ if (ts11.isVariableStatement(statement)) {
10996
11316
  for (const declaration of statement.declarationList.declarations) {
10997
11317
  const call = declaration.initializer;
10998
- if (call && ts9.isCallExpression(call) && ["defineModule", "defineFeatureSlice"].includes(call.expression.getText()) && call.arguments[0] && ts9.isObjectLiteralExpression(call.arguments[0])) {
11318
+ if (call && ts11.isCallExpression(call) && ["defineModule", "defineFeatureSlice"].includes(call.expression.getText()) && call.arguments[0] && ts11.isObjectLiteralExpression(call.arguments[0])) {
10999
11319
  result.push(call.arguments[0]);
11000
11320
  }
11001
11321
  }
@@ -11009,19 +11329,19 @@ function importSymbol(source, path, symbol) {
11009
11329
  const target = resolve8(dirname6(source.fileName), path).replace(/\.(tsx?|mts|cts)$/, "");
11010
11330
  if (current === target)
11011
11331
  return source.text;
11012
- const matches = source.statements.filter((item) => ts9.isImportDeclaration(item) && ts9.isStringLiteral(item.moduleSpecifier) && item.moduleSpecifier.text === path);
11332
+ const matches = source.statements.filter((item) => ts11.isImportDeclaration(item) && ts11.isStringLiteral(item.moduleSpecifier) && item.moduleSpecifier.text === path);
11013
11333
  if (matches.length > 1)
11014
11334
  throw new Error(`Ambiguous imports from '${path}'`);
11015
11335
  const match = matches[0];
11016
- if (match && ts9.isImportDeclaration(match) && match.importClause?.namedBindings && ts9.isNamedImports(match.importClause.namedBindings) && !match.importClause.isTypeOnly) {
11336
+ if (match && ts11.isImportDeclaration(match) && match.importClause?.namedBindings && ts11.isNamedImports(match.importClause.namedBindings) && !match.importClause.isTypeOnly) {
11017
11337
  if (match.importClause.namedBindings.elements.some((item) => item.name.text === symbol))
11018
11338
  return source.text;
11019
11339
  const bindings = match.importClause.namedBindings;
11020
- const updated = ts9.factory.updateNamedImports(bindings, [
11340
+ const updated = ts11.factory.updateNamedImports(bindings, [
11021
11341
  ...bindings.elements,
11022
- ts9.factory.createImportSpecifier(false, undefined, ts9.factory.createIdentifier(symbol))
11342
+ ts11.factory.createImportSpecifier(false, undefined, ts11.factory.createIdentifier(symbol))
11023
11343
  ]);
11024
- return source.text.slice(0, bindings.getStart(source)) + ts9.createPrinter().printNode(ts9.EmitHint.Unspecified, updated, source) + source.text.slice(bindings.end);
11344
+ return source.text.slice(0, bindings.getStart(source)) + ts11.createPrinter().printNode(ts11.EmitHint.Unspecified, updated, source) + source.text.slice(bindings.end);
11025
11345
  }
11026
11346
  if (match)
11027
11347
  throw new Error(`Import from '${path}' is not a named value import`);
@@ -11436,7 +11756,7 @@ function watchProject(options) {
11436
11756
  // src/migrations.ts
11437
11757
  import { rename as rename5, readFile as readFile9, writeFile as writeFile4, rm as rm3 } from "node:fs/promises";
11438
11758
  import { relative as relative10, resolve as resolve12 } from "node:path";
11439
- import * as ts10 from "@typescript/typescript6";
11759
+ import * as ts12 from "@typescript/typescript6";
11440
11760
 
11441
11761
  // src/migration-policy.ts
11442
11762
  import { readFile as readFile8 } from "node:fs/promises";
@@ -11455,9 +11775,9 @@ function compilerVersion() {
11455
11775
  }
11456
11776
  function migrationDependencies() {
11457
11777
  return {
11458
- "@supacloud/app": "0.14.0",
11778
+ "@supacloud/app": "0.15.0",
11459
11779
  "@supacloud/compiler": compilerVersion(),
11460
- "@supacloud/elysia": "0.16.0",
11780
+ "@supacloud/elysia": "0.18.0",
11461
11781
  elysia: "1.4.30",
11462
11782
  typescript: "7.0.2"
11463
11783
  };
@@ -11480,29 +11800,29 @@ async function checkMigrationDependencies(rootDir) {
11480
11800
  // src/migrations.ts
11481
11801
  var ROUTE_DECORATORS2 = new Set(["Get", "Post", "Put", "Patch", "Delete", "Head", "Options"]);
11482
11802
  var MIGRATION_COMPILER_OPTIONS = {
11483
- target: ts10.ScriptTarget.ES2022,
11484
- module: ts10.ModuleKind.ESNext,
11485
- moduleResolution: ts10.ModuleResolutionKind.Bundler,
11803
+ target: ts12.ScriptTarget.ES2022,
11804
+ module: ts12.ModuleKind.ESNext,
11805
+ moduleResolution: ts12.ModuleResolutionKind.Bundler,
11486
11806
  noEmit: true,
11487
11807
  skipLibCheck: true
11488
11808
  };
11489
11809
  function migrationCompilerOptions(rootDir) {
11490
11810
  if (!rootDir)
11491
11811
  return MIGRATION_COMPILER_OPTIONS;
11492
- const configPath = ts10.findConfigFile(rootDir, ts10.sys.fileExists);
11812
+ const configPath = ts12.findConfigFile(rootDir, ts12.sys.fileExists);
11493
11813
  if (!configPath)
11494
11814
  return MIGRATION_COMPILER_OPTIONS;
11495
11815
  const configHost = {
11496
- ...ts10.sys,
11816
+ ...ts12.sys,
11497
11817
  onUnRecoverableConfigFileDiagnostic: (_diagnostic) => {}
11498
11818
  };
11499
- const parsed = ts10.getParsedCommandLineOfConfigFile(configPath, {}, configHost);
11819
+ const parsed = ts12.getParsedCommandLineOfConfigFile(configPath, {}, configHost);
11500
11820
  if (!parsed || parsed.errors.length > 0)
11501
11821
  return MIGRATION_COMPILER_OPTIONS;
11502
11822
  return { ...parsed.options, noEmit: true, skipLibCheck: true };
11503
11823
  }
11504
11824
  function propertyName2(property) {
11505
- if (ts10.isIdentifier(property) || ts10.isStringLiteral(property) || ts10.isNumericLiteral(property))
11825
+ if (ts12.isIdentifier(property) || ts12.isStringLiteral(property) || ts12.isNumericLiteral(property))
11506
11826
  return property.text;
11507
11827
  return;
11508
11828
  }
@@ -11512,7 +11832,7 @@ function lineOf2(sourceFile, node) {
11512
11832
  function resolveSymbol(symbol, checker) {
11513
11833
  if (!symbol)
11514
11834
  return;
11515
- for (let guard = 0;guard < 4 && (symbol.flags & ts10.SymbolFlags.Alias) !== 0; guard += 1) {
11835
+ for (let guard = 0;guard < 4 && (symbol.flags & ts12.SymbolFlags.Alias) !== 0; guard += 1) {
11516
11836
  const aliased = checker.getAliasedSymbol(symbol);
11517
11837
  if (aliased === symbol)
11518
11838
  break;
@@ -11521,12 +11841,12 @@ function resolveSymbol(symbol, checker) {
11521
11841
  return symbol;
11522
11842
  }
11523
11843
  function symbolForExpression(expression, checker) {
11524
- const location = ts10.isIdentifier(expression) ? expression : ts10.isPropertyAccessExpression(expression) ? expression.name : ts10.isElementAccessExpression(expression) && expression.argumentExpression && ts10.isStringLiteral(expression.argumentExpression) ? expression : undefined;
11844
+ const location = ts12.isIdentifier(expression) ? expression : ts12.isPropertyAccessExpression(expression) ? expression.name : ts12.isElementAccessExpression(expression) && expression.argumentExpression && ts12.isStringLiteral(expression.argumentExpression) ? expression : undefined;
11525
11845
  return location ? resolveSymbol(checker.getSymbolAtLocation(location), checker) : undefined;
11526
11846
  }
11527
11847
  function unwrapExpression(expression) {
11528
11848
  let current = expression;
11529
- while (ts10.isAsExpression(current) || ts10.isSatisfiesExpression(current) || ts10.isParenthesizedExpression(current) || ts10.isTypeAssertionExpression(current)) {
11849
+ while (ts12.isAsExpression(current) || ts12.isSatisfiesExpression(current) || ts12.isParenthesizedExpression(current) || ts12.isTypeAssertionExpression(current)) {
11530
11850
  current = current.expression;
11531
11851
  }
11532
11852
  return current;
@@ -11539,7 +11859,7 @@ function isDefineRouteContractCall(node, checker) {
11539
11859
  }
11540
11860
  function isRouteDecoratorCall(node, checker) {
11541
11861
  const name = node.expression.getText(node.getSourceFile());
11542
- if (ts10.isIdentifier(node.expression) && ROUTE_DECORATORS2.has(node.expression.text))
11862
+ if (ts12.isIdentifier(node.expression) && ROUTE_DECORATORS2.has(node.expression.text))
11543
11863
  return true;
11544
11864
  if (ROUTE_DECORATORS2.has(name))
11545
11865
  return true;
@@ -11553,14 +11873,14 @@ function resolveStaticObjectLiteral2(input, checker, seen = new Set) {
11553
11873
  if (seen.has(expression))
11554
11874
  return;
11555
11875
  seen.add(expression);
11556
- if (ts10.isObjectLiteralExpression(expression))
11876
+ if (ts12.isObjectLiteralExpression(expression))
11557
11877
  return expression;
11558
- if (ts10.isCallExpression(expression) && isDefineRouteContractCall(expression, checker)) {
11878
+ if (ts12.isCallExpression(expression) && isDefineRouteContractCall(expression, checker)) {
11559
11879
  return resolveStaticObjectLiteral2(expression.arguments[0], checker, seen);
11560
11880
  }
11561
11881
  const symbol = symbolForExpression(expression, checker);
11562
11882
  for (const declaration of symbol?.declarations ?? []) {
11563
- if (ts10.isVariableDeclaration(declaration) && declaration.initializer) {
11883
+ if (ts12.isVariableDeclaration(declaration) && declaration.initializer) {
11564
11884
  const resolved = resolveStaticObjectLiteral2(declaration.initializer, checker, seen);
11565
11885
  if (resolved)
11566
11886
  return resolved;
@@ -11574,7 +11894,7 @@ function displayFile(rootDir, fileName) {
11574
11894
  }
11575
11895
  function createMigrationProgram(fileNames, sourceOverrides, rootDir) {
11576
11896
  const compilerOptions = migrationCompilerOptions(rootDir);
11577
- const host = ts10.createCompilerHost(compilerOptions);
11897
+ const host = ts12.createCompilerHost(compilerOptions);
11578
11898
  const getSourceFile = host.getSourceFile.bind(host);
11579
11899
  const fileExists = host.fileExists.bind(host);
11580
11900
  const readFile = host.readFile.bind(host);
@@ -11583,16 +11903,16 @@ function createMigrationProgram(fileNames, sourceOverrides, rootDir) {
11583
11903
  host.readFile = (fileName) => sourceOverrides.get(resolve12(fileName)) ?? readFile(fileName);
11584
11904
  host.getSourceFile = (fileName, languageVersion, onError, shouldCreateNewSourceFile) => {
11585
11905
  const source = sourceOverrides.get(resolve12(fileName));
11586
- return source === undefined ? getSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile) : ts10.createSourceFile(fileName, source, languageVersion, true);
11906
+ return source === undefined ? getSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile) : ts12.createSourceFile(fileName, source, languageVersion, true);
11587
11907
  };
11588
11908
  host.getCurrentDirectory = () => rootDir ?? currentDirectory();
11589
- return ts10.createProgram(fileNames, compilerOptions, host);
11909
+ return ts12.createProgram(fileNames, compilerOptions, host);
11590
11910
  }
11591
11911
  function routeResponseProperties(object) {
11592
- const responseProperties = object.properties.filter((property) => ts10.isPropertyAssignment(property) && propertyName2(property.name) === "response");
11912
+ const responseProperties = object.properties.filter((property) => ts12.isPropertyAssignment(property) && propertyName2(property.name) === "response");
11593
11913
  return {
11594
11914
  response: responseProperties[0],
11595
- hasResponses: object.properties.some((property) => (ts10.isPropertyAssignment(property) || ts10.isShorthandPropertyAssignment(property)) && propertyName2(property.name) === "responses"),
11915
+ hasResponses: object.properties.some((property) => (ts12.isPropertyAssignment(property) || ts12.isShorthandPropertyAssignment(property)) && propertyName2(property.name) === "responses"),
11596
11916
  duplicateResponse: responseProperties.length > 1
11597
11917
  };
11598
11918
  }
@@ -11612,7 +11932,7 @@ function planRouteResponseMigration(sourceFiles, checker, rootDir, includedFiles
11612
11932
  if (!includedFiles.has(sourcePath))
11613
11933
  continue;
11614
11934
  const visit = (node) => {
11615
- if (ts10.isCallExpression(node) && isRouteDecoratorCall(node, checker)) {
11935
+ if (ts12.isCallExpression(node) && isRouteDecoratorCall(node, checker)) {
11616
11936
  const options = node.arguments[1];
11617
11937
  const object = options && resolveStaticObjectLiteral2(options, checker);
11618
11938
  if (object) {
@@ -11632,7 +11952,7 @@ function planRouteResponseMigration(sourceFiles, checker, rootDir, includedFiles
11632
11952
  }
11633
11953
  }
11634
11954
  }
11635
- ts10.forEachChild(node, visit);
11955
+ ts12.forEachChild(node, visit);
11636
11956
  };
11637
11957
  visit(sourceFile);
11638
11958
  }
@@ -11792,7 +12112,7 @@ async function migrateProject(options) {
11792
12112
  }
11793
12113
  }
11794
12114
  const include = options.include ?? ["**/*.ts", "**/*.tsx", "**/*.mts", "**/*.cts"];
11795
- const files = ts10.sys.readDirectory(rootDir, [".ts", ".tsx", ".mts", ".cts"], ["node_modules", "dist", "generated"], include).sort();
12115
+ const files = ts12.sys.readDirectory(rootDir, [".ts", ".tsx", ".mts", ".cts"], ["node_modules", "dist", "generated"], include).sort();
11796
12116
  const results = [];
11797
12117
  const issues = [];
11798
12118
  const pendingWrites = new Map;
@@ -12678,6 +12998,13 @@ var DEFAULT_SUPACLOUD_CONFIG = {
12678
12998
  generateOpenApi: true,
12679
12999
  generatePermissions: true,
12680
13000
  treeShakeUnusedProviders: true,
13001
+ commandCapabilities: {
13002
+ requirePersistentAdapters: true,
13003
+ permission: true,
13004
+ audit: true,
13005
+ idempotency: true,
13006
+ transaction: true
13007
+ },
12681
13008
  moduleBoundaryPreset: "modular-monolith"
12682
13009
  };
12683
13010
  function defineSupacloudConfig(config = {}) {
@@ -12761,7 +13088,7 @@ function resolveSupacloudConfig(config = {}, cwd = process.cwd()) {
12761
13088
  ...resolved.openApi === undefined ? {} : { openApi: resolved.openApi },
12762
13089
  generatePermissions: resolved.generatePermissions ?? DEFAULT_SUPACLOUD_CONFIG.generatePermissions,
12763
13090
  moduleBoundaryPreset: resolved.moduleBoundaryPreset ?? DEFAULT_SUPACLOUD_CONFIG.moduleBoundaryPreset,
12764
- commandCapabilities: resolved.commandCapabilities,
13091
+ commandCapabilities: resolved.commandCapabilities ?? DEFAULT_SUPACLOUD_CONFIG.commandCapabilities,
12765
13092
  ...resolved.moduleBoundaries ? { moduleBoundaries: resolved.moduleBoundaries } : {},
12766
13093
  ...resolved.typeSafety ? { typeSafety: resolved.typeSafety } : {},
12767
13094
  ...resolved.allowRouteCommandBindings === undefined ? {} : { allowRouteCommandBindings: resolved.allowRouteCommandBindings },
@@ -12793,6 +13120,7 @@ function compileOptionsFromConfig(config, cwd = process.cwd()) {
12793
13120
 
12794
13121
  // src/index.ts
12795
13122
  init_graphql_schema();
13123
+ init_database_contracts();
12796
13124
  export {
12797
13125
  ANGULAR_ENTERPRISE_RULES,
12798
13126
  CLEAN_ARCHITECTURE_RULES,
@@ -12809,6 +13137,7 @@ export {
12809
13137
  MODULE_BOUNDARY_PROFILES,
12810
13138
  ModuleDependencyGraph,
12811
13139
  OpenApiDocumentError,
13140
+ SQL_SAFETY_DIAGNOSTIC_CODES,
12812
13141
  SUPACLOUD_MIGRATIONS,
12813
13142
  TYPE_SAFETY_DIAGNOSTIC_CODES,
12814
13143
  TraitCompiler,
@@ -12837,6 +13166,7 @@ export {
12837
13166
  formatGraph,
12838
13167
  formatOpenApiDiff,
12839
13168
  generateApplication,
13169
+ generateDatabaseContracts,
12840
13170
  generateFeatureSource,
12841
13171
  getModuleBoundaryPreset,
12842
13172
  getModuleBoundaryProfile,
@@ -12845,6 +13175,7 @@ export {
12845
13175
  loadSupacloudConfig,
12846
13176
  migrateProject,
12847
13177
  migrateRouteResponse,
13178
+ parseDatabaseContractsOptions,
12848
13179
  parseDeliveryBuildManifest,
12849
13180
  parseDeliveryBuildResult,
12850
13181
  parseDeliveryOptions,
@@ -12858,6 +13189,8 @@ export {
12858
13189
  renderOpenApi,
12859
13190
  resolveModuleBoundaries,
12860
13191
  resolveSupacloudConfig,
13192
+ runDatabaseContractsFile,
13193
+ scanDrizzleSql,
12861
13194
  scanGeneratedArtifacts,
12862
13195
  scanProductionSource,
12863
13196
  serializeOpenApiJson,