@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/cli.js CHANGED
@@ -197,10 +197,24 @@ function renderApplication(graph, options) {
197
197
  ""
198
198
  ].join(`
199
199
  `);
200
+ const commandGovernance = graph.modules.flatMap((module) => module.commands.map((command) => ({
201
+ module: module.name,
202
+ className: command.className,
203
+ name: command.name,
204
+ permission: command.permission ?? null,
205
+ rpc: command.rpc ?? null,
206
+ transaction: command.transaction ?? null,
207
+ audit: command.audit ?? null,
208
+ idempotency: command.idempotency ?? null
209
+ }))).sort((left, right) => `${left.module}:${left.name}`.localeCompare(`${right.module}:${right.name}`));
200
210
  const manifest = {
201
211
  version: 1,
202
212
  modules: graph.modules,
203
- externalTokens: graph.externalTokens
213
+ externalTokens: graph.externalTokens,
214
+ commandGovernance: {
215
+ defaults: { authorization: "required", audit: "required", idempotency: "required", transaction: "required" },
216
+ commands: commandGovernance
217
+ }
204
218
  };
205
219
  const clientCode = options.generateClient ? renderClient(graph, options) : undefined;
206
220
  const openApiCode = options.generateOpenApi ? renderOpenApi(graph, options) : undefined;
@@ -355,7 +369,7 @@ class ModuleGenerator {
355
369
  this.imports = imports;
356
370
  this.pascal = pascalName(module.name);
357
371
  if (module.providers.some((provider) => (provider.functionalInjects?.length ?? 0) > 0) || module.controllers.some((controller) => (controller.functionalInjects?.length ?? 0) > 0)) {
358
- imports.add("runInInjectionContext", undefined, "@supacloud/app");
372
+ throw new Error("SC2012: Compiled DI requires constructor injection; property inject() is not supported.");
359
373
  }
360
374
  }
361
375
  renderFactories() {
@@ -389,6 +403,7 @@ class ModuleGenerator {
389
403
  lines.push(` jobs: ${this.renderJobs()},`);
390
404
  if (this.module.aspects && this.module.aspects.length > 0) {
391
405
  lines.push(` aspects: ${this.renderAspects(this.module.aspects)},`);
406
+ lines.push(` aspectPipeline: ${this.renderAspectPipeline(this.module.aspects)},`);
392
407
  }
393
408
  lines.push(`}`);
394
409
  return lines.join(`
@@ -465,6 +480,7 @@ class ModuleGenerator {
465
480
  }
466
481
  if (route.aspects && route.aspects.length > 0) {
467
482
  fields.push(`aspects: ${this.renderAspects(route.aspects)}`);
483
+ fields.push(`aspectPipeline: ${this.renderAspectPipeline(route.aspects)}`);
468
484
  }
469
485
  const invokerArgs = (route.handlerParams ?? []).map((hp) => {
470
486
  if (hp.kind === "param") {
@@ -545,7 +561,7 @@ ${indent(item, 2)}`).join(",")}
545
561
  `idempotency: ${JSON.stringify(command.idempotency)}`,
546
562
  ...command.rpc ? [`rpc: ${JSON.stringify(command.rpc)}`] : [],
547
563
  ...command.standalone ? ["standalone: true"] : [],
548
- ...command.aspects && command.aspects.length > 0 ? [`aspects: ${this.renderAspects(command.aspects)}`] : []
564
+ ...command.aspects && command.aspects.length > 0 ? [`aspects: ${this.renderAspects(command.aspects)}`, `aspectPipeline: ${this.renderAspectPipeline(command.aspects)}`] : []
549
565
  ];
550
566
  return `{ ${fields.join(", ")} }`;
551
567
  }).join(", ")}]`;
@@ -578,6 +594,7 @@ ${indent(item, 2)}`).join(",")}
578
594
  fields.push(`idempotency: ${JSON.stringify(job.idempotency)}`);
579
595
  if (job.aspects && job.aspects.length > 0) {
580
596
  fields.push(`aspects: ${this.renderAspects(job.aspects)}`);
597
+ fields.push(`aspectPipeline: ${this.renderAspectPipeline(job.aspects)}`);
581
598
  }
582
599
  return `{ ${fields.join(", ")}, }`;
583
600
  }).join(", ")}]`;
@@ -585,6 +602,24 @@ ${indent(item, 2)}`).join(",")}
585
602
  renderAspects(aspects) {
586
603
  return `[${aspects.map((aspect) => this.imports.add(aspect.name, aspect.importPath, aspect.importModule)).join(", ")}]`;
587
604
  }
605
+ renderAspectPipeline(aspects) {
606
+ const lines = [
607
+ `async (context, next, observe) => {`,
608
+ ` const state = { active: true };`,
609
+ ` const step${aspects.length} = compiledAspectNext(next, state);`
610
+ ];
611
+ for (let index = aspects.length - 1;index >= 0; index--) {
612
+ const aspect = aspects[index];
613
+ if (!aspect)
614
+ continue;
615
+ const name = this.imports.add(aspect.name, aspect.importPath, aspect.importModule);
616
+ const stage = JSON.stringify(`aspect[${index}]:${aspect.name}`);
617
+ lines.push(` const step${index} = compiledAspectNext(() => observeCompiledAspect(observe, ${stage}, () => ${name}(context, step${index + 1})), state);`);
618
+ }
619
+ lines.push(` try { return await step0(); } finally { state.active = false; }`, `}`);
620
+ return lines.join(`
621
+ `);
622
+ }
588
623
  renderServicesFactory() {
589
624
  return [
590
625
  `function create${this.pascal}Services(`,
@@ -699,7 +734,7 @@ ${indent(item, 2)}`).join(",")}
699
734
  const args = provider.deps.map((dep, index) => this.typedDepExpr(dep, kind, this.depOptions(provider, dep), `ConstructorParameters<typeof ${useClass}>[${index}]`)).join(", ");
700
735
  const local = this.localVar(isMulti ? provider.useClass ?? `${provider.token}Item` : provider.token, kind);
701
736
  return {
702
- constLine: `const ${local} = ${this.instantiate(useClass, args, kind, provider.functionalInjects)};`,
737
+ constLine: `const ${local} = new ${useClass}(${args});`,
703
738
  key,
704
739
  expr: local
705
740
  };
@@ -735,32 +770,11 @@ ${indent(item, 2)}`).join(",")}
735
770
  const key = camelName(controller.className);
736
771
  const local = this.localVar(controller.className, kind);
737
772
  return {
738
- constLine: `const ${local} = ${this.instantiate(className, args, kind, controller.functionalInjects)};`,
773
+ constLine: `const ${local} = new ${className}(${args});`,
739
774
  key,
740
775
  expr: local
741
776
  };
742
777
  }
743
- instantiate(className, args, kind, functionalInjects) {
744
- if (!functionalInjects || functionalInjects.length === 0) {
745
- return `new ${className}(${args})`;
746
- }
747
- const clauses = functionalInjects.map((entry) => {
748
- const token = this.imports.add(entry.expression, entry.importPath, entry.importModule);
749
- const value = this.depExpr(entry.token, kind, entry);
750
- return `if (token === ${token}) return ${value} as T;`;
751
- });
752
- const missing = `if (options?.optional) return undefined; throw new Error("Static inject token not available: " + String(token));`;
753
- const injector = [
754
- `{`,
755
- `get<T>(token: unknown, options?: { optional?: boolean; self?: boolean; skipSelf?: boolean; host?: boolean }): T | undefined {`,
756
- ...clauses,
757
- missing,
758
- `},`,
759
- `}`
760
- ].join(`
761
- `);
762
- return `runInInjectionContext(${injector}, () => new ${className}(${args}))`;
763
- }
764
778
  localVar(token, kind) {
765
779
  const locals = this.locals[kind];
766
780
  const existing = locals.get(token);
@@ -1933,6 +1947,7 @@ var HEADER = "// GENERATED BY @supacloud/compiler — do not edit", INTERFACES =
1933
1947
  title?: string;
1934
1948
  data?: Record<string, unknown>;
1935
1949
  aspects?: CompiledAspect[];
1950
+ aspectPipeline?: CompiledAspectPipeline;
1936
1951
  invoker?: (
1937
1952
  controller: unknown,
1938
1953
  request: {
@@ -1956,6 +1971,7 @@ export interface CompiledCommand {
1956
1971
  idempotency: "required" | "none";
1957
1972
  standalone?: boolean;
1958
1973
  aspects?: CompiledAspect[];
1974
+ aspectPipeline?: CompiledAspectPipeline;
1959
1975
  }
1960
1976
 
1961
1977
  export interface CompiledJob {
@@ -1970,6 +1986,7 @@ export interface CompiledJob {
1970
1986
  maxAttempts?: number;
1971
1987
  idempotency?: "required" | "none";
1972
1988
  aspects?: CompiledAspect[];
1989
+ aspectPipeline?: CompiledAspectPipeline;
1973
1990
  }
1974
1991
 
1975
1992
  export interface CompiledAspectContext {
@@ -2017,7 +2034,24 @@ export interface CompiledModule {
2017
2034
  commands: CompiledCommand[];
2018
2035
  jobs: CompiledJob[];
2019
2036
  aspects?: CompiledAspect[];
2020
- }`, TYPE_GUARDS = `function isRecord(value: unknown): value is Record<string, unknown> {
2037
+ aspectPipeline?: CompiledAspectPipeline;
2038
+ }`, TYPE_GUARDS = `type CompiledAspectObserver = (stage: string, run: () => unknown | Promise<unknown>) => unknown | Promise<unknown>;
2039
+ type CompiledAspectPipeline = (context: CompiledAspectContext, next: () => unknown | Promise<unknown>, observe?: CompiledAspectObserver) => unknown | Promise<unknown>;
2040
+
2041
+ function compiledAspectNext(next: () => unknown | Promise<unknown>, state: { active: boolean }): () => Promise<unknown> {
2042
+ let called = false;
2043
+ return async () => {
2044
+ if (!state.active) throw new Error("Aspect continuation is closed");
2045
+ if (called) throw new Error("Aspect continuation called multiple times");
2046
+ called = true;
2047
+ return await next();
2048
+ };
2049
+ }
2050
+ function observeCompiledAspect(observe: CompiledAspectObserver | undefined, stage: string, run: () => unknown | Promise<unknown>): unknown | Promise<unknown> {
2051
+ return observe ? observe(stage, run) : run();
2052
+ }
2053
+
2054
+ function isRecord(value: unknown): value is Record<string, unknown> {
2021
2055
  return typeof value === "object" && value !== null;
2022
2056
  }
2023
2057
 
@@ -2199,7 +2233,7 @@ var init_graphql_options = __esm(() => {
2199
2233
 
2200
2234
  // src/graphql-inputs.ts
2201
2235
  import { resolve as resolve3 } from "node:path";
2202
- import * as ts5 from "@typescript/typescript6";
2236
+ import * as ts7 from "@typescript/typescript6";
2203
2237
  function graphqlInputPaths(options) {
2204
2238
  if (!options.graphql)
2205
2239
  return [];
@@ -2210,7 +2244,7 @@ function graphqlInputPaths(options) {
2210
2244
  }
2211
2245
  const root = resolve3(options.rootDir);
2212
2246
  const schema = resolve3(root, options.graphql.schema);
2213
- 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);
2247
+ 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);
2214
2248
  return [schema, ...[...new Set(documents)].sort()];
2215
2249
  }
2216
2250
  var init_graphql_inputs = __esm(() => {
@@ -2218,7 +2252,7 @@ var init_graphql_inputs = __esm(() => {
2218
2252
  });
2219
2253
 
2220
2254
  // src/graphql-runtime.ts
2221
- import * as ts6 from "@typescript/typescript6";
2255
+ import * as ts8 from "@typescript/typescript6";
2222
2256
  import { resolve as resolve4 } from "node:path";
2223
2257
  function renderGraphqlValidators(source, operationNames) {
2224
2258
  const fileName = resolve4("/__supacloud_graphql__/contracts.ts");
@@ -2230,18 +2264,18 @@ function renderGraphqlValidators(source, operationNames) {
2230
2264
  noPropertyAccessFromIndexSignature: true,
2231
2265
  noFallthroughCasesInSwitch: true,
2232
2266
  skipLibCheck: false,
2233
- target: ts6.ScriptTarget.ES2022,
2267
+ target: ts8.ScriptTarget.ES2022,
2234
2268
  lib: ["lib.es2022.d.ts"],
2235
2269
  types: [],
2236
2270
  noEmit: true
2237
2271
  };
2238
- const host = ts6.createCompilerHost(options);
2272
+ const host = ts8.createCompilerHost(options);
2239
2273
  const getSourceFile = host.getSourceFile.bind(host);
2240
- host.getSourceFile = (path, languageVersion, onError, shouldCreateNewSourceFile) => path === fileName ? ts6.createSourceFile(path, source, languageVersion, true) : getSourceFile(path, languageVersion, onError, shouldCreateNewSourceFile);
2241
- const program = ts6.createProgram([fileName], options, host);
2242
- const diagnostics = ts6.getPreEmitDiagnostics(program);
2274
+ host.getSourceFile = (path, languageVersion, onError, shouldCreateNewSourceFile) => path === fileName ? ts8.createSourceFile(path, source, languageVersion, true) : getSourceFile(path, languageVersion, onError, shouldCreateNewSourceFile);
2275
+ const program = ts8.createProgram([fileName], options, host);
2276
+ const diagnostics = ts8.getPreEmitDiagnostics(program);
2243
2277
  if (diagnostics.length) {
2244
- throw new Error(`Generated GraphQL types cannot be validated: ${diagnostics.map((item) => ts6.flattenDiagnosticMessageText(item.messageText, `
2278
+ throw new Error(`Generated GraphQL types cannot be validated: ${diagnostics.map((item) => ts8.flattenDiagnosticMessageText(item.messageText, `
2245
2279
  `)).join("; ")}`);
2246
2280
  }
2247
2281
  const checker = program.getTypeChecker();
@@ -2271,25 +2305,25 @@ function renderGraphqlValidators(source, operationNames) {
2271
2305
  return name;
2272
2306
  }
2273
2307
  function expression(type) {
2274
- if (type.flags & ts6.TypeFlags.Any)
2308
+ if (type.flags & ts8.TypeFlags.Any)
2275
2309
  return unsupported(type);
2276
- if (type.flags & ts6.TypeFlags.Unknown)
2310
+ if (type.flags & ts8.TypeFlags.Unknown)
2277
2311
  return "true";
2278
- if (type.flags & ts6.TypeFlags.Never)
2312
+ if (type.flags & ts8.TypeFlags.Never)
2279
2313
  return "false";
2280
- if (type.flags & ts6.TypeFlags.Null)
2314
+ if (type.flags & ts8.TypeFlags.Null)
2281
2315
  return "value === null";
2282
- if (type.flags & ts6.TypeFlags.Undefined)
2316
+ if (type.flags & ts8.TypeFlags.Undefined)
2283
2317
  return "value === undefined";
2284
2318
  if (type.isStringLiteral() || type.isNumberLiteral())
2285
2319
  return `value === ${JSON.stringify(type.value)}`;
2286
- if (type.flags & ts6.TypeFlags.BooleanLiteral)
2320
+ if (type.flags & ts8.TypeFlags.BooleanLiteral)
2287
2321
  return `value === ${checker.typeToString(type)}`;
2288
- if (type.flags & ts6.TypeFlags.String)
2322
+ if (type.flags & ts8.TypeFlags.String)
2289
2323
  return 'typeof value === "string"';
2290
- if (type.flags & ts6.TypeFlags.Number)
2324
+ if (type.flags & ts8.TypeFlags.Number)
2291
2325
  return 'typeof value === "number" && Number.isFinite(value)';
2292
- if (type.flags & ts6.TypeFlags.Boolean)
2326
+ if (type.flags & ts8.TypeFlags.Boolean)
2293
2327
  return 'typeof value === "boolean"';
2294
2328
  if (type.isUnion())
2295
2329
  return type.types.map((part) => `${reference(part)}(value)`).join(" || ");
@@ -2298,16 +2332,16 @@ function renderGraphqlValidators(source, operationNames) {
2298
2332
  if (checker.isTupleType(type))
2299
2333
  return unsupported(type);
2300
2334
  if (checker.isArrayType(type)) {
2301
- const item = checker.getIndexTypeOfType(type, ts6.IndexKind.Number);
2335
+ const item = checker.getIndexTypeOfType(type, ts8.IndexKind.Number);
2302
2336
  if (!item)
2303
2337
  return unsupported(type);
2304
2338
  return `isGraphqlArray(value) && Array.from(value).every(${reference(item)})`;
2305
2339
  }
2306
- if (type.flags & ts6.TypeFlags.Object) {
2340
+ if (type.flags & ts8.TypeFlags.Object) {
2307
2341
  if (type.getCallSignatures().length || type.getConstructSignatures().length)
2308
2342
  return unsupported(type);
2309
2343
  const indexes = checker.getIndexInfosOfType(type);
2310
- if (indexes.some((index) => !(index.keyType.flags & ts6.TypeFlags.String)))
2344
+ if (indexes.some((index) => !(index.keyType.flags & ts8.TypeFlags.String)))
2311
2345
  return unsupported(type);
2312
2346
  const properties = checker.getPropertiesOfType(type).map((property) => {
2313
2347
  const declaration = property.valueDeclaration ?? property.declarations?.[0];
@@ -2316,7 +2350,7 @@ function renderGraphqlValidators(source, operationNames) {
2316
2350
  const check = reference(checker.getTypeOfSymbolAtLocation(property, declaration));
2317
2351
  const key = JSON.stringify(property.name);
2318
2352
  const present = `Object.prototype.hasOwnProperty.call(value, ${key})`;
2319
- return property.flags & ts6.SymbolFlags.Optional ? `(!${present} || ${check}(value[${key}]))` : `(${present} && ${check}(value[${key}]))`;
2353
+ return property.flags & ts8.SymbolFlags.Optional ? `(!${present} || ${check}(value[${key}]))` : `(${present} && ${check}(value[${key}]))`;
2320
2354
  });
2321
2355
  const indexedValues = indexes.map((index) => `Object.values(value).every(${reference(index.type)})`);
2322
2356
  return ["isGraphqlRecord(value)", ...properties, ...indexedValues].join(" && ");
@@ -2574,10 +2608,155 @@ var init_graphql = __esm(() => {
2574
2608
  init_graphql_runtime();
2575
2609
  });
2576
2610
 
2577
- // src/graphql-schema.ts
2578
- import { mkdir as mkdir5, readFile as readFile11 } from "node:fs/promises";
2611
+ // src/database-contracts.ts
2579
2612
  import { createHash as createHash9 } from "node:crypto";
2580
- import { dirname as dirname10, resolve as resolve15 } from "node:path";
2613
+ import { mkdir as mkdir5, readFile as readFile11 } from "node:fs/promises";
2614
+ import { dirname as dirname10, relative as relative12, resolve as resolve15 } from "node:path";
2615
+ import * as ts13 from "@typescript/typescript6";
2616
+ function hash2(value) {
2617
+ return createHash9("sha256").update(value).digest("hex");
2618
+ }
2619
+ function importPath(out, path) {
2620
+ const value = relative12(out, path).replaceAll("\\", "/").replace(/\.(?:d\.)?[cm]?ts$/, "");
2621
+ return value.startsWith(".") ? value : `./${value}`;
2622
+ }
2623
+ function parseDatabaseContractsOptions(value, directory) {
2624
+ if (!value || typeof value !== "object" || Array.isArray(value))
2625
+ throw new TypeError("Expected database contracts configuration");
2626
+ const allowed = ["rootDir", "outDir", "postgrestTypes", "drizzleSchema", "role", "graphql", "migrations"];
2627
+ if (Object.keys(value).some((name) => !allowed.includes(name)))
2628
+ throw new TypeError("Unknown database contracts option");
2629
+ const field = (name) => {
2630
+ const result = Reflect.get(value, name);
2631
+ if (typeof result !== "string" || !result.trim())
2632
+ throw new TypeError(`Missing database contracts ${name}`);
2633
+ return result;
2634
+ };
2635
+ const graphql = Reflect.get(value, "graphql");
2636
+ assertGraphqlOptions(graphql);
2637
+ const migrations = Reflect.get(value, "migrations");
2638
+ if (!Array.isArray(migrations) || !migrations.every((entry) => typeof entry === "string" && entry.endsWith(".sql"))) {
2639
+ throw new TypeError("migrations must be an ordered list of SQL files");
2640
+ }
2641
+ return {
2642
+ rootDir: resolve15(directory, field("rootDir")),
2643
+ outDir: resolve15(directory, field("outDir")),
2644
+ postgrestTypes: resolve15(directory, field("postgrestTypes")),
2645
+ drizzleSchema: resolve15(directory, field("drizzleSchema")),
2646
+ role: field("role"),
2647
+ graphql: { ...graphql, schema: resolve15(directory, graphql.schema) },
2648
+ migrations: migrations.map((file) => resolve15(directory, file))
2649
+ };
2650
+ }
2651
+ async function generateDatabaseContracts(options, check = false) {
2652
+ const rootDir = resolve15(options.rootDir), outDir = resolve15(options.outDir);
2653
+ const postgrestTypes = resolve15(rootDir, options.postgrestTypes), drizzleSchema = resolve15(rootDir, options.drizzleSchema);
2654
+ const snapshot = await readFile11(postgrestTypes, "utf8");
2655
+ const syntax = ts13.createSourceFile(postgrestTypes, snapshot, ts13.ScriptTarget.Latest, true);
2656
+ 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));
2657
+ if (!database)
2658
+ throw new Error("PostgREST snapshot must export Database from the official type generator");
2659
+ const program = ts13.createProgram([postgrestTypes], {
2660
+ strict: true,
2661
+ noEmit: true,
2662
+ skipLibCheck: true,
2663
+ types: [],
2664
+ target: ts13.ScriptTarget.ES2022,
2665
+ module: ts13.ModuleKind.ESNext,
2666
+ moduleResolution: ts13.ModuleResolutionKind.Bundler
2667
+ });
2668
+ if (ts13.getPreEmitDiagnostics(program).length)
2669
+ throw new Error("PostgREST snapshot has TypeScript errors");
2670
+ const artifacts = await renderGraphql({
2671
+ rootDir,
2672
+ outDir,
2673
+ graphql: options.graphql
2674
+ });
2675
+ if (artifacts.diagnostics.some((item) => item.severity === "error")) {
2676
+ throw new Error(artifacts.diagnostics.map((item) => item.message).join(`
2677
+ `));
2678
+ }
2679
+ const inputs = {};
2680
+ const addInput = async (path) => {
2681
+ const absolute = resolve15(rootDir, path);
2682
+ inputs[relative12(rootDir, absolute).replaceAll("\\", "/")] = hash2(await readFile11(absolute, "utf8"));
2683
+ };
2684
+ await addInput(postgrestTypes);
2685
+ await addInput(drizzleSchema);
2686
+ const drizzleProgram = ts13.createProgram([drizzleSchema], {
2687
+ noEmit: true,
2688
+ moduleResolution: ts13.ModuleResolutionKind.Bundler,
2689
+ module: ts13.ModuleKind.ESNext,
2690
+ target: ts13.ScriptTarget.ES2022,
2691
+ types: [],
2692
+ skipLibCheck: true
2693
+ });
2694
+ for (const source of drizzleProgram.getSourceFiles()) {
2695
+ if (!source.isDeclarationFile && !source.fileName.includes("/node_modules/"))
2696
+ await addInput(source.fileName);
2697
+ }
2698
+ await addInput(resolve15(rootDir, options.graphql.schema));
2699
+ if (new Set(options.migrations.map((path) => resolve15(rootDir, path))).size !== options.migrations.length) {
2700
+ throw new Error("Duplicate migration in database contracts configuration");
2701
+ }
2702
+ for (const path of options.migrations)
2703
+ await addInput(path);
2704
+ const files = {
2705
+ ...artifacts.files,
2706
+ "database.ts": [
2707
+ "// GENERATED BY @supacloud/compiler database-contracts. Do not edit.",
2708
+ `export type { Database } from ${JSON.stringify(importPath(outDir, postgrestTypes))};`,
2709
+ 'export type { QueryData, QueryResult, QueryError } from "@supabase/supabase-js";',
2710
+ `export type DrizzleSchema = typeof import(${JSON.stringify(importPath(outDir, drizzleSchema))});`,
2711
+ 'export * from "./graphql";',
2712
+ ""
2713
+ ].join(`
2714
+ `)
2715
+ };
2716
+ const manifest = {
2717
+ version: 1,
2718
+ role: options.role,
2719
+ inputs: Object.fromEntries(Object.entries(inputs).sort(([a], [b]) => a.localeCompare(b))),
2720
+ migrationOrder: options.migrations.map((path) => relative12(rootDir, resolve15(rootDir, path)).replaceAll("\\", "/")),
2721
+ outputs: Object.fromEntries(Object.entries(files).sort(([a], [b]) => a.localeCompare(b)).map(([file, text]) => [file, hash2(text)]))
2722
+ };
2723
+ files["database.manifest.json"] = JSON.stringify(manifest, null, 2) + `
2724
+ `;
2725
+ const mismatches = [];
2726
+ for (const [file, content] of Object.entries(files)) {
2727
+ const path = resolve15(outDir, file);
2728
+ let current;
2729
+ try {
2730
+ current = await readFile11(path, "utf8");
2731
+ } catch (error) {
2732
+ if (!(error instanceof Error && ("code" in error) && error.code === "ENOENT"))
2733
+ throw error;
2734
+ }
2735
+ if (current !== content)
2736
+ mismatches.push(file);
2737
+ }
2738
+ if (!check) {
2739
+ await mkdir5(outDir, { recursive: true });
2740
+ for (const [file, content] of Object.entries(files))
2741
+ await writeFileIfChanged(resolve15(outDir, file), content);
2742
+ }
2743
+ return { upToDate: mismatches.length === 0, mismatches, written: check ? [] : mismatches, manifest };
2744
+ }
2745
+ async function runDatabaseContractsFile(path, check = false) {
2746
+ const absolute = resolve15(path);
2747
+ const value = JSON.parse(await readFile11(absolute, "utf8"));
2748
+ return generateDatabaseContracts(parseDatabaseContractsOptions(value, dirname10(absolute)), check);
2749
+ }
2750
+ var init_database_contracts = __esm(() => {
2751
+ init_graphql();
2752
+ init_generate();
2753
+ init_graphql_options();
2754
+ });
2755
+
2756
+ // src/graphql-schema.ts
2757
+ import { mkdir as mkdir6, readFile as readFile12 } from "node:fs/promises";
2758
+ import { createHash as createHash10 } from "node:crypto";
2759
+ import { dirname as dirname11, resolve as resolve16 } from "node:path";
2581
2760
  async function pullGraphqlSchema(options) {
2582
2761
  assertGraphqlOptions({ schema: options.output });
2583
2762
  const endpoint = new URL(options.url);
@@ -2617,7 +2796,7 @@ async function pullGraphqlSchema(options) {
2617
2796
  throw new Error("GraphQL schema export failed. Verify caller grants and enable introspection only in the intended development environment.");
2618
2797
  }
2619
2798
  const schema = lexicographicSortSchema(buildClientSchema(data));
2620
- const path = resolve15(options.output);
2799
+ const path = resolve16(options.output);
2621
2800
  const content = path.endsWith(".json") ? JSON.stringify(introspectionFromSchema(schema), null, 2) + `
2622
2801
  ` : `# GENERATED BY supacloud-compiler graphql-schema. DO NOT EDIT.
2623
2802
  # Database First: change database declarations, apply migrations, then re-export for the intended role.
@@ -2625,16 +2804,16 @@ async function pullGraphqlSchema(options) {
2625
2804
  `;
2626
2805
  let previous;
2627
2806
  try {
2628
- previous = await readFile11(path, "utf8");
2807
+ previous = await readFile12(path, "utf8");
2629
2808
  } catch (error) {
2630
2809
  if (!(error instanceof Error && ("code" in error) && error.code === "ENOENT"))
2631
2810
  throw error;
2632
2811
  }
2633
2812
  const upToDate = previous === content;
2634
- const schemaHash = createHash9("sha256").update(content).digest("hex");
2813
+ const schemaHash = createHash10("sha256").update(content).digest("hex");
2635
2814
  if (options.check)
2636
2815
  return { path, schemaHash, upToDate, written: false };
2637
- await mkdir5(dirname10(path), { recursive: true });
2816
+ await mkdir6(dirname11(path), { recursive: true });
2638
2817
  await writeFileIfChanged(path, content);
2639
2818
  return { path, schemaHash, upToDate: true, written: true };
2640
2819
  }
@@ -2644,13 +2823,13 @@ var init_graphql_schema = __esm(() => {
2644
2823
  });
2645
2824
 
2646
2825
  // src/cli.ts
2647
- import { resolve as resolve16 } from "node:path";
2648
- import { readFile as readFile12 } from "node:fs/promises";
2826
+ import { resolve as resolve17 } from "node:path";
2827
+ import { readFile as readFile13 } from "node:fs/promises";
2649
2828
 
2650
2829
  // src/analyze.ts
2651
2830
  import { createHash as createHash3 } from "node:crypto";
2652
2831
  import { relative as relative2, resolve as resolvePath, sep as sep2 } from "node:path";
2653
- import * as ts3 from "@typescript/typescript6";
2832
+ import * as ts4 from "@typescript/typescript6";
2654
2833
 
2655
2834
  // src/program.ts
2656
2835
  import { createHash as createHash2 } from "node:crypto";
@@ -3300,6 +3479,7 @@ var COMPILER_DIAGNOSTIC_CODES = {
3300
3479
  "missing-token-factory": { code: "SC2009", docsUrl: "https://supacloud.dev/errors/SC2009" },
3301
3480
  "provider-type-mismatch": { code: "SC2010", docsUrl: "https://supacloud.dev/errors/SC2010" },
3302
3481
  "unsupported-provider-helper": { code: "SC2011", docsUrl: "https://supacloud.dev/errors/SC2011" },
3482
+ "runtime-injection-disallowed": { code: "SC2012", docsUrl: "https://supacloud.dev/errors/SC2012" },
3303
3483
  "command-missing-permission": { code: "SC4001", docsUrl: "https://supacloud.dev/errors/SC4001" },
3304
3484
  "duplicate-command": { code: "SC4002", docsUrl: "https://supacloud.dev/errors/SC4002" },
3305
3485
  "route-command-unresolved": { code: "SC4003", docsUrl: "https://supacloud.dev/errors/SC4003" },
@@ -3346,6 +3526,20 @@ var COMPILER_DIAGNOSTIC_CODES = {
3346
3526
  function validateGraph(graph, options = false) {
3347
3527
  const strict = typeof options === "boolean" ? options : options.strict ?? false;
3348
3528
  const diagnostics = [];
3529
+ for (const module of graph.modules) {
3530
+ for (const owner of [...module.providers, ...module.controllers]) {
3531
+ if (owner.functionalInjects?.length)
3532
+ diagnostics.push({
3533
+ severity: "error",
3534
+ code: "runtime-injection-disallowed",
3535
+ errorCode: "SC2012",
3536
+ docsUrl: "https://supacloud.dev/errors/SC2012",
3537
+ file: owner.file,
3538
+ message: "Property inject() requires runtime token resolution. Compiled applications require constructor injection.",
3539
+ suggestion: "Move injected fields into typed constructor parameters with @Inject(TOKEN) where needed."
3540
+ });
3541
+ }
3542
+ }
3349
3543
  let moduleBoundaries;
3350
3544
  if (typeof options === "object") {
3351
3545
  try {
@@ -3773,7 +3967,7 @@ function validateGraph(graph, options = false) {
3773
3967
  if (typeof options === "object" && options.commandCapabilities) {
3774
3968
  const hostCaps = options.commandCapabilities;
3775
3969
  const rpcCaps = command.rpc && Object.hasOwn(hostCaps.rpc ?? {}, command.rpc) ? hostCaps.rpc?.[command.rpc] : undefined;
3776
- 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"))) {
3970
+ 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"))) {
3777
3971
  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.");
3778
3972
  }
3779
3973
  if (rpcCaps?.boundary === "external" && (command.transaction === "required" || rpcCaps.transaction === true)) {
@@ -4126,6 +4320,67 @@ function detectOrphanModules(graph) {
4126
4320
  }
4127
4321
  return diagnostics;
4128
4322
  }
4323
+ // src/static-di.ts
4324
+ import * as ts3 from "@typescript/typescript6";
4325
+ var runtimeApis = new Set([
4326
+ "inject",
4327
+ "createEnvironmentInjector",
4328
+ "runInInjectionContext",
4329
+ "EnvironmentInjector",
4330
+ "bootstrapBun",
4331
+ "runInScope",
4332
+ "runInRequestContext",
4333
+ "runInJobContext",
4334
+ "runInTransactionContext"
4335
+ ]);
4336
+ function scanRuntimeDi(source, file) {
4337
+ const diagnostics = [];
4338
+ const namespaces = new Set;
4339
+ const report = (node) => diagnostics.push({
4340
+ severity: "error",
4341
+ code: "runtime-injection-disallowed",
4342
+ errorCode: "SC2012",
4343
+ docsUrl: "https://supacloud.dev/errors/SC2012",
4344
+ file,
4345
+ line: source.getLineAndCharacterOfPosition(node.getStart()).line + 1,
4346
+ message: "Compiled applications cannot import runtime DI. Use explicit constructors and generated scope factories."
4347
+ });
4348
+ for (const statement of source.statements) {
4349
+ if (!(ts3.isImportDeclaration(statement) || ts3.isExportDeclaration(statement)) || !statement.moduleSpecifier || !ts3.isStringLiteral(statement.moduleSpecifier) || !/^@supacloud\/app(?:\/|$)/.test(statement.moduleSpecifier.text))
4350
+ continue;
4351
+ if (ts3.isImportDeclaration(statement)) {
4352
+ if (statement.importClause?.isTypeOnly)
4353
+ continue;
4354
+ const binding = statement.importClause?.namedBindings;
4355
+ if (binding && ts3.isNamespaceImport(binding))
4356
+ namespaces.add(binding.name.text);
4357
+ if (binding && ts3.isNamedImports(binding))
4358
+ for (const item of binding.elements) {
4359
+ if (!item.isTypeOnly && runtimeApis.has((item.propertyName ?? item.name).text))
4360
+ report(item);
4361
+ }
4362
+ } else if (!statement.isTypeOnly) {
4363
+ if (!statement.exportClause)
4364
+ report(statement);
4365
+ else if (ts3.isNamedExports(statement.exportClause))
4366
+ for (const item of statement.exportClause.elements) {
4367
+ if (!item.isTypeOnly && runtimeApis.has((item.propertyName ?? item.name).text))
4368
+ report(item);
4369
+ }
4370
+ }
4371
+ }
4372
+ const visit = (node) => {
4373
+ if (ts3.isPropertyAccessExpression(node) && ts3.isIdentifier(node.expression) && namespaces.has(node.expression.text) && runtimeApis.has(node.name.text))
4374
+ report(node);
4375
+ if (ts3.isElementAccessExpression(node) && ts3.isIdentifier(node.expression) && namespaces.has(node.expression.text) && (!ts3.isStringLiteral(node.argumentExpression) || runtimeApis.has(node.argumentExpression.text)))
4376
+ report(node);
4377
+ if (ts3.isVariableDeclaration(node) && node.initializer && ts3.isIdentifier(node.initializer) && namespaces.has(node.initializer.text))
4378
+ report(node);
4379
+ ts3.forEachChild(node, visit);
4380
+ };
4381
+ visit(source);
4382
+ return diagnostics;
4383
+ }
4129
4384
 
4130
4385
  // src/analyze.ts
4131
4386
  var DEFAULT_INCLUDE = ["**/*.module.ts", "**/*.ts"];
@@ -4167,26 +4422,26 @@ function lineOf(node) {
4167
4422
  return sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;
4168
4423
  }
4169
4424
  function variableName(decl) {
4170
- return ts3.isIdentifier(decl.name) ? decl.name.text : nodeText(decl.name);
4425
+ return ts4.isIdentifier(decl.name) ? decl.name.text : nodeText(decl.name);
4171
4426
  }
4172
4427
  function propertyName(name) {
4173
- if (ts3.isIdentifier(name) || ts3.isPrivateIdentifier(name))
4428
+ if (ts4.isIdentifier(name) || ts4.isPrivateIdentifier(name))
4174
4429
  return name.text;
4175
- if (ts3.isStringLiteral(name) || ts3.isNumericLiteral(name))
4430
+ if (ts4.isStringLiteral(name) || ts4.isNumericLiteral(name))
4176
4431
  return name.text;
4177
4432
  return nodeText(name);
4178
4433
  }
4179
4434
  function parameterName(param) {
4180
- return ts3.isIdentifier(param.name) ? param.name.text : nodeText(param.name);
4435
+ return ts4.isIdentifier(param.name) ? param.name.text : nodeText(param.name);
4181
4436
  }
4182
4437
  function decoratorsOf(node) {
4183
- return ts3.canHaveDecorators(node) ? ts3.getDecorators(node) ?? [] : [];
4438
+ return ts4.canHaveDecorators(node) ? ts4.getDecorators(node) ?? [] : [];
4184
4439
  }
4185
4440
  function decoratorArguments(dec) {
4186
- return ts3.isCallExpression(dec.expression) ? dec.expression.arguments : [];
4441
+ return ts4.isCallExpression(dec.expression) ? dec.expression.arguments : [];
4187
4442
  }
4188
4443
  function hasMethod(cls, name) {
4189
- return cls.members.some((member) => (ts3.isMethodDeclaration(member) || ts3.isGetAccessorDeclaration(member) || ts3.isSetAccessorDeclaration(member)) && member.name !== undefined && propertyName(member.name) === name);
4444
+ return cls.members.some((member) => (ts4.isMethodDeclaration(member) || ts4.isGetAccessorDeclaration(member) || ts4.isSetAccessorDeclaration(member)) && member.name !== undefined && propertyName(member.name) === name);
4190
4445
  }
4191
4446
  function hasDestroyHook(cls) {
4192
4447
  return hasMethod(cls, "onDestroy") || hasMethod(cls, "ngOnDestroy");
@@ -4196,7 +4451,7 @@ function descendantsOfKind(root, predicate) {
4196
4451
  const visit = (node) => {
4197
4452
  if (predicate(node))
4198
4453
  result.push(node);
4199
- ts3.forEachChild(node, visit);
4454
+ ts4.forEachChild(node, visit);
4200
4455
  };
4201
4456
  visit(root);
4202
4457
  return result;
@@ -4205,7 +4460,7 @@ async function analyzeProject(rootDir, include, cache, changedPaths) {
4205
4460
  const session = cache?.programSession ?? createIncrementalProgramSession(rootDir);
4206
4461
  if (cache)
4207
4462
  cache.programSession = session;
4208
- const rootNames = ts3.sys.readDirectory(rootDir, [".ts", ".tsx"], ["node_modules", "dist"], include ?? DEFAULT_INCLUDE);
4463
+ const rootNames = ts4.sys.readDirectory(rootDir, [".ts", ".tsx"], ["node_modules", "dist"], include ?? DEFAULT_INCLUDE);
4209
4464
  const update = session.update(rootNames, changedPaths);
4210
4465
  const program = update.program;
4211
4466
  const checker = program.getTypeChecker();
@@ -4229,13 +4484,16 @@ async function analyzeProject(rootDir, include, cache, changedPaths) {
4229
4484
  nativeTraitFiles.set(trait.file, kinds);
4230
4485
  }
4231
4486
  for (const sf of sourceFiles) {
4487
+ if (!/\.(?:test|spec)\.[cm]?tsx?$/.test(sf.fileName)) {
4488
+ ctx.diagnostics.push(...scanRuntimeDi(sf, sourcePath(rootDir, sf.fileName)));
4489
+ }
4232
4490
  indexFile(sf, ctx);
4233
4491
  }
4234
4492
  const candidates = [];
4235
4493
  for (const sf of sourceFiles) {
4236
4494
  const traits = nativeTraitFiles.get(sf.fileName);
4237
4495
  if (!cache || traits?.has("module")) {
4238
- for (const cls of sf.statements.filter(ts3.isClassDeclaration)) {
4496
+ for (const cls of sf.statements.filter(ts4.isClassDeclaration)) {
4239
4497
  const moduleDec = findDecorator(cls, "Module");
4240
4498
  if (!moduleDec)
4241
4499
  continue;
@@ -4252,14 +4510,14 @@ async function analyzeProject(rootDir, include, cache, changedPaths) {
4252
4510
  }
4253
4511
  }
4254
4512
  if (!cache || traits?.has("defineModule") || traits?.has("defineFeatureSlice")) {
4255
- for (const call of descendantsOfKind(sf, ts3.isCallExpression)) {
4513
+ for (const call of descendantsOfKind(sf, ts4.isCallExpression)) {
4256
4514
  if (!["defineModule", "defineFeatureSlice"].includes(nodeText(call.expression)))
4257
4515
  continue;
4258
4516
  const parent = call.parent;
4259
- if (!parent || !ts3.isVariableDeclaration(parent))
4517
+ if (!parent || !ts4.isVariableDeclaration(parent))
4260
4518
  continue;
4261
4519
  const arg = call.arguments[0];
4262
- if (!arg || !ts3.isObjectLiteralExpression(arg))
4520
+ if (!arg || !ts4.isObjectLiteralExpression(arg))
4263
4521
  continue;
4264
4522
  candidates.push({
4265
4523
  node: parent,
@@ -4403,7 +4661,7 @@ async function analyzeProject(rootDir, include, cache, changedPaths) {
4403
4661
  const controllerDec = findDecorator(classInfo.decl, "Controller");
4404
4662
  if (controllerDec) {
4405
4663
  const arg = decoratorArguments(controllerDec)[0];
4406
- const isStandalone = arg && ts3.isObjectLiteralExpression(arg) && booleanProp(arg, "standalone");
4664
+ const isStandalone = arg && ts4.isObjectLiteralExpression(arg) && booleanProp(arg, "standalone");
4407
4665
  if (isStandalone) {
4408
4666
  const ctrl = parseController(classInfo.decl, ctx);
4409
4667
  if (ctrl)
@@ -4528,16 +4786,16 @@ function collectModuleSourceClosure(module, ctx) {
4528
4786
  ownedFiles.add(relativeFile);
4529
4787
  for (const statement of sourceFile.statements) {
4530
4788
  let moduleName;
4531
- if (ts3.isImportDeclaration(statement) && ts3.isStringLiteral(statement.moduleSpecifier)) {
4789
+ if (ts4.isImportDeclaration(statement) && ts4.isStringLiteral(statement.moduleSpecifier)) {
4532
4790
  moduleName = statement.moduleSpecifier.text;
4533
- } else if (ts3.isExportDeclaration(statement) && statement.moduleSpecifier && ts3.isStringLiteral(statement.moduleSpecifier)) {
4791
+ } else if (ts4.isExportDeclaration(statement) && statement.moduleSpecifier && ts4.isStringLiteral(statement.moduleSpecifier)) {
4534
4792
  moduleName = statement.moduleSpecifier.text;
4535
- } else if (ts3.isImportEqualsDeclaration(statement) && ts3.isExternalModuleReference(statement.moduleReference) && ts3.isStringLiteral(statement.moduleReference.expression)) {
4793
+ } else if (ts4.isImportEqualsDeclaration(statement) && ts4.isExternalModuleReference(statement.moduleReference) && ts4.isStringLiteral(statement.moduleReference.expression)) {
4536
4794
  moduleName = statement.moduleReference.expression.text;
4537
4795
  }
4538
4796
  if (!moduleName || moduleName.startsWith("node:"))
4539
4797
  continue;
4540
- const resolved = ts3.resolveModuleName(moduleName, sourceFile.fileName, ctx.program.getCompilerOptions(), ts3.sys).resolvedModule?.resolvedFileName;
4798
+ const resolved = ts4.resolveModuleName(moduleName, sourceFile.fileName, ctx.program.getCompilerOptions(), ts4.sys).resolvedModule?.resolvedFileName;
4541
4799
  if (resolved && isProjectSourcePath(resolved, ctx.rootDir) && !enqueued.has(resolved)) {
4542
4800
  enqueued.add(resolved);
4543
4801
  queue.push(resolved);
@@ -4559,15 +4817,15 @@ function isProjectSourceFile(sourceFile, rootDir) {
4559
4817
  return isProjectSourcePath(sourceFile.fileName, rootDir) && /\.(tsx?|mts|cts)$/.test(sourceFile.fileName);
4560
4818
  }
4561
4819
  function indexFile(sf, ctx) {
4562
- for (const cls of sf.statements.filter(ts3.isClassDeclaration)) {
4820
+ for (const cls of sf.statements.filter(ts4.isClassDeclaration)) {
4563
4821
  const name = cls.name?.text;
4564
4822
  if (name && !ctx.classesByName.has(name)) {
4565
4823
  ctx.classesByName.set(name, { name, decl: cls, file: sf.fileName });
4566
4824
  }
4567
4825
  }
4568
- for (const statement of sf.statements.filter(ts3.isVariableStatement)) {
4826
+ for (const statement of sf.statements.filter(ts4.isVariableStatement)) {
4569
4827
  for (const decl of statement.declarationList.declarations) {
4570
- if (ts3.isIdentifier(decl.name) && !ctx.variablesByName.has(decl.name.text)) {
4828
+ if (ts4.isIdentifier(decl.name) && !ctx.variablesByName.has(decl.name.text)) {
4571
4829
  ctx.variablesByName.set(decl.name.text, decl);
4572
4830
  }
4573
4831
  const info = parseTokenVariable(decl, sf.fileName);
@@ -4579,16 +4837,16 @@ function indexFile(sf, ctx) {
4579
4837
  }
4580
4838
  function parseTokenVariable(decl, file) {
4581
4839
  const init = decl.initializer;
4582
- if (!init || !ts3.isNewExpression(init))
4840
+ if (!init || !ts4.isNewExpression(init))
4583
4841
  return;
4584
4842
  if (nodeText(init.expression) !== "InjectionToken")
4585
4843
  return;
4586
4844
  const [nameArg, optionsArg] = init.arguments ?? [];
4587
4845
  const info = { name: variableName(decl), file, line: lineOf(decl) };
4588
- if (nameArg && ts3.isStringLiteral(nameArg)) {
4846
+ if (nameArg && ts4.isStringLiteral(nameArg)) {
4589
4847
  info.stringName = nameArg.text;
4590
4848
  }
4591
- if (optionsArg && ts3.isObjectLiteralExpression(optionsArg)) {
4849
+ if (optionsArg && ts4.isObjectLiteralExpression(optionsArg)) {
4592
4850
  const scope = stringLiteralProp(optionsArg, "scope");
4593
4851
  if (scope && isScope(scope)) {
4594
4852
  info.scope = scope;
@@ -4608,22 +4866,22 @@ function parseModule(candidate, nameByNode, ctx) {
4608
4866
  const { options, className, file, line } = candidate;
4609
4867
  const name = nameByNode.get(candidate.node) ?? className;
4610
4868
  const featureSpec = parseFeatureSpec(getProp(options, "spec"), ctx);
4611
- const tags = arrayProp(options, "tags").map((el) => ts3.isStringLiteral(el) ? el.text : nodeText(el).replace(/['"]/g, "")).filter(Boolean);
4869
+ const tags = arrayProp(options, "tags").map((el) => ts4.isStringLiteral(el) ? el.text : nodeText(el).replace(/['"]/g, "")).filter(Boolean);
4612
4870
  const aspects = parseAspectRefs(getProp(options, "aspects"), ctx, `module ${name}`);
4613
4871
  const imports = arrayProp(options, "imports").map((el) => {
4614
4872
  const unwrapped = unwrapForwardRef(el);
4615
- const decl = ts3.isIdentifier(unwrapped) ? resolveDeclaration(unwrapped, ctx)[0] : undefined;
4873
+ const decl = ts4.isIdentifier(unwrapped) ? resolveDeclaration(unwrapped, ctx)[0] : undefined;
4616
4874
  if (decl) {
4617
4875
  const known = nameByNode.get(decl);
4618
4876
  if (known)
4619
4877
  return known;
4620
- if (ts3.isClassDeclaration(decl)) {
4878
+ if (ts4.isClassDeclaration(decl)) {
4621
4879
  const dec = findDecorator(decl, "Module");
4622
4880
  const decOptions = dec && decoratorObjectArg(dec);
4623
4881
  const decName = decOptions && stringLiteralProp(decOptions, "name");
4624
4882
  return decName ?? decl.name?.text ?? nodeText(el);
4625
4883
  }
4626
- if (ts3.isVariableDeclaration(decl))
4884
+ if (ts4.isVariableDeclaration(decl))
4627
4885
  return variableName(decl);
4628
4886
  }
4629
4887
  return nodeText(el);
@@ -4637,7 +4895,7 @@ function parseModule(candidate, nameByNode, ctx) {
4637
4895
  providers.push(...parsedProviders);
4638
4896
  continue;
4639
4897
  }
4640
- if (ts3.isCallExpression(el)) {
4898
+ if (ts4.isCallExpression(el)) {
4641
4899
  const helper = nodeText(el.expression).split(".").pop() ?? nodeText(el.expression);
4642
4900
  warn(ctx, "unsupported-provider-helper", `无法静态展开 provider helper '${helper}';请改用显式 Provider 或实现编译器支持的 helper`, sourcePath(ctx.rootDir, el.getSourceFile().fileName), lineOf(el));
4643
4901
  continue;
@@ -4647,10 +4905,10 @@ function parseModule(candidate, nameByNode, ctx) {
4647
4905
  providers.push(provider);
4648
4906
  }
4649
4907
  for (const el of arrayProp(options, "jobs")) {
4650
- if (!ts3.isIdentifier(el))
4908
+ if (!ts4.isIdentifier(el))
4651
4909
  continue;
4652
4910
  const decl = resolveDeclaration(el, ctx)[0];
4653
- if (!decl || !ts3.isClassDeclaration(decl))
4911
+ if (!decl || !ts4.isClassDeclaration(decl))
4654
4912
  continue;
4655
4913
  const className = decl.name?.text ?? el.text;
4656
4914
  const registeredProvider = providers.find((provider) => provider.token === className || provider.useClass === className);
@@ -4687,18 +4945,18 @@ function parseModule(candidate, nameByNode, ctx) {
4687
4945
  const handlerClasses = [];
4688
4946
  const seenHandlers = new Set;
4689
4947
  const collectHandler = (expr) => {
4690
- if (!ts3.isIdentifier(expr))
4948
+ if (!ts4.isIdentifier(expr))
4691
4949
  return;
4692
4950
  const decl = resolveDeclaration(expr, ctx)[0];
4693
- if (decl && ts3.isClassDeclaration(decl) && !seenHandlers.has(decl.name?.text ?? "")) {
4951
+ if (decl && ts4.isClassDeclaration(decl) && !seenHandlers.has(decl.name?.text ?? "")) {
4694
4952
  seenHandlers.add(decl.name?.text ?? "");
4695
4953
  handlerClasses.push(decl);
4696
4954
  }
4697
4955
  };
4698
4956
  for (const el of arrayProp(options, "providers")) {
4699
- if (ts3.isIdentifier(el))
4957
+ if (ts4.isIdentifier(el))
4700
4958
  collectHandler(el);
4701
- if (ts3.isObjectLiteralExpression(el)) {
4959
+ if (ts4.isObjectLiteralExpression(el)) {
4702
4960
  const useClass = getProp(el, "useClass");
4703
4961
  if (useClass)
4704
4962
  collectHandler(useClass);
@@ -4798,17 +5056,17 @@ function parseFeatureSpec(input, ctx, seen = new Set) {
4798
5056
  if (seen.has(input))
4799
5057
  return;
4800
5058
  seen.add(input);
4801
- if (ts3.isIdentifier(input)) {
4802
- const local = input.getSourceFile().statements.flatMap((statement) => ts3.isVariableStatement(statement) ? [...statement.declarationList.declarations] : []);
5059
+ if (ts4.isIdentifier(input)) {
5060
+ const local = input.getSourceFile().statements.flatMap((statement) => ts4.isVariableStatement(statement) ? [...statement.declarationList.declarations] : []);
4803
5061
  const resolved = resolveDeclaration(input, ctx)[0];
4804
- 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);
4805
- if (decl && ts3.isVariableDeclaration(decl))
5062
+ 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);
5063
+ if (decl && ts4.isVariableDeclaration(decl))
4806
5064
  return parseFeatureSpec(decl.initializer, ctx, seen);
4807
5065
  }
4808
- if (ts3.isCallExpression(input) && nodeText(input.expression) === "defineFeatureSpec") {
5066
+ if (ts4.isCallExpression(input) && nodeText(input.expression) === "defineFeatureSpec") {
4809
5067
  return parseFeatureSpec(input.arguments[0], ctx, seen);
4810
5068
  }
4811
- if (ts3.isAsExpression(input) || ts3.isSatisfiesExpression(input) || ts3.isParenthesizedExpression(input)) {
5069
+ if (ts4.isAsExpression(input) || ts4.isSatisfiesExpression(input) || ts4.isParenthesizedExpression(input)) {
4812
5070
  return parseFeatureSpec(input.expression, ctx, seen);
4813
5071
  }
4814
5072
  const invalid = () => {
@@ -4821,28 +5079,28 @@ function parseFeatureSpec(input, ctx, seen = new Set) {
4821
5079
  });
4822
5080
  return;
4823
5081
  };
4824
- if (!ts3.isObjectLiteralExpression(input))
5082
+ if (!ts4.isObjectLiteralExpression(input))
4825
5083
  return invalid();
4826
5084
  const name = stringLiteralProp(input, "name");
4827
5085
  const statesExpr = getProp(input, "states");
4828
5086
  const transitionObject = getProp(input, "transitions");
4829
- if (!name || !statesExpr || !ts3.isArrayLiteralExpression(statesExpr) || statesExpr.elements.some((state) => !ts3.isStringLiteral(state)) || !transitionObject || !ts3.isObjectLiteralExpression(transitionObject) || input.properties.some((property) => !ts3.isPropertyAssignment(property))) {
5087
+ if (!name || !statesExpr || !ts4.isArrayLiteralExpression(statesExpr) || statesExpr.elements.some((state) => !ts4.isStringLiteral(state)) || !transitionObject || !ts4.isObjectLiteralExpression(transitionObject) || input.properties.some((property) => !ts4.isPropertyAssignment(property))) {
4830
5088
  return invalid();
4831
5089
  }
4832
5090
  const states = [];
4833
5091
  for (const state of statesExpr.elements) {
4834
- if (!ts3.isStringLiteral(state))
5092
+ if (!ts4.isStringLiteral(state))
4835
5093
  return invalid();
4836
5094
  states.push(state.text);
4837
5095
  }
4838
5096
  const transitions = [];
4839
5097
  for (const property of transitionObject.properties) {
4840
- if (!ts3.isPropertyAssignment(property) || ts3.isComputedPropertyName(property.name) || !ts3.isObjectLiteralExpression(property.initializer))
5098
+ if (!ts4.isPropertyAssignment(property) || ts4.isComputedPropertyName(property.name) || !ts4.isObjectLiteralExpression(property.initializer))
4841
5099
  return invalid();
4842
5100
  const options = property.initializer;
4843
5101
  const from = stringLiteralProp(options, "from");
4844
5102
  const to = stringLiteralProp(options, "to");
4845
- 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))) {
5103
+ 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))) {
4846
5104
  return invalid();
4847
5105
  }
4848
5106
  const permission = stringLiteralProp(options, "permission");
@@ -4869,21 +5127,21 @@ function resolveStaticObjectLiteral(input, ctx, seen = new Set) {
4869
5127
  if (!input || seen.has(input))
4870
5128
  return;
4871
5129
  seen.add(input);
4872
- if (ts3.isAsExpression(input) || ts3.isSatisfiesExpression(input) || ts3.isParenthesizedExpression(input)) {
5130
+ if (ts4.isAsExpression(input) || ts4.isSatisfiesExpression(input) || ts4.isParenthesizedExpression(input)) {
4873
5131
  return resolveStaticObjectLiteral(input.expression, ctx, seen);
4874
5132
  }
4875
- if (ts3.isIdentifier(input)) {
4876
- const declaration = resolveDeclaration(input, ctx).find(ts3.isVariableDeclaration);
5133
+ if (ts4.isIdentifier(input)) {
5134
+ const declaration = resolveDeclaration(input, ctx).find(ts4.isVariableDeclaration);
4877
5135
  return declaration?.initializer ? resolveStaticObjectLiteral(declaration.initializer, ctx, seen) : undefined;
4878
5136
  }
4879
- if (ts3.isCallExpression(input)) {
5137
+ if (ts4.isCallExpression(input)) {
4880
5138
  const expressionName = nodeText(input.expression);
4881
5139
  if (expressionName === "defineRouteContract" || expressionName.endsWith(".defineRouteContract")) {
4882
5140
  return resolveStaticObjectLiteral(input.arguments[0], ctx, seen);
4883
5141
  }
4884
5142
  return;
4885
5143
  }
4886
- return ts3.isObjectLiteralExpression(input) ? input : undefined;
5144
+ return ts4.isObjectLiteralExpression(input) ? input : undefined;
4887
5145
  }
4888
5146
  function commandModeProp(object, name) {
4889
5147
  const value = stringLiteralProp(object, name);
@@ -4918,9 +5176,9 @@ function parseProvider(el, exportsSet, ctx) {
4918
5176
  const file = sourcePath(ctx.rootDir, el.getSourceFile().fileName);
4919
5177
  const line = lineOf(el);
4920
5178
  const unwrappedEl = unwrapForwardRef(el);
4921
- if (ts3.isIdentifier(unwrappedEl)) {
5179
+ if (ts4.isIdentifier(unwrappedEl)) {
4922
5180
  const decl = resolveDeclaration(unwrappedEl, ctx)[0];
4923
- const cls = decl && ts3.isClassDeclaration(decl) ? decl : undefined;
5181
+ const cls = decl && ts4.isClassDeclaration(decl) ? decl : undefined;
4924
5182
  const className = cls?.name?.text ?? unwrappedEl.text;
4925
5183
  const { deps, optionalDeps, selfDeps, skipSelfDeps, hostDeps, functionalInjects, missing } = cls ? classDeps(cls, ctx) : { deps: [], optionalDeps: [], selfDeps: [], skipSelfDeps: [], hostDeps: [], functionalInjects: [], missing: false };
4926
5184
  const injectable = cls ? parseInjectableOptions(cls, ctx) : undefined;
@@ -4947,7 +5205,7 @@ function parseProvider(el, exportsSet, ctx) {
4947
5205
  ...cls ? { importPath: modulePath(ctx.rootDir, cls.getSourceFile().fileName) } : {}
4948
5206
  };
4949
5207
  }
4950
- if (!ts3.isObjectLiteralExpression(el))
5208
+ if (!ts4.isObjectLiteralExpression(el))
4951
5209
  return;
4952
5210
  const provideExpr = getProp(el, "provide");
4953
5211
  if (!provideExpr)
@@ -4962,8 +5220,8 @@ function parseProvider(el, exportsSet, ctx) {
4962
5220
  const useExistingExpr = getProp(el, "useExisting");
4963
5221
  if (useClassExpr) {
4964
5222
  const unwrappedClass = unwrapForwardRef(useClassExpr);
4965
- const decl = ts3.isIdentifier(unwrappedClass) ? resolveDeclaration(unwrappedClass, ctx)[0] : undefined;
4966
- const cls = decl && ts3.isClassDeclaration(decl) ? decl : undefined;
5223
+ const decl = ts4.isIdentifier(unwrappedClass) ? resolveDeclaration(unwrappedClass, ctx)[0] : undefined;
5224
+ const cls = decl && ts4.isClassDeclaration(decl) ? decl : undefined;
4967
5225
  const useClass = cls?.name?.text ?? nodeText(unwrappedClass);
4968
5226
  let deps = explicitDeps;
4969
5227
  let optionalDeps = [];
@@ -5019,7 +5277,7 @@ function parseProvider(el, exportsSet, ctx) {
5019
5277
  }
5020
5278
  if (useValueExpr) {
5021
5279
  validateProviderCompatibility(provideExpr, useValueExpr, "value", token, ctx, file, line);
5022
- const importPath = ts3.isIdentifier(useValueExpr) ? importPathOf(useValueExpr, ctx) : undefined;
5280
+ const importPath = ts4.isIdentifier(useValueExpr) ? importPathOf(useValueExpr, ctx) : undefined;
5023
5281
  return {
5024
5282
  token,
5025
5283
  tokenKind,
@@ -5035,12 +5293,12 @@ function parseProvider(el, exportsSet, ctx) {
5035
5293
  };
5036
5294
  }
5037
5295
  if (useFactoryExpr) {
5038
- const factoryName = ts3.isIdentifier(useFactoryExpr) ? (() => {
5296
+ const factoryName = ts4.isIdentifier(useFactoryExpr) ? (() => {
5039
5297
  const decl = resolveDeclaration(useFactoryExpr, ctx)[0];
5040
- return decl && (ts3.isFunctionDeclaration(decl) || ts3.isVariableDeclaration(decl)) ? (ts3.isFunctionDeclaration(decl) ? decl.name?.text : variableName(decl)) ?? useFactoryExpr.text : useFactoryExpr.text;
5298
+ return decl && (ts4.isFunctionDeclaration(decl) || ts4.isVariableDeclaration(decl)) ? (ts4.isFunctionDeclaration(decl) ? decl.name?.text : variableName(decl)) ?? useFactoryExpr.text : useFactoryExpr.text;
5041
5299
  })() : nodeText(useFactoryExpr);
5042
5300
  validateProviderCompatibility(provideExpr, useFactoryExpr, "factory", token, ctx, file, line);
5043
- const importPath = ts3.isIdentifier(useFactoryExpr) ? importPathOf(useFactoryExpr, ctx) : undefined;
5301
+ const importPath = ts4.isIdentifier(useFactoryExpr) ? importPathOf(useFactoryExpr, ctx) : undefined;
5044
5302
  return {
5045
5303
  token,
5046
5304
  tokenKind,
@@ -5076,20 +5334,20 @@ function parseProvider(el, exportsSet, ctx) {
5076
5334
  function expandProviderExpressions(expressions, ctx, seen = new Set) {
5077
5335
  const result = [];
5078
5336
  for (const expression of expressions) {
5079
- if (ts3.isSpreadElement(expression)) {
5337
+ if (ts4.isSpreadElement(expression)) {
5080
5338
  result.push(...expandProviderExpressions([expression.expression], ctx, seen));
5081
5339
  continue;
5082
5340
  }
5083
- if (ts3.isIdentifier(expression)) {
5341
+ if (ts4.isIdentifier(expression)) {
5084
5342
  const declaration = resolveDeclaration(expression, ctx)[0];
5085
- if (declaration && ts3.isVariableDeclaration(declaration) && declaration.initializer) {
5343
+ if (declaration && ts4.isVariableDeclaration(declaration) && declaration.initializer) {
5086
5344
  const key = `${declaration.getSourceFile().fileName}:${declaration.pos}`;
5087
5345
  if (seen.has(key))
5088
5346
  continue;
5089
5347
  const initializer = declaration.initializer;
5090
- if (ts3.isCallExpression(initializer) && isProviderHelper(initializer, "makeEnvironmentProviders")) {
5348
+ if (ts4.isCallExpression(initializer) && isProviderHelper(initializer, "makeEnvironmentProviders")) {
5091
5349
  const nested = initializer.arguments[0];
5092
- if (nested && ts3.isArrayLiteralExpression(nested)) {
5350
+ if (nested && ts4.isArrayLiteralExpression(nested)) {
5093
5351
  seen.add(key);
5094
5352
  result.push(...expandProviderExpressions([...nested.elements], ctx, seen));
5095
5353
  seen.delete(key);
@@ -5098,9 +5356,9 @@ function expandProviderExpressions(expressions, ctx, seen = new Set) {
5098
5356
  }
5099
5357
  }
5100
5358
  }
5101
- if (ts3.isCallExpression(expression) && isProviderHelper(expression, "makeEnvironmentProviders")) {
5359
+ if (ts4.isCallExpression(expression) && isProviderHelper(expression, "makeEnvironmentProviders")) {
5102
5360
  const nested = expression.arguments[0];
5103
- if (nested && ts3.isArrayLiteralExpression(nested)) {
5361
+ if (nested && ts4.isArrayLiteralExpression(nested)) {
5104
5362
  result.push(...expandProviderExpressions([...nested.elements], ctx, seen));
5105
5363
  continue;
5106
5364
  }
@@ -5113,7 +5371,7 @@ function isProviderHelper(expression, name) {
5113
5371
  return nodeText(expression.expression).split(".").pop() === name;
5114
5372
  }
5115
5373
  function parseFunctionalProvider(expression, exportsSet, ctx) {
5116
- if (!ts3.isCallExpression(expression))
5374
+ if (!ts4.isCallExpression(expression))
5117
5375
  return;
5118
5376
  const helper = nodeText(expression.expression).split(".").pop();
5119
5377
  const args = expression.arguments;
@@ -5126,7 +5384,7 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
5126
5384
  return [];
5127
5385
  const { name: token, kind: tokenKind } = tokenNameOf(tokenExpr, ctx);
5128
5386
  validateProviderCompatibility(tokenExpr, valueExpr, "value", token, ctx, file, line);
5129
- const importPath = ts3.isIdentifier(valueExpr) ? importPathOf(valueExpr, ctx) : undefined;
5387
+ const importPath = ts4.isIdentifier(valueExpr) ? importPathOf(valueExpr, ctx) : undefined;
5130
5388
  return [{
5131
5389
  token,
5132
5390
  tokenKind,
@@ -5145,7 +5403,7 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
5145
5403
  if (!initializer)
5146
5404
  return [];
5147
5405
  const token = helper === "provideAppInitializer" ? "APP_INITIALIZER" : "ENVIRONMENT_INITIALIZER";
5148
- const importPath = ts3.isIdentifier(initializer) ? importPathOf(initializer, ctx) : undefined;
5406
+ const importPath = ts4.isIdentifier(initializer) ? importPathOf(initializer, ctx) : undefined;
5149
5407
  return [{
5150
5408
  token,
5151
5409
  tokenKind: "injection-token",
@@ -5164,7 +5422,7 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
5164
5422
  const providers = [];
5165
5423
  const routes = args[0];
5166
5424
  if (routes) {
5167
- const importPath = ts3.isIdentifier(routes) ? importPathOf(routes, ctx) : undefined;
5425
+ const importPath = ts4.isIdentifier(routes) ? importPathOf(routes, ctx) : undefined;
5168
5426
  providers.push({
5169
5427
  token: "ROUTE_CONFIG",
5170
5428
  tokenKind: "injection-token",
@@ -5179,7 +5437,7 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
5179
5437
  });
5180
5438
  }
5181
5439
  for (const feature of args.slice(1)) {
5182
- if (!ts3.isCallExpression(feature))
5440
+ if (!ts4.isCallExpression(feature))
5183
5441
  continue;
5184
5442
  const featureName = nodeText(feature.expression).split(".").pop();
5185
5443
  if (featureName === "withRouterConfig" && feature.arguments[0]) {
@@ -5196,8 +5454,8 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
5196
5454
  });
5197
5455
  } else if (featureName === "withTitleStrategy" && feature.arguments[0]) {
5198
5456
  const strategy = feature.arguments[0];
5199
- const isClass = ts3.isIdentifier(strategy) && Boolean(resolveDeclaration(strategy, ctx).find((declaration) => ts3.isClassDeclaration(declaration)));
5200
- const importPath = ts3.isIdentifier(strategy) ? importPathOf(strategy, ctx) : undefined;
5457
+ const isClass = ts4.isIdentifier(strategy) && Boolean(resolveDeclaration(strategy, ctx).find((declaration) => ts4.isClassDeclaration(declaration)));
5458
+ const importPath = ts4.isIdentifier(strategy) ? importPathOf(strategy, ctx) : undefined;
5201
5459
  providers.push({
5202
5460
  token: "TITLE_STRATEGY",
5203
5461
  tokenKind: "injection-token",
@@ -5229,14 +5487,14 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
5229
5487
  importModule: "@supacloud/app"
5230
5488
  }];
5231
5489
  for (const feature of args) {
5232
- if (!ts3.isCallExpression(feature))
5490
+ if (!ts4.isCallExpression(feature))
5233
5491
  continue;
5234
5492
  const featureName = nodeText(feature.expression).split(".").pop();
5235
5493
  if (featureName === "withInterceptors") {
5236
5494
  for (const interceptorArg of feature.arguments) {
5237
- const values = ts3.isArrayLiteralExpression(interceptorArg) ? [...interceptorArg.elements] : [interceptorArg];
5495
+ const values = ts4.isArrayLiteralExpression(interceptorArg) ? [...interceptorArg.elements] : [interceptorArg];
5238
5496
  for (const value of values) {
5239
- const importPath = ts3.isIdentifier(value) ? importPathOf(value, ctx) : undefined;
5497
+ const importPath = ts4.isIdentifier(value) ? importPathOf(value, ctx) : undefined;
5240
5498
  providers.push({
5241
5499
  token: "HTTP_INTERCEPTORS",
5242
5500
  tokenKind: "injection-token",
@@ -5283,9 +5541,9 @@ function providerTokenValueType(expr, ctx) {
5283
5541
  const typeArguments = typeArgumentsOf(type, ctx);
5284
5542
  if (typeArguments.length > 0)
5285
5543
  return typeArguments[0];
5286
- if (ts3.isIdentifier(expr)) {
5544
+ if (ts4.isIdentifier(expr)) {
5287
5545
  const declaration = resolveDeclaration(expr, ctx)[0];
5288
- if (declaration && ts3.isClassDeclaration(declaration)) {
5546
+ if (declaration && ts4.isClassDeclaration(declaration)) {
5289
5547
  return declaredClassType(declaration, ctx);
5290
5548
  }
5291
5549
  }
@@ -5293,9 +5551,9 @@ function providerTokenValueType(expr, ctx) {
5293
5551
  }
5294
5552
  function providerImplementationType(expr, kind, ctx) {
5295
5553
  if (kind === "class" || kind === "existing") {
5296
- if (ts3.isIdentifier(expr)) {
5554
+ if (ts4.isIdentifier(expr)) {
5297
5555
  const declaration = resolveDeclaration(expr, ctx)[0];
5298
- if (declaration && ts3.isClassDeclaration(declaration)) {
5556
+ if (declaration && ts4.isClassDeclaration(declaration)) {
5299
5557
  return declaredClassType(declaration, ctx);
5300
5558
  }
5301
5559
  }
@@ -5305,7 +5563,7 @@ function providerImplementationType(expr, kind, ctx) {
5305
5563
  }
5306
5564
  if (kind === "factory") {
5307
5565
  const type = ctx.checker.getTypeAtLocation(expr);
5308
- const signature = ctx.checker.getSignaturesOfType(type, ts3.SignatureKind.Call)[0];
5566
+ const signature = ctx.checker.getSignaturesOfType(type, ts4.SignatureKind.Call)[0];
5309
5567
  return signature?.getReturnType();
5310
5568
  }
5311
5569
  return ctx.checker.getTypeAtLocation(expr);
@@ -5324,16 +5582,16 @@ function isTypeReference(type) {
5324
5582
  return "target" in type;
5325
5583
  }
5326
5584
  function isUnknownOrAny(type) {
5327
- return (type.flags & (ts3.TypeFlags.Any | ts3.TypeFlags.Unknown)) !== 0;
5585
+ return (type.flags & (ts4.TypeFlags.Any | ts4.TypeFlags.Unknown)) !== 0;
5328
5586
  }
5329
5587
  function parseController(input, ctx) {
5330
5588
  let decl;
5331
- if (ts3.isClassDeclaration(input)) {
5589
+ if (ts4.isClassDeclaration(input)) {
5332
5590
  decl = input;
5333
5591
  } else {
5334
5592
  const unwrapped = unwrapForwardRef(input);
5335
- const resolved = ts3.isIdentifier(unwrapped) ? resolveDeclaration(unwrapped, ctx)[0] : undefined;
5336
- if (resolved && ts3.isClassDeclaration(resolved)) {
5593
+ const resolved = ts4.isIdentifier(unwrapped) ? resolveDeclaration(unwrapped, ctx)[0] : undefined;
5594
+ if (resolved && ts4.isClassDeclaration(resolved)) {
5337
5595
  decl = resolved;
5338
5596
  }
5339
5597
  }
@@ -5346,9 +5604,9 @@ function parseController(input, ctx) {
5346
5604
  let standalone;
5347
5605
  const pathArg = decoratorArguments(controllerDec)[0];
5348
5606
  if (pathArg) {
5349
- if (ts3.isStringLiteral(pathArg)) {
5607
+ if (ts4.isStringLiteral(pathArg)) {
5350
5608
  path = pathArg.text;
5351
- } else if (ts3.isObjectLiteralExpression(pathArg)) {
5609
+ } else if (ts4.isObjectLiteralExpression(pathArg)) {
5352
5610
  const p = stringLiteralProp(pathArg, "path");
5353
5611
  if (p)
5354
5612
  path = p;
@@ -5371,7 +5629,7 @@ function parseController(input, ctx) {
5371
5629
  }
5372
5630
  }
5373
5631
  }
5374
- for (const method of decl.members.filter(ts3.isMethodDeclaration)) {
5632
+ for (const method of decl.members.filter(ts4.isMethodDeclaration)) {
5375
5633
  for (const dec of decoratorsOf(method)) {
5376
5634
  const name = decoratorName2(dec);
5377
5635
  const httpMethod = name ? ROUTE_DECORATORS[name] : undefined;
@@ -5379,7 +5637,7 @@ function parseController(input, ctx) {
5379
5637
  continue;
5380
5638
  const args = decoratorArguments(dec);
5381
5639
  const pathArg = args[0];
5382
- const routePath = pathArg && ts3.isStringLiteral(pathArg) ? pathArg.text : "/";
5640
+ const routePath = pathArg && ts4.isStringLiteral(pathArg) ? pathArg.text : "/";
5383
5641
  const route = {
5384
5642
  method: httpMethod,
5385
5643
  path: routePath,
@@ -5450,12 +5708,12 @@ function parseController(input, ctx) {
5450
5708
  } else if (dName === "Headers") {
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: "headers", ...bindingName === undefined ? {} : { bindingName } };
5455
5713
  } else if (dName === "Cookie") {
5456
5714
  hasBindingDecorator = true;
5457
5715
  const argument = dArgs[0];
5458
- const bindingName = argument !== undefined && ts3.isStringLiteral(argument) ? argument.text : undefined;
5716
+ const bindingName = argument !== undefined && ts4.isStringLiteral(argument) ? argument.text : undefined;
5459
5717
  paramNode = { name: pName, kind: "cookie", ...bindingName === undefined ? {} : { bindingName } };
5460
5718
  }
5461
5719
  }
@@ -5517,20 +5775,20 @@ function parseController(input, ctx) {
5517
5775
  }
5518
5776
  } else if (dName === "Title") {
5519
5777
  const tArg = mArgs[0];
5520
- if (tArg && ts3.isStringLiteral(tArg)) {
5778
+ if (tArg && ts4.isStringLiteral(tArg)) {
5521
5779
  route.title = tArg.text;
5522
5780
  }
5523
5781
  } else if (dName === "Data") {
5524
5782
  const dArg = mArgs[0];
5525
- if (dArg && ts3.isObjectLiteralExpression(dArg)) {
5783
+ if (dArg && ts4.isObjectLiteralExpression(dArg)) {
5526
5784
  route.data = { ...route.data, ...parseObjectLiteralValues(dArg) };
5527
5785
  }
5528
5786
  } else if (dName === "Resolve") {
5529
5787
  const rArg = mArgs[0];
5530
- if (rArg && ts3.isObjectLiteralExpression(rArg)) {
5788
+ if (rArg && ts4.isObjectLiteralExpression(rArg)) {
5531
5789
  const resolvers = route.resolvers ?? {};
5532
5790
  for (const prop of rArg.properties) {
5533
- if (ts3.isPropertyAssignment(prop)) {
5791
+ if (ts4.isPropertyAssignment(prop)) {
5534
5792
  const rName = propertyName(prop.name);
5535
5793
  const init = prop.initializer;
5536
5794
  if (init)
@@ -5561,7 +5819,7 @@ function parseController(input, ctx) {
5561
5819
  });
5562
5820
  }
5563
5821
  const contract = getProp(optionsObject, "contract");
5564
- if (contract && ts3.isObjectLiteralExpression(contract)) {
5822
+ if (contract && ts4.isObjectLiteralExpression(contract)) {
5565
5823
  route.contract = {};
5566
5824
  for (const field of ["body", "response", "evidence"]) {
5567
5825
  const value = stringLiteralProp(contract, field);
@@ -5579,15 +5837,15 @@ function parseController(input, ctx) {
5579
5837
  }
5580
5838
  for (const field of ["body", "params", "query", "headers", "cookie", "response"]) {
5581
5839
  const schemaExpr = getProp(optionsObject, field);
5582
- if (schemaExpr && ts3.isIdentifier(schemaExpr)) {
5840
+ if (schemaExpr && ts4.isIdentifier(schemaExpr)) {
5583
5841
  route[field] = nodeText(schemaExpr);
5584
5842
  const importPath = importPathOf(schemaExpr, ctx);
5585
5843
  if (importPath)
5586
5844
  schemaImports[schemaExpr.text] = importPath;
5587
5845
  const declaration = resolveDeclaration(schemaExpr, ctx)[0];
5588
5846
  const typeName = ctx.checker.typeToString(ctx.checker.getTypeAtLocation(schemaExpr));
5589
- const initializer = declaration && ts3.isVariableDeclaration(declaration) ? declaration.initializer : undefined;
5590
- const opaque = /\bT(?:Unknown|Any)\b/.test(typeName) || initializer && ts3.isCallExpression(initializer) && ts3.isPropertyAccessExpression(initializer.expression) && ["Unknown", "Any"].includes(initializer.expression.name.text);
5847
+ const initializer = declaration && ts4.isVariableDeclaration(declaration) ? declaration.initializer : undefined;
5848
+ const opaque = /\bT(?:Unknown|Any)\b/.test(typeName) || initializer && ts4.isCallExpression(initializer) && ts4.isPropertyAccessExpression(initializer.expression) && ["Unknown", "Any"].includes(initializer.expression.name.text);
5591
5849
  (route.schemaKinds ??= {})[field] = opaque ? "opaque" : "declared";
5592
5850
  }
5593
5851
  }
@@ -5596,7 +5854,7 @@ function parseController(input, ctx) {
5596
5854
  const responses = {};
5597
5855
  const selectors = new Map;
5598
5856
  for (const property of responsesObject.properties) {
5599
- if (!ts3.isPropertyAssignment(property) || ts3.isComputedPropertyName(property.name))
5857
+ if (!ts4.isPropertyAssignment(property) || ts4.isComputedPropertyName(property.name))
5600
5858
  continue;
5601
5859
  const status = propertyName(property.name);
5602
5860
  if (!isRouteResponseSelector(status)) {
@@ -5628,7 +5886,7 @@ function parseController(input, ctx) {
5628
5886
  }
5629
5887
  selectors.set(canonical, status);
5630
5888
  const schemaExpr = property.initializer;
5631
- if (!ts3.isIdentifier(schemaExpr)) {
5889
+ if (!ts4.isIdentifier(schemaExpr)) {
5632
5890
  ctx.diagnostics.push({
5633
5891
  severity: "error",
5634
5892
  code: "invalid-route-response-map",
@@ -5643,8 +5901,8 @@ function parseController(input, ctx) {
5643
5901
  schemaImports[schemaExpr.text] = importPath;
5644
5902
  const declaration = resolveDeclaration(schemaExpr, ctx)[0];
5645
5903
  const typeName = ctx.checker.typeToString(ctx.checker.getTypeAtLocation(schemaExpr));
5646
- const initializer = declaration && ts3.isVariableDeclaration(declaration) ? declaration.initializer : undefined;
5647
- const opaque = /\bT(?:Unknown|Any)\b/.test(typeName) || initializer && ts3.isCallExpression(initializer) && ts3.isPropertyAccessExpression(initializer.expression) && ["Unknown", "Any"].includes(initializer.expression.name.text);
5904
+ const initializer = declaration && ts4.isVariableDeclaration(declaration) ? declaration.initializer : undefined;
5905
+ const opaque = /\bT(?:Unknown|Any)\b/.test(typeName) || initializer && ts4.isCallExpression(initializer) && ts4.isPropertyAccessExpression(initializer.expression) && ["Unknown", "Any"].includes(initializer.expression.name.text);
5648
5906
  const previousKind = route.schemaKinds?.response;
5649
5907
  (route.schemaKinds ??= {}).response = opaque || previousKind === "opaque" ? "opaque" : "declared";
5650
5908
  }
@@ -5652,18 +5910,18 @@ function parseController(input, ctx) {
5652
5910
  route.responses = responses;
5653
5911
  }
5654
5912
  const commandExpr = getProp(optionsObject, "command");
5655
- if (commandExpr && ts3.isIdentifier(commandExpr)) {
5913
+ if (commandExpr && ts4.isIdentifier(commandExpr)) {
5656
5914
  const commandDecl = resolveDeclaration(commandExpr, ctx)[0];
5657
- route.command = commandDecl && ts3.isClassDeclaration(commandDecl) ? commandDecl.name?.text ?? commandExpr.text : commandExpr.text;
5915
+ route.command = commandDecl && ts4.isClassDeclaration(commandDecl) ? commandDecl.name?.text ?? commandExpr.text : commandExpr.text;
5658
5916
  }
5659
5917
  const guardsExpr = getProp(optionsObject, "guards");
5660
- if (guardsExpr && ts3.isArrayLiteralExpression(guardsExpr)) {
5918
+ if (guardsExpr && ts4.isArrayLiteralExpression(guardsExpr)) {
5661
5919
  for (const el of guardsExpr.elements) {
5662
5920
  routeGuards.push(tokenText(el, ctx));
5663
5921
  }
5664
5922
  }
5665
5923
  const canMatchExpr = getProp(optionsObject, "canMatch");
5666
- if (canMatchExpr && ts3.isArrayLiteralExpression(canMatchExpr)) {
5924
+ if (canMatchExpr && ts4.isArrayLiteralExpression(canMatchExpr)) {
5667
5925
  const canMatchList = [];
5668
5926
  for (const el of canMatchExpr.elements) {
5669
5927
  canMatchList.push(tokenText(el, ctx));
@@ -5673,16 +5931,16 @@ function parseController(input, ctx) {
5673
5931
  }
5674
5932
  }
5675
5933
  const canDeactivateExpr = getProp(optionsObject, "canDeactivate");
5676
- if (canDeactivateExpr && ts3.isArrayLiteralExpression(canDeactivateExpr)) {
5934
+ if (canDeactivateExpr && ts4.isArrayLiteralExpression(canDeactivateExpr)) {
5677
5935
  for (const el of canDeactivateExpr.elements) {
5678
5936
  routeCanDeactivate.push(tokenText(el, ctx));
5679
5937
  }
5680
5938
  }
5681
5939
  const resolversExpr = getProp(optionsObject, "resolvers");
5682
- if (resolversExpr && ts3.isObjectLiteralExpression(resolversExpr)) {
5940
+ if (resolversExpr && ts4.isObjectLiteralExpression(resolversExpr)) {
5683
5941
  const resolvers = {};
5684
5942
  for (const prop of resolversExpr.properties) {
5685
- if (ts3.isPropertyAssignment(prop)) {
5943
+ if (ts4.isPropertyAssignment(prop)) {
5686
5944
  const rName = propertyName(prop.name);
5687
5945
  const init = prop.initializer;
5688
5946
  if (init)
@@ -5694,22 +5952,22 @@ function parseController(input, ctx) {
5694
5952
  }
5695
5953
  }
5696
5954
  const redirectToExpr = getProp(optionsObject, "redirectTo");
5697
- if (redirectToExpr && ts3.isStringLiteral(redirectToExpr)) {
5955
+ if (redirectToExpr && ts4.isStringLiteral(redirectToExpr)) {
5698
5956
  route.redirectTo = redirectToExpr.text;
5699
5957
  }
5700
5958
  const pathMatchExpr = getProp(optionsObject, "pathMatch");
5701
- if (pathMatchExpr && ts3.isStringLiteral(pathMatchExpr)) {
5959
+ if (pathMatchExpr && ts4.isStringLiteral(pathMatchExpr)) {
5702
5960
  const val = pathMatchExpr.text;
5703
5961
  if (val === "full" || val === "prefix") {
5704
5962
  route.pathMatch = val;
5705
5963
  }
5706
5964
  }
5707
5965
  const titleExpr = getProp(optionsObject, "title");
5708
- if (titleExpr && ts3.isStringLiteral(titleExpr)) {
5966
+ if (titleExpr && ts4.isStringLiteral(titleExpr)) {
5709
5967
  route.title = titleExpr.text;
5710
5968
  }
5711
5969
  const dataExpr = getProp(optionsObject, "data");
5712
- if (dataExpr && ts3.isObjectLiteralExpression(dataExpr)) {
5970
+ if (dataExpr && ts4.isObjectLiteralExpression(dataExpr)) {
5713
5971
  route.data = { ...route.data, ...parseObjectLiteralValues(dataExpr) };
5714
5972
  }
5715
5973
  const aspects = parseAspectRefs(getProp(optionsObject, "aspects"), ctx, `route ${httpMethod} ${routePath}`);
@@ -5764,7 +6022,7 @@ function parseJobOptions(meta, owner, ctx) {
5764
6022
  const expression = getProp(meta, field);
5765
6023
  if (!expression)
5766
6024
  continue;
5767
- if (!ts3.isIdentifier(expression)) {
6025
+ if (!ts4.isIdentifier(expression)) {
5768
6026
  jobOptionError(ctx, "invalid-job-schema", `${owner} 的 ${field} schema 必须是可静态解析的标识符引用,不能使用内联调用或动态表达式`, expression, "SC4019", `将 schema 提取为命名导出,例如 ${field}: ${field === "input" ? "JobInput" : "JobOutput"}。`);
5769
6027
  continue;
5770
6028
  }
@@ -5788,7 +6046,7 @@ function parseJobEnum(meta, field, allowed, owner, ctx, code, errorCode) {
5788
6046
  const expression = getProp(meta, field);
5789
6047
  if (!expression)
5790
6048
  return;
5791
- if (!ts3.isStringLiteral(expression) || !allowed.includes(expression.text)) {
6049
+ if (!ts4.isStringLiteral(expression) || !allowed.includes(expression.text)) {
5792
6050
  jobOptionError(ctx, code, `${owner} 的 ${field} 必须是 ${allowed.map((value) => JSON.stringify(value)).join(" 或 ")} 字符串字面量`, expression, errorCode);
5793
6051
  return;
5794
6052
  }
@@ -5798,7 +6056,7 @@ function parseJobInteger(meta, field, min, max, owner, ctx, code, errorCode) {
5798
6056
  const expression = getProp(meta, field);
5799
6057
  if (!expression)
5800
6058
  return;
5801
- const value = ts3.isNumericLiteral(expression) ? Number(expression.text) : Number.NaN;
6059
+ const value = ts4.isNumericLiteral(expression) ? Number(expression.text) : Number.NaN;
5802
6060
  if (!Number.isSafeInteger(value) || value < min || value > max) {
5803
6061
  jobOptionError(ctx, code, `${owner} 的 ${field} 必须是 ${min} 到 ${max} 之间的安全整数`, expression, errorCode);
5804
6062
  return;
@@ -5819,8 +6077,8 @@ function jobOptionError(ctx, code, message, node, errorCode, suggestion) {
5819
6077
  }
5820
6078
  function jobSchemaKind(identifier, declaration, ctx) {
5821
6079
  const typeName = ctx.checker.typeToString(ctx.checker.getTypeAtLocation(identifier));
5822
- const initializer = ts3.isVariableDeclaration(declaration) ? declaration.initializer : undefined;
5823
- const opaque = /\bT(?:Unknown|Any)\b/.test(typeName) || initializer && ts3.isCallExpression(initializer) && ts3.isPropertyAccessExpression(initializer.expression) && ["Unknown", "Any"].includes(initializer.expression.name.text);
6080
+ const initializer = ts4.isVariableDeclaration(declaration) ? declaration.initializer : undefined;
6081
+ const opaque = /\bT(?:Unknown|Any)\b/.test(typeName) || initializer && ts4.isCallExpression(initializer) && ts4.isPropertyAccessExpression(initializer.expression) && ["Unknown", "Any"].includes(initializer.expression.name.text);
5824
6082
  return opaque ? "opaque" : "declared";
5825
6083
  }
5826
6084
  function checkedRpc(meta, ctx) {
@@ -5842,7 +6100,7 @@ function checkedRpc(meta, ctx) {
5842
6100
  }
5843
6101
  function classDeps(cls, ctx) {
5844
6102
  const injectable = parseInjectableOptions(cls, ctx);
5845
- const ctor = cls.members.find(ts3.isConstructorDeclaration);
6103
+ const ctor = cls.members.find(ts4.isConstructorDeclaration);
5846
6104
  const deps = injectable?.deps ? [...injectable.deps] : [];
5847
6105
  const optionalDeps = [];
5848
6106
  const selfDeps = [];
@@ -5876,23 +6134,23 @@ function classDeps(cls, ctx) {
5876
6134
  }
5877
6135
  });
5878
6136
  }
5879
- for (const prop of cls.members.filter(ts3.isPropertyDeclaration)) {
6137
+ for (const prop of cls.members.filter(ts4.isPropertyDeclaration)) {
5880
6138
  const init = prop.initializer;
5881
- if (init && ts3.isCallExpression(init)) {
6139
+ if (init && ts4.isCallExpression(init)) {
5882
6140
  const callName = nodeText(init.expression).split(".").pop();
5883
6141
  if (callName === "inject") {
5884
6142
  const [tokenArg, optionsArg] = init.arguments;
5885
6143
  if (tokenArg) {
5886
6144
  const tokenName = tokenText(tokenArg, ctx);
5887
6145
  const unwrappedToken = unwrapForwardRef(tokenArg);
5888
- const known = ts3.isStringLiteral(unwrappedToken) || ts3.isIdentifier(unwrappedToken) && (ctx.tokensByName.has(tokenName) || ctx.classesByName.has(tokenName));
6146
+ const known = ts4.isStringLiteral(unwrappedToken) || ts4.isIdentifier(unwrappedToken) && (ctx.tokensByName.has(tokenName) || ctx.classesByName.has(tokenName));
5889
6147
  if (!known) {
5890
6148
  missing = true;
5891
6149
  continue;
5892
6150
  }
5893
6151
  if (!deps.includes(tokenName))
5894
6152
  deps.push(tokenName);
5895
- const options = optionsArg && ts3.isObjectLiteralExpression(optionsArg) ? {
6153
+ const options = optionsArg && ts4.isObjectLiteralExpression(optionsArg) ? {
5896
6154
  optional: booleanProp(optionsArg, "optional") ?? false,
5897
6155
  self: booleanProp(optionsArg, "self") ?? false,
5898
6156
  skipSelf: booleanProp(optionsArg, "skipSelf") ?? false,
@@ -5907,9 +6165,9 @@ function classDeps(cls, ctx) {
5907
6165
  if (options.host && !hostDeps.includes(tokenName))
5908
6166
  hostDeps.push(tokenName);
5909
6167
  if (!functionalInjects.some((entry) => entry.token === tokenName)) {
5910
- const declaration = ts3.isIdentifier(unwrappedToken) ? resolveDeclaration(unwrappedToken, ctx)[0] : undefined;
6168
+ const declaration = ts4.isIdentifier(unwrappedToken) ? resolveDeclaration(unwrappedToken, ctx)[0] : undefined;
5911
6169
  const localFile = declaration && isProjectSourcePath(declaration.getSourceFile().fileName, ctx.rootDir) ? declaration.getSourceFile().fileName : undefined;
5912
- const importModule = declaration && !localFile && ts3.isIdentifier(unwrappedToken) ? importModuleOf(unwrappedToken, ctx) : undefined;
6170
+ const importModule = declaration && !localFile && ts4.isIdentifier(unwrappedToken) ? importModuleOf(unwrappedToken, ctx) : undefined;
5913
6171
  functionalInjects.push({
5914
6172
  token: tokenName,
5915
6173
  expression: nodeText(unwrappedToken),
@@ -5953,7 +6211,7 @@ function parseInjectableOptions(cls, ctx) {
5953
6211
  }
5954
6212
  function parseInjectParams(cls, ctx) {
5955
6213
  const result = new Map;
5956
- const ctor = cls.members.find(ts3.isConstructorDeclaration);
6214
+ const ctor = cls.members.find(ts4.isConstructorDeclaration);
5957
6215
  if (!ctor)
5958
6216
  return result;
5959
6217
  ctor.parameters.forEach((param, index) => {
@@ -5969,7 +6227,7 @@ function parseInjectParams(cls, ctx) {
5969
6227
  }
5970
6228
  function parseOptionalParams(cls) {
5971
6229
  const result = new Set;
5972
- const ctor = cls.members.find(ts3.isConstructorDeclaration);
6230
+ const ctor = cls.members.find(ts4.isConstructorDeclaration);
5973
6231
  if (!ctor)
5974
6232
  return result;
5975
6233
  ctor.parameters.forEach((param, index) => {
@@ -5984,7 +6242,7 @@ function parseOptionalParams(cls) {
5984
6242
  }
5985
6243
  function parseModifierParams(cls, modifierName) {
5986
6244
  const result = new Set;
5987
- const ctor = cls.members.find(ts3.isConstructorDeclaration);
6245
+ const ctor = cls.members.find(ts4.isConstructorDeclaration);
5988
6246
  if (!ctor)
5989
6247
  return result;
5990
6248
  ctor.parameters.forEach((param, index) => {
@@ -5996,13 +6254,13 @@ function parseModifierParams(cls, modifierName) {
5996
6254
  return result;
5997
6255
  }
5998
6256
  function unwrapForwardRef(expr) {
5999
- if (ts3.isCallExpression(expr)) {
6257
+ if (ts4.isCallExpression(expr)) {
6000
6258
  const exprText = nodeText(expr.expression);
6001
6259
  if (exprText === "forwardRef" || exprText.endsWith(".forwardRef")) {
6002
6260
  const arg = expr.arguments[0];
6003
- if (arg && (ts3.isArrowFunction(arg) || ts3.isFunctionExpression(arg))) {
6261
+ if (arg && (ts4.isArrowFunction(arg) || ts4.isFunctionExpression(arg))) {
6004
6262
  const body = arg.body;
6005
- if (body && ts3.isExpression(body)) {
6263
+ if (body && ts4.isExpression(body)) {
6006
6264
  return unwrapForwardRef(body);
6007
6265
  }
6008
6266
  }
@@ -6012,13 +6270,13 @@ function unwrapForwardRef(expr) {
6012
6270
  }
6013
6271
  function tokenText(expr, ctx) {
6014
6272
  const unwrapped = unwrapForwardRef(expr);
6015
- if (ts3.isStringLiteral(unwrapped))
6273
+ if (ts4.isStringLiteral(unwrapped))
6016
6274
  return unwrapped.text;
6017
- if (ts3.isIdentifier(unwrapped)) {
6275
+ if (ts4.isIdentifier(unwrapped)) {
6018
6276
  const decl = resolveDeclaration(unwrapped, ctx)[0];
6019
- if (decl && ts3.isClassDeclaration(decl))
6277
+ if (decl && ts4.isClassDeclaration(decl))
6020
6278
  return decl.name?.text ?? unwrapped.text;
6021
- if (decl && ts3.isVariableDeclaration(decl))
6279
+ if (decl && ts4.isVariableDeclaration(decl))
6022
6280
  return variableName(decl);
6023
6281
  }
6024
6282
  return nodeText(unwrapped);
@@ -6038,12 +6296,12 @@ function resolveScope(input, ctx) {
6038
6296
  }
6039
6297
  function tokenNameOf(expr, ctx) {
6040
6298
  const unwrapped = unwrapForwardRef(expr);
6041
- if (ts3.isIdentifier(unwrapped)) {
6299
+ if (ts4.isIdentifier(unwrapped)) {
6042
6300
  const decl = resolveDeclaration(unwrapped, ctx)[0];
6043
- if (decl && ts3.isClassDeclaration(decl)) {
6301
+ if (decl && ts4.isClassDeclaration(decl)) {
6044
6302
  return { name: decl.name?.text ?? nodeText(expr), kind: "class" };
6045
6303
  }
6046
- if (decl && ts3.isVariableDeclaration(decl)) {
6304
+ if (decl && ts4.isVariableDeclaration(decl)) {
6047
6305
  const name = variableName(decl);
6048
6306
  return { name, kind: ctx.tokensByName.has(name) ? "injection-token" : "class" };
6049
6307
  }
@@ -6059,10 +6317,10 @@ function resolveDeclaration(id, ctx) {
6059
6317
  return [];
6060
6318
  let declarations = symbol.declarations ?? [];
6061
6319
  for (let guard = 0;guard < 4; guard += 1) {
6062
- const isAlias = declarations.some((d) => ts3.isImportSpecifier(d) || ts3.isImportClause(d) || ts3.isNamespaceImport(d));
6320
+ const isAlias = declarations.some((d) => ts4.isImportSpecifier(d) || ts4.isImportClause(d) || ts4.isNamespaceImport(d));
6063
6321
  if (!isAlias)
6064
6322
  break;
6065
- if (!(symbol.flags & ts3.SymbolFlags.Alias))
6323
+ if (!(symbol.flags & ts4.SymbolFlags.Alias))
6066
6324
  break;
6067
6325
  const aliased = ctx.checker.getAliasedSymbol(symbol);
6068
6326
  symbol = aliased;
@@ -6082,9 +6340,9 @@ function importModuleOf(id, ctx) {
6082
6340
  for (const declaration of declarations) {
6083
6341
  let current = declaration;
6084
6342
  while (current) {
6085
- if (ts3.isImportDeclaration(current)) {
6343
+ if (ts4.isImportDeclaration(current)) {
6086
6344
  const moduleSpecifier = current.moduleSpecifier;
6087
- return ts3.isStringLiteral(moduleSpecifier) ? moduleSpecifier.text : undefined;
6345
+ return ts4.isStringLiteral(moduleSpecifier) ? moduleSpecifier.text : undefined;
6088
6346
  }
6089
6347
  current = current.parent;
6090
6348
  }
@@ -6096,27 +6354,27 @@ function findDecorator(cls, name) {
6096
6354
  }
6097
6355
  function decoratorName2(dec) {
6098
6356
  const expr = dec.expression;
6099
- if (ts3.isCallExpression(expr)) {
6357
+ if (ts4.isCallExpression(expr)) {
6100
6358
  return nodeText(expr.expression).split(".").pop();
6101
6359
  }
6102
- if (ts3.isIdentifier(expr))
6360
+ if (ts4.isIdentifier(expr))
6103
6361
  return expr.text;
6104
6362
  return;
6105
6363
  }
6106
6364
  function decoratorObjectArg(dec) {
6107
6365
  const expr = dec.expression;
6108
- if (!ts3.isCallExpression(expr))
6366
+ if (!ts4.isCallExpression(expr))
6109
6367
  return;
6110
6368
  const arg = expr.arguments[0];
6111
- return arg && ts3.isObjectLiteralExpression(arg) ? arg : undefined;
6369
+ return arg && ts4.isObjectLiteralExpression(arg) ? arg : undefined;
6112
6370
  }
6113
6371
  function getProp(obj, name) {
6114
- const prop = obj.properties.find((item) => (ts3.isPropertyAssignment(item) || ts3.isShorthandPropertyAssignment(item)) && propertyName(item.name) === name);
6372
+ const prop = obj.properties.find((item) => (ts4.isPropertyAssignment(item) || ts4.isShorthandPropertyAssignment(item)) && propertyName(item.name) === name);
6115
6373
  if (!prop)
6116
6374
  return;
6117
- if (ts3.isPropertyAssignment(prop))
6375
+ if (ts4.isPropertyAssignment(prop))
6118
6376
  return prop.initializer;
6119
- if (ts3.isShorthandPropertyAssignment(prop))
6377
+ if (ts4.isShorthandPropertyAssignment(prop))
6120
6378
  return prop.name;
6121
6379
  return;
6122
6380
  }
@@ -6124,10 +6382,10 @@ function toCompilerDiagnostic(diagnostic, rootDir) {
6124
6382
  const file = diagnostic.file;
6125
6383
  const position = file && diagnostic.start !== undefined ? file.getLineAndCharacterOfPosition(diagnostic.start) : undefined;
6126
6384
  return {
6127
- severity: diagnostic.category === ts3.DiagnosticCategory.Error ? "error" : "warn",
6385
+ severity: diagnostic.category === ts4.DiagnosticCategory.Error ? "error" : "warn",
6128
6386
  code: `typescript-${diagnostic.code}`,
6129
6387
  errorCode: `TS${diagnostic.code}`,
6130
- message: ts3.flattenDiagnosticMessageText(diagnostic.messageText, `
6388
+ message: ts4.flattenDiagnosticMessageText(diagnostic.messageText, `
6131
6389
  `),
6132
6390
  ...file ? { file: sourcePath(rootDir, file.fileName) } : {},
6133
6391
  ...position ? { line: position.line + 1 } : {}
@@ -6135,16 +6393,16 @@ function toCompilerDiagnostic(diagnostic, rootDir) {
6135
6393
  }
6136
6394
  function stringLiteralProp(obj, name) {
6137
6395
  const expr = getProp(obj, name);
6138
- return expr && ts3.isStringLiteral(expr) ? expr.text : undefined;
6396
+ return expr && ts4.isStringLiteral(expr) ? expr.text : undefined;
6139
6397
  }
6140
6398
  function arrayProp(obj, name) {
6141
6399
  const expr = getProp(obj, name);
6142
- return expr && ts3.isArrayLiteralExpression(expr) ? [...expr.elements] : [];
6400
+ return expr && ts4.isArrayLiteralExpression(expr) ? [...expr.elements] : [];
6143
6401
  }
6144
6402
  function parseAspectRefs(expression, ctx, owner) {
6145
6403
  if (!expression)
6146
6404
  return [];
6147
- if (!ts3.isArrayLiteralExpression(expression)) {
6405
+ if (!ts4.isArrayLiteralExpression(expression)) {
6148
6406
  ctx.diagnostics.push({
6149
6407
  severity: "error",
6150
6408
  code: "dynamic-aspect-reference",
@@ -6159,7 +6417,7 @@ function parseAspectRefs(expression, ctx, owner) {
6159
6417
  }
6160
6418
  const refs = [];
6161
6419
  for (const element of expression.elements) {
6162
- if (ts3.isSpreadElement(element) || !ts3.isIdentifier(element)) {
6420
+ if (ts4.isSpreadElement(element) || !ts4.isIdentifier(element)) {
6163
6421
  ctx.diagnostics.push({
6164
6422
  severity: "error",
6165
6423
  code: "dynamic-aspect-reference",
@@ -6172,7 +6430,7 @@ function parseAspectRefs(expression, ctx, owner) {
6172
6430
  });
6173
6431
  continue;
6174
6432
  }
6175
- const declaration = resolveDeclaration(element, ctx).find((candidate) => ts3.isFunctionDeclaration(candidate) || ts3.isVariableDeclaration(candidate) && candidate.initializer !== undefined && (ts3.isArrowFunction(candidate.initializer) || ts3.isFunctionExpression(candidate.initializer)));
6433
+ const declaration = resolveDeclaration(element, ctx).find((candidate) => ts4.isFunctionDeclaration(candidate) || ts4.isVariableDeclaration(candidate) && candidate.initializer !== undefined && (ts4.isArrowFunction(candidate.initializer) || ts4.isFunctionExpression(candidate.initializer)));
6176
6434
  if (!declaration) {
6177
6435
  ctx.diagnostics.push({
6178
6436
  severity: "error",
@@ -6186,7 +6444,7 @@ function parseAspectRefs(expression, ctx, owner) {
6186
6444
  });
6187
6445
  continue;
6188
6446
  }
6189
- const name = ts3.isFunctionDeclaration(declaration) ? declaration.name?.text : ts3.isVariableDeclaration(declaration) ? variableName(declaration) : undefined;
6447
+ const name = ts4.isFunctionDeclaration(declaration) ? declaration.name?.text : ts4.isVariableDeclaration(declaration) ? variableName(declaration) : undefined;
6190
6448
  if (!name)
6191
6449
  continue;
6192
6450
  const declaredFile = declaration.getSourceFile().fileName;
@@ -6206,9 +6464,9 @@ function booleanProp(obj, name) {
6206
6464
  const expr = getProp(obj, name);
6207
6465
  if (!expr)
6208
6466
  return;
6209
- if (expr.kind === ts3.SyntaxKind.TrueKeyword)
6467
+ if (expr.kind === ts4.SyntaxKind.TrueKeyword)
6210
6468
  return true;
6211
- if (expr.kind === ts3.SyntaxKind.FalseKeyword)
6469
+ if (expr.kind === ts4.SyntaxKind.FalseKeyword)
6212
6470
  return false;
6213
6471
  return;
6214
6472
  }
@@ -6222,15 +6480,15 @@ function parseBindingOptions(args, defaultName) {
6222
6480
  let defaultValue;
6223
6481
  const first = args[0];
6224
6482
  const second = args[1];
6225
- if (first && ts3.isStringLiteral(first)) {
6483
+ if (first && ts4.isStringLiteral(first)) {
6226
6484
  name = first.text;
6227
- } else if (first && ts3.isObjectLiteralExpression(first)) {
6485
+ } else if (first && ts4.isObjectLiteralExpression(first)) {
6228
6486
  const nameProp = getProp(first, "name");
6229
- if (nameProp && ts3.isStringLiteral(nameProp)) {
6487
+ if (nameProp && ts4.isStringLiteral(nameProp)) {
6230
6488
  name = nameProp.text;
6231
6489
  }
6232
6490
  const trProp = getProp(first, "transform");
6233
- if (trProp && ts3.isStringLiteral(trProp)) {
6491
+ if (trProp && ts4.isStringLiteral(trProp)) {
6234
6492
  const val = trProp.text;
6235
6493
  if (val === "number" || val === "boolean" || val === "string") {
6236
6494
  transform = val;
@@ -6241,9 +6499,9 @@ function parseBindingOptions(args, defaultName) {
6241
6499
  defaultValue = parseLiteralValue(defProp);
6242
6500
  }
6243
6501
  }
6244
- if (second && ts3.isObjectLiteralExpression(second)) {
6502
+ if (second && ts4.isObjectLiteralExpression(second)) {
6245
6503
  const trProp = getProp(second, "transform");
6246
- if (trProp && ts3.isStringLiteral(trProp)) {
6504
+ if (trProp && ts4.isStringLiteral(trProp)) {
6247
6505
  const val = trProp.text;
6248
6506
  if (val === "number" || val === "boolean" || val === "string") {
6249
6507
  transform = val;
@@ -6257,18 +6515,18 @@ function parseBindingOptions(args, defaultName) {
6257
6515
  return { name, ...transform ? { transform } : {}, default: defaultValue };
6258
6516
  }
6259
6517
  function parseLiteralValue(node) {
6260
- if (ts3.isStringLiteral(node))
6518
+ if (ts4.isStringLiteral(node))
6261
6519
  return node.text;
6262
- if (ts3.isNumericLiteral(node))
6520
+ if (ts4.isNumericLiteral(node))
6263
6521
  return Number(node.text);
6264
- if (node.kind === ts3.SyntaxKind.TrueKeyword)
6522
+ if (node.kind === ts4.SyntaxKind.TrueKeyword)
6265
6523
  return true;
6266
- if (node.kind === ts3.SyntaxKind.FalseKeyword)
6524
+ if (node.kind === ts4.SyntaxKind.FalseKeyword)
6267
6525
  return false;
6268
- if (ts3.isArrayLiteralExpression(node)) {
6526
+ if (ts4.isArrayLiteralExpression(node)) {
6269
6527
  return node.elements.map(parseLiteralValue);
6270
6528
  }
6271
- if (ts3.isObjectLiteralExpression(node)) {
6529
+ if (ts4.isObjectLiteralExpression(node)) {
6272
6530
  return parseObjectLiteralValues(node);
6273
6531
  }
6274
6532
  return;
@@ -6276,7 +6534,7 @@ function parseLiteralValue(node) {
6276
6534
  function parseObjectLiteralValues(obj) {
6277
6535
  const result = {};
6278
6536
  for (const prop of obj.properties) {
6279
- if (ts3.isPropertyAssignment(prop)) {
6537
+ if (ts4.isPropertyAssignment(prop)) {
6280
6538
  const name = propertyName(prop.name);
6281
6539
  const init = prop.initializer;
6282
6540
  if (init) {
@@ -6310,7 +6568,50 @@ import { join as join4 } from "node:path";
6310
6568
  // src/type-safety.ts
6311
6569
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
6312
6570
  import { dirname as dirname3, join as join3, relative as relative3, resolve as resolve2, sep as sep3 } from "node:path";
6313
- import * as ts4 from "@typescript/typescript6";
6571
+ import * as ts6 from "@typescript/typescript6";
6572
+
6573
+ // src/sql-safety.ts
6574
+ import * as ts5 from "@typescript/typescript6";
6575
+ var SQL_SAFETY_DIAGNOSTIC_CODES = {
6576
+ "sql-result-assertion": { errorCode: "SC6007", docsUrl: "https://supacloud.dev/errors/SC6007" },
6577
+ "sql-raw-dynamic": { errorCode: "SC6008", docsUrl: "https://supacloud.dev/errors/SC6008" }
6578
+ };
6579
+ function scanDrizzleSql(sourceFile, checker, file, strict) {
6580
+ const diagnostics = [];
6581
+ const importedSql = (expression) => {
6582
+ const symbol = checker.getSymbolAtLocation(ts5.isPropertyAccessExpression(expression) ? expression.name : expression);
6583
+ if (!symbol)
6584
+ return false;
6585
+ const target = symbol.flags & ts5.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
6586
+ return target.name === "sql" && (target.declarations ?? []).some((declaration) => /(?:^|\/)node_modules\/drizzle-orm\//.test(declaration.getSourceFile().fileName.replaceAll("\\", "/")));
6587
+ };
6588
+ const report = (code, node, message) => {
6589
+ diagnostics.push({
6590
+ severity: strict ? "error" : "warn",
6591
+ code,
6592
+ ...SQL_SAFETY_DIAGNOSTIC_CODES[code],
6593
+ message,
6594
+ file,
6595
+ line: sourceFile.getLineAndCharacterOfPosition(node.getStart()).line + 1
6596
+ });
6597
+ };
6598
+ const visit = (node) => {
6599
+ if (ts5.isTaggedTemplateExpression(node) && importedSql(node.tag) && node.typeArguments?.some((type) => type.kind !== ts5.SyntaxKind.UnknownKeyword)) {
6600
+ 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.");
6601
+ }
6602
+ if (ts5.isCallExpression(node) && ts5.isPropertyAccessExpression(node.expression) && node.expression.name.text === "raw" && importedSql(node.expression.expression)) {
6603
+ const argument = node.arguments[0];
6604
+ if (!argument || !ts5.isStringLiteral(argument) && !ts5.isNoSubstitutionTemplateLiteral(argument)) {
6605
+ report("sql-raw-dynamic", node, "Dynamic sql.raw bypasses parameter binding. Interpolate values with sql templates; keep reviewed static DDL in migrations.");
6606
+ }
6607
+ }
6608
+ ts5.forEachChild(node, visit);
6609
+ };
6610
+ visit(sourceFile);
6611
+ return diagnostics;
6612
+ }
6613
+
6614
+ // src/type-safety.ts
6314
6615
  var DEFAULT_EXCLUDES = [
6315
6616
  "**/*.test.ts",
6316
6617
  "**/*.spec.ts",
@@ -6323,6 +6624,7 @@ var DEFAULT_EXCLUDES = [
6323
6624
  "**/*.d.ts"
6324
6625
  ];
6325
6626
  var TYPE_SAFETY_DIAGNOSTIC_CODES = {
6627
+ ...SQL_SAFETY_DIAGNOSTIC_CODES,
6326
6628
  "generated-any": { errorCode: "SC6001", docsUrl: "https://supacloud.dev/errors/SC6001" },
6327
6629
  "source-any": { errorCode: "SC6002", docsUrl: "https://supacloud.dev/errors/SC6002" },
6328
6630
  "source-type-assertion": { errorCode: "SC6003", docsUrl: "https://supacloud.dev/errors/SC6003" },
@@ -6335,7 +6637,7 @@ function scanGeneratedArtifacts(artifacts, strict = true) {
6335
6637
  for (const [file, content] of Object.entries(artifacts)) {
6336
6638
  if (content === undefined)
6337
6639
  continue;
6338
- const sourceFile = ts4.createSourceFile(file, content, ts4.ScriptTarget.Latest, true, ts4.ScriptKind.TS);
6640
+ const sourceFile = ts6.createSourceFile(file, content, ts6.ScriptTarget.Latest, true, ts6.ScriptKind.TS);
6339
6641
  for (const node of descendantsOfKind2(sourceFile, isAnyKeyword)) {
6340
6642
  diagnostics.push(makeDiagnostic("generated-any", `生成产物 ${file} 包含 any;严格生成模式要求使用 unknown、具体接口或泛型约束。`, sourceFile, node, strict));
6341
6643
  }
@@ -6344,30 +6646,30 @@ function scanGeneratedArtifacts(artifacts, strict = true) {
6344
6646
  }
6345
6647
  function scanProductionSource(options) {
6346
6648
  const rootDir = resolve2(options.rootDir);
6347
- const configPath = ts4.findConfigFile(rootDir, ts4.sys.fileExists) ?? join3(rootDir, "tsconfig.json");
6649
+ const configPath = ts6.findConfigFile(rootDir, ts6.sys.fileExists) ?? join3(rootDir, "tsconfig.json");
6348
6650
  const projectConfig = existsSync2(configPath) ? readProjectConfig2(configPath) : {
6349
6651
  options: {
6350
6652
  strict: true,
6351
6653
  skipLibCheck: true,
6352
- target: ts4.ScriptTarget.ES2022,
6353
- module: ts4.ModuleKind.ESNext,
6354
- moduleResolution: ts4.ModuleResolutionKind.Bundler
6654
+ target: ts6.ScriptTarget.ES2022,
6655
+ module: ts6.ModuleKind.ESNext,
6656
+ moduleResolution: ts6.ModuleResolutionKind.Bundler
6355
6657
  },
6356
6658
  errors: []
6357
6659
  };
6358
6660
  const include = options.include ?? ["**/*.ts", "**/*.tsx", "**/*.mts", "**/*.cts"];
6359
- const rootNames = ts4.sys.readDirectory(rootDir, [".ts", ".tsx", ".mts", ".cts"], ["node_modules", "dist"], include).filter((file) => isProductionSourcePath(rootDir, file, [...DEFAULT_EXCLUDES, ...options.exclude ?? []]));
6661
+ const rootNames = ts6.sys.readDirectory(rootDir, [".ts", ".tsx", ".mts", ".cts"], ["node_modules", "dist"], include).filter((file) => isProductionSourcePath(rootDir, file, [...DEFAULT_EXCLUDES, ...options.exclude ?? []]));
6360
6662
  const compilerOptions = { ...projectConfig.options, noEmit: true };
6361
- const host = ts4.createCompilerHost(compilerOptions);
6663
+ const host = ts6.createCompilerHost(compilerOptions);
6362
6664
  host.getCurrentDirectory = () => dirname3(configPath);
6363
- const program = ts4.createProgram(rootNames, compilerOptions, host);
6665
+ const program = ts6.createProgram(rootNames, compilerOptions, host);
6364
6666
  const outDir = options.outDir ? normalizeRelative(rootDir, options.outDir) : undefined;
6365
6667
  const excludes = [...DEFAULT_EXCLUDES, ...options.exclude ?? []];
6366
6668
  const sourceFiles = program.getSourceFiles().filter((sourceFile) => isProductionSource(rootDir, sourceFile, excludes, outDir));
6367
6669
  const diagnostics = [...projectConfig.errors, ...program.getOptionsDiagnostics()].map((diagnostic) => ({
6368
6670
  severity: "error",
6369
6671
  code: "source-config",
6370
- message: ts4.flattenDiagnosticMessageText(diagnostic.messageText, `
6672
+ message: ts6.flattenDiagnosticMessageText(diagnostic.messageText, `
6371
6673
  `),
6372
6674
  file: diagnostic.file ? normalizeRelative(rootDir, diagnostic.file.fileName) : normalizeRelative(rootDir, configPath),
6373
6675
  ...diagnostic.file && diagnostic.start !== undefined ? { line: diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start).line + 1 } : {},
@@ -6384,7 +6686,7 @@ function scanProductionSource(options) {
6384
6686
  diagnostics.push({
6385
6687
  severity: "error",
6386
6688
  code: "source-typescript",
6387
- message: ts4.flattenDiagnosticMessageText(diagnostic.messageText, `
6689
+ message: ts6.flattenDiagnosticMessageText(diagnostic.messageText, `
6388
6690
  `),
6389
6691
  ...diagnostic.file ? { file: normalizeRelative(rootDir, diagnostic.file.fileName) } : {},
6390
6692
  ...diagnostic.file && diagnostic.start !== undefined ? { line: diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start).line + 1 } : {},
@@ -6393,9 +6695,10 @@ function scanProductionSource(options) {
6393
6695
  }
6394
6696
  for (const sourceFile of sourceFiles) {
6395
6697
  scanSourceFile(sourceFile, checker, rootDir, diagnostics, options.strict ?? false);
6396
- const scanner = ts4.createScanner(ts4.ScriptTarget.Latest, false, sourceFile.languageVariant, sourceFile.text);
6397
- for (let kind = scanner.scan();kind !== ts4.SyntaxKind.EndOfFileToken; kind = scanner.scan()) {
6398
- if ((kind === ts4.SyntaxKind.SingleLineCommentTrivia || kind === ts4.SyntaxKind.MultiLineCommentTrivia) && /@ts-(?:ignore|nocheck|expect-error)\b/.test(scanner.getTokenText())) {
6698
+ diagnostics.push(...scanDrizzleSql(sourceFile, checker, normalizeRelative(rootDir, sourceFile.fileName), options.strict ?? false));
6699
+ const scanner = ts6.createScanner(ts6.ScriptTarget.Latest, false, sourceFile.languageVariant, sourceFile.text);
6700
+ for (let kind = scanner.scan();kind !== ts6.SyntaxKind.EndOfFileToken; kind = scanner.scan()) {
6701
+ if ((kind === ts6.SyntaxKind.SingleLineCommentTrivia || kind === ts6.SyntaxKind.MultiLineCommentTrivia) && /@ts-(?:ignore|nocheck|expect-error)\b/.test(scanner.getTokenText())) {
6399
6702
  diagnostics.push({
6400
6703
  severity: "error",
6401
6704
  code: "source-type-suppression",
@@ -6415,22 +6718,22 @@ function scanSourceFile(sourceFile, checker, rootDir, diagnostics, strict) {
6415
6718
  diagnostics.push(makeDiagnostic("source-any", "生产源码使用了显式 any;请改用 unknown、具体接口或泛型约束。", sourceFile, node, strict, rootDir));
6416
6719
  }
6417
6720
  for (const node of descendants(sourceFile)) {
6418
- if (ts4.isAsExpression(node)) {
6419
- if (ts4.isAsExpression(node.parent) || ts4.isTypeAssertionExpression(node.parent))
6721
+ if (ts6.isAsExpression(node)) {
6722
+ if (ts6.isAsExpression(node.parent) || ts6.isTypeAssertionExpression(node.parent))
6420
6723
  continue;
6421
6724
  const assertedType = node.type.getText(sourceFile);
6422
6725
  if (assertedType === "const")
6423
6726
  continue;
6424
6727
  diagnostics.push(makeDiagnostic("source-type-assertion", `生产源码包含类型断言 ${node.getText(sourceFile)};请优先使用类型守卫、satisfies 或显式边界解析。`, sourceFile, node, strict, rootDir));
6425
- } else if (ts4.isTypeAssertionExpression(node)) {
6426
- if (ts4.isAsExpression(node.parent) || ts4.isTypeAssertionExpression(node.parent))
6728
+ } else if (ts6.isTypeAssertionExpression(node)) {
6729
+ if (ts6.isAsExpression(node.parent) || ts6.isTypeAssertionExpression(node.parent))
6427
6730
  continue;
6428
6731
  diagnostics.push(makeDiagnostic("source-type-assertion", `生产源码包含类型断言 ${node.getText(sourceFile)};请优先使用类型守卫、satisfies 或显式边界解析。`, sourceFile, node, strict, rootDir));
6429
- } else if (ts4.isNonNullExpression(node)) {
6732
+ } else if (ts6.isNonNullExpression(node)) {
6430
6733
  diagnostics.push(makeDiagnostic("source-non-null-assertion", `生产源码包含非空断言 ${node.getText(sourceFile)};请显式处理 null/undefined。`, sourceFile, node, strict, rootDir));
6431
6734
  }
6432
6735
  }
6433
- for (const declaration of descendantsOfKind2(sourceFile, ts4.isVariableDeclaration)) {
6736
+ for (const declaration of descendantsOfKind2(sourceFile, ts6.isVariableDeclaration)) {
6434
6737
  const initializer = declaration.initializer;
6435
6738
  if (!initializer || declaration.type)
6436
6739
  continue;
@@ -6446,11 +6749,11 @@ function scanSourceFile(sourceFile, checker, rootDir, diagnostics, strict) {
6446
6749
  if (isLetDeclaration(declaration) && isLiteralSyntax(initializer) && !isLiteralType(declarationType)) {
6447
6750
  diagnostics.push(makeDiagnostic("source-implicit-widening", `变量 ${declaration.name.getText(sourceFile)} 的字面量类型从 ${checker.typeToString(initializerType, initializer)} 隐式宽化为 ${checker.typeToString(declarationType, declaration)};请补充类型或使用 const。`, sourceFile, declaration, strict, rootDir));
6448
6751
  }
6449
- 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))) {
6752
+ 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))) {
6450
6753
  diagnostics.push(makeDiagnostic("source-implicit-widening", `常量对象 ${declaration.name.getText(sourceFile)} 的字面量属性会隐式宽化;请补充对象类型或使用 as const。`, sourceFile, declaration, strict, rootDir));
6451
6754
  }
6452
6755
  }
6453
- for (const parameter of descendantsOfKind2(sourceFile, ts4.isParameter)) {
6756
+ for (const parameter of descendantsOfKind2(sourceFile, ts6.isParameter)) {
6454
6757
  if (parameter.type)
6455
6758
  continue;
6456
6759
  for (const name of bindingNames(parameter.name)) {
@@ -6461,10 +6764,10 @@ function scanSourceFile(sourceFile, checker, rootDir, diagnostics, strict) {
6461
6764
  }
6462
6765
  }
6463
6766
  function readProjectConfig2(configPath) {
6464
- const config = ts4.readConfigFile(configPath, (file) => readFileSync2(file, "utf8"));
6767
+ const config = ts6.readConfigFile(configPath, (file) => readFileSync2(file, "utf8"));
6465
6768
  if (config.error)
6466
6769
  return { options: {}, errors: [config.error] };
6467
- const parsed = ts4.parseJsonConfigFileContent(config.config, ts4.sys, dirname3(configPath));
6770
+ const parsed = ts6.parseJsonConfigFileContent(config.config, ts6.sys, dirname3(configPath));
6468
6771
  return { options: parsed.options, errors: parsed.errors };
6469
6772
  }
6470
6773
  function isProductionSource(rootDir, sourceFile, excludes, outDir) {
@@ -6484,42 +6787,42 @@ function globMatches(value, pattern) {
6484
6787
  return new RegExp(`^${escaped}$`).test(value);
6485
6788
  }
6486
6789
  function bindingNames(name) {
6487
- if (ts4.isIdentifier(name))
6790
+ if (ts6.isIdentifier(name))
6488
6791
  return [name];
6489
- return name.elements.flatMap((element) => ts4.isBindingElement(element) ? bindingNames(element.name) : []);
6792
+ return name.elements.flatMap((element) => ts6.isBindingElement(element) ? bindingNames(element.name) : []);
6490
6793
  }
6491
6794
  function isLiteralExpression(node) {
6492
6795
  if (!node)
6493
6796
  return false;
6494
6797
  return [
6495
- ts4.SyntaxKind.StringLiteral,
6496
- ts4.SyntaxKind.NumericLiteral,
6497
- ts4.SyntaxKind.TrueKeyword,
6498
- ts4.SyntaxKind.FalseKeyword
6798
+ ts6.SyntaxKind.StringLiteral,
6799
+ ts6.SyntaxKind.NumericLiteral,
6800
+ ts6.SyntaxKind.TrueKeyword,
6801
+ ts6.SyntaxKind.FalseKeyword
6499
6802
  ].includes(node.kind);
6500
6803
  }
6501
6804
  function isLiteralSyntax(node) {
6502
- return ts4.isStringLiteral(node) || ts4.isNumericLiteral(node) || node.kind === ts4.SyntaxKind.TrueKeyword || node.kind === ts4.SyntaxKind.FalseKeyword;
6805
+ return ts6.isStringLiteral(node) || ts6.isNumericLiteral(node) || node.kind === ts6.SyntaxKind.TrueKeyword || node.kind === ts6.SyntaxKind.FalseKeyword;
6503
6806
  }
6504
6807
  function isLiteralType(type) {
6505
- return (type.flags & (ts4.TypeFlags.StringLiteral | ts4.TypeFlags.NumberLiteral | ts4.TypeFlags.BooleanLiteral | ts4.TypeFlags.BigIntLiteral)) !== 0;
6808
+ return (type.flags & (ts6.TypeFlags.StringLiteral | ts6.TypeFlags.NumberLiteral | ts6.TypeFlags.BooleanLiteral | ts6.TypeFlags.BigIntLiteral)) !== 0;
6506
6809
  }
6507
6810
  function isAnyType(type) {
6508
- return (type.flags & ts4.TypeFlags.Any) !== 0;
6811
+ return (type.flags & ts6.TypeFlags.Any) !== 0;
6509
6812
  }
6510
6813
  function isLetDeclaration(declaration) {
6511
- return ts4.isVariableDeclarationList(declaration.parent) && (declaration.parent.flags & ts4.NodeFlags.Let) !== 0;
6814
+ return ts6.isVariableDeclarationList(declaration.parent) && (declaration.parent.flags & ts6.NodeFlags.Let) !== 0;
6512
6815
  }
6513
6816
  function isConstDeclaration(declaration) {
6514
- return ts4.isVariableDeclarationList(declaration.parent) && (declaration.parent.flags & ts4.NodeFlags.Const) !== 0;
6817
+ return ts6.isVariableDeclarationList(declaration.parent) && (declaration.parent.flags & ts6.NodeFlags.Const) !== 0;
6515
6818
  }
6516
6819
  function descendants(root) {
6517
6820
  const result = [];
6518
6821
  const visit = (node) => {
6519
6822
  result.push(node);
6520
- ts4.forEachChild(node, visit);
6823
+ ts6.forEachChild(node, visit);
6521
6824
  };
6522
- ts4.forEachChild(root, visit);
6825
+ ts6.forEachChild(root, visit);
6523
6826
  return result;
6524
6827
  }
6525
6828
  function descendantsOfKind2(root, predicate) {
@@ -6527,9 +6830,9 @@ function descendantsOfKind2(root, predicate) {
6527
6830
  const visit = (node) => {
6528
6831
  if (predicate(node))
6529
6832
  result.push(node);
6530
- ts4.forEachChild(node, visit);
6833
+ ts6.forEachChild(node, visit);
6531
6834
  };
6532
- ts4.forEachChild(root, visit);
6835
+ ts6.forEachChild(root, visit);
6533
6836
  return result;
6534
6837
  }
6535
6838
  function makeDiagnostic(code, message, fileOrSourceFile, node, strict, rootDir) {
@@ -6550,7 +6853,7 @@ function normalizeRelative(rootDir, filePath) {
6550
6853
  return relative3(rootDir, filePath).split(sep3).join("/").replace(/^\.\//, "");
6551
6854
  }
6552
6855
  function isAnyKeyword(node) {
6553
- return node.kind === ts4.SyntaxKind.AnyKeyword;
6856
+ return node.kind === ts6.SyntaxKind.AnyKeyword;
6554
6857
  }
6555
6858
 
6556
6859
  // src/route-contracts.ts
@@ -6634,15 +6937,28 @@ function validateRouteContracts(graph) {
6634
6937
  }
6635
6938
 
6636
6939
  // src/compile.ts
6940
+ function withDefaultGovernance(options) {
6941
+ return options.commandCapabilities === undefined ? { ...options, commandCapabilities: {
6942
+ requirePersistentAdapters: true,
6943
+ permission: true,
6944
+ audit: true,
6945
+ idempotency: true,
6946
+ transaction: true
6947
+ } } : options;
6948
+ }
6637
6949
  async function renderOptionalGraphql(options) {
6638
6950
  return options.graphql ? (await Promise.resolve().then(() => (init_graphql(), exports_graphql))).renderGraphql(options) : { diagnostics: [], files: {} };
6639
6951
  }
6640
6952
  async function compileProject(options) {
6953
+ options = withDefaultGovernance(options);
6641
6954
  const graph = await analyzeProject(options.rootDir, options.include, options.cache, options.changedPaths);
6642
6955
  const diagnostics = [
6643
6956
  ...graph.diagnostics ?? [],
6644
6957
  ...validateGraph(graph, options)
6645
6958
  ];
6959
+ if (diagnostics.some((item) => item.code === "runtime-injection-disallowed")) {
6960
+ return { diagnostics, graph, written: [] };
6961
+ }
6646
6962
  if (options.strict) {
6647
6963
  for (const diagnostic of diagnostics) {
6648
6964
  if (diagnostic.severity === "warn")
@@ -6696,11 +7012,15 @@ async function compileProject(options) {
6696
7012
  return { diagnostics, graph, written, ...stats ? { stats } : {} };
6697
7013
  }
6698
7014
  async function checkProject(options) {
7015
+ options = withDefaultGovernance(options);
6699
7016
  const graph = await analyzeProject(options.rootDir, options.include, options.cache, options.changedPaths);
6700
7017
  const diagnostics = [
6701
7018
  ...graph.diagnostics ?? [],
6702
7019
  ...validateGraph(graph, options)
6703
7020
  ];
7021
+ if (diagnostics.some((item) => item.code === "runtime-injection-disallowed")) {
7022
+ return { diagnostics, graph, upToDate: false, mismatches: ["Runtime DI must be migrated to constructor injection."] };
7023
+ }
6704
7024
  if (options.strict) {
6705
7025
  for (const diagnostic of diagnostics) {
6706
7026
  if (diagnostic.severity === "warn")
@@ -10722,6 +11042,13 @@ var DEFAULT_SUPACLOUD_CONFIG = {
10722
11042
  generateOpenApi: true,
10723
11043
  generatePermissions: true,
10724
11044
  treeShakeUnusedProviders: true,
11045
+ commandCapabilities: {
11046
+ requirePersistentAdapters: true,
11047
+ permission: true,
11048
+ audit: true,
11049
+ idempotency: true,
11050
+ transaction: true
11051
+ },
10725
11052
  moduleBoundaryPreset: "modular-monolith"
10726
11053
  };
10727
11054
  function defineSupacloudConfig(config = {}) {
@@ -10805,7 +11132,7 @@ function resolveSupacloudConfig(config = {}, cwd = process.cwd()) {
10805
11132
  ...resolved.openApi === undefined ? {} : { openApi: resolved.openApi },
10806
11133
  generatePermissions: resolved.generatePermissions ?? DEFAULT_SUPACLOUD_CONFIG.generatePermissions,
10807
11134
  moduleBoundaryPreset: resolved.moduleBoundaryPreset ?? DEFAULT_SUPACLOUD_CONFIG.moduleBoundaryPreset,
10808
- commandCapabilities: resolved.commandCapabilities,
11135
+ commandCapabilities: resolved.commandCapabilities ?? DEFAULT_SUPACLOUD_CONFIG.commandCapabilities,
10809
11136
  ...resolved.moduleBoundaries ? { moduleBoundaries: resolved.moduleBoundaries } : {},
10810
11137
  ...resolved.typeSafety ? { typeSafety: resolved.typeSafety } : {},
10811
11138
  ...resolved.allowRouteCommandBindings === undefined ? {} : { allowRouteCommandBindings: resolved.allowRouteCommandBindings },
@@ -10839,7 +11166,7 @@ function compileOptionsFromConfig(config, cwd = process.cwd()) {
10839
11166
  import { randomUUID } from "node:crypto";
10840
11167
  import { lstat, readFile as readFile4, realpath, rename as rename2, unlink as unlink2, writeFile as writeFile2 } from "node:fs/promises";
10841
11168
  import { dirname as dirname6, isAbsolute as isAbsolute2, relative as relative8, resolve as resolve8, sep as sep8 } from "node:path";
10842
- import * as ts7 from "@typescript/typescript6";
11169
+ import * as ts9 from "@typescript/typescript6";
10843
11170
  async function applyDiagnosticFix(fix, options = {}) {
10844
11171
  if (!fix || typeof fix.targetFile !== "string")
10845
11172
  throw new Error("Invalid DiagnosticFix");
@@ -10864,7 +11191,7 @@ async function applyDiagnosticFix(fix, options = {}) {
10864
11191
  if (!current || current.initializer.getText(source) !== fix.expectedExpression) {
10865
11192
  throw new Error("Command mode changed since diagnosis; analyze the project again");
10866
11193
  }
10867
- content = replaceProperty(source, object, fix.property, ts7.factory.createStringLiteral(fix.value));
11194
+ content = replaceProperty(source, object, fix.property, ts9.factory.createStringLiteral(fix.value));
10868
11195
  break;
10869
11196
  }
10870
11197
  case "add_module_import": {
@@ -10875,15 +11202,15 @@ async function applyDiagnosticFix(fix, options = {}) {
10875
11202
  source = parse3(file, withImport);
10876
11203
  const object = unique(moduleObjects(source).filter((candidate) => !fix.targetModule || stringProperty(candidate, "name") === fix.targetModule), "target module");
10877
11204
  const imports = property(object, "imports");
10878
- if (imports && !ts7.isArrayLiteralExpression(imports.initializer)) {
11205
+ if (imports && !ts9.isArrayLiteralExpression(imports.initializer)) {
10879
11206
  throw new Error("Module imports must be a static array");
10880
11207
  }
10881
- const values = imports && ts7.isArrayLiteralExpression(imports.initializer) ? imports.initializer.elements : [];
10882
- if (values.some(ts7.isSpreadElement))
11208
+ const values = imports && ts9.isArrayLiteralExpression(imports.initializer) ? imports.initializer.elements : [];
11209
+ if (values.some(ts9.isSpreadElement))
10883
11210
  throw new Error("Module imports cannot contain spread elements");
10884
- content = values.some((value) => ts7.isIdentifier(value) && value.text === fix.symbol) ? withImport : replaceProperty(source, object, "imports", ts7.factory.createArrayLiteralExpression([
11211
+ content = values.some((value) => ts9.isIdentifier(value) && value.text === fix.symbol) ? withImport : replaceProperty(source, object, "imports", ts9.factory.createArrayLiteralExpression([
10885
11212
  ...values,
10886
- ts7.factory.createIdentifier(fix.symbol)
11213
+ ts9.factory.createIdentifier(fix.symbol)
10887
11214
  ]));
10888
11215
  break;
10889
11216
  }
@@ -10895,24 +11222,24 @@ async function applyDiagnosticFix(fix, options = {}) {
10895
11222
  const command = findClass(source, fix.command);
10896
11223
  const object = decoratorObject(command, "Command");
10897
11224
  const current = property(object, "permission");
10898
- if (current && (!ts7.isStringLiteral(current.initializer) || current.initializer.text !== permission)) {
11225
+ if (current && (!ts9.isStringLiteral(current.initializer) || current.initializer.text !== permission)) {
10899
11226
  throw new Error("Command permission already exists with a different value");
10900
11227
  }
10901
- content = current ? original : replaceProperty(source, object, "permission", ts7.factory.createStringLiteral(permission));
11228
+ content = current ? original : replaceProperty(source, object, "permission", ts9.factory.createStringLiteral(permission));
10902
11229
  break;
10903
11230
  }
10904
11231
  case "add_route_parameter_binding": {
10905
11232
  const controller = findClass(source, fix.controller);
10906
- const method = unique(controller.members.filter((member) => ts7.isMethodDeclaration(member) && nameOf(member.name) === fix.route), "route handler");
10907
- const parameter = unique(method.parameters.filter((candidate) => ts7.isIdentifier(candidate.name) && candidate.name.text === fix.parameter), "same-named route parameter");
11233
+ const method = unique(controller.members.filter((member) => ts9.isMethodDeclaration(member) && nameOf(member.name) === fix.route), "route handler");
11234
+ const parameter = unique(method.parameters.filter((candidate) => ts9.isIdentifier(candidate.name) && candidate.name.text === fix.parameter), "same-named route parameter");
10908
11235
  const binding = fix.binding === "param" ? "Param" : fix.binding === "query" ? "Query" : undefined;
10909
11236
  if (!binding)
10910
11237
  throw new Error("Invalid route binding");
10911
- const decorators = ts7.getDecorators(parameter) ?? [];
11238
+ const decorators = ts9.getDecorators(parameter) ?? [];
10912
11239
  if (decorators.length > 0)
10913
11240
  throw new Error("Parameter already has a decorator");
10914
- const framework = unique(source.statements.filter((statement) => ts7.isImportDeclaration(statement) && statement.importClause?.namedBindings && ts7.isNamedImports(statement.importClause.namedBindings) && statement.importClause.namedBindings.elements.some((element) => ["Controller", "Get", "Post", "Put", "Patch", "Delete", "Head", "Options"].includes(element.name.text))), "framework import");
10915
- if (!ts7.isImportDeclaration(framework) || !ts7.isStringLiteral(framework.moduleSpecifier)) {
11241
+ 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");
11242
+ if (!ts9.isImportDeclaration(framework) || !ts9.isStringLiteral(framework.moduleSpecifier)) {
10916
11243
  throw new Error("Framework import must be static");
10917
11244
  }
10918
11245
  const edited = original.slice(0, parameter.getStart(source)) + `@${binding}(${JSON.stringify(fix.parameter)}) ` + original.slice(parameter.getStart(source));
@@ -10938,15 +11265,15 @@ async function applyDiagnosticFix(fix, options = {}) {
10938
11265
  return result;
10939
11266
  }
10940
11267
  function parse3(file, text) {
10941
- const result = ts7.transpileModule(text, {
11268
+ const result = ts9.transpileModule(text, {
10942
11269
  fileName: file,
10943
11270
  reportDiagnostics: true,
10944
- compilerOptions: { target: ts7.ScriptTarget.ESNext, experimentalDecorators: true }
11271
+ compilerOptions: { target: ts9.ScriptTarget.ESNext, experimentalDecorators: true }
10945
11272
  });
10946
- if (result.diagnostics?.some((item) => item.category === ts7.DiagnosticCategory.Error)) {
11273
+ if (result.diagnostics?.some((item) => item.category === ts9.DiagnosticCategory.Error)) {
10947
11274
  throw new Error("Cannot fix syntactically invalid TypeScript");
10948
11275
  }
10949
- return ts7.createSourceFile(file, text, ts7.ScriptTarget.Latest, true, ts7.ScriptKind.TS);
11276
+ return ts9.createSourceFile(file, text, ts9.ScriptTarget.Latest, true, ts9.ScriptKind.TS);
10950
11277
  }
10951
11278
  function unique(items, description) {
10952
11279
  if (items.length !== 1)
@@ -10960,50 +11287,50 @@ function identifier(value) {
10960
11287
  function nameOf(name) {
10961
11288
  if (!name)
10962
11289
  return "";
10963
- return ts7.isIdentifier(name) || ts7.isStringLiteral(name) || ts7.isNumericLiteral(name) ? name.text : "";
11290
+ return ts9.isIdentifier(name) || ts9.isStringLiteral(name) || ts9.isNumericLiteral(name) ? name.text : "";
10964
11291
  }
10965
11292
  function property(object, key) {
10966
- if (object.properties.some((item) => !ts7.isPropertyAssignment(item) || ts7.isComputedPropertyName(item.name))) {
11293
+ if (object.properties.some((item) => !ts9.isPropertyAssignment(item) || ts9.isComputedPropertyName(item.name))) {
10967
11294
  throw new Error("Fix requires explicit static object properties");
10968
11295
  }
10969
- const values = object.properties.filter((item) => ts7.isPropertyAssignment(item) && nameOf(item.name) === key);
11296
+ const values = object.properties.filter((item) => ts9.isPropertyAssignment(item) && nameOf(item.name) === key);
10970
11297
  if (values.length > 1)
10971
11298
  throw new Error(`Duplicate '${key}' property`);
10972
11299
  return values[0];
10973
11300
  }
10974
11301
  function stringProperty(object, key) {
10975
11302
  const value = property(object, key)?.initializer;
10976
- return value && ts7.isStringLiteral(value) ? value.text : undefined;
11303
+ return value && ts9.isStringLiteral(value) ? value.text : undefined;
10977
11304
  }
10978
11305
  function replaceProperty(source, object, key, value) {
10979
11306
  const previous = property(object, key);
10980
- const replacement = ts7.factory.createPropertyAssignment(key, value);
11307
+ const replacement = ts9.factory.createPropertyAssignment(key, value);
10981
11308
  const properties = object.properties.map((item) => item === previous ? replacement : item);
10982
11309
  if (!previous)
10983
11310
  properties.push(replacement);
10984
- const updated = ts7.factory.updateObjectLiteralExpression(object, properties);
10985
- return source.text.slice(0, object.getStart(source)) + ts7.createPrinter().printNode(ts7.EmitHint.Expression, updated, source) + source.text.slice(object.end);
11311
+ const updated = ts9.factory.updateObjectLiteralExpression(object, properties);
11312
+ return source.text.slice(0, object.getStart(source)) + ts9.createPrinter().printNode(ts9.EmitHint.Expression, updated, source) + source.text.slice(object.end);
10986
11313
  }
10987
11314
  function findClass(source, name) {
10988
- return unique(source.statements.filter((statement) => ts7.isClassDeclaration(statement) && statement.name?.text === name), `class '${name}'`);
11315
+ return unique(source.statements.filter((statement) => ts9.isClassDeclaration(statement) && statement.name?.text === name), `class '${name}'`);
10989
11316
  }
10990
11317
  function decoratorObject(node, name) {
10991
- const decorator = unique((ts7.getDecorators(node) ?? []).filter((item) => ts7.isCallExpression(item.expression) && item.expression.expression.getText() === name), `@${name} decorator`);
10992
- const argument = ts7.isCallExpression(decorator.expression) ? decorator.expression.arguments[0] : undefined;
10993
- if (!argument || !ts7.isObjectLiteralExpression(argument))
11318
+ const decorator = unique((ts9.getDecorators(node) ?? []).filter((item) => ts9.isCallExpression(item.expression) && item.expression.expression.getText() === name), `@${name} decorator`);
11319
+ const argument = ts9.isCallExpression(decorator.expression) ? decorator.expression.arguments[0] : undefined;
11320
+ if (!argument || !ts9.isObjectLiteralExpression(argument))
10994
11321
  throw new Error(`@${name} requires a static object`);
10995
11322
  return argument;
10996
11323
  }
10997
11324
  function moduleObjects(source) {
10998
11325
  const result = [];
10999
11326
  for (const statement of source.statements) {
11000
- if (ts7.isClassDeclaration(statement) && (ts7.getDecorators(statement) ?? []).some((item) => ts7.isCallExpression(item.expression) && item.expression.expression.getText() === "Module")) {
11327
+ if (ts9.isClassDeclaration(statement) && (ts9.getDecorators(statement) ?? []).some((item) => ts9.isCallExpression(item.expression) && item.expression.expression.getText() === "Module")) {
11001
11328
  result.push(decoratorObject(statement, "Module"));
11002
11329
  }
11003
- if (ts7.isVariableStatement(statement)) {
11330
+ if (ts9.isVariableStatement(statement)) {
11004
11331
  for (const declaration of statement.declarationList.declarations) {
11005
11332
  const call = declaration.initializer;
11006
- if (call && ts7.isCallExpression(call) && ["defineModule", "defineFeatureSlice"].includes(call.expression.getText()) && call.arguments[0] && ts7.isObjectLiteralExpression(call.arguments[0])) {
11333
+ if (call && ts9.isCallExpression(call) && ["defineModule", "defineFeatureSlice"].includes(call.expression.getText()) && call.arguments[0] && ts9.isObjectLiteralExpression(call.arguments[0])) {
11007
11334
  result.push(call.arguments[0]);
11008
11335
  }
11009
11336
  }
@@ -11017,19 +11344,19 @@ function importSymbol(source, path, symbol) {
11017
11344
  const target = resolve8(dirname6(source.fileName), path).replace(/\.(tsx?|mts|cts)$/, "");
11018
11345
  if (current === target)
11019
11346
  return source.text;
11020
- const matches = source.statements.filter((item) => ts7.isImportDeclaration(item) && ts7.isStringLiteral(item.moduleSpecifier) && item.moduleSpecifier.text === path);
11347
+ const matches = source.statements.filter((item) => ts9.isImportDeclaration(item) && ts9.isStringLiteral(item.moduleSpecifier) && item.moduleSpecifier.text === path);
11021
11348
  if (matches.length > 1)
11022
11349
  throw new Error(`Ambiguous imports from '${path}'`);
11023
11350
  const match = matches[0];
11024
- if (match && ts7.isImportDeclaration(match) && match.importClause?.namedBindings && ts7.isNamedImports(match.importClause.namedBindings) && !match.importClause.isTypeOnly) {
11351
+ if (match && ts9.isImportDeclaration(match) && match.importClause?.namedBindings && ts9.isNamedImports(match.importClause.namedBindings) && !match.importClause.isTypeOnly) {
11025
11352
  if (match.importClause.namedBindings.elements.some((item) => item.name.text === symbol))
11026
11353
  return source.text;
11027
11354
  const bindings = match.importClause.namedBindings;
11028
- const updated = ts7.factory.updateNamedImports(bindings, [
11355
+ const updated = ts9.factory.updateNamedImports(bindings, [
11029
11356
  ...bindings.elements,
11030
- ts7.factory.createImportSpecifier(false, undefined, ts7.factory.createIdentifier(symbol))
11357
+ ts9.factory.createImportSpecifier(false, undefined, ts9.factory.createIdentifier(symbol))
11031
11358
  ]);
11032
- return source.text.slice(0, bindings.getStart(source)) + ts7.createPrinter().printNode(ts7.EmitHint.Unspecified, updated, source) + source.text.slice(bindings.end);
11359
+ return source.text.slice(0, bindings.getStart(source)) + ts9.createPrinter().printNode(ts9.EmitHint.Unspecified, updated, source) + source.text.slice(bindings.end);
11033
11360
  }
11034
11361
  if (match)
11035
11362
  throw new Error(`Import from '${path}' is not a named value import`);
@@ -11276,7 +11603,7 @@ function formatDeliveryPlan(result) {
11276
11603
  import { mkdir as mkdir3, mkdtemp, readFile as readFile7, realpath as realpath3, rename as rename4, rm as rm2 } from "node:fs/promises";
11277
11604
  import { readFileSync as readFileSync3 } from "node:fs";
11278
11605
  import { dirname as dirname8, join as join8, relative as relative10, resolve as resolve11, sep as sep10 } from "node:path";
11279
- import * as ts9 from "@typescript/typescript6";
11606
+ import * as ts11 from "@typescript/typescript6";
11280
11607
 
11281
11608
  // src/delivery-files.ts
11282
11609
  import { createHash as createHash8 } from "node:crypto";
@@ -11510,19 +11837,19 @@ function renderDeliveryTarget(graph, target, options) {
11510
11837
  import { isBuiltin } from "node:module";
11511
11838
  import { readFile as readFile6 } from "node:fs/promises";
11512
11839
  import { resolve as resolve10 } from "node:path";
11513
- import * as ts8 from "@typescript/typescript6";
11840
+ import * as ts10 from "@typescript/typescript6";
11514
11841
  function checkStaticImports(path, contents) {
11515
11842
  if (!/\.[cm]?[jt]sx?$/.test(path))
11516
11843
  return;
11517
- const source = ts8.createSourceFile(path, new TextDecoder().decode(contents), ts8.ScriptTarget.Latest, true);
11844
+ const source = ts10.createSourceFile(path, new TextDecoder().decode(contents), ts10.ScriptTarget.Latest, true);
11518
11845
  function visit(node) {
11519
- if (ts8.isCallExpression(node) && (node.expression.kind === ts8.SyntaxKind.ImportKeyword || ts8.isIdentifier(node.expression) && node.expression.text === "require")) {
11846
+ if (ts10.isCallExpression(node) && (node.expression.kind === ts10.SyntaxKind.ImportKeyword || ts10.isIdentifier(node.expression) && node.expression.text === "require")) {
11520
11847
  const argument = node.arguments[0];
11521
- if (!argument || !ts8.isStringLiteral(argument) && !ts8.isNoSubstitutionTemplateLiteral(argument)) {
11848
+ if (!argument || !ts10.isStringLiteral(argument) && !ts10.isNoSubstitutionTemplateLiteral(argument)) {
11522
11849
  throw new Error("Computed module loading is not supported in independent delivery bundles.");
11523
11850
  }
11524
11851
  }
11525
- ts8.forEachChild(node, visit);
11852
+ ts10.forEachChild(node, visit);
11526
11853
  }
11527
11854
  visit(source);
11528
11855
  }
@@ -11611,7 +11938,7 @@ async function buildDeliveryProject(options, delivery) {
11611
11938
  const settings = parseDeliveryOptions(delivery);
11612
11939
  if (typeof Bun === "undefined")
11613
11940
  throw new Error("Independent delivery builds require Bun.");
11614
- const configPath = ts9.findConfigFile(resolve11(options.rootDir), ts9.sys.fileExists);
11941
+ const configPath = ts11.findConfigFile(resolve11(options.rootDir), ts11.sys.fileExists);
11615
11942
  if (!configPath)
11616
11943
  throw new Error("Independent delivery builds require a project tsconfig.json.");
11617
11944
  const lexicalProject = dirname8(configPath);
@@ -11627,8 +11954,8 @@ async function buildDeliveryProject(options, delivery) {
11627
11954
  if (inside(generatedRoot, sourceRoot))
11628
11955
  throw new Error("Output must not contain the application source root.");
11629
11956
  const configInputs = new Map;
11630
- const parsedConfig = ts9.getParsedCommandLineOfConfigFile(await realpath3(configPath), {}, {
11631
- ...ts9.sys,
11957
+ const parsedConfig = ts11.getParsedCommandLineOfConfigFile(await realpath3(configPath), {}, {
11958
+ ...ts11.sys,
11632
11959
  readFile(path) {
11633
11960
  const contents = readFileSync3(path, "utf8");
11634
11961
  configInputs.set(resolve11(path), digest(contents));
@@ -11714,7 +12041,7 @@ async function buildDeliveryProject(options, delivery) {
11714
12041
  for (const [name, contents] of Object.entries(generated))
11715
12042
  await writeArtifact(stage, `generated/${name}`, contents);
11716
12043
  {
11717
- const program = ts9.createProgram({
12044
+ const program = ts11.createProgram({
11718
12045
  rootNames: [
11719
12046
  ...parsedConfig.fileNames.filter((path) => !inside(generatedRoot, path)),
11720
12047
  ...Object.keys(generated).map((name) => join8(stage, "generated", name))
@@ -11722,12 +12049,12 @@ async function buildDeliveryProject(options, delivery) {
11722
12049
  options: { ...parsedConfig.options, rootDir: project },
11723
12050
  ...parsedConfig.projectReferences ? { projectReferences: parsedConfig.projectReferences } : {}
11724
12051
  });
11725
- const diagnostics = ts9.getPreEmitDiagnostics(program);
11726
- if (diagnostics.some((item) => item.category === ts9.DiagnosticCategory.Error)) {
11727
- return failed(diagnostics.filter((item) => item.category === ts9.DiagnosticCategory.Error).map((item) => ({
12052
+ const diagnostics = ts11.getPreEmitDiagnostics(program);
12053
+ if (diagnostics.some((item) => item.category === ts11.DiagnosticCategory.Error)) {
12054
+ return failed(diagnostics.filter((item) => item.category === ts11.DiagnosticCategory.Error).map((item) => ({
11728
12055
  severity: "error",
11729
12056
  code: "delivery-generated-type-error",
11730
- message: ts9.flattenDiagnosticMessageText(item.messageText, `
12057
+ message: ts11.flattenDiagnosticMessageText(item.messageText, `
11731
12058
  `),
11732
12059
  ...item.file ? { file: item.file.fileName } : {}
11733
12060
  })));
@@ -11859,7 +12186,7 @@ async function buildDeliveryProject(options, delivery) {
11859
12186
  // src/migrations.ts
11860
12187
  import { rename as rename5, readFile as readFile9, writeFile as writeFile4, rm as rm3 } from "node:fs/promises";
11861
12188
  import { relative as relative11, resolve as resolve13 } from "node:path";
11862
- import * as ts10 from "@typescript/typescript6";
12189
+ import * as ts12 from "@typescript/typescript6";
11863
12190
 
11864
12191
  // src/migration-policy.ts
11865
12192
  import { readFile as readFile8 } from "node:fs/promises";
@@ -11878,9 +12205,9 @@ function compilerVersion() {
11878
12205
  }
11879
12206
  function migrationDependencies() {
11880
12207
  return {
11881
- "@supacloud/app": "0.14.0",
12208
+ "@supacloud/app": "0.15.0",
11882
12209
  "@supacloud/compiler": compilerVersion(),
11883
- "@supacloud/elysia": "0.16.0",
12210
+ "@supacloud/elysia": "0.18.0",
11884
12211
  elysia: "1.4.30",
11885
12212
  typescript: "7.0.2"
11886
12213
  };
@@ -11903,29 +12230,29 @@ async function checkMigrationDependencies(rootDir) {
11903
12230
  // src/migrations.ts
11904
12231
  var ROUTE_DECORATORS2 = new Set(["Get", "Post", "Put", "Patch", "Delete", "Head", "Options"]);
11905
12232
  var MIGRATION_COMPILER_OPTIONS = {
11906
- target: ts10.ScriptTarget.ES2022,
11907
- module: ts10.ModuleKind.ESNext,
11908
- moduleResolution: ts10.ModuleResolutionKind.Bundler,
12233
+ target: ts12.ScriptTarget.ES2022,
12234
+ module: ts12.ModuleKind.ESNext,
12235
+ moduleResolution: ts12.ModuleResolutionKind.Bundler,
11909
12236
  noEmit: true,
11910
12237
  skipLibCheck: true
11911
12238
  };
11912
12239
  function migrationCompilerOptions(rootDir) {
11913
12240
  if (!rootDir)
11914
12241
  return MIGRATION_COMPILER_OPTIONS;
11915
- const configPath = ts10.findConfigFile(rootDir, ts10.sys.fileExists);
12242
+ const configPath = ts12.findConfigFile(rootDir, ts12.sys.fileExists);
11916
12243
  if (!configPath)
11917
12244
  return MIGRATION_COMPILER_OPTIONS;
11918
12245
  const configHost = {
11919
- ...ts10.sys,
12246
+ ...ts12.sys,
11920
12247
  onUnRecoverableConfigFileDiagnostic: (_diagnostic) => {}
11921
12248
  };
11922
- const parsed = ts10.getParsedCommandLineOfConfigFile(configPath, {}, configHost);
12249
+ const parsed = ts12.getParsedCommandLineOfConfigFile(configPath, {}, configHost);
11923
12250
  if (!parsed || parsed.errors.length > 0)
11924
12251
  return MIGRATION_COMPILER_OPTIONS;
11925
12252
  return { ...parsed.options, noEmit: true, skipLibCheck: true };
11926
12253
  }
11927
12254
  function propertyName2(property) {
11928
- if (ts10.isIdentifier(property) || ts10.isStringLiteral(property) || ts10.isNumericLiteral(property))
12255
+ if (ts12.isIdentifier(property) || ts12.isStringLiteral(property) || ts12.isNumericLiteral(property))
11929
12256
  return property.text;
11930
12257
  return;
11931
12258
  }
@@ -11935,7 +12262,7 @@ function lineOf2(sourceFile, node) {
11935
12262
  function resolveSymbol(symbol, checker) {
11936
12263
  if (!symbol)
11937
12264
  return;
11938
- for (let guard = 0;guard < 4 && (symbol.flags & ts10.SymbolFlags.Alias) !== 0; guard += 1) {
12265
+ for (let guard = 0;guard < 4 && (symbol.flags & ts12.SymbolFlags.Alias) !== 0; guard += 1) {
11939
12266
  const aliased = checker.getAliasedSymbol(symbol);
11940
12267
  if (aliased === symbol)
11941
12268
  break;
@@ -11944,12 +12271,12 @@ function resolveSymbol(symbol, checker) {
11944
12271
  return symbol;
11945
12272
  }
11946
12273
  function symbolForExpression(expression, checker) {
11947
- const location = ts10.isIdentifier(expression) ? expression : ts10.isPropertyAccessExpression(expression) ? expression.name : ts10.isElementAccessExpression(expression) && expression.argumentExpression && ts10.isStringLiteral(expression.argumentExpression) ? expression : undefined;
12274
+ const location = ts12.isIdentifier(expression) ? expression : ts12.isPropertyAccessExpression(expression) ? expression.name : ts12.isElementAccessExpression(expression) && expression.argumentExpression && ts12.isStringLiteral(expression.argumentExpression) ? expression : undefined;
11948
12275
  return location ? resolveSymbol(checker.getSymbolAtLocation(location), checker) : undefined;
11949
12276
  }
11950
12277
  function unwrapExpression(expression) {
11951
12278
  let current = expression;
11952
- while (ts10.isAsExpression(current) || ts10.isSatisfiesExpression(current) || ts10.isParenthesizedExpression(current) || ts10.isTypeAssertionExpression(current)) {
12279
+ while (ts12.isAsExpression(current) || ts12.isSatisfiesExpression(current) || ts12.isParenthesizedExpression(current) || ts12.isTypeAssertionExpression(current)) {
11953
12280
  current = current.expression;
11954
12281
  }
11955
12282
  return current;
@@ -11962,7 +12289,7 @@ function isDefineRouteContractCall(node, checker) {
11962
12289
  }
11963
12290
  function isRouteDecoratorCall(node, checker) {
11964
12291
  const name = node.expression.getText(node.getSourceFile());
11965
- if (ts10.isIdentifier(node.expression) && ROUTE_DECORATORS2.has(node.expression.text))
12292
+ if (ts12.isIdentifier(node.expression) && ROUTE_DECORATORS2.has(node.expression.text))
11966
12293
  return true;
11967
12294
  if (ROUTE_DECORATORS2.has(name))
11968
12295
  return true;
@@ -11976,14 +12303,14 @@ function resolveStaticObjectLiteral2(input, checker, seen = new Set) {
11976
12303
  if (seen.has(expression))
11977
12304
  return;
11978
12305
  seen.add(expression);
11979
- if (ts10.isObjectLiteralExpression(expression))
12306
+ if (ts12.isObjectLiteralExpression(expression))
11980
12307
  return expression;
11981
- if (ts10.isCallExpression(expression) && isDefineRouteContractCall(expression, checker)) {
12308
+ if (ts12.isCallExpression(expression) && isDefineRouteContractCall(expression, checker)) {
11982
12309
  return resolveStaticObjectLiteral2(expression.arguments[0], checker, seen);
11983
12310
  }
11984
12311
  const symbol = symbolForExpression(expression, checker);
11985
12312
  for (const declaration of symbol?.declarations ?? []) {
11986
- if (ts10.isVariableDeclaration(declaration) && declaration.initializer) {
12313
+ if (ts12.isVariableDeclaration(declaration) && declaration.initializer) {
11987
12314
  const resolved = resolveStaticObjectLiteral2(declaration.initializer, checker, seen);
11988
12315
  if (resolved)
11989
12316
  return resolved;
@@ -11997,7 +12324,7 @@ function displayFile(rootDir, fileName) {
11997
12324
  }
11998
12325
  function createMigrationProgram(fileNames, sourceOverrides, rootDir) {
11999
12326
  const compilerOptions = migrationCompilerOptions(rootDir);
12000
- const host = ts10.createCompilerHost(compilerOptions);
12327
+ const host = ts12.createCompilerHost(compilerOptions);
12001
12328
  const getSourceFile = host.getSourceFile.bind(host);
12002
12329
  const fileExists = host.fileExists.bind(host);
12003
12330
  const readFile = host.readFile.bind(host);
@@ -12006,16 +12333,16 @@ function createMigrationProgram(fileNames, sourceOverrides, rootDir) {
12006
12333
  host.readFile = (fileName) => sourceOverrides.get(resolve13(fileName)) ?? readFile(fileName);
12007
12334
  host.getSourceFile = (fileName, languageVersion, onError, shouldCreateNewSourceFile) => {
12008
12335
  const source = sourceOverrides.get(resolve13(fileName));
12009
- return source === undefined ? getSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile) : ts10.createSourceFile(fileName, source, languageVersion, true);
12336
+ return source === undefined ? getSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile) : ts12.createSourceFile(fileName, source, languageVersion, true);
12010
12337
  };
12011
12338
  host.getCurrentDirectory = () => rootDir ?? currentDirectory();
12012
- return ts10.createProgram(fileNames, compilerOptions, host);
12339
+ return ts12.createProgram(fileNames, compilerOptions, host);
12013
12340
  }
12014
12341
  function routeResponseProperties(object) {
12015
- const responseProperties = object.properties.filter((property) => ts10.isPropertyAssignment(property) && propertyName2(property.name) === "response");
12342
+ const responseProperties = object.properties.filter((property) => ts12.isPropertyAssignment(property) && propertyName2(property.name) === "response");
12016
12343
  return {
12017
12344
  response: responseProperties[0],
12018
- hasResponses: object.properties.some((property) => (ts10.isPropertyAssignment(property) || ts10.isShorthandPropertyAssignment(property)) && propertyName2(property.name) === "responses"),
12345
+ hasResponses: object.properties.some((property) => (ts12.isPropertyAssignment(property) || ts12.isShorthandPropertyAssignment(property)) && propertyName2(property.name) === "responses"),
12019
12346
  duplicateResponse: responseProperties.length > 1
12020
12347
  };
12021
12348
  }
@@ -12035,7 +12362,7 @@ function planRouteResponseMigration(sourceFiles, checker, rootDir, includedFiles
12035
12362
  if (!includedFiles.has(sourcePath))
12036
12363
  continue;
12037
12364
  const visit = (node) => {
12038
- if (ts10.isCallExpression(node) && isRouteDecoratorCall(node, checker)) {
12365
+ if (ts12.isCallExpression(node) && isRouteDecoratorCall(node, checker)) {
12039
12366
  const options = node.arguments[1];
12040
12367
  const object = options && resolveStaticObjectLiteral2(options, checker);
12041
12368
  if (object) {
@@ -12055,7 +12382,7 @@ function planRouteResponseMigration(sourceFiles, checker, rootDir, includedFiles
12055
12382
  }
12056
12383
  }
12057
12384
  }
12058
- ts10.forEachChild(node, visit);
12385
+ ts12.forEachChild(node, visit);
12059
12386
  };
12060
12387
  visit(sourceFile);
12061
12388
  }
@@ -12215,7 +12542,7 @@ async function migrateProject(options) {
12215
12542
  }
12216
12543
  }
12217
12544
  const include = options.include ?? ["**/*.ts", "**/*.tsx", "**/*.mts", "**/*.cts"];
12218
- const files = ts10.sys.readDirectory(rootDir, [".ts", ".tsx", ".mts", ".cts"], ["node_modules", "dist", "generated"], include).sort();
12545
+ const files = ts12.sys.readDirectory(rootDir, [".ts", ".tsx", ".mts", ".cts"], ["node_modules", "dist", "generated"], include).sort();
12219
12546
  const results = [];
12220
12547
  const issues = [];
12221
12548
  const pendingWrites = new Map;
@@ -12827,6 +13154,7 @@ Usage:
12827
13154
  supacloud-compiler openapi-diff <base.json> <current.json> [options]
12828
13155
  supacloud-compiler fix <fix.json> [options]
12829
13156
  supacloud-compiler graphql-schema --url <project-url> --key-env <name> [--token-env <name>]
13157
+ supacloud-compiler database-contracts <config.json> [--check]
12830
13158
 
12831
13159
  Commands:
12832
13160
  compile Compile application modules and generate artifacts
@@ -12878,6 +13206,18 @@ async function run() {
12878
13206
  process.exit(0);
12879
13207
  }
12880
13208
  const command = args[0];
13209
+ if (command === "database-contracts") {
13210
+ const path = args[1];
13211
+ if (!path || path.startsWith("-") || args.slice(2).some((arg) => arg !== "--check")) {
13212
+ throw new Error("database-contracts requires <config.json> and optional --check");
13213
+ }
13214
+ await Promise.resolve().then(() => init_database_contracts());
13215
+ const result = await runDatabaseContractsFile(path, args.includes("--check"));
13216
+ console.log(JSON.stringify(result, null, 2));
13217
+ if (args.includes("--check") && !result.upToDate)
13218
+ process.exitCode = 1;
13219
+ return;
13220
+ }
12881
13221
  if (!command || !["compile", "check", "dev", "graph", "explain", "context", "doctor", "migrate", "fix", "graphql-schema", "plan", "build-delivery", "openapi-export", "openapi-diff"].includes(command)) {
12882
13222
  console.error(`Error: unknown command "${command}"`);
12883
13223
  printUsage();
@@ -13049,7 +13389,7 @@ async function run() {
13049
13389
  const currentPath = openApiDiffPaths[1];
13050
13390
  if (!basePath || !currentPath)
13051
13391
  throw new Error("openapi-diff requires two JSON file paths");
13052
- const result = diffOpenApiDocuments(await readOpenApiJson(resolve16(process.cwd(), basePath)), await readOpenApiJson(resolve16(process.cwd(), currentPath)));
13392
+ const result = diffOpenApiDocuments(await readOpenApiJson(resolve17(process.cwd(), basePath)), await readOpenApiJson(resolve17(process.cwd(), currentPath)));
13053
13393
  console.log(json ? JSON.stringify(result, null, 2) : formatOpenApiDiff(result));
13054
13394
  if (!result.ok)
13055
13395
  process.exitCode = 1;
@@ -13064,8 +13404,8 @@ async function run() {
13064
13404
  if (!modulePath || !outputPath)
13065
13405
  throw new Error("openapi-export requires an OpenAPI module and output path");
13066
13406
  const result = await exportGeneratedOpenApiJson({
13067
- modulePath: resolve16(process.cwd(), modulePath),
13068
- outputPath: resolve16(process.cwd(), outputPath),
13407
+ modulePath: resolve17(process.cwd(), modulePath),
13408
+ outputPath: resolve17(process.cwd(), outputPath),
13069
13409
  ...openApiExportSpace === undefined ? {} : { space: openApiExportSpace }
13070
13410
  });
13071
13411
  console.log(json ? JSON.stringify({ ok: true, ...result }, null, 2) : result.written ? `OpenAPI JSON written: ${result.path}` : `OpenAPI JSON matches: ${result.path}`);
@@ -13073,7 +13413,7 @@ async function run() {
13073
13413
  }
13074
13414
  if (command === "migrate") {
13075
13415
  const result = await migrateProject({
13076
- rootDir: rootDir ? resolve16(process.cwd(), rootDir) : process.cwd(),
13416
+ rootDir: rootDir ? resolve17(process.cwd(), rootDir) : process.cwd(),
13077
13417
  write: !dryRun,
13078
13418
  ...fromVersion === undefined ? {} : { fromVersion },
13079
13419
  ...toVersion === undefined ? {} : { toVersion }
@@ -13101,8 +13441,8 @@ async function run() {
13101
13441
  if (checkSchema && command !== "graphql-schema")
13102
13442
  throw new Error("--check is only supported by graphql-schema");
13103
13443
  const defaults = resolveSupacloudConfig(loadedConfig, process.cwd());
13104
- const resolvedRoot = rootDir ? resolve16(process.cwd(), rootDir) : defaults.rootDir;
13105
- const resolvedOut = outDir ? resolve16(process.cwd(), outDir) : defaults.outDir;
13444
+ const resolvedRoot = rootDir ? resolve17(process.cwd(), rootDir) : defaults.rootDir;
13445
+ const resolvedOut = outDir ? resolve17(process.cwd(), outDir) : defaults.outDir;
13106
13446
  const configured = compileOptionsFromConfig({
13107
13447
  ...loadedConfig,
13108
13448
  root: resolvedRoot,
@@ -13121,7 +13461,7 @@ async function run() {
13121
13461
  let delivery = loadedConfig.delivery;
13122
13462
  if (deliveryPath !== undefined) {
13123
13463
  try {
13124
- delivery = JSON.parse(await readFile12(resolve16(process.cwd(), deliveryPath), "utf8"));
13464
+ delivery = JSON.parse(await readFile13(resolve17(process.cwd(), deliveryPath), "utf8"));
13125
13465
  } catch {
13126
13466
  throw new DeliveryConfigurationError;
13127
13467
  }
@@ -13168,7 +13508,7 @@ ${item.suggestion ?? ""}`).join(`
13168
13508
  } else if (command === "fix") {
13169
13509
  if (!query)
13170
13510
  throw new Error("fix requires a JSON file containing one DiagnosticFix");
13171
- const fix = JSON.parse(await readFile12(resolve16(process.cwd(), query), "utf8"));
13511
+ const fix = JSON.parse(await readFile13(resolve17(process.cwd(), query), "utf8"));
13172
13512
  const result = await applyDiagnosticFix(fix, { rootDir: resolvedRoot, dryRun });
13173
13513
  console.log(JSON.stringify({ ok: true, ...result }, null, 2));
13174
13514
  } else if (command === "compile") {