@supacloud/compiler 0.21.1 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -354,7 +354,7 @@ class ModuleGenerator {
354
354
  this.imports = imports;
355
355
  this.pascal = pascalName(module.name);
356
356
  if (module.providers.some((provider) => (provider.functionalInjects?.length ?? 0) > 0) || module.controllers.some((controller) => (controller.functionalInjects?.length ?? 0) > 0)) {
357
- imports.add("runInInjectionContext", undefined, "@supacloud/app");
357
+ throw new Error("SC2012: Compiled DI requires constructor injection; property inject() is not supported.");
358
358
  }
359
359
  }
360
360
  renderFactories() {
@@ -388,6 +388,7 @@ class ModuleGenerator {
388
388
  lines.push(` jobs: ${this.renderJobs()},`);
389
389
  if (this.module.aspects && this.module.aspects.length > 0) {
390
390
  lines.push(` aspects: ${this.renderAspects(this.module.aspects)},`);
391
+ lines.push(` aspectPipeline: ${this.renderAspectPipeline(this.module.aspects)},`);
391
392
  }
392
393
  lines.push(`}`);
393
394
  return lines.join(`
@@ -464,6 +465,7 @@ class ModuleGenerator {
464
465
  }
465
466
  if (route.aspects && route.aspects.length > 0) {
466
467
  fields.push(`aspects: ${this.renderAspects(route.aspects)}`);
468
+ fields.push(`aspectPipeline: ${this.renderAspectPipeline(route.aspects)}`);
467
469
  }
468
470
  const invokerArgs = (route.handlerParams ?? []).map((hp) => {
469
471
  if (hp.kind === "param") {
@@ -544,7 +546,7 @@ ${indent(item, 2)}`).join(",")}
544
546
  `idempotency: ${JSON.stringify(command.idempotency)}`,
545
547
  ...command.rpc ? [`rpc: ${JSON.stringify(command.rpc)}`] : [],
546
548
  ...command.standalone ? ["standalone: true"] : [],
547
- ...command.aspects && command.aspects.length > 0 ? [`aspects: ${this.renderAspects(command.aspects)}`] : []
549
+ ...command.aspects && command.aspects.length > 0 ? [`aspects: ${this.renderAspects(command.aspects)}`, `aspectPipeline: ${this.renderAspectPipeline(command.aspects)}`] : []
548
550
  ];
549
551
  return `{ ${fields.join(", ")} }`;
550
552
  }).join(", ")}]`;
@@ -577,6 +579,7 @@ ${indent(item, 2)}`).join(",")}
577
579
  fields.push(`idempotency: ${JSON.stringify(job.idempotency)}`);
578
580
  if (job.aspects && job.aspects.length > 0) {
579
581
  fields.push(`aspects: ${this.renderAspects(job.aspects)}`);
582
+ fields.push(`aspectPipeline: ${this.renderAspectPipeline(job.aspects)}`);
580
583
  }
581
584
  return `{ ${fields.join(", ")}, }`;
582
585
  }).join(", ")}]`;
@@ -584,6 +587,24 @@ ${indent(item, 2)}`).join(",")}
584
587
  renderAspects(aspects) {
585
588
  return `[${aspects.map((aspect) => this.imports.add(aspect.name, aspect.importPath, aspect.importModule)).join(", ")}]`;
586
589
  }
590
+ renderAspectPipeline(aspects) {
591
+ const lines = [
592
+ `async (context, next, observe) => {`,
593
+ ` const state = { active: true };`,
594
+ ` const step${aspects.length} = compiledAspectNext(next, state);`
595
+ ];
596
+ for (let index = aspects.length - 1;index >= 0; index--) {
597
+ const aspect = aspects[index];
598
+ if (!aspect)
599
+ continue;
600
+ const name = this.imports.add(aspect.name, aspect.importPath, aspect.importModule);
601
+ const stage = JSON.stringify(`aspect[${index}]:${aspect.name}`);
602
+ lines.push(` const step${index} = compiledAspectNext(() => observeCompiledAspect(observe, ${stage}, () => ${name}(context, step${index + 1})), state);`);
603
+ }
604
+ lines.push(` try { return await step0(); } finally { state.active = false; }`, `}`);
605
+ return lines.join(`
606
+ `);
607
+ }
587
608
  renderServicesFactory() {
588
609
  return [
589
610
  `function create${this.pascal}Services(`,
@@ -698,7 +719,7 @@ ${indent(item, 2)}`).join(",")}
698
719
  const args = provider.deps.map((dep, index) => this.typedDepExpr(dep, kind, this.depOptions(provider, dep), `ConstructorParameters<typeof ${useClass}>[${index}]`)).join(", ");
699
720
  const local = this.localVar(isMulti ? provider.useClass ?? `${provider.token}Item` : provider.token, kind);
700
721
  return {
701
- constLine: `const ${local} = ${this.instantiate(useClass, args, kind, provider.functionalInjects)};`,
722
+ constLine: `const ${local} = new ${useClass}(${args});`,
702
723
  key,
703
724
  expr: local
704
725
  };
@@ -734,32 +755,11 @@ ${indent(item, 2)}`).join(",")}
734
755
  const key = camelName(controller.className);
735
756
  const local = this.localVar(controller.className, kind);
736
757
  return {
737
- constLine: `const ${local} = ${this.instantiate(className, args, kind, controller.functionalInjects)};`,
758
+ constLine: `const ${local} = new ${className}(${args});`,
738
759
  key,
739
760
  expr: local
740
761
  };
741
762
  }
742
- instantiate(className, args, kind, functionalInjects) {
743
- if (!functionalInjects || functionalInjects.length === 0) {
744
- return `new ${className}(${args})`;
745
- }
746
- const clauses = functionalInjects.map((entry) => {
747
- const token = this.imports.add(entry.expression, entry.importPath, entry.importModule);
748
- const value = this.depExpr(entry.token, kind, entry);
749
- return `if (token === ${token}) return ${value} as T;`;
750
- });
751
- const missing = `if (options?.optional) return undefined; throw new Error("Static inject token not available: " + String(token));`;
752
- const injector = [
753
- `{`,
754
- `get<T>(token: unknown, options?: { optional?: boolean; self?: boolean; skipSelf?: boolean; host?: boolean }): T | undefined {`,
755
- ...clauses,
756
- missing,
757
- `},`,
758
- `}`
759
- ].join(`
760
- `);
761
- return `runInInjectionContext(${injector}, () => new ${className}(${args}))`;
762
- }
763
763
  localVar(token, kind) {
764
764
  const locals = this.locals[kind];
765
765
  const existing = locals.get(token);
@@ -1932,6 +1932,7 @@ var HEADER = "// GENERATED BY @supacloud/compiler — do not edit", INTERFACES =
1932
1932
  title?: string;
1933
1933
  data?: Record<string, unknown>;
1934
1934
  aspects?: CompiledAspect[];
1935
+ aspectPipeline?: CompiledAspectPipeline;
1935
1936
  invoker?: (
1936
1937
  controller: unknown,
1937
1938
  request: {
@@ -1955,6 +1956,7 @@ export interface CompiledCommand {
1955
1956
  idempotency: "required" | "none";
1956
1957
  standalone?: boolean;
1957
1958
  aspects?: CompiledAspect[];
1959
+ aspectPipeline?: CompiledAspectPipeline;
1958
1960
  }
1959
1961
 
1960
1962
  export interface CompiledJob {
@@ -1969,6 +1971,7 @@ export interface CompiledJob {
1969
1971
  maxAttempts?: number;
1970
1972
  idempotency?: "required" | "none";
1971
1973
  aspects?: CompiledAspect[];
1974
+ aspectPipeline?: CompiledAspectPipeline;
1972
1975
  }
1973
1976
 
1974
1977
  export interface CompiledAspectContext {
@@ -2016,7 +2019,24 @@ export interface CompiledModule {
2016
2019
  commands: CompiledCommand[];
2017
2020
  jobs: CompiledJob[];
2018
2021
  aspects?: CompiledAspect[];
2019
- }`, TYPE_GUARDS = `function isRecord(value: unknown): value is Record<string, unknown> {
2022
+ aspectPipeline?: CompiledAspectPipeline;
2023
+ }`, TYPE_GUARDS = `type CompiledAspectObserver = (stage: string, run: () => unknown | Promise<unknown>) => unknown | Promise<unknown>;
2024
+ type CompiledAspectPipeline = (context: CompiledAspectContext, next: () => unknown | Promise<unknown>, observe?: CompiledAspectObserver) => unknown | Promise<unknown>;
2025
+
2026
+ function compiledAspectNext(next: () => unknown | Promise<unknown>, state: { active: boolean }): () => Promise<unknown> {
2027
+ let called = false;
2028
+ return async () => {
2029
+ if (!state.active) throw new Error("Aspect continuation is closed");
2030
+ if (called) throw new Error("Aspect continuation called multiple times");
2031
+ called = true;
2032
+ return await next();
2033
+ };
2034
+ }
2035
+ function observeCompiledAspect(observe: CompiledAspectObserver | undefined, stage: string, run: () => unknown | Promise<unknown>): unknown | Promise<unknown> {
2036
+ return observe ? observe(stage, run) : run();
2037
+ }
2038
+
2039
+ function isRecord(value: unknown): value is Record<string, unknown> {
2020
2040
  return typeof value === "object" && value !== null;
2021
2041
  }
2022
2042
 
@@ -2198,7 +2218,7 @@ var init_graphql_options = __esm(() => {
2198
2218
 
2199
2219
  // src/graphql-inputs.ts
2200
2220
  import { resolve as resolve3 } from "node:path";
2201
- import * as ts5 from "@typescript/typescript6";
2221
+ import * as ts7 from "@typescript/typescript6";
2202
2222
  function graphqlInputPaths(options) {
2203
2223
  if (!options.graphql)
2204
2224
  return [];
@@ -2209,7 +2229,7 @@ function graphqlInputPaths(options) {
2209
2229
  }
2210
2230
  const root = resolve3(options.rootDir);
2211
2231
  const schema = resolve3(root, options.graphql.schema);
2212
- const documents = ts5.sys.readDirectory(root, [".graphql", ".gql"], ["**/node_modules/**", "**/.git/**", resolve3(options.outDir)], options.graphql.documents ?? ["**/*.graphql", "**/*.gql"]).map((path) => resolve3(path)).filter((path) => path !== schema);
2232
+ const documents = ts7.sys.readDirectory(root, [".graphql", ".gql"], ["**/node_modules/**", "**/.git/**", resolve3(options.outDir)], options.graphql.documents ?? ["**/*.graphql", "**/*.gql"]).map((path) => resolve3(path)).filter((path) => path !== schema);
2213
2233
  return [schema, ...[...new Set(documents)].sort()];
2214
2234
  }
2215
2235
  var init_graphql_inputs = __esm(() => {
@@ -2217,7 +2237,7 @@ var init_graphql_inputs = __esm(() => {
2217
2237
  });
2218
2238
 
2219
2239
  // src/graphql-runtime.ts
2220
- import * as ts6 from "@typescript/typescript6";
2240
+ import * as ts8 from "@typescript/typescript6";
2221
2241
  import { resolve as resolve4 } from "node:path";
2222
2242
  function renderGraphqlValidators(source, operationNames) {
2223
2243
  const fileName = resolve4("/__supacloud_graphql__/contracts.ts");
@@ -2229,18 +2249,18 @@ function renderGraphqlValidators(source, operationNames) {
2229
2249
  noPropertyAccessFromIndexSignature: true,
2230
2250
  noFallthroughCasesInSwitch: true,
2231
2251
  skipLibCheck: false,
2232
- target: ts6.ScriptTarget.ES2022,
2252
+ target: ts8.ScriptTarget.ES2022,
2233
2253
  lib: ["lib.es2022.d.ts"],
2234
2254
  types: [],
2235
2255
  noEmit: true
2236
2256
  };
2237
- const host = ts6.createCompilerHost(options);
2257
+ const host = ts8.createCompilerHost(options);
2238
2258
  const getSourceFile = host.getSourceFile.bind(host);
2239
- host.getSourceFile = (path, languageVersion, onError, shouldCreateNewSourceFile) => path === fileName ? ts6.createSourceFile(path, source, languageVersion, true) : getSourceFile(path, languageVersion, onError, shouldCreateNewSourceFile);
2240
- const program = ts6.createProgram([fileName], options, host);
2241
- const diagnostics = ts6.getPreEmitDiagnostics(program);
2259
+ host.getSourceFile = (path, languageVersion, onError, shouldCreateNewSourceFile) => path === fileName ? ts8.createSourceFile(path, source, languageVersion, true) : getSourceFile(path, languageVersion, onError, shouldCreateNewSourceFile);
2260
+ const program = ts8.createProgram([fileName], options, host);
2261
+ const diagnostics = ts8.getPreEmitDiagnostics(program);
2242
2262
  if (diagnostics.length) {
2243
- throw new Error(`Generated GraphQL types cannot be validated: ${diagnostics.map((item) => ts6.flattenDiagnosticMessageText(item.messageText, `
2263
+ throw new Error(`Generated GraphQL types cannot be validated: ${diagnostics.map((item) => ts8.flattenDiagnosticMessageText(item.messageText, `
2244
2264
  `)).join("; ")}`);
2245
2265
  }
2246
2266
  const checker = program.getTypeChecker();
@@ -2270,25 +2290,25 @@ function renderGraphqlValidators(source, operationNames) {
2270
2290
  return name;
2271
2291
  }
2272
2292
  function expression(type) {
2273
- if (type.flags & ts6.TypeFlags.Any)
2293
+ if (type.flags & ts8.TypeFlags.Any)
2274
2294
  return unsupported(type);
2275
- if (type.flags & ts6.TypeFlags.Unknown)
2295
+ if (type.flags & ts8.TypeFlags.Unknown)
2276
2296
  return "true";
2277
- if (type.flags & ts6.TypeFlags.Never)
2297
+ if (type.flags & ts8.TypeFlags.Never)
2278
2298
  return "false";
2279
- if (type.flags & ts6.TypeFlags.Null)
2299
+ if (type.flags & ts8.TypeFlags.Null)
2280
2300
  return "value === null";
2281
- if (type.flags & ts6.TypeFlags.Undefined)
2301
+ if (type.flags & ts8.TypeFlags.Undefined)
2282
2302
  return "value === undefined";
2283
2303
  if (type.isStringLiteral() || type.isNumberLiteral())
2284
2304
  return `value === ${JSON.stringify(type.value)}`;
2285
- if (type.flags & ts6.TypeFlags.BooleanLiteral)
2305
+ if (type.flags & ts8.TypeFlags.BooleanLiteral)
2286
2306
  return `value === ${checker.typeToString(type)}`;
2287
- if (type.flags & ts6.TypeFlags.String)
2307
+ if (type.flags & ts8.TypeFlags.String)
2288
2308
  return 'typeof value === "string"';
2289
- if (type.flags & ts6.TypeFlags.Number)
2309
+ if (type.flags & ts8.TypeFlags.Number)
2290
2310
  return 'typeof value === "number" && Number.isFinite(value)';
2291
- if (type.flags & ts6.TypeFlags.Boolean)
2311
+ if (type.flags & ts8.TypeFlags.Boolean)
2292
2312
  return 'typeof value === "boolean"';
2293
2313
  if (type.isUnion())
2294
2314
  return type.types.map((part) => `${reference(part)}(value)`).join(" || ");
@@ -2297,16 +2317,16 @@ function renderGraphqlValidators(source, operationNames) {
2297
2317
  if (checker.isTupleType(type))
2298
2318
  return unsupported(type);
2299
2319
  if (checker.isArrayType(type)) {
2300
- const item = checker.getIndexTypeOfType(type, ts6.IndexKind.Number);
2320
+ const item = checker.getIndexTypeOfType(type, ts8.IndexKind.Number);
2301
2321
  if (!item)
2302
2322
  return unsupported(type);
2303
2323
  return `isGraphqlArray(value) && Array.from(value).every(${reference(item)})`;
2304
2324
  }
2305
- if (type.flags & ts6.TypeFlags.Object) {
2325
+ if (type.flags & ts8.TypeFlags.Object) {
2306
2326
  if (type.getCallSignatures().length || type.getConstructSignatures().length)
2307
2327
  return unsupported(type);
2308
2328
  const indexes = checker.getIndexInfosOfType(type);
2309
- if (indexes.some((index) => !(index.keyType.flags & ts6.TypeFlags.String)))
2329
+ if (indexes.some((index) => !(index.keyType.flags & ts8.TypeFlags.String)))
2310
2330
  return unsupported(type);
2311
2331
  const properties = checker.getPropertiesOfType(type).map((property) => {
2312
2332
  const declaration = property.valueDeclaration ?? property.declarations?.[0];
@@ -2315,7 +2335,7 @@ function renderGraphqlValidators(source, operationNames) {
2315
2335
  const check = reference(checker.getTypeOfSymbolAtLocation(property, declaration));
2316
2336
  const key = JSON.stringify(property.name);
2317
2337
  const present = `Object.prototype.hasOwnProperty.call(value, ${key})`;
2318
- return property.flags & ts6.SymbolFlags.Optional ? `(!${present} || ${check}(value[${key}]))` : `(${present} && ${check}(value[${key}]))`;
2338
+ return property.flags & ts8.SymbolFlags.Optional ? `(!${present} || ${check}(value[${key}]))` : `(${present} && ${check}(value[${key}]))`;
2319
2339
  });
2320
2340
  const indexedValues = indexes.map((index) => `Object.values(value).every(${reference(index.type)})`);
2321
2341
  return ["isGraphqlRecord(value)", ...properties, ...indexedValues].join(" && ");
@@ -2642,10 +2662,155 @@ var init_graphql_schema = __esm(() => {
2642
2662
  init_graphql_options();
2643
2663
  });
2644
2664
 
2665
+ // src/database-contracts.ts
2666
+ import { createHash as createHash10 } from "node:crypto";
2667
+ import { mkdir as mkdir6, readFile as readFile12 } from "node:fs/promises";
2668
+ import { dirname as dirname11, relative as relative12, resolve as resolve16 } from "node:path";
2669
+ import * as ts13 from "@typescript/typescript6";
2670
+ function hash2(value) {
2671
+ return createHash10("sha256").update(value).digest("hex");
2672
+ }
2673
+ function importPath(out, path) {
2674
+ const value = relative12(out, path).replaceAll("\\", "/").replace(/\.(?:d\.)?[cm]?ts$/, "");
2675
+ return value.startsWith(".") ? value : `./${value}`;
2676
+ }
2677
+ function parseDatabaseContractsOptions(value, directory) {
2678
+ if (!value || typeof value !== "object" || Array.isArray(value))
2679
+ throw new TypeError("Expected database contracts configuration");
2680
+ const allowed = ["rootDir", "outDir", "postgrestTypes", "drizzleSchema", "role", "graphql", "migrations"];
2681
+ if (Object.keys(value).some((name) => !allowed.includes(name)))
2682
+ throw new TypeError("Unknown database contracts option");
2683
+ const field = (name) => {
2684
+ const result = Reflect.get(value, name);
2685
+ if (typeof result !== "string" || !result.trim())
2686
+ throw new TypeError(`Missing database contracts ${name}`);
2687
+ return result;
2688
+ };
2689
+ const graphql = Reflect.get(value, "graphql");
2690
+ assertGraphqlOptions(graphql);
2691
+ const migrations = Reflect.get(value, "migrations");
2692
+ if (!Array.isArray(migrations) || !migrations.every((entry) => typeof entry === "string" && entry.endsWith(".sql"))) {
2693
+ throw new TypeError("migrations must be an ordered list of SQL files");
2694
+ }
2695
+ return {
2696
+ rootDir: resolve16(directory, field("rootDir")),
2697
+ outDir: resolve16(directory, field("outDir")),
2698
+ postgrestTypes: resolve16(directory, field("postgrestTypes")),
2699
+ drizzleSchema: resolve16(directory, field("drizzleSchema")),
2700
+ role: field("role"),
2701
+ graphql: { ...graphql, schema: resolve16(directory, graphql.schema) },
2702
+ migrations: migrations.map((file) => resolve16(directory, file))
2703
+ };
2704
+ }
2705
+ async function generateDatabaseContracts(options, check = false) {
2706
+ const rootDir = resolve16(options.rootDir), outDir = resolve16(options.outDir);
2707
+ const postgrestTypes = resolve16(rootDir, options.postgrestTypes), drizzleSchema = resolve16(rootDir, options.drizzleSchema);
2708
+ const snapshot = await readFile12(postgrestTypes, "utf8");
2709
+ const syntax = ts13.createSourceFile(postgrestTypes, snapshot, ts13.ScriptTarget.Latest, true);
2710
+ 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));
2711
+ if (!database)
2712
+ throw new Error("PostgREST snapshot must export Database from the official type generator");
2713
+ const program = ts13.createProgram([postgrestTypes], {
2714
+ strict: true,
2715
+ noEmit: true,
2716
+ skipLibCheck: true,
2717
+ types: [],
2718
+ target: ts13.ScriptTarget.ES2022,
2719
+ module: ts13.ModuleKind.ESNext,
2720
+ moduleResolution: ts13.ModuleResolutionKind.Bundler
2721
+ });
2722
+ if (ts13.getPreEmitDiagnostics(program).length)
2723
+ throw new Error("PostgREST snapshot has TypeScript errors");
2724
+ const artifacts = await renderGraphql({
2725
+ rootDir,
2726
+ outDir,
2727
+ graphql: options.graphql
2728
+ });
2729
+ if (artifacts.diagnostics.some((item) => item.severity === "error")) {
2730
+ throw new Error(artifacts.diagnostics.map((item) => item.message).join(`
2731
+ `));
2732
+ }
2733
+ const inputs = {};
2734
+ const addInput = async (path) => {
2735
+ const absolute = resolve16(rootDir, path);
2736
+ inputs[relative12(rootDir, absolute).replaceAll("\\", "/")] = hash2(await readFile12(absolute, "utf8"));
2737
+ };
2738
+ await addInput(postgrestTypes);
2739
+ await addInput(drizzleSchema);
2740
+ const drizzleProgram = ts13.createProgram([drizzleSchema], {
2741
+ noEmit: true,
2742
+ moduleResolution: ts13.ModuleResolutionKind.Bundler,
2743
+ module: ts13.ModuleKind.ESNext,
2744
+ target: ts13.ScriptTarget.ES2022,
2745
+ types: [],
2746
+ skipLibCheck: true
2747
+ });
2748
+ for (const source of drizzleProgram.getSourceFiles()) {
2749
+ if (!source.isDeclarationFile && !source.fileName.includes("/node_modules/"))
2750
+ await addInput(source.fileName);
2751
+ }
2752
+ await addInput(resolve16(rootDir, options.graphql.schema));
2753
+ if (new Set(options.migrations.map((path) => resolve16(rootDir, path))).size !== options.migrations.length) {
2754
+ throw new Error("Duplicate migration in database contracts configuration");
2755
+ }
2756
+ for (const path of options.migrations)
2757
+ await addInput(path);
2758
+ const files = {
2759
+ ...artifacts.files,
2760
+ "database.ts": [
2761
+ "// GENERATED BY @supacloud/compiler database-contracts. Do not edit.",
2762
+ `export type { Database } from ${JSON.stringify(importPath(outDir, postgrestTypes))};`,
2763
+ 'export type { QueryData, QueryResult, QueryError } from "@supabase/supabase-js";',
2764
+ `export type DrizzleSchema = typeof import(${JSON.stringify(importPath(outDir, drizzleSchema))});`,
2765
+ 'export * from "./graphql";',
2766
+ ""
2767
+ ].join(`
2768
+ `)
2769
+ };
2770
+ const manifest = {
2771
+ version: 1,
2772
+ role: options.role,
2773
+ inputs: Object.fromEntries(Object.entries(inputs).sort(([a], [b]) => a.localeCompare(b))),
2774
+ migrationOrder: options.migrations.map((path) => relative12(rootDir, resolve16(rootDir, path)).replaceAll("\\", "/")),
2775
+ outputs: Object.fromEntries(Object.entries(files).sort(([a], [b]) => a.localeCompare(b)).map(([file, text]) => [file, hash2(text)]))
2776
+ };
2777
+ files["database.manifest.json"] = JSON.stringify(manifest, null, 2) + `
2778
+ `;
2779
+ const mismatches = [];
2780
+ for (const [file, content] of Object.entries(files)) {
2781
+ const path = resolve16(outDir, file);
2782
+ let current;
2783
+ try {
2784
+ current = await readFile12(path, "utf8");
2785
+ } catch (error) {
2786
+ if (!(error instanceof Error && ("code" in error) && error.code === "ENOENT"))
2787
+ throw error;
2788
+ }
2789
+ if (current !== content)
2790
+ mismatches.push(file);
2791
+ }
2792
+ if (!check) {
2793
+ await mkdir6(outDir, { recursive: true });
2794
+ for (const [file, content] of Object.entries(files))
2795
+ await writeFileIfChanged(resolve16(outDir, file), content);
2796
+ }
2797
+ return { upToDate: mismatches.length === 0, mismatches, written: check ? [] : mismatches, manifest };
2798
+ }
2799
+ async function runDatabaseContractsFile(path, check = false) {
2800
+ const absolute = resolve16(path);
2801
+ const value = JSON.parse(await readFile12(absolute, "utf8"));
2802
+ return generateDatabaseContracts(parseDatabaseContractsOptions(value, dirname11(absolute)), check);
2803
+ }
2804
+ var init_database_contracts = __esm(() => {
2805
+ init_graphql();
2806
+ init_generate();
2807
+ init_graphql_options();
2808
+ });
2809
+
2645
2810
  // src/analyze.ts
2646
2811
  import { createHash as createHash3 } from "node:crypto";
2647
2812
  import { relative as relative2, resolve as resolvePath, sep as sep2 } from "node:path";
2648
- import * as ts3 from "@typescript/typescript6";
2813
+ import * as ts4 from "@typescript/typescript6";
2649
2814
 
2650
2815
  // src/program.ts
2651
2816
  import { createHash as createHash2 } from "node:crypto";
@@ -3295,6 +3460,7 @@ var COMPILER_DIAGNOSTIC_CODES = {
3295
3460
  "missing-token-factory": { code: "SC2009", docsUrl: "https://supacloud.dev/errors/SC2009" },
3296
3461
  "provider-type-mismatch": { code: "SC2010", docsUrl: "https://supacloud.dev/errors/SC2010" },
3297
3462
  "unsupported-provider-helper": { code: "SC2011", docsUrl: "https://supacloud.dev/errors/SC2011" },
3463
+ "runtime-injection-disallowed": { code: "SC2012", docsUrl: "https://supacloud.dev/errors/SC2012" },
3298
3464
  "command-missing-permission": { code: "SC4001", docsUrl: "https://supacloud.dev/errors/SC4001" },
3299
3465
  "duplicate-command": { code: "SC4002", docsUrl: "https://supacloud.dev/errors/SC4002" },
3300
3466
  "route-command-unresolved": { code: "SC4003", docsUrl: "https://supacloud.dev/errors/SC4003" },
@@ -3341,6 +3507,20 @@ var COMPILER_DIAGNOSTIC_CODES = {
3341
3507
  function validateGraph(graph, options = false) {
3342
3508
  const strict = typeof options === "boolean" ? options : options.strict ?? false;
3343
3509
  const diagnostics = [];
3510
+ for (const module of graph.modules) {
3511
+ for (const owner of [...module.providers, ...module.controllers]) {
3512
+ if (owner.functionalInjects?.length)
3513
+ diagnostics.push({
3514
+ severity: "error",
3515
+ code: "runtime-injection-disallowed",
3516
+ errorCode: "SC2012",
3517
+ docsUrl: "https://supacloud.dev/errors/SC2012",
3518
+ file: owner.file,
3519
+ message: "Property inject() requires runtime token resolution. Compiled applications require constructor injection.",
3520
+ suggestion: "Move injected fields into typed constructor parameters with @Inject(TOKEN) where needed."
3521
+ });
3522
+ }
3523
+ }
3344
3524
  let moduleBoundaries;
3345
3525
  if (typeof options === "object") {
3346
3526
  try {
@@ -4121,6 +4301,67 @@ function detectOrphanModules(graph) {
4121
4301
  }
4122
4302
  return diagnostics;
4123
4303
  }
4304
+ // src/static-di.ts
4305
+ import * as ts3 from "@typescript/typescript6";
4306
+ var runtimeApis = new Set([
4307
+ "inject",
4308
+ "createEnvironmentInjector",
4309
+ "runInInjectionContext",
4310
+ "EnvironmentInjector",
4311
+ "bootstrapBun",
4312
+ "runInScope",
4313
+ "runInRequestContext",
4314
+ "runInJobContext",
4315
+ "runInTransactionContext"
4316
+ ]);
4317
+ function scanRuntimeDi(source, file) {
4318
+ const diagnostics = [];
4319
+ const namespaces = new Set;
4320
+ const report = (node) => diagnostics.push({
4321
+ severity: "error",
4322
+ code: "runtime-injection-disallowed",
4323
+ errorCode: "SC2012",
4324
+ docsUrl: "https://supacloud.dev/errors/SC2012",
4325
+ file,
4326
+ line: source.getLineAndCharacterOfPosition(node.getStart()).line + 1,
4327
+ message: "Compiled applications cannot import runtime DI. Use explicit constructors and generated scope factories."
4328
+ });
4329
+ for (const statement of source.statements) {
4330
+ if (!(ts3.isImportDeclaration(statement) || ts3.isExportDeclaration(statement)) || !statement.moduleSpecifier || !ts3.isStringLiteral(statement.moduleSpecifier) || !/^@supacloud\/app(?:\/|$)/.test(statement.moduleSpecifier.text))
4331
+ continue;
4332
+ if (ts3.isImportDeclaration(statement)) {
4333
+ if (statement.importClause?.isTypeOnly)
4334
+ continue;
4335
+ const binding = statement.importClause?.namedBindings;
4336
+ if (binding && ts3.isNamespaceImport(binding))
4337
+ namespaces.add(binding.name.text);
4338
+ if (binding && ts3.isNamedImports(binding))
4339
+ for (const item of binding.elements) {
4340
+ if (!item.isTypeOnly && runtimeApis.has((item.propertyName ?? item.name).text))
4341
+ report(item);
4342
+ }
4343
+ } else if (!statement.isTypeOnly) {
4344
+ if (!statement.exportClause)
4345
+ report(statement);
4346
+ else if (ts3.isNamedExports(statement.exportClause))
4347
+ for (const item of statement.exportClause.elements) {
4348
+ if (!item.isTypeOnly && runtimeApis.has((item.propertyName ?? item.name).text))
4349
+ report(item);
4350
+ }
4351
+ }
4352
+ }
4353
+ const visit = (node) => {
4354
+ if (ts3.isPropertyAccessExpression(node) && ts3.isIdentifier(node.expression) && namespaces.has(node.expression.text) && runtimeApis.has(node.name.text))
4355
+ report(node);
4356
+ if (ts3.isElementAccessExpression(node) && ts3.isIdentifier(node.expression) && namespaces.has(node.expression.text) && (!ts3.isStringLiteral(node.argumentExpression) || runtimeApis.has(node.argumentExpression.text)))
4357
+ report(node);
4358
+ if (ts3.isVariableDeclaration(node) && node.initializer && ts3.isIdentifier(node.initializer) && namespaces.has(node.initializer.text))
4359
+ report(node);
4360
+ ts3.forEachChild(node, visit);
4361
+ };
4362
+ visit(source);
4363
+ return diagnostics;
4364
+ }
4124
4365
 
4125
4366
  // src/analyze.ts
4126
4367
  var DEFAULT_INCLUDE = ["**/*.module.ts", "**/*.ts"];
@@ -4162,26 +4403,26 @@ function lineOf(node) {
4162
4403
  return sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;
4163
4404
  }
4164
4405
  function variableName(decl) {
4165
- return ts3.isIdentifier(decl.name) ? decl.name.text : nodeText(decl.name);
4406
+ return ts4.isIdentifier(decl.name) ? decl.name.text : nodeText(decl.name);
4166
4407
  }
4167
4408
  function propertyName(name) {
4168
- if (ts3.isIdentifier(name) || ts3.isPrivateIdentifier(name))
4409
+ if (ts4.isIdentifier(name) || ts4.isPrivateIdentifier(name))
4169
4410
  return name.text;
4170
- if (ts3.isStringLiteral(name) || ts3.isNumericLiteral(name))
4411
+ if (ts4.isStringLiteral(name) || ts4.isNumericLiteral(name))
4171
4412
  return name.text;
4172
4413
  return nodeText(name);
4173
4414
  }
4174
4415
  function parameterName(param) {
4175
- return ts3.isIdentifier(param.name) ? param.name.text : nodeText(param.name);
4416
+ return ts4.isIdentifier(param.name) ? param.name.text : nodeText(param.name);
4176
4417
  }
4177
4418
  function decoratorsOf(node) {
4178
- return ts3.canHaveDecorators(node) ? ts3.getDecorators(node) ?? [] : [];
4419
+ return ts4.canHaveDecorators(node) ? ts4.getDecorators(node) ?? [] : [];
4179
4420
  }
4180
4421
  function decoratorArguments(dec) {
4181
- return ts3.isCallExpression(dec.expression) ? dec.expression.arguments : [];
4422
+ return ts4.isCallExpression(dec.expression) ? dec.expression.arguments : [];
4182
4423
  }
4183
4424
  function hasMethod(cls, name) {
4184
- return cls.members.some((member) => (ts3.isMethodDeclaration(member) || ts3.isGetAccessorDeclaration(member) || ts3.isSetAccessorDeclaration(member)) && member.name !== undefined && propertyName(member.name) === name);
4425
+ return cls.members.some((member) => (ts4.isMethodDeclaration(member) || ts4.isGetAccessorDeclaration(member) || ts4.isSetAccessorDeclaration(member)) && member.name !== undefined && propertyName(member.name) === name);
4185
4426
  }
4186
4427
  function hasDestroyHook(cls) {
4187
4428
  return hasMethod(cls, "onDestroy") || hasMethod(cls, "ngOnDestroy");
@@ -4191,7 +4432,7 @@ function descendantsOfKind(root, predicate) {
4191
4432
  const visit = (node) => {
4192
4433
  if (predicate(node))
4193
4434
  result.push(node);
4194
- ts3.forEachChild(node, visit);
4435
+ ts4.forEachChild(node, visit);
4195
4436
  };
4196
4437
  visit(root);
4197
4438
  return result;
@@ -4200,7 +4441,7 @@ async function analyzeProject(rootDir, include, cache, changedPaths) {
4200
4441
  const session = cache?.programSession ?? createIncrementalProgramSession(rootDir);
4201
4442
  if (cache)
4202
4443
  cache.programSession = session;
4203
- const rootNames = ts3.sys.readDirectory(rootDir, [".ts", ".tsx"], ["node_modules", "dist"], include ?? DEFAULT_INCLUDE);
4444
+ const rootNames = ts4.sys.readDirectory(rootDir, [".ts", ".tsx"], ["node_modules", "dist"], include ?? DEFAULT_INCLUDE);
4204
4445
  const update = session.update(rootNames, changedPaths);
4205
4446
  const program = update.program;
4206
4447
  const checker = program.getTypeChecker();
@@ -4224,13 +4465,16 @@ async function analyzeProject(rootDir, include, cache, changedPaths) {
4224
4465
  nativeTraitFiles.set(trait.file, kinds);
4225
4466
  }
4226
4467
  for (const sf of sourceFiles) {
4468
+ if (!/\.(?:test|spec)\.[cm]?tsx?$/.test(sf.fileName)) {
4469
+ ctx.diagnostics.push(...scanRuntimeDi(sf, sourcePath(rootDir, sf.fileName)));
4470
+ }
4227
4471
  indexFile(sf, ctx);
4228
4472
  }
4229
4473
  const candidates = [];
4230
4474
  for (const sf of sourceFiles) {
4231
4475
  const traits = nativeTraitFiles.get(sf.fileName);
4232
4476
  if (!cache || traits?.has("module")) {
4233
- for (const cls of sf.statements.filter(ts3.isClassDeclaration)) {
4477
+ for (const cls of sf.statements.filter(ts4.isClassDeclaration)) {
4234
4478
  const moduleDec = findDecorator(cls, "Module");
4235
4479
  if (!moduleDec)
4236
4480
  continue;
@@ -4247,14 +4491,14 @@ async function analyzeProject(rootDir, include, cache, changedPaths) {
4247
4491
  }
4248
4492
  }
4249
4493
  if (!cache || traits?.has("defineModule") || traits?.has("defineFeatureSlice")) {
4250
- for (const call of descendantsOfKind(sf, ts3.isCallExpression)) {
4494
+ for (const call of descendantsOfKind(sf, ts4.isCallExpression)) {
4251
4495
  if (!["defineModule", "defineFeatureSlice"].includes(nodeText(call.expression)))
4252
4496
  continue;
4253
4497
  const parent = call.parent;
4254
- if (!parent || !ts3.isVariableDeclaration(parent))
4498
+ if (!parent || !ts4.isVariableDeclaration(parent))
4255
4499
  continue;
4256
4500
  const arg = call.arguments[0];
4257
- if (!arg || !ts3.isObjectLiteralExpression(arg))
4501
+ if (!arg || !ts4.isObjectLiteralExpression(arg))
4258
4502
  continue;
4259
4503
  candidates.push({
4260
4504
  node: parent,
@@ -4398,7 +4642,7 @@ async function analyzeProject(rootDir, include, cache, changedPaths) {
4398
4642
  const controllerDec = findDecorator(classInfo.decl, "Controller");
4399
4643
  if (controllerDec) {
4400
4644
  const arg = decoratorArguments(controllerDec)[0];
4401
- const isStandalone = arg && ts3.isObjectLiteralExpression(arg) && booleanProp(arg, "standalone");
4645
+ const isStandalone = arg && ts4.isObjectLiteralExpression(arg) && booleanProp(arg, "standalone");
4402
4646
  if (isStandalone) {
4403
4647
  const ctrl = parseController(classInfo.decl, ctx);
4404
4648
  if (ctrl)
@@ -4523,16 +4767,16 @@ function collectModuleSourceClosure(module, ctx) {
4523
4767
  ownedFiles.add(relativeFile);
4524
4768
  for (const statement of sourceFile.statements) {
4525
4769
  let moduleName;
4526
- if (ts3.isImportDeclaration(statement) && ts3.isStringLiteral(statement.moduleSpecifier)) {
4770
+ if (ts4.isImportDeclaration(statement) && ts4.isStringLiteral(statement.moduleSpecifier)) {
4527
4771
  moduleName = statement.moduleSpecifier.text;
4528
- } else if (ts3.isExportDeclaration(statement) && statement.moduleSpecifier && ts3.isStringLiteral(statement.moduleSpecifier)) {
4772
+ } else if (ts4.isExportDeclaration(statement) && statement.moduleSpecifier && ts4.isStringLiteral(statement.moduleSpecifier)) {
4529
4773
  moduleName = statement.moduleSpecifier.text;
4530
- } else if (ts3.isImportEqualsDeclaration(statement) && ts3.isExternalModuleReference(statement.moduleReference) && ts3.isStringLiteral(statement.moduleReference.expression)) {
4774
+ } else if (ts4.isImportEqualsDeclaration(statement) && ts4.isExternalModuleReference(statement.moduleReference) && ts4.isStringLiteral(statement.moduleReference.expression)) {
4531
4775
  moduleName = statement.moduleReference.expression.text;
4532
4776
  }
4533
4777
  if (!moduleName || moduleName.startsWith("node:"))
4534
4778
  continue;
4535
- const resolved = ts3.resolveModuleName(moduleName, sourceFile.fileName, ctx.program.getCompilerOptions(), ts3.sys).resolvedModule?.resolvedFileName;
4779
+ const resolved = ts4.resolveModuleName(moduleName, sourceFile.fileName, ctx.program.getCompilerOptions(), ts4.sys).resolvedModule?.resolvedFileName;
4536
4780
  if (resolved && isProjectSourcePath(resolved, ctx.rootDir) && !enqueued.has(resolved)) {
4537
4781
  enqueued.add(resolved);
4538
4782
  queue.push(resolved);
@@ -4554,15 +4798,15 @@ function isProjectSourceFile(sourceFile, rootDir) {
4554
4798
  return isProjectSourcePath(sourceFile.fileName, rootDir) && /\.(tsx?|mts|cts)$/.test(sourceFile.fileName);
4555
4799
  }
4556
4800
  function indexFile(sf, ctx) {
4557
- for (const cls of sf.statements.filter(ts3.isClassDeclaration)) {
4801
+ for (const cls of sf.statements.filter(ts4.isClassDeclaration)) {
4558
4802
  const name = cls.name?.text;
4559
4803
  if (name && !ctx.classesByName.has(name)) {
4560
4804
  ctx.classesByName.set(name, { name, decl: cls, file: sf.fileName });
4561
4805
  }
4562
4806
  }
4563
- for (const statement of sf.statements.filter(ts3.isVariableStatement)) {
4807
+ for (const statement of sf.statements.filter(ts4.isVariableStatement)) {
4564
4808
  for (const decl of statement.declarationList.declarations) {
4565
- if (ts3.isIdentifier(decl.name) && !ctx.variablesByName.has(decl.name.text)) {
4809
+ if (ts4.isIdentifier(decl.name) && !ctx.variablesByName.has(decl.name.text)) {
4566
4810
  ctx.variablesByName.set(decl.name.text, decl);
4567
4811
  }
4568
4812
  const info = parseTokenVariable(decl, sf.fileName);
@@ -4574,16 +4818,16 @@ function indexFile(sf, ctx) {
4574
4818
  }
4575
4819
  function parseTokenVariable(decl, file) {
4576
4820
  const init = decl.initializer;
4577
- if (!init || !ts3.isNewExpression(init))
4821
+ if (!init || !ts4.isNewExpression(init))
4578
4822
  return;
4579
4823
  if (nodeText(init.expression) !== "InjectionToken")
4580
4824
  return;
4581
4825
  const [nameArg, optionsArg] = init.arguments ?? [];
4582
4826
  const info = { name: variableName(decl), file, line: lineOf(decl) };
4583
- if (nameArg && ts3.isStringLiteral(nameArg)) {
4827
+ if (nameArg && ts4.isStringLiteral(nameArg)) {
4584
4828
  info.stringName = nameArg.text;
4585
4829
  }
4586
- if (optionsArg && ts3.isObjectLiteralExpression(optionsArg)) {
4830
+ if (optionsArg && ts4.isObjectLiteralExpression(optionsArg)) {
4587
4831
  const scope = stringLiteralProp(optionsArg, "scope");
4588
4832
  if (scope && isScope(scope)) {
4589
4833
  info.scope = scope;
@@ -4603,22 +4847,22 @@ function parseModule(candidate, nameByNode, ctx) {
4603
4847
  const { options, className, file, line } = candidate;
4604
4848
  const name = nameByNode.get(candidate.node) ?? className;
4605
4849
  const featureSpec = parseFeatureSpec(getProp(options, "spec"), ctx);
4606
- const tags = arrayProp(options, "tags").map((el) => ts3.isStringLiteral(el) ? el.text : nodeText(el).replace(/['"]/g, "")).filter(Boolean);
4850
+ const tags = arrayProp(options, "tags").map((el) => ts4.isStringLiteral(el) ? el.text : nodeText(el).replace(/['"]/g, "")).filter(Boolean);
4607
4851
  const aspects = parseAspectRefs(getProp(options, "aspects"), ctx, `module ${name}`);
4608
4852
  const imports = arrayProp(options, "imports").map((el) => {
4609
4853
  const unwrapped = unwrapForwardRef(el);
4610
- const decl = ts3.isIdentifier(unwrapped) ? resolveDeclaration(unwrapped, ctx)[0] : undefined;
4854
+ const decl = ts4.isIdentifier(unwrapped) ? resolveDeclaration(unwrapped, ctx)[0] : undefined;
4611
4855
  if (decl) {
4612
4856
  const known = nameByNode.get(decl);
4613
4857
  if (known)
4614
4858
  return known;
4615
- if (ts3.isClassDeclaration(decl)) {
4859
+ if (ts4.isClassDeclaration(decl)) {
4616
4860
  const dec = findDecorator(decl, "Module");
4617
4861
  const decOptions = dec && decoratorObjectArg(dec);
4618
4862
  const decName = decOptions && stringLiteralProp(decOptions, "name");
4619
4863
  return decName ?? decl.name?.text ?? nodeText(el);
4620
4864
  }
4621
- if (ts3.isVariableDeclaration(decl))
4865
+ if (ts4.isVariableDeclaration(decl))
4622
4866
  return variableName(decl);
4623
4867
  }
4624
4868
  return nodeText(el);
@@ -4632,7 +4876,7 @@ function parseModule(candidate, nameByNode, ctx) {
4632
4876
  providers.push(...parsedProviders);
4633
4877
  continue;
4634
4878
  }
4635
- if (ts3.isCallExpression(el)) {
4879
+ if (ts4.isCallExpression(el)) {
4636
4880
  const helper = nodeText(el.expression).split(".").pop() ?? nodeText(el.expression);
4637
4881
  warn(ctx, "unsupported-provider-helper", `无法静态展开 provider helper '${helper}';请改用显式 Provider 或实现编译器支持的 helper`, sourcePath(ctx.rootDir, el.getSourceFile().fileName), lineOf(el));
4638
4882
  continue;
@@ -4642,10 +4886,10 @@ function parseModule(candidate, nameByNode, ctx) {
4642
4886
  providers.push(provider);
4643
4887
  }
4644
4888
  for (const el of arrayProp(options, "jobs")) {
4645
- if (!ts3.isIdentifier(el))
4889
+ if (!ts4.isIdentifier(el))
4646
4890
  continue;
4647
4891
  const decl = resolveDeclaration(el, ctx)[0];
4648
- if (!decl || !ts3.isClassDeclaration(decl))
4892
+ if (!decl || !ts4.isClassDeclaration(decl))
4649
4893
  continue;
4650
4894
  const className = decl.name?.text ?? el.text;
4651
4895
  const registeredProvider = providers.find((provider) => provider.token === className || provider.useClass === className);
@@ -4682,18 +4926,18 @@ function parseModule(candidate, nameByNode, ctx) {
4682
4926
  const handlerClasses = [];
4683
4927
  const seenHandlers = new Set;
4684
4928
  const collectHandler = (expr) => {
4685
- if (!ts3.isIdentifier(expr))
4929
+ if (!ts4.isIdentifier(expr))
4686
4930
  return;
4687
4931
  const decl = resolveDeclaration(expr, ctx)[0];
4688
- if (decl && ts3.isClassDeclaration(decl) && !seenHandlers.has(decl.name?.text ?? "")) {
4932
+ if (decl && ts4.isClassDeclaration(decl) && !seenHandlers.has(decl.name?.text ?? "")) {
4689
4933
  seenHandlers.add(decl.name?.text ?? "");
4690
4934
  handlerClasses.push(decl);
4691
4935
  }
4692
4936
  };
4693
4937
  for (const el of arrayProp(options, "providers")) {
4694
- if (ts3.isIdentifier(el))
4938
+ if (ts4.isIdentifier(el))
4695
4939
  collectHandler(el);
4696
- if (ts3.isObjectLiteralExpression(el)) {
4940
+ if (ts4.isObjectLiteralExpression(el)) {
4697
4941
  const useClass = getProp(el, "useClass");
4698
4942
  if (useClass)
4699
4943
  collectHandler(useClass);
@@ -4793,17 +5037,17 @@ function parseFeatureSpec(input, ctx, seen = new Set) {
4793
5037
  if (seen.has(input))
4794
5038
  return;
4795
5039
  seen.add(input);
4796
- if (ts3.isIdentifier(input)) {
4797
- const local = input.getSourceFile().statements.flatMap((statement) => ts3.isVariableStatement(statement) ? [...statement.declarationList.declarations] : []);
5040
+ if (ts4.isIdentifier(input)) {
5041
+ const local = input.getSourceFile().statements.flatMap((statement) => ts4.isVariableStatement(statement) ? [...statement.declarationList.declarations] : []);
4798
5042
  const resolved = resolveDeclaration(input, ctx)[0];
4799
- const decl = (resolved && ts3.isVariableDeclaration(resolved) ? resolved : undefined) ?? ctx.variablesByName.get(input.text) ?? local.find((candidate) => ts3.isIdentifier(candidate.name) && candidate.name.text === input.text) ?? descendantsOfKind(input.getSourceFile(), ts3.isVariableDeclaration).find((candidate) => ts3.isIdentifier(candidate.name) && candidate.name.text === input.text);
4800
- if (decl && ts3.isVariableDeclaration(decl))
5043
+ 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);
5044
+ if (decl && ts4.isVariableDeclaration(decl))
4801
5045
  return parseFeatureSpec(decl.initializer, ctx, seen);
4802
5046
  }
4803
- if (ts3.isCallExpression(input) && nodeText(input.expression) === "defineFeatureSpec") {
5047
+ if (ts4.isCallExpression(input) && nodeText(input.expression) === "defineFeatureSpec") {
4804
5048
  return parseFeatureSpec(input.arguments[0], ctx, seen);
4805
5049
  }
4806
- if (ts3.isAsExpression(input) || ts3.isSatisfiesExpression(input) || ts3.isParenthesizedExpression(input)) {
5050
+ if (ts4.isAsExpression(input) || ts4.isSatisfiesExpression(input) || ts4.isParenthesizedExpression(input)) {
4807
5051
  return parseFeatureSpec(input.expression, ctx, seen);
4808
5052
  }
4809
5053
  const invalid = () => {
@@ -4816,28 +5060,28 @@ function parseFeatureSpec(input, ctx, seen = new Set) {
4816
5060
  });
4817
5061
  return;
4818
5062
  };
4819
- if (!ts3.isObjectLiteralExpression(input))
5063
+ if (!ts4.isObjectLiteralExpression(input))
4820
5064
  return invalid();
4821
5065
  const name = stringLiteralProp(input, "name");
4822
5066
  const statesExpr = getProp(input, "states");
4823
5067
  const transitionObject = getProp(input, "transitions");
4824
- if (!name || !statesExpr || !ts3.isArrayLiteralExpression(statesExpr) || statesExpr.elements.some((state) => !ts3.isStringLiteral(state)) || !transitionObject || !ts3.isObjectLiteralExpression(transitionObject) || input.properties.some((property) => !ts3.isPropertyAssignment(property))) {
5068
+ if (!name || !statesExpr || !ts4.isArrayLiteralExpression(statesExpr) || statesExpr.elements.some((state) => !ts4.isStringLiteral(state)) || !transitionObject || !ts4.isObjectLiteralExpression(transitionObject) || input.properties.some((property) => !ts4.isPropertyAssignment(property))) {
4825
5069
  return invalid();
4826
5070
  }
4827
5071
  const states = [];
4828
5072
  for (const state of statesExpr.elements) {
4829
- if (!ts3.isStringLiteral(state))
5073
+ if (!ts4.isStringLiteral(state))
4830
5074
  return invalid();
4831
5075
  states.push(state.text);
4832
5076
  }
4833
5077
  const transitions = [];
4834
5078
  for (const property of transitionObject.properties) {
4835
- if (!ts3.isPropertyAssignment(property) || ts3.isComputedPropertyName(property.name) || !ts3.isObjectLiteralExpression(property.initializer))
5079
+ if (!ts4.isPropertyAssignment(property) || ts4.isComputedPropertyName(property.name) || !ts4.isObjectLiteralExpression(property.initializer))
4836
5080
  return invalid();
4837
5081
  const options = property.initializer;
4838
5082
  const from = stringLiteralProp(options, "from");
4839
5083
  const to = stringLiteralProp(options, "to");
4840
- if (!from || !to || options.properties.some((prop) => !ts3.isPropertyAssignment(prop)) || ["permission", "command", "route", "audit"].some((key) => getProp(options, key) && !stringLiteralProp(options, key)) || ["transaction", "idempotency"].some((key) => getProp(options, key) && !commandModeProp(options, key))) {
5084
+ if (!from || !to || options.properties.some((prop) => !ts4.isPropertyAssignment(prop)) || ["permission", "command", "route", "audit"].some((key) => getProp(options, key) && !stringLiteralProp(options, key)) || ["transaction", "idempotency"].some((key) => getProp(options, key) && !commandModeProp(options, key))) {
4841
5085
  return invalid();
4842
5086
  }
4843
5087
  const permission = stringLiteralProp(options, "permission");
@@ -4864,21 +5108,21 @@ function resolveStaticObjectLiteral(input, ctx, seen = new Set) {
4864
5108
  if (!input || seen.has(input))
4865
5109
  return;
4866
5110
  seen.add(input);
4867
- if (ts3.isAsExpression(input) || ts3.isSatisfiesExpression(input) || ts3.isParenthesizedExpression(input)) {
5111
+ if (ts4.isAsExpression(input) || ts4.isSatisfiesExpression(input) || ts4.isParenthesizedExpression(input)) {
4868
5112
  return resolveStaticObjectLiteral(input.expression, ctx, seen);
4869
5113
  }
4870
- if (ts3.isIdentifier(input)) {
4871
- const declaration = resolveDeclaration(input, ctx).find(ts3.isVariableDeclaration);
5114
+ if (ts4.isIdentifier(input)) {
5115
+ const declaration = resolveDeclaration(input, ctx).find(ts4.isVariableDeclaration);
4872
5116
  return declaration?.initializer ? resolveStaticObjectLiteral(declaration.initializer, ctx, seen) : undefined;
4873
5117
  }
4874
- if (ts3.isCallExpression(input)) {
5118
+ if (ts4.isCallExpression(input)) {
4875
5119
  const expressionName = nodeText(input.expression);
4876
5120
  if (expressionName === "defineRouteContract" || expressionName.endsWith(".defineRouteContract")) {
4877
5121
  return resolveStaticObjectLiteral(input.arguments[0], ctx, seen);
4878
5122
  }
4879
5123
  return;
4880
5124
  }
4881
- return ts3.isObjectLiteralExpression(input) ? input : undefined;
5125
+ return ts4.isObjectLiteralExpression(input) ? input : undefined;
4882
5126
  }
4883
5127
  function commandModeProp(object, name) {
4884
5128
  const value = stringLiteralProp(object, name);
@@ -4913,9 +5157,9 @@ function parseProvider(el, exportsSet, ctx) {
4913
5157
  const file = sourcePath(ctx.rootDir, el.getSourceFile().fileName);
4914
5158
  const line = lineOf(el);
4915
5159
  const unwrappedEl = unwrapForwardRef(el);
4916
- if (ts3.isIdentifier(unwrappedEl)) {
5160
+ if (ts4.isIdentifier(unwrappedEl)) {
4917
5161
  const decl = resolveDeclaration(unwrappedEl, ctx)[0];
4918
- const cls = decl && ts3.isClassDeclaration(decl) ? decl : undefined;
5162
+ const cls = decl && ts4.isClassDeclaration(decl) ? decl : undefined;
4919
5163
  const className = cls?.name?.text ?? unwrappedEl.text;
4920
5164
  const { deps, optionalDeps, selfDeps, skipSelfDeps, hostDeps, functionalInjects, missing } = cls ? classDeps(cls, ctx) : { deps: [], optionalDeps: [], selfDeps: [], skipSelfDeps: [], hostDeps: [], functionalInjects: [], missing: false };
4921
5165
  const injectable = cls ? parseInjectableOptions(cls, ctx) : undefined;
@@ -4942,7 +5186,7 @@ function parseProvider(el, exportsSet, ctx) {
4942
5186
  ...cls ? { importPath: modulePath(ctx.rootDir, cls.getSourceFile().fileName) } : {}
4943
5187
  };
4944
5188
  }
4945
- if (!ts3.isObjectLiteralExpression(el))
5189
+ if (!ts4.isObjectLiteralExpression(el))
4946
5190
  return;
4947
5191
  const provideExpr = getProp(el, "provide");
4948
5192
  if (!provideExpr)
@@ -4957,8 +5201,8 @@ function parseProvider(el, exportsSet, ctx) {
4957
5201
  const useExistingExpr = getProp(el, "useExisting");
4958
5202
  if (useClassExpr) {
4959
5203
  const unwrappedClass = unwrapForwardRef(useClassExpr);
4960
- const decl = ts3.isIdentifier(unwrappedClass) ? resolveDeclaration(unwrappedClass, ctx)[0] : undefined;
4961
- const cls = decl && ts3.isClassDeclaration(decl) ? decl : undefined;
5204
+ const decl = ts4.isIdentifier(unwrappedClass) ? resolveDeclaration(unwrappedClass, ctx)[0] : undefined;
5205
+ const cls = decl && ts4.isClassDeclaration(decl) ? decl : undefined;
4962
5206
  const useClass = cls?.name?.text ?? nodeText(unwrappedClass);
4963
5207
  let deps = explicitDeps;
4964
5208
  let optionalDeps = [];
@@ -5014,7 +5258,7 @@ function parseProvider(el, exportsSet, ctx) {
5014
5258
  }
5015
5259
  if (useValueExpr) {
5016
5260
  validateProviderCompatibility(provideExpr, useValueExpr, "value", token, ctx, file, line);
5017
- const importPath = ts3.isIdentifier(useValueExpr) ? importPathOf(useValueExpr, ctx) : undefined;
5261
+ const importPath = ts4.isIdentifier(useValueExpr) ? importPathOf(useValueExpr, ctx) : undefined;
5018
5262
  return {
5019
5263
  token,
5020
5264
  tokenKind,
@@ -5030,12 +5274,12 @@ function parseProvider(el, exportsSet, ctx) {
5030
5274
  };
5031
5275
  }
5032
5276
  if (useFactoryExpr) {
5033
- const factoryName = ts3.isIdentifier(useFactoryExpr) ? (() => {
5277
+ const factoryName = ts4.isIdentifier(useFactoryExpr) ? (() => {
5034
5278
  const decl = resolveDeclaration(useFactoryExpr, ctx)[0];
5035
- return decl && (ts3.isFunctionDeclaration(decl) || ts3.isVariableDeclaration(decl)) ? (ts3.isFunctionDeclaration(decl) ? decl.name?.text : variableName(decl)) ?? useFactoryExpr.text : useFactoryExpr.text;
5279
+ return decl && (ts4.isFunctionDeclaration(decl) || ts4.isVariableDeclaration(decl)) ? (ts4.isFunctionDeclaration(decl) ? decl.name?.text : variableName(decl)) ?? useFactoryExpr.text : useFactoryExpr.text;
5036
5280
  })() : nodeText(useFactoryExpr);
5037
5281
  validateProviderCompatibility(provideExpr, useFactoryExpr, "factory", token, ctx, file, line);
5038
- const importPath = ts3.isIdentifier(useFactoryExpr) ? importPathOf(useFactoryExpr, ctx) : undefined;
5282
+ const importPath = ts4.isIdentifier(useFactoryExpr) ? importPathOf(useFactoryExpr, ctx) : undefined;
5039
5283
  return {
5040
5284
  token,
5041
5285
  tokenKind,
@@ -5071,20 +5315,20 @@ function parseProvider(el, exportsSet, ctx) {
5071
5315
  function expandProviderExpressions(expressions, ctx, seen = new Set) {
5072
5316
  const result = [];
5073
5317
  for (const expression of expressions) {
5074
- if (ts3.isSpreadElement(expression)) {
5318
+ if (ts4.isSpreadElement(expression)) {
5075
5319
  result.push(...expandProviderExpressions([expression.expression], ctx, seen));
5076
5320
  continue;
5077
5321
  }
5078
- if (ts3.isIdentifier(expression)) {
5322
+ if (ts4.isIdentifier(expression)) {
5079
5323
  const declaration = resolveDeclaration(expression, ctx)[0];
5080
- if (declaration && ts3.isVariableDeclaration(declaration) && declaration.initializer) {
5324
+ if (declaration && ts4.isVariableDeclaration(declaration) && declaration.initializer) {
5081
5325
  const key = `${declaration.getSourceFile().fileName}:${declaration.pos}`;
5082
5326
  if (seen.has(key))
5083
5327
  continue;
5084
5328
  const initializer = declaration.initializer;
5085
- if (ts3.isCallExpression(initializer) && isProviderHelper(initializer, "makeEnvironmentProviders")) {
5329
+ if (ts4.isCallExpression(initializer) && isProviderHelper(initializer, "makeEnvironmentProviders")) {
5086
5330
  const nested = initializer.arguments[0];
5087
- if (nested && ts3.isArrayLiteralExpression(nested)) {
5331
+ if (nested && ts4.isArrayLiteralExpression(nested)) {
5088
5332
  seen.add(key);
5089
5333
  result.push(...expandProviderExpressions([...nested.elements], ctx, seen));
5090
5334
  seen.delete(key);
@@ -5093,9 +5337,9 @@ function expandProviderExpressions(expressions, ctx, seen = new Set) {
5093
5337
  }
5094
5338
  }
5095
5339
  }
5096
- if (ts3.isCallExpression(expression) && isProviderHelper(expression, "makeEnvironmentProviders")) {
5340
+ if (ts4.isCallExpression(expression) && isProviderHelper(expression, "makeEnvironmentProviders")) {
5097
5341
  const nested = expression.arguments[0];
5098
- if (nested && ts3.isArrayLiteralExpression(nested)) {
5342
+ if (nested && ts4.isArrayLiteralExpression(nested)) {
5099
5343
  result.push(...expandProviderExpressions([...nested.elements], ctx, seen));
5100
5344
  continue;
5101
5345
  }
@@ -5108,7 +5352,7 @@ function isProviderHelper(expression, name) {
5108
5352
  return nodeText(expression.expression).split(".").pop() === name;
5109
5353
  }
5110
5354
  function parseFunctionalProvider(expression, exportsSet, ctx) {
5111
- if (!ts3.isCallExpression(expression))
5355
+ if (!ts4.isCallExpression(expression))
5112
5356
  return;
5113
5357
  const helper = nodeText(expression.expression).split(".").pop();
5114
5358
  const args = expression.arguments;
@@ -5121,7 +5365,7 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
5121
5365
  return [];
5122
5366
  const { name: token, kind: tokenKind } = tokenNameOf(tokenExpr, ctx);
5123
5367
  validateProviderCompatibility(tokenExpr, valueExpr, "value", token, ctx, file, line);
5124
- const importPath = ts3.isIdentifier(valueExpr) ? importPathOf(valueExpr, ctx) : undefined;
5368
+ const importPath = ts4.isIdentifier(valueExpr) ? importPathOf(valueExpr, ctx) : undefined;
5125
5369
  return [{
5126
5370
  token,
5127
5371
  tokenKind,
@@ -5140,7 +5384,7 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
5140
5384
  if (!initializer)
5141
5385
  return [];
5142
5386
  const token = helper === "provideAppInitializer" ? "APP_INITIALIZER" : "ENVIRONMENT_INITIALIZER";
5143
- const importPath = ts3.isIdentifier(initializer) ? importPathOf(initializer, ctx) : undefined;
5387
+ const importPath = ts4.isIdentifier(initializer) ? importPathOf(initializer, ctx) : undefined;
5144
5388
  return [{
5145
5389
  token,
5146
5390
  tokenKind: "injection-token",
@@ -5159,7 +5403,7 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
5159
5403
  const providers = [];
5160
5404
  const routes = args[0];
5161
5405
  if (routes) {
5162
- const importPath = ts3.isIdentifier(routes) ? importPathOf(routes, ctx) : undefined;
5406
+ const importPath = ts4.isIdentifier(routes) ? importPathOf(routes, ctx) : undefined;
5163
5407
  providers.push({
5164
5408
  token: "ROUTE_CONFIG",
5165
5409
  tokenKind: "injection-token",
@@ -5174,7 +5418,7 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
5174
5418
  });
5175
5419
  }
5176
5420
  for (const feature of args.slice(1)) {
5177
- if (!ts3.isCallExpression(feature))
5421
+ if (!ts4.isCallExpression(feature))
5178
5422
  continue;
5179
5423
  const featureName = nodeText(feature.expression).split(".").pop();
5180
5424
  if (featureName === "withRouterConfig" && feature.arguments[0]) {
@@ -5191,8 +5435,8 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
5191
5435
  });
5192
5436
  } else if (featureName === "withTitleStrategy" && feature.arguments[0]) {
5193
5437
  const strategy = feature.arguments[0];
5194
- const isClass = ts3.isIdentifier(strategy) && Boolean(resolveDeclaration(strategy, ctx).find((declaration) => ts3.isClassDeclaration(declaration)));
5195
- const importPath = ts3.isIdentifier(strategy) ? importPathOf(strategy, ctx) : undefined;
5438
+ const isClass = ts4.isIdentifier(strategy) && Boolean(resolveDeclaration(strategy, ctx).find((declaration) => ts4.isClassDeclaration(declaration)));
5439
+ const importPath = ts4.isIdentifier(strategy) ? importPathOf(strategy, ctx) : undefined;
5196
5440
  providers.push({
5197
5441
  token: "TITLE_STRATEGY",
5198
5442
  tokenKind: "injection-token",
@@ -5224,14 +5468,14 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
5224
5468
  importModule: "@supacloud/app"
5225
5469
  }];
5226
5470
  for (const feature of args) {
5227
- if (!ts3.isCallExpression(feature))
5471
+ if (!ts4.isCallExpression(feature))
5228
5472
  continue;
5229
5473
  const featureName = nodeText(feature.expression).split(".").pop();
5230
5474
  if (featureName === "withInterceptors") {
5231
5475
  for (const interceptorArg of feature.arguments) {
5232
- const values = ts3.isArrayLiteralExpression(interceptorArg) ? [...interceptorArg.elements] : [interceptorArg];
5476
+ const values = ts4.isArrayLiteralExpression(interceptorArg) ? [...interceptorArg.elements] : [interceptorArg];
5233
5477
  for (const value of values) {
5234
- const importPath = ts3.isIdentifier(value) ? importPathOf(value, ctx) : undefined;
5478
+ const importPath = ts4.isIdentifier(value) ? importPathOf(value, ctx) : undefined;
5235
5479
  providers.push({
5236
5480
  token: "HTTP_INTERCEPTORS",
5237
5481
  tokenKind: "injection-token",
@@ -5278,9 +5522,9 @@ function providerTokenValueType(expr, ctx) {
5278
5522
  const typeArguments = typeArgumentsOf(type, ctx);
5279
5523
  if (typeArguments.length > 0)
5280
5524
  return typeArguments[0];
5281
- if (ts3.isIdentifier(expr)) {
5525
+ if (ts4.isIdentifier(expr)) {
5282
5526
  const declaration = resolveDeclaration(expr, ctx)[0];
5283
- if (declaration && ts3.isClassDeclaration(declaration)) {
5527
+ if (declaration && ts4.isClassDeclaration(declaration)) {
5284
5528
  return declaredClassType(declaration, ctx);
5285
5529
  }
5286
5530
  }
@@ -5288,9 +5532,9 @@ function providerTokenValueType(expr, ctx) {
5288
5532
  }
5289
5533
  function providerImplementationType(expr, kind, ctx) {
5290
5534
  if (kind === "class" || kind === "existing") {
5291
- if (ts3.isIdentifier(expr)) {
5535
+ if (ts4.isIdentifier(expr)) {
5292
5536
  const declaration = resolveDeclaration(expr, ctx)[0];
5293
- if (declaration && ts3.isClassDeclaration(declaration)) {
5537
+ if (declaration && ts4.isClassDeclaration(declaration)) {
5294
5538
  return declaredClassType(declaration, ctx);
5295
5539
  }
5296
5540
  }
@@ -5300,7 +5544,7 @@ function providerImplementationType(expr, kind, ctx) {
5300
5544
  }
5301
5545
  if (kind === "factory") {
5302
5546
  const type = ctx.checker.getTypeAtLocation(expr);
5303
- const signature = ctx.checker.getSignaturesOfType(type, ts3.SignatureKind.Call)[0];
5547
+ const signature = ctx.checker.getSignaturesOfType(type, ts4.SignatureKind.Call)[0];
5304
5548
  return signature?.getReturnType();
5305
5549
  }
5306
5550
  return ctx.checker.getTypeAtLocation(expr);
@@ -5319,16 +5563,16 @@ function isTypeReference(type) {
5319
5563
  return "target" in type;
5320
5564
  }
5321
5565
  function isUnknownOrAny(type) {
5322
- return (type.flags & (ts3.TypeFlags.Any | ts3.TypeFlags.Unknown)) !== 0;
5566
+ return (type.flags & (ts4.TypeFlags.Any | ts4.TypeFlags.Unknown)) !== 0;
5323
5567
  }
5324
5568
  function parseController(input, ctx) {
5325
5569
  let decl;
5326
- if (ts3.isClassDeclaration(input)) {
5570
+ if (ts4.isClassDeclaration(input)) {
5327
5571
  decl = input;
5328
5572
  } else {
5329
5573
  const unwrapped = unwrapForwardRef(input);
5330
- const resolved = ts3.isIdentifier(unwrapped) ? resolveDeclaration(unwrapped, ctx)[0] : undefined;
5331
- if (resolved && ts3.isClassDeclaration(resolved)) {
5574
+ const resolved = ts4.isIdentifier(unwrapped) ? resolveDeclaration(unwrapped, ctx)[0] : undefined;
5575
+ if (resolved && ts4.isClassDeclaration(resolved)) {
5332
5576
  decl = resolved;
5333
5577
  }
5334
5578
  }
@@ -5341,9 +5585,9 @@ function parseController(input, ctx) {
5341
5585
  let standalone;
5342
5586
  const pathArg = decoratorArguments(controllerDec)[0];
5343
5587
  if (pathArg) {
5344
- if (ts3.isStringLiteral(pathArg)) {
5588
+ if (ts4.isStringLiteral(pathArg)) {
5345
5589
  path = pathArg.text;
5346
- } else if (ts3.isObjectLiteralExpression(pathArg)) {
5590
+ } else if (ts4.isObjectLiteralExpression(pathArg)) {
5347
5591
  const p = stringLiteralProp(pathArg, "path");
5348
5592
  if (p)
5349
5593
  path = p;
@@ -5366,7 +5610,7 @@ function parseController(input, ctx) {
5366
5610
  }
5367
5611
  }
5368
5612
  }
5369
- for (const method of decl.members.filter(ts3.isMethodDeclaration)) {
5613
+ for (const method of decl.members.filter(ts4.isMethodDeclaration)) {
5370
5614
  for (const dec of decoratorsOf(method)) {
5371
5615
  const name = decoratorName2(dec);
5372
5616
  const httpMethod = name ? ROUTE_DECORATORS[name] : undefined;
@@ -5374,7 +5618,7 @@ function parseController(input, ctx) {
5374
5618
  continue;
5375
5619
  const args = decoratorArguments(dec);
5376
5620
  const pathArg = args[0];
5377
- const routePath = pathArg && ts3.isStringLiteral(pathArg) ? pathArg.text : "/";
5621
+ const routePath = pathArg && ts4.isStringLiteral(pathArg) ? pathArg.text : "/";
5378
5622
  const route = {
5379
5623
  method: httpMethod,
5380
5624
  path: routePath,
@@ -5445,12 +5689,12 @@ function parseController(input, ctx) {
5445
5689
  } else if (dName === "Headers") {
5446
5690
  hasBindingDecorator = true;
5447
5691
  const argument = dArgs[0];
5448
- const bindingName = argument !== undefined && ts3.isStringLiteral(argument) ? argument.text : undefined;
5692
+ const bindingName = argument !== undefined && ts4.isStringLiteral(argument) ? argument.text : undefined;
5449
5693
  paramNode = { name: pName, kind: "headers", ...bindingName === undefined ? {} : { bindingName } };
5450
5694
  } else if (dName === "Cookie") {
5451
5695
  hasBindingDecorator = true;
5452
5696
  const argument = dArgs[0];
5453
- const bindingName = argument !== undefined && ts3.isStringLiteral(argument) ? argument.text : undefined;
5697
+ const bindingName = argument !== undefined && ts4.isStringLiteral(argument) ? argument.text : undefined;
5454
5698
  paramNode = { name: pName, kind: "cookie", ...bindingName === undefined ? {} : { bindingName } };
5455
5699
  }
5456
5700
  }
@@ -5512,20 +5756,20 @@ function parseController(input, ctx) {
5512
5756
  }
5513
5757
  } else if (dName === "Title") {
5514
5758
  const tArg = mArgs[0];
5515
- if (tArg && ts3.isStringLiteral(tArg)) {
5759
+ if (tArg && ts4.isStringLiteral(tArg)) {
5516
5760
  route.title = tArg.text;
5517
5761
  }
5518
5762
  } else if (dName === "Data") {
5519
5763
  const dArg = mArgs[0];
5520
- if (dArg && ts3.isObjectLiteralExpression(dArg)) {
5764
+ if (dArg && ts4.isObjectLiteralExpression(dArg)) {
5521
5765
  route.data = { ...route.data, ...parseObjectLiteralValues(dArg) };
5522
5766
  }
5523
5767
  } else if (dName === "Resolve") {
5524
5768
  const rArg = mArgs[0];
5525
- if (rArg && ts3.isObjectLiteralExpression(rArg)) {
5769
+ if (rArg && ts4.isObjectLiteralExpression(rArg)) {
5526
5770
  const resolvers = route.resolvers ?? {};
5527
5771
  for (const prop of rArg.properties) {
5528
- if (ts3.isPropertyAssignment(prop)) {
5772
+ if (ts4.isPropertyAssignment(prop)) {
5529
5773
  const rName = propertyName(prop.name);
5530
5774
  const init = prop.initializer;
5531
5775
  if (init)
@@ -5556,7 +5800,7 @@ function parseController(input, ctx) {
5556
5800
  });
5557
5801
  }
5558
5802
  const contract = getProp(optionsObject, "contract");
5559
- if (contract && ts3.isObjectLiteralExpression(contract)) {
5803
+ if (contract && ts4.isObjectLiteralExpression(contract)) {
5560
5804
  route.contract = {};
5561
5805
  for (const field of ["body", "response", "evidence"]) {
5562
5806
  const value = stringLiteralProp(contract, field);
@@ -5574,15 +5818,15 @@ function parseController(input, ctx) {
5574
5818
  }
5575
5819
  for (const field of ["body", "params", "query", "headers", "cookie", "response"]) {
5576
5820
  const schemaExpr = getProp(optionsObject, field);
5577
- if (schemaExpr && ts3.isIdentifier(schemaExpr)) {
5821
+ if (schemaExpr && ts4.isIdentifier(schemaExpr)) {
5578
5822
  route[field] = nodeText(schemaExpr);
5579
5823
  const importPath = importPathOf(schemaExpr, ctx);
5580
5824
  if (importPath)
5581
5825
  schemaImports[schemaExpr.text] = importPath;
5582
5826
  const declaration = resolveDeclaration(schemaExpr, ctx)[0];
5583
5827
  const typeName = ctx.checker.typeToString(ctx.checker.getTypeAtLocation(schemaExpr));
5584
- const initializer = declaration && ts3.isVariableDeclaration(declaration) ? declaration.initializer : undefined;
5585
- const opaque = /\bT(?:Unknown|Any)\b/.test(typeName) || initializer && ts3.isCallExpression(initializer) && ts3.isPropertyAccessExpression(initializer.expression) && ["Unknown", "Any"].includes(initializer.expression.name.text);
5828
+ const initializer = declaration && ts4.isVariableDeclaration(declaration) ? declaration.initializer : undefined;
5829
+ const opaque = /\bT(?:Unknown|Any)\b/.test(typeName) || initializer && ts4.isCallExpression(initializer) && ts4.isPropertyAccessExpression(initializer.expression) && ["Unknown", "Any"].includes(initializer.expression.name.text);
5586
5830
  (route.schemaKinds ??= {})[field] = opaque ? "opaque" : "declared";
5587
5831
  }
5588
5832
  }
@@ -5591,7 +5835,7 @@ function parseController(input, ctx) {
5591
5835
  const responses = {};
5592
5836
  const selectors = new Map;
5593
5837
  for (const property of responsesObject.properties) {
5594
- if (!ts3.isPropertyAssignment(property) || ts3.isComputedPropertyName(property.name))
5838
+ if (!ts4.isPropertyAssignment(property) || ts4.isComputedPropertyName(property.name))
5595
5839
  continue;
5596
5840
  const status = propertyName(property.name);
5597
5841
  if (!isRouteResponseSelector(status)) {
@@ -5623,7 +5867,7 @@ function parseController(input, ctx) {
5623
5867
  }
5624
5868
  selectors.set(canonical, status);
5625
5869
  const schemaExpr = property.initializer;
5626
- if (!ts3.isIdentifier(schemaExpr)) {
5870
+ if (!ts4.isIdentifier(schemaExpr)) {
5627
5871
  ctx.diagnostics.push({
5628
5872
  severity: "error",
5629
5873
  code: "invalid-route-response-map",
@@ -5638,8 +5882,8 @@ function parseController(input, ctx) {
5638
5882
  schemaImports[schemaExpr.text] = importPath;
5639
5883
  const declaration = resolveDeclaration(schemaExpr, ctx)[0];
5640
5884
  const typeName = ctx.checker.typeToString(ctx.checker.getTypeAtLocation(schemaExpr));
5641
- const initializer = declaration && ts3.isVariableDeclaration(declaration) ? declaration.initializer : undefined;
5642
- const opaque = /\bT(?:Unknown|Any)\b/.test(typeName) || initializer && ts3.isCallExpression(initializer) && ts3.isPropertyAccessExpression(initializer.expression) && ["Unknown", "Any"].includes(initializer.expression.name.text);
5885
+ const initializer = declaration && ts4.isVariableDeclaration(declaration) ? declaration.initializer : undefined;
5886
+ const opaque = /\bT(?:Unknown|Any)\b/.test(typeName) || initializer && ts4.isCallExpression(initializer) && ts4.isPropertyAccessExpression(initializer.expression) && ["Unknown", "Any"].includes(initializer.expression.name.text);
5643
5887
  const previousKind = route.schemaKinds?.response;
5644
5888
  (route.schemaKinds ??= {}).response = opaque || previousKind === "opaque" ? "opaque" : "declared";
5645
5889
  }
@@ -5647,18 +5891,18 @@ function parseController(input, ctx) {
5647
5891
  route.responses = responses;
5648
5892
  }
5649
5893
  const commandExpr = getProp(optionsObject, "command");
5650
- if (commandExpr && ts3.isIdentifier(commandExpr)) {
5894
+ if (commandExpr && ts4.isIdentifier(commandExpr)) {
5651
5895
  const commandDecl = resolveDeclaration(commandExpr, ctx)[0];
5652
- route.command = commandDecl && ts3.isClassDeclaration(commandDecl) ? commandDecl.name?.text ?? commandExpr.text : commandExpr.text;
5896
+ route.command = commandDecl && ts4.isClassDeclaration(commandDecl) ? commandDecl.name?.text ?? commandExpr.text : commandExpr.text;
5653
5897
  }
5654
5898
  const guardsExpr = getProp(optionsObject, "guards");
5655
- if (guardsExpr && ts3.isArrayLiteralExpression(guardsExpr)) {
5899
+ if (guardsExpr && ts4.isArrayLiteralExpression(guardsExpr)) {
5656
5900
  for (const el of guardsExpr.elements) {
5657
5901
  routeGuards.push(tokenText(el, ctx));
5658
5902
  }
5659
5903
  }
5660
5904
  const canMatchExpr = getProp(optionsObject, "canMatch");
5661
- if (canMatchExpr && ts3.isArrayLiteralExpression(canMatchExpr)) {
5905
+ if (canMatchExpr && ts4.isArrayLiteralExpression(canMatchExpr)) {
5662
5906
  const canMatchList = [];
5663
5907
  for (const el of canMatchExpr.elements) {
5664
5908
  canMatchList.push(tokenText(el, ctx));
@@ -5668,16 +5912,16 @@ function parseController(input, ctx) {
5668
5912
  }
5669
5913
  }
5670
5914
  const canDeactivateExpr = getProp(optionsObject, "canDeactivate");
5671
- if (canDeactivateExpr && ts3.isArrayLiteralExpression(canDeactivateExpr)) {
5915
+ if (canDeactivateExpr && ts4.isArrayLiteralExpression(canDeactivateExpr)) {
5672
5916
  for (const el of canDeactivateExpr.elements) {
5673
5917
  routeCanDeactivate.push(tokenText(el, ctx));
5674
5918
  }
5675
5919
  }
5676
5920
  const resolversExpr = getProp(optionsObject, "resolvers");
5677
- if (resolversExpr && ts3.isObjectLiteralExpression(resolversExpr)) {
5921
+ if (resolversExpr && ts4.isObjectLiteralExpression(resolversExpr)) {
5678
5922
  const resolvers = {};
5679
5923
  for (const prop of resolversExpr.properties) {
5680
- if (ts3.isPropertyAssignment(prop)) {
5924
+ if (ts4.isPropertyAssignment(prop)) {
5681
5925
  const rName = propertyName(prop.name);
5682
5926
  const init = prop.initializer;
5683
5927
  if (init)
@@ -5689,22 +5933,22 @@ function parseController(input, ctx) {
5689
5933
  }
5690
5934
  }
5691
5935
  const redirectToExpr = getProp(optionsObject, "redirectTo");
5692
- if (redirectToExpr && ts3.isStringLiteral(redirectToExpr)) {
5936
+ if (redirectToExpr && ts4.isStringLiteral(redirectToExpr)) {
5693
5937
  route.redirectTo = redirectToExpr.text;
5694
5938
  }
5695
5939
  const pathMatchExpr = getProp(optionsObject, "pathMatch");
5696
- if (pathMatchExpr && ts3.isStringLiteral(pathMatchExpr)) {
5940
+ if (pathMatchExpr && ts4.isStringLiteral(pathMatchExpr)) {
5697
5941
  const val = pathMatchExpr.text;
5698
5942
  if (val === "full" || val === "prefix") {
5699
5943
  route.pathMatch = val;
5700
5944
  }
5701
5945
  }
5702
5946
  const titleExpr = getProp(optionsObject, "title");
5703
- if (titleExpr && ts3.isStringLiteral(titleExpr)) {
5947
+ if (titleExpr && ts4.isStringLiteral(titleExpr)) {
5704
5948
  route.title = titleExpr.text;
5705
5949
  }
5706
5950
  const dataExpr = getProp(optionsObject, "data");
5707
- if (dataExpr && ts3.isObjectLiteralExpression(dataExpr)) {
5951
+ if (dataExpr && ts4.isObjectLiteralExpression(dataExpr)) {
5708
5952
  route.data = { ...route.data, ...parseObjectLiteralValues(dataExpr) };
5709
5953
  }
5710
5954
  const aspects = parseAspectRefs(getProp(optionsObject, "aspects"), ctx, `route ${httpMethod} ${routePath}`);
@@ -5759,7 +6003,7 @@ function parseJobOptions(meta, owner, ctx) {
5759
6003
  const expression = getProp(meta, field);
5760
6004
  if (!expression)
5761
6005
  continue;
5762
- if (!ts3.isIdentifier(expression)) {
6006
+ if (!ts4.isIdentifier(expression)) {
5763
6007
  jobOptionError(ctx, "invalid-job-schema", `${owner} 的 ${field} schema 必须是可静态解析的标识符引用,不能使用内联调用或动态表达式`, expression, "SC4019", `将 schema 提取为命名导出,例如 ${field}: ${field === "input" ? "JobInput" : "JobOutput"}。`);
5764
6008
  continue;
5765
6009
  }
@@ -5783,7 +6027,7 @@ function parseJobEnum(meta, field, allowed, owner, ctx, code, errorCode) {
5783
6027
  const expression = getProp(meta, field);
5784
6028
  if (!expression)
5785
6029
  return;
5786
- if (!ts3.isStringLiteral(expression) || !allowed.includes(expression.text)) {
6030
+ if (!ts4.isStringLiteral(expression) || !allowed.includes(expression.text)) {
5787
6031
  jobOptionError(ctx, code, `${owner} 的 ${field} 必须是 ${allowed.map((value) => JSON.stringify(value)).join(" 或 ")} 字符串字面量`, expression, errorCode);
5788
6032
  return;
5789
6033
  }
@@ -5793,7 +6037,7 @@ function parseJobInteger(meta, field, min, max, owner, ctx, code, errorCode) {
5793
6037
  const expression = getProp(meta, field);
5794
6038
  if (!expression)
5795
6039
  return;
5796
- const value = ts3.isNumericLiteral(expression) ? Number(expression.text) : Number.NaN;
6040
+ const value = ts4.isNumericLiteral(expression) ? Number(expression.text) : Number.NaN;
5797
6041
  if (!Number.isSafeInteger(value) || value < min || value > max) {
5798
6042
  jobOptionError(ctx, code, `${owner} 的 ${field} 必须是 ${min} 到 ${max} 之间的安全整数`, expression, errorCode);
5799
6043
  return;
@@ -5814,8 +6058,8 @@ function jobOptionError(ctx, code, message, node, errorCode, suggestion) {
5814
6058
  }
5815
6059
  function jobSchemaKind(identifier, declaration, ctx) {
5816
6060
  const typeName = ctx.checker.typeToString(ctx.checker.getTypeAtLocation(identifier));
5817
- const initializer = ts3.isVariableDeclaration(declaration) ? declaration.initializer : undefined;
5818
- const opaque = /\bT(?:Unknown|Any)\b/.test(typeName) || initializer && ts3.isCallExpression(initializer) && ts3.isPropertyAccessExpression(initializer.expression) && ["Unknown", "Any"].includes(initializer.expression.name.text);
6061
+ const initializer = ts4.isVariableDeclaration(declaration) ? declaration.initializer : undefined;
6062
+ const opaque = /\bT(?:Unknown|Any)\b/.test(typeName) || initializer && ts4.isCallExpression(initializer) && ts4.isPropertyAccessExpression(initializer.expression) && ["Unknown", "Any"].includes(initializer.expression.name.text);
5819
6063
  return opaque ? "opaque" : "declared";
5820
6064
  }
5821
6065
  function checkedRpc(meta, ctx) {
@@ -5837,7 +6081,7 @@ function checkedRpc(meta, ctx) {
5837
6081
  }
5838
6082
  function classDeps(cls, ctx) {
5839
6083
  const injectable = parseInjectableOptions(cls, ctx);
5840
- const ctor = cls.members.find(ts3.isConstructorDeclaration);
6084
+ const ctor = cls.members.find(ts4.isConstructorDeclaration);
5841
6085
  const deps = injectable?.deps ? [...injectable.deps] : [];
5842
6086
  const optionalDeps = [];
5843
6087
  const selfDeps = [];
@@ -5871,23 +6115,23 @@ function classDeps(cls, ctx) {
5871
6115
  }
5872
6116
  });
5873
6117
  }
5874
- for (const prop of cls.members.filter(ts3.isPropertyDeclaration)) {
6118
+ for (const prop of cls.members.filter(ts4.isPropertyDeclaration)) {
5875
6119
  const init = prop.initializer;
5876
- if (init && ts3.isCallExpression(init)) {
6120
+ if (init && ts4.isCallExpression(init)) {
5877
6121
  const callName = nodeText(init.expression).split(".").pop();
5878
6122
  if (callName === "inject") {
5879
6123
  const [tokenArg, optionsArg] = init.arguments;
5880
6124
  if (tokenArg) {
5881
6125
  const tokenName = tokenText(tokenArg, ctx);
5882
6126
  const unwrappedToken = unwrapForwardRef(tokenArg);
5883
- const known = ts3.isStringLiteral(unwrappedToken) || ts3.isIdentifier(unwrappedToken) && (ctx.tokensByName.has(tokenName) || ctx.classesByName.has(tokenName));
6127
+ const known = ts4.isStringLiteral(unwrappedToken) || ts4.isIdentifier(unwrappedToken) && (ctx.tokensByName.has(tokenName) || ctx.classesByName.has(tokenName));
5884
6128
  if (!known) {
5885
6129
  missing = true;
5886
6130
  continue;
5887
6131
  }
5888
6132
  if (!deps.includes(tokenName))
5889
6133
  deps.push(tokenName);
5890
- const options = optionsArg && ts3.isObjectLiteralExpression(optionsArg) ? {
6134
+ const options = optionsArg && ts4.isObjectLiteralExpression(optionsArg) ? {
5891
6135
  optional: booleanProp(optionsArg, "optional") ?? false,
5892
6136
  self: booleanProp(optionsArg, "self") ?? false,
5893
6137
  skipSelf: booleanProp(optionsArg, "skipSelf") ?? false,
@@ -5902,9 +6146,9 @@ function classDeps(cls, ctx) {
5902
6146
  if (options.host && !hostDeps.includes(tokenName))
5903
6147
  hostDeps.push(tokenName);
5904
6148
  if (!functionalInjects.some((entry) => entry.token === tokenName)) {
5905
- const declaration = ts3.isIdentifier(unwrappedToken) ? resolveDeclaration(unwrappedToken, ctx)[0] : undefined;
6149
+ const declaration = ts4.isIdentifier(unwrappedToken) ? resolveDeclaration(unwrappedToken, ctx)[0] : undefined;
5906
6150
  const localFile = declaration && isProjectSourcePath(declaration.getSourceFile().fileName, ctx.rootDir) ? declaration.getSourceFile().fileName : undefined;
5907
- const importModule = declaration && !localFile && ts3.isIdentifier(unwrappedToken) ? importModuleOf(unwrappedToken, ctx) : undefined;
6151
+ const importModule = declaration && !localFile && ts4.isIdentifier(unwrappedToken) ? importModuleOf(unwrappedToken, ctx) : undefined;
5908
6152
  functionalInjects.push({
5909
6153
  token: tokenName,
5910
6154
  expression: nodeText(unwrappedToken),
@@ -5948,7 +6192,7 @@ function parseInjectableOptions(cls, ctx) {
5948
6192
  }
5949
6193
  function parseInjectParams(cls, ctx) {
5950
6194
  const result = new Map;
5951
- const ctor = cls.members.find(ts3.isConstructorDeclaration);
6195
+ const ctor = cls.members.find(ts4.isConstructorDeclaration);
5952
6196
  if (!ctor)
5953
6197
  return result;
5954
6198
  ctor.parameters.forEach((param, index) => {
@@ -5964,7 +6208,7 @@ function parseInjectParams(cls, ctx) {
5964
6208
  }
5965
6209
  function parseOptionalParams(cls) {
5966
6210
  const result = new Set;
5967
- const ctor = cls.members.find(ts3.isConstructorDeclaration);
6211
+ const ctor = cls.members.find(ts4.isConstructorDeclaration);
5968
6212
  if (!ctor)
5969
6213
  return result;
5970
6214
  ctor.parameters.forEach((param, index) => {
@@ -5979,7 +6223,7 @@ function parseOptionalParams(cls) {
5979
6223
  }
5980
6224
  function parseModifierParams(cls, modifierName) {
5981
6225
  const result = new Set;
5982
- const ctor = cls.members.find(ts3.isConstructorDeclaration);
6226
+ const ctor = cls.members.find(ts4.isConstructorDeclaration);
5983
6227
  if (!ctor)
5984
6228
  return result;
5985
6229
  ctor.parameters.forEach((param, index) => {
@@ -5991,13 +6235,13 @@ function parseModifierParams(cls, modifierName) {
5991
6235
  return result;
5992
6236
  }
5993
6237
  function unwrapForwardRef(expr) {
5994
- if (ts3.isCallExpression(expr)) {
6238
+ if (ts4.isCallExpression(expr)) {
5995
6239
  const exprText = nodeText(expr.expression);
5996
6240
  if (exprText === "forwardRef" || exprText.endsWith(".forwardRef")) {
5997
6241
  const arg = expr.arguments[0];
5998
- if (arg && (ts3.isArrowFunction(arg) || ts3.isFunctionExpression(arg))) {
6242
+ if (arg && (ts4.isArrowFunction(arg) || ts4.isFunctionExpression(arg))) {
5999
6243
  const body = arg.body;
6000
- if (body && ts3.isExpression(body)) {
6244
+ if (body && ts4.isExpression(body)) {
6001
6245
  return unwrapForwardRef(body);
6002
6246
  }
6003
6247
  }
@@ -6007,13 +6251,13 @@ function unwrapForwardRef(expr) {
6007
6251
  }
6008
6252
  function tokenText(expr, ctx) {
6009
6253
  const unwrapped = unwrapForwardRef(expr);
6010
- if (ts3.isStringLiteral(unwrapped))
6254
+ if (ts4.isStringLiteral(unwrapped))
6011
6255
  return unwrapped.text;
6012
- if (ts3.isIdentifier(unwrapped)) {
6256
+ if (ts4.isIdentifier(unwrapped)) {
6013
6257
  const decl = resolveDeclaration(unwrapped, ctx)[0];
6014
- if (decl && ts3.isClassDeclaration(decl))
6258
+ if (decl && ts4.isClassDeclaration(decl))
6015
6259
  return decl.name?.text ?? unwrapped.text;
6016
- if (decl && ts3.isVariableDeclaration(decl))
6260
+ if (decl && ts4.isVariableDeclaration(decl))
6017
6261
  return variableName(decl);
6018
6262
  }
6019
6263
  return nodeText(unwrapped);
@@ -6033,12 +6277,12 @@ function resolveScope(input, ctx) {
6033
6277
  }
6034
6278
  function tokenNameOf(expr, ctx) {
6035
6279
  const unwrapped = unwrapForwardRef(expr);
6036
- if (ts3.isIdentifier(unwrapped)) {
6280
+ if (ts4.isIdentifier(unwrapped)) {
6037
6281
  const decl = resolveDeclaration(unwrapped, ctx)[0];
6038
- if (decl && ts3.isClassDeclaration(decl)) {
6282
+ if (decl && ts4.isClassDeclaration(decl)) {
6039
6283
  return { name: decl.name?.text ?? nodeText(expr), kind: "class" };
6040
6284
  }
6041
- if (decl && ts3.isVariableDeclaration(decl)) {
6285
+ if (decl && ts4.isVariableDeclaration(decl)) {
6042
6286
  const name = variableName(decl);
6043
6287
  return { name, kind: ctx.tokensByName.has(name) ? "injection-token" : "class" };
6044
6288
  }
@@ -6054,10 +6298,10 @@ function resolveDeclaration(id, ctx) {
6054
6298
  return [];
6055
6299
  let declarations = symbol.declarations ?? [];
6056
6300
  for (let guard = 0;guard < 4; guard += 1) {
6057
- const isAlias = declarations.some((d) => ts3.isImportSpecifier(d) || ts3.isImportClause(d) || ts3.isNamespaceImport(d));
6301
+ const isAlias = declarations.some((d) => ts4.isImportSpecifier(d) || ts4.isImportClause(d) || ts4.isNamespaceImport(d));
6058
6302
  if (!isAlias)
6059
6303
  break;
6060
- if (!(symbol.flags & ts3.SymbolFlags.Alias))
6304
+ if (!(symbol.flags & ts4.SymbolFlags.Alias))
6061
6305
  break;
6062
6306
  const aliased = ctx.checker.getAliasedSymbol(symbol);
6063
6307
  symbol = aliased;
@@ -6077,9 +6321,9 @@ function importModuleOf(id, ctx) {
6077
6321
  for (const declaration of declarations) {
6078
6322
  let current = declaration;
6079
6323
  while (current) {
6080
- if (ts3.isImportDeclaration(current)) {
6324
+ if (ts4.isImportDeclaration(current)) {
6081
6325
  const moduleSpecifier = current.moduleSpecifier;
6082
- return ts3.isStringLiteral(moduleSpecifier) ? moduleSpecifier.text : undefined;
6326
+ return ts4.isStringLiteral(moduleSpecifier) ? moduleSpecifier.text : undefined;
6083
6327
  }
6084
6328
  current = current.parent;
6085
6329
  }
@@ -6091,27 +6335,27 @@ function findDecorator(cls, name) {
6091
6335
  }
6092
6336
  function decoratorName2(dec) {
6093
6337
  const expr = dec.expression;
6094
- if (ts3.isCallExpression(expr)) {
6338
+ if (ts4.isCallExpression(expr)) {
6095
6339
  return nodeText(expr.expression).split(".").pop();
6096
6340
  }
6097
- if (ts3.isIdentifier(expr))
6341
+ if (ts4.isIdentifier(expr))
6098
6342
  return expr.text;
6099
6343
  return;
6100
6344
  }
6101
6345
  function decoratorObjectArg(dec) {
6102
6346
  const expr = dec.expression;
6103
- if (!ts3.isCallExpression(expr))
6347
+ if (!ts4.isCallExpression(expr))
6104
6348
  return;
6105
6349
  const arg = expr.arguments[0];
6106
- return arg && ts3.isObjectLiteralExpression(arg) ? arg : undefined;
6350
+ return arg && ts4.isObjectLiteralExpression(arg) ? arg : undefined;
6107
6351
  }
6108
6352
  function getProp(obj, name) {
6109
- const prop = obj.properties.find((item) => (ts3.isPropertyAssignment(item) || ts3.isShorthandPropertyAssignment(item)) && propertyName(item.name) === name);
6353
+ const prop = obj.properties.find((item) => (ts4.isPropertyAssignment(item) || ts4.isShorthandPropertyAssignment(item)) && propertyName(item.name) === name);
6110
6354
  if (!prop)
6111
6355
  return;
6112
- if (ts3.isPropertyAssignment(prop))
6356
+ if (ts4.isPropertyAssignment(prop))
6113
6357
  return prop.initializer;
6114
- if (ts3.isShorthandPropertyAssignment(prop))
6358
+ if (ts4.isShorthandPropertyAssignment(prop))
6115
6359
  return prop.name;
6116
6360
  return;
6117
6361
  }
@@ -6119,10 +6363,10 @@ function toCompilerDiagnostic(diagnostic, rootDir) {
6119
6363
  const file = diagnostic.file;
6120
6364
  const position = file && diagnostic.start !== undefined ? file.getLineAndCharacterOfPosition(diagnostic.start) : undefined;
6121
6365
  return {
6122
- severity: diagnostic.category === ts3.DiagnosticCategory.Error ? "error" : "warn",
6366
+ severity: diagnostic.category === ts4.DiagnosticCategory.Error ? "error" : "warn",
6123
6367
  code: `typescript-${diagnostic.code}`,
6124
6368
  errorCode: `TS${diagnostic.code}`,
6125
- message: ts3.flattenDiagnosticMessageText(diagnostic.messageText, `
6369
+ message: ts4.flattenDiagnosticMessageText(diagnostic.messageText, `
6126
6370
  `),
6127
6371
  ...file ? { file: sourcePath(rootDir, file.fileName) } : {},
6128
6372
  ...position ? { line: position.line + 1 } : {}
@@ -6130,16 +6374,16 @@ function toCompilerDiagnostic(diagnostic, rootDir) {
6130
6374
  }
6131
6375
  function stringLiteralProp(obj, name) {
6132
6376
  const expr = getProp(obj, name);
6133
- return expr && ts3.isStringLiteral(expr) ? expr.text : undefined;
6377
+ return expr && ts4.isStringLiteral(expr) ? expr.text : undefined;
6134
6378
  }
6135
6379
  function arrayProp(obj, name) {
6136
6380
  const expr = getProp(obj, name);
6137
- return expr && ts3.isArrayLiteralExpression(expr) ? [...expr.elements] : [];
6381
+ return expr && ts4.isArrayLiteralExpression(expr) ? [...expr.elements] : [];
6138
6382
  }
6139
6383
  function parseAspectRefs(expression, ctx, owner) {
6140
6384
  if (!expression)
6141
6385
  return [];
6142
- if (!ts3.isArrayLiteralExpression(expression)) {
6386
+ if (!ts4.isArrayLiteralExpression(expression)) {
6143
6387
  ctx.diagnostics.push({
6144
6388
  severity: "error",
6145
6389
  code: "dynamic-aspect-reference",
@@ -6154,7 +6398,7 @@ function parseAspectRefs(expression, ctx, owner) {
6154
6398
  }
6155
6399
  const refs = [];
6156
6400
  for (const element of expression.elements) {
6157
- if (ts3.isSpreadElement(element) || !ts3.isIdentifier(element)) {
6401
+ if (ts4.isSpreadElement(element) || !ts4.isIdentifier(element)) {
6158
6402
  ctx.diagnostics.push({
6159
6403
  severity: "error",
6160
6404
  code: "dynamic-aspect-reference",
@@ -6167,7 +6411,7 @@ function parseAspectRefs(expression, ctx, owner) {
6167
6411
  });
6168
6412
  continue;
6169
6413
  }
6170
- const declaration = resolveDeclaration(element, ctx).find((candidate) => ts3.isFunctionDeclaration(candidate) || ts3.isVariableDeclaration(candidate) && candidate.initializer !== undefined && (ts3.isArrowFunction(candidate.initializer) || ts3.isFunctionExpression(candidate.initializer)));
6414
+ const declaration = resolveDeclaration(element, ctx).find((candidate) => ts4.isFunctionDeclaration(candidate) || ts4.isVariableDeclaration(candidate) && candidate.initializer !== undefined && (ts4.isArrowFunction(candidate.initializer) || ts4.isFunctionExpression(candidate.initializer)));
6171
6415
  if (!declaration) {
6172
6416
  ctx.diagnostics.push({
6173
6417
  severity: "error",
@@ -6181,7 +6425,7 @@ function parseAspectRefs(expression, ctx, owner) {
6181
6425
  });
6182
6426
  continue;
6183
6427
  }
6184
- const name = ts3.isFunctionDeclaration(declaration) ? declaration.name?.text : ts3.isVariableDeclaration(declaration) ? variableName(declaration) : undefined;
6428
+ const name = ts4.isFunctionDeclaration(declaration) ? declaration.name?.text : ts4.isVariableDeclaration(declaration) ? variableName(declaration) : undefined;
6185
6429
  if (!name)
6186
6430
  continue;
6187
6431
  const declaredFile = declaration.getSourceFile().fileName;
@@ -6201,9 +6445,9 @@ function booleanProp(obj, name) {
6201
6445
  const expr = getProp(obj, name);
6202
6446
  if (!expr)
6203
6447
  return;
6204
- if (expr.kind === ts3.SyntaxKind.TrueKeyword)
6448
+ if (expr.kind === ts4.SyntaxKind.TrueKeyword)
6205
6449
  return true;
6206
- if (expr.kind === ts3.SyntaxKind.FalseKeyword)
6450
+ if (expr.kind === ts4.SyntaxKind.FalseKeyword)
6207
6451
  return false;
6208
6452
  return;
6209
6453
  }
@@ -6217,15 +6461,15 @@ function parseBindingOptions(args, defaultName) {
6217
6461
  let defaultValue;
6218
6462
  const first = args[0];
6219
6463
  const second = args[1];
6220
- if (first && ts3.isStringLiteral(first)) {
6464
+ if (first && ts4.isStringLiteral(first)) {
6221
6465
  name = first.text;
6222
- } else if (first && ts3.isObjectLiteralExpression(first)) {
6466
+ } else if (first && ts4.isObjectLiteralExpression(first)) {
6223
6467
  const nameProp = getProp(first, "name");
6224
- if (nameProp && ts3.isStringLiteral(nameProp)) {
6468
+ if (nameProp && ts4.isStringLiteral(nameProp)) {
6225
6469
  name = nameProp.text;
6226
6470
  }
6227
6471
  const trProp = getProp(first, "transform");
6228
- if (trProp && ts3.isStringLiteral(trProp)) {
6472
+ if (trProp && ts4.isStringLiteral(trProp)) {
6229
6473
  const val = trProp.text;
6230
6474
  if (val === "number" || val === "boolean" || val === "string") {
6231
6475
  transform = val;
@@ -6236,9 +6480,9 @@ function parseBindingOptions(args, defaultName) {
6236
6480
  defaultValue = parseLiteralValue(defProp);
6237
6481
  }
6238
6482
  }
6239
- if (second && ts3.isObjectLiteralExpression(second)) {
6483
+ if (second && ts4.isObjectLiteralExpression(second)) {
6240
6484
  const trProp = getProp(second, "transform");
6241
- if (trProp && ts3.isStringLiteral(trProp)) {
6485
+ if (trProp && ts4.isStringLiteral(trProp)) {
6242
6486
  const val = trProp.text;
6243
6487
  if (val === "number" || val === "boolean" || val === "string") {
6244
6488
  transform = val;
@@ -6252,18 +6496,18 @@ function parseBindingOptions(args, defaultName) {
6252
6496
  return { name, ...transform ? { transform } : {}, default: defaultValue };
6253
6497
  }
6254
6498
  function parseLiteralValue(node) {
6255
- if (ts3.isStringLiteral(node))
6499
+ if (ts4.isStringLiteral(node))
6256
6500
  return node.text;
6257
- if (ts3.isNumericLiteral(node))
6501
+ if (ts4.isNumericLiteral(node))
6258
6502
  return Number(node.text);
6259
- if (node.kind === ts3.SyntaxKind.TrueKeyword)
6503
+ if (node.kind === ts4.SyntaxKind.TrueKeyword)
6260
6504
  return true;
6261
- if (node.kind === ts3.SyntaxKind.FalseKeyword)
6505
+ if (node.kind === ts4.SyntaxKind.FalseKeyword)
6262
6506
  return false;
6263
- if (ts3.isArrayLiteralExpression(node)) {
6507
+ if (ts4.isArrayLiteralExpression(node)) {
6264
6508
  return node.elements.map(parseLiteralValue);
6265
6509
  }
6266
- if (ts3.isObjectLiteralExpression(node)) {
6510
+ if (ts4.isObjectLiteralExpression(node)) {
6267
6511
  return parseObjectLiteralValues(node);
6268
6512
  }
6269
6513
  return;
@@ -6271,7 +6515,7 @@ function parseLiteralValue(node) {
6271
6515
  function parseObjectLiteralValues(obj) {
6272
6516
  const result = {};
6273
6517
  for (const prop of obj.properties) {
6274
- if (ts3.isPropertyAssignment(prop)) {
6518
+ if (ts4.isPropertyAssignment(prop)) {
6275
6519
  const name = propertyName(prop.name);
6276
6520
  const init = prop.initializer;
6277
6521
  if (init) {
@@ -6307,7 +6551,50 @@ import { join as join4 } from "node:path";
6307
6551
  // src/type-safety.ts
6308
6552
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
6309
6553
  import { dirname as dirname3, join as join3, relative as relative3, resolve as resolve2, sep as sep3 } from "node:path";
6310
- import * as ts4 from "@typescript/typescript6";
6554
+ import * as ts6 from "@typescript/typescript6";
6555
+
6556
+ // src/sql-safety.ts
6557
+ import * as ts5 from "@typescript/typescript6";
6558
+ var SQL_SAFETY_DIAGNOSTIC_CODES = {
6559
+ "sql-result-assertion": { errorCode: "SC6007", docsUrl: "https://supacloud.dev/errors/SC6007" },
6560
+ "sql-raw-dynamic": { errorCode: "SC6008", docsUrl: "https://supacloud.dev/errors/SC6008" }
6561
+ };
6562
+ function scanDrizzleSql(sourceFile, checker, file, strict) {
6563
+ const diagnostics = [];
6564
+ const importedSql = (expression) => {
6565
+ const symbol = checker.getSymbolAtLocation(ts5.isPropertyAccessExpression(expression) ? expression.name : expression);
6566
+ if (!symbol)
6567
+ return false;
6568
+ const target = symbol.flags & ts5.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
6569
+ return target.name === "sql" && (target.declarations ?? []).some((declaration) => /(?:^|\/)node_modules\/drizzle-orm\//.test(declaration.getSourceFile().fileName.replaceAll("\\", "/")));
6570
+ };
6571
+ const report = (code, node, message) => {
6572
+ diagnostics.push({
6573
+ severity: strict ? "error" : "warn",
6574
+ code,
6575
+ ...SQL_SAFETY_DIAGNOSTIC_CODES[code],
6576
+ message,
6577
+ file,
6578
+ line: sourceFile.getLineAndCharacterOfPosition(node.getStart()).line + 1
6579
+ });
6580
+ };
6581
+ const visit = (node) => {
6582
+ if (ts5.isTaggedTemplateExpression(node) && importedSql(node.tag) && node.typeArguments?.some((type) => type.kind !== ts5.SyntaxKind.UnknownKeyword)) {
6583
+ 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.");
6584
+ }
6585
+ if (ts5.isCallExpression(node) && ts5.isPropertyAccessExpression(node.expression) && node.expression.name.text === "raw" && importedSql(node.expression.expression)) {
6586
+ const argument = node.arguments[0];
6587
+ if (!argument || !ts5.isStringLiteral(argument) && !ts5.isNoSubstitutionTemplateLiteral(argument)) {
6588
+ report("sql-raw-dynamic", node, "Dynamic sql.raw bypasses parameter binding. Interpolate values with sql templates; keep reviewed static DDL in migrations.");
6589
+ }
6590
+ }
6591
+ ts5.forEachChild(node, visit);
6592
+ };
6593
+ visit(sourceFile);
6594
+ return diagnostics;
6595
+ }
6596
+
6597
+ // src/type-safety.ts
6311
6598
  var DEFAULT_EXCLUDES = [
6312
6599
  "**/*.test.ts",
6313
6600
  "**/*.spec.ts",
@@ -6320,6 +6607,7 @@ var DEFAULT_EXCLUDES = [
6320
6607
  "**/*.d.ts"
6321
6608
  ];
6322
6609
  var TYPE_SAFETY_DIAGNOSTIC_CODES = {
6610
+ ...SQL_SAFETY_DIAGNOSTIC_CODES,
6323
6611
  "generated-any": { errorCode: "SC6001", docsUrl: "https://supacloud.dev/errors/SC6001" },
6324
6612
  "source-any": { errorCode: "SC6002", docsUrl: "https://supacloud.dev/errors/SC6002" },
6325
6613
  "source-type-assertion": { errorCode: "SC6003", docsUrl: "https://supacloud.dev/errors/SC6003" },
@@ -6332,7 +6620,7 @@ function scanGeneratedArtifacts(artifacts, strict = true) {
6332
6620
  for (const [file, content] of Object.entries(artifacts)) {
6333
6621
  if (content === undefined)
6334
6622
  continue;
6335
- const sourceFile = ts4.createSourceFile(file, content, ts4.ScriptTarget.Latest, true, ts4.ScriptKind.TS);
6623
+ const sourceFile = ts6.createSourceFile(file, content, ts6.ScriptTarget.Latest, true, ts6.ScriptKind.TS);
6336
6624
  for (const node of descendantsOfKind2(sourceFile, isAnyKeyword)) {
6337
6625
  diagnostics.push(makeDiagnostic("generated-any", `生成产物 ${file} 包含 any;严格生成模式要求使用 unknown、具体接口或泛型约束。`, sourceFile, node, strict));
6338
6626
  }
@@ -6341,30 +6629,30 @@ function scanGeneratedArtifacts(artifacts, strict = true) {
6341
6629
  }
6342
6630
  function scanProductionSource(options) {
6343
6631
  const rootDir = resolve2(options.rootDir);
6344
- const configPath = ts4.findConfigFile(rootDir, ts4.sys.fileExists) ?? join3(rootDir, "tsconfig.json");
6632
+ const configPath = ts6.findConfigFile(rootDir, ts6.sys.fileExists) ?? join3(rootDir, "tsconfig.json");
6345
6633
  const projectConfig = existsSync2(configPath) ? readProjectConfig2(configPath) : {
6346
6634
  options: {
6347
6635
  strict: true,
6348
6636
  skipLibCheck: true,
6349
- target: ts4.ScriptTarget.ES2022,
6350
- module: ts4.ModuleKind.ESNext,
6351
- moduleResolution: ts4.ModuleResolutionKind.Bundler
6637
+ target: ts6.ScriptTarget.ES2022,
6638
+ module: ts6.ModuleKind.ESNext,
6639
+ moduleResolution: ts6.ModuleResolutionKind.Bundler
6352
6640
  },
6353
6641
  errors: []
6354
6642
  };
6355
6643
  const include = options.include ?? ["**/*.ts", "**/*.tsx", "**/*.mts", "**/*.cts"];
6356
- const rootNames = ts4.sys.readDirectory(rootDir, [".ts", ".tsx", ".mts", ".cts"], ["node_modules", "dist"], include).filter((file) => isProductionSourcePath(rootDir, file, [...DEFAULT_EXCLUDES, ...options.exclude ?? []]));
6644
+ const rootNames = ts6.sys.readDirectory(rootDir, [".ts", ".tsx", ".mts", ".cts"], ["node_modules", "dist"], include).filter((file) => isProductionSourcePath(rootDir, file, [...DEFAULT_EXCLUDES, ...options.exclude ?? []]));
6357
6645
  const compilerOptions = { ...projectConfig.options, noEmit: true };
6358
- const host = ts4.createCompilerHost(compilerOptions);
6646
+ const host = ts6.createCompilerHost(compilerOptions);
6359
6647
  host.getCurrentDirectory = () => dirname3(configPath);
6360
- const program = ts4.createProgram(rootNames, compilerOptions, host);
6648
+ const program = ts6.createProgram(rootNames, compilerOptions, host);
6361
6649
  const outDir = options.outDir ? normalizeRelative(rootDir, options.outDir) : undefined;
6362
6650
  const excludes = [...DEFAULT_EXCLUDES, ...options.exclude ?? []];
6363
6651
  const sourceFiles = program.getSourceFiles().filter((sourceFile) => isProductionSource(rootDir, sourceFile, excludes, outDir));
6364
6652
  const diagnostics = [...projectConfig.errors, ...program.getOptionsDiagnostics()].map((diagnostic) => ({
6365
6653
  severity: "error",
6366
6654
  code: "source-config",
6367
- message: ts4.flattenDiagnosticMessageText(diagnostic.messageText, `
6655
+ message: ts6.flattenDiagnosticMessageText(diagnostic.messageText, `
6368
6656
  `),
6369
6657
  file: diagnostic.file ? normalizeRelative(rootDir, diagnostic.file.fileName) : normalizeRelative(rootDir, configPath),
6370
6658
  ...diagnostic.file && diagnostic.start !== undefined ? { line: diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start).line + 1 } : {},
@@ -6381,7 +6669,7 @@ function scanProductionSource(options) {
6381
6669
  diagnostics.push({
6382
6670
  severity: "error",
6383
6671
  code: "source-typescript",
6384
- message: ts4.flattenDiagnosticMessageText(diagnostic.messageText, `
6672
+ message: ts6.flattenDiagnosticMessageText(diagnostic.messageText, `
6385
6673
  `),
6386
6674
  ...diagnostic.file ? { file: normalizeRelative(rootDir, diagnostic.file.fileName) } : {},
6387
6675
  ...diagnostic.file && diagnostic.start !== undefined ? { line: diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start).line + 1 } : {},
@@ -6390,9 +6678,10 @@ function scanProductionSource(options) {
6390
6678
  }
6391
6679
  for (const sourceFile of sourceFiles) {
6392
6680
  scanSourceFile(sourceFile, checker, rootDir, diagnostics, options.strict ?? false);
6393
- const scanner = ts4.createScanner(ts4.ScriptTarget.Latest, false, sourceFile.languageVariant, sourceFile.text);
6394
- for (let kind = scanner.scan();kind !== ts4.SyntaxKind.EndOfFileToken; kind = scanner.scan()) {
6395
- if ((kind === ts4.SyntaxKind.SingleLineCommentTrivia || kind === ts4.SyntaxKind.MultiLineCommentTrivia) && /@ts-(?:ignore|nocheck|expect-error)\b/.test(scanner.getTokenText())) {
6681
+ diagnostics.push(...scanDrizzleSql(sourceFile, checker, normalizeRelative(rootDir, sourceFile.fileName), options.strict ?? false));
6682
+ const scanner = ts6.createScanner(ts6.ScriptTarget.Latest, false, sourceFile.languageVariant, sourceFile.text);
6683
+ for (let kind = scanner.scan();kind !== ts6.SyntaxKind.EndOfFileToken; kind = scanner.scan()) {
6684
+ if ((kind === ts6.SyntaxKind.SingleLineCommentTrivia || kind === ts6.SyntaxKind.MultiLineCommentTrivia) && /@ts-(?:ignore|nocheck|expect-error)\b/.test(scanner.getTokenText())) {
6396
6685
  diagnostics.push({
6397
6686
  severity: "error",
6398
6687
  code: "source-type-suppression",
@@ -6412,22 +6701,22 @@ function scanSourceFile(sourceFile, checker, rootDir, diagnostics, strict) {
6412
6701
  diagnostics.push(makeDiagnostic("source-any", "生产源码使用了显式 any;请改用 unknown、具体接口或泛型约束。", sourceFile, node, strict, rootDir));
6413
6702
  }
6414
6703
  for (const node of descendants(sourceFile)) {
6415
- if (ts4.isAsExpression(node)) {
6416
- if (ts4.isAsExpression(node.parent) || ts4.isTypeAssertionExpression(node.parent))
6704
+ if (ts6.isAsExpression(node)) {
6705
+ if (ts6.isAsExpression(node.parent) || ts6.isTypeAssertionExpression(node.parent))
6417
6706
  continue;
6418
6707
  const assertedType = node.type.getText(sourceFile);
6419
6708
  if (assertedType === "const")
6420
6709
  continue;
6421
6710
  diagnostics.push(makeDiagnostic("source-type-assertion", `生产源码包含类型断言 ${node.getText(sourceFile)};请优先使用类型守卫、satisfies 或显式边界解析。`, sourceFile, node, strict, rootDir));
6422
- } else if (ts4.isTypeAssertionExpression(node)) {
6423
- if (ts4.isAsExpression(node.parent) || ts4.isTypeAssertionExpression(node.parent))
6711
+ } else if (ts6.isTypeAssertionExpression(node)) {
6712
+ if (ts6.isAsExpression(node.parent) || ts6.isTypeAssertionExpression(node.parent))
6424
6713
  continue;
6425
6714
  diagnostics.push(makeDiagnostic("source-type-assertion", `生产源码包含类型断言 ${node.getText(sourceFile)};请优先使用类型守卫、satisfies 或显式边界解析。`, sourceFile, node, strict, rootDir));
6426
- } else if (ts4.isNonNullExpression(node)) {
6715
+ } else if (ts6.isNonNullExpression(node)) {
6427
6716
  diagnostics.push(makeDiagnostic("source-non-null-assertion", `生产源码包含非空断言 ${node.getText(sourceFile)};请显式处理 null/undefined。`, sourceFile, node, strict, rootDir));
6428
6717
  }
6429
6718
  }
6430
- for (const declaration of descendantsOfKind2(sourceFile, ts4.isVariableDeclaration)) {
6719
+ for (const declaration of descendantsOfKind2(sourceFile, ts6.isVariableDeclaration)) {
6431
6720
  const initializer = declaration.initializer;
6432
6721
  if (!initializer || declaration.type)
6433
6722
  continue;
@@ -6443,11 +6732,11 @@ function scanSourceFile(sourceFile, checker, rootDir, diagnostics, strict) {
6443
6732
  if (isLetDeclaration(declaration) && isLiteralSyntax(initializer) && !isLiteralType(declarationType)) {
6444
6733
  diagnostics.push(makeDiagnostic("source-implicit-widening", `变量 ${declaration.name.getText(sourceFile)} 的字面量类型从 ${checker.typeToString(initializerType, initializer)} 隐式宽化为 ${checker.typeToString(declarationType, declaration)};请补充类型或使用 const。`, sourceFile, declaration, strict, rootDir));
6445
6734
  }
6446
- if (ts4.isObjectLiteralExpression(initializer) && isConstDeclaration(declaration) && initializer.getText(sourceFile).length > 0 && initializer.properties.some((property) => ts4.isPropertyAssignment(property) && property.initializer !== undefined && !ts4.isAsExpression(property.initializer) && isLiteralExpression(property.initializer))) {
6735
+ if (ts6.isObjectLiteralExpression(initializer) && isConstDeclaration(declaration) && initializer.getText(sourceFile).length > 0 && initializer.properties.some((property) => ts6.isPropertyAssignment(property) && property.initializer !== undefined && !ts6.isAsExpression(property.initializer) && isLiteralExpression(property.initializer))) {
6447
6736
  diagnostics.push(makeDiagnostic("source-implicit-widening", `常量对象 ${declaration.name.getText(sourceFile)} 的字面量属性会隐式宽化;请补充对象类型或使用 as const。`, sourceFile, declaration, strict, rootDir));
6448
6737
  }
6449
6738
  }
6450
- for (const parameter of descendantsOfKind2(sourceFile, ts4.isParameter)) {
6739
+ for (const parameter of descendantsOfKind2(sourceFile, ts6.isParameter)) {
6451
6740
  if (parameter.type)
6452
6741
  continue;
6453
6742
  for (const name of bindingNames(parameter.name)) {
@@ -6458,10 +6747,10 @@ function scanSourceFile(sourceFile, checker, rootDir, diagnostics, strict) {
6458
6747
  }
6459
6748
  }
6460
6749
  function readProjectConfig2(configPath) {
6461
- const config = ts4.readConfigFile(configPath, (file) => readFileSync2(file, "utf8"));
6750
+ const config = ts6.readConfigFile(configPath, (file) => readFileSync2(file, "utf8"));
6462
6751
  if (config.error)
6463
6752
  return { options: {}, errors: [config.error] };
6464
- const parsed = ts4.parseJsonConfigFileContent(config.config, ts4.sys, dirname3(configPath));
6753
+ const parsed = ts6.parseJsonConfigFileContent(config.config, ts6.sys, dirname3(configPath));
6465
6754
  return { options: parsed.options, errors: parsed.errors };
6466
6755
  }
6467
6756
  function isProductionSource(rootDir, sourceFile, excludes, outDir) {
@@ -6481,42 +6770,42 @@ function globMatches(value, pattern) {
6481
6770
  return new RegExp(`^${escaped}$`).test(value);
6482
6771
  }
6483
6772
  function bindingNames(name) {
6484
- if (ts4.isIdentifier(name))
6773
+ if (ts6.isIdentifier(name))
6485
6774
  return [name];
6486
- return name.elements.flatMap((element) => ts4.isBindingElement(element) ? bindingNames(element.name) : []);
6775
+ return name.elements.flatMap((element) => ts6.isBindingElement(element) ? bindingNames(element.name) : []);
6487
6776
  }
6488
6777
  function isLiteralExpression(node) {
6489
6778
  if (!node)
6490
6779
  return false;
6491
6780
  return [
6492
- ts4.SyntaxKind.StringLiteral,
6493
- ts4.SyntaxKind.NumericLiteral,
6494
- ts4.SyntaxKind.TrueKeyword,
6495
- ts4.SyntaxKind.FalseKeyword
6781
+ ts6.SyntaxKind.StringLiteral,
6782
+ ts6.SyntaxKind.NumericLiteral,
6783
+ ts6.SyntaxKind.TrueKeyword,
6784
+ ts6.SyntaxKind.FalseKeyword
6496
6785
  ].includes(node.kind);
6497
6786
  }
6498
6787
  function isLiteralSyntax(node) {
6499
- return ts4.isStringLiteral(node) || ts4.isNumericLiteral(node) || node.kind === ts4.SyntaxKind.TrueKeyword || node.kind === ts4.SyntaxKind.FalseKeyword;
6788
+ return ts6.isStringLiteral(node) || ts6.isNumericLiteral(node) || node.kind === ts6.SyntaxKind.TrueKeyword || node.kind === ts6.SyntaxKind.FalseKeyword;
6500
6789
  }
6501
6790
  function isLiteralType(type) {
6502
- return (type.flags & (ts4.TypeFlags.StringLiteral | ts4.TypeFlags.NumberLiteral | ts4.TypeFlags.BooleanLiteral | ts4.TypeFlags.BigIntLiteral)) !== 0;
6791
+ return (type.flags & (ts6.TypeFlags.StringLiteral | ts6.TypeFlags.NumberLiteral | ts6.TypeFlags.BooleanLiteral | ts6.TypeFlags.BigIntLiteral)) !== 0;
6503
6792
  }
6504
6793
  function isAnyType(type) {
6505
- return (type.flags & ts4.TypeFlags.Any) !== 0;
6794
+ return (type.flags & ts6.TypeFlags.Any) !== 0;
6506
6795
  }
6507
6796
  function isLetDeclaration(declaration) {
6508
- return ts4.isVariableDeclarationList(declaration.parent) && (declaration.parent.flags & ts4.NodeFlags.Let) !== 0;
6797
+ return ts6.isVariableDeclarationList(declaration.parent) && (declaration.parent.flags & ts6.NodeFlags.Let) !== 0;
6509
6798
  }
6510
6799
  function isConstDeclaration(declaration) {
6511
- return ts4.isVariableDeclarationList(declaration.parent) && (declaration.parent.flags & ts4.NodeFlags.Const) !== 0;
6800
+ return ts6.isVariableDeclarationList(declaration.parent) && (declaration.parent.flags & ts6.NodeFlags.Const) !== 0;
6512
6801
  }
6513
6802
  function descendants(root) {
6514
6803
  const result = [];
6515
6804
  const visit = (node) => {
6516
6805
  result.push(node);
6517
- ts4.forEachChild(node, visit);
6806
+ ts6.forEachChild(node, visit);
6518
6807
  };
6519
- ts4.forEachChild(root, visit);
6808
+ ts6.forEachChild(root, visit);
6520
6809
  return result;
6521
6810
  }
6522
6811
  function descendantsOfKind2(root, predicate) {
@@ -6524,9 +6813,9 @@ function descendantsOfKind2(root, predicate) {
6524
6813
  const visit = (node) => {
6525
6814
  if (predicate(node))
6526
6815
  result.push(node);
6527
- ts4.forEachChild(node, visit);
6816
+ ts6.forEachChild(node, visit);
6528
6817
  };
6529
- ts4.forEachChild(root, visit);
6818
+ ts6.forEachChild(root, visit);
6530
6819
  return result;
6531
6820
  }
6532
6821
  function makeDiagnostic(code, message, fileOrSourceFile, node, strict, rootDir) {
@@ -6547,7 +6836,7 @@ function normalizeRelative(rootDir, filePath) {
6547
6836
  return relative3(rootDir, filePath).split(sep3).join("/").replace(/^\.\//, "");
6548
6837
  }
6549
6838
  function isAnyKeyword(node) {
6550
- return node.kind === ts4.SyntaxKind.AnyKeyword;
6839
+ return node.kind === ts6.SyntaxKind.AnyKeyword;
6551
6840
  }
6552
6841
 
6553
6842
  // src/route-contracts.ts
@@ -6640,6 +6929,9 @@ async function compileProject(options) {
6640
6929
  ...graph.diagnostics ?? [],
6641
6930
  ...validateGraph(graph, options)
6642
6931
  ];
6932
+ if (diagnostics.some((item) => item.code === "runtime-injection-disallowed")) {
6933
+ return { diagnostics, graph, written: [] };
6934
+ }
6643
6935
  if (options.strict) {
6644
6936
  for (const diagnostic of diagnostics) {
6645
6937
  if (diagnostic.severity === "warn")
@@ -6698,6 +6990,9 @@ async function checkProject(options) {
6698
6990
  ...graph.diagnostics ?? [],
6699
6991
  ...validateGraph(graph, options)
6700
6992
  ];
6993
+ if (diagnostics.some((item) => item.code === "runtime-injection-disallowed")) {
6994
+ return { diagnostics, graph, upToDate: false, mismatches: ["Runtime DI must be migrated to constructor injection."] };
6995
+ }
6701
6996
  if (options.strict) {
6702
6997
  for (const diagnostic of diagnostics) {
6703
6998
  if (diagnostic.severity === "warn")
@@ -10248,7 +10543,7 @@ function formatDeliveryPlan(result) {
10248
10543
  import { mkdir as mkdir3, mkdtemp, readFile as readFile5, realpath as realpath2, rename as rename3, rm as rm2 } from "node:fs/promises";
10249
10544
  import { readFileSync as readFileSync3 } from "node:fs";
10250
10545
  import { dirname as dirname5, join as join6, relative as relative6, resolve as resolve7, sep as sep6 } from "node:path";
10251
- import * as ts8 from "@typescript/typescript6";
10546
+ import * as ts10 from "@typescript/typescript6";
10252
10547
 
10253
10548
  // src/delivery-files.ts
10254
10549
  import { createHash as createHash7 } from "node:crypto";
@@ -10482,19 +10777,19 @@ function renderDeliveryTarget(graph, target, options) {
10482
10777
  import { isBuiltin } from "node:module";
10483
10778
  import { readFile as readFile4 } from "node:fs/promises";
10484
10779
  import { resolve as resolve6 } from "node:path";
10485
- import * as ts7 from "@typescript/typescript6";
10780
+ import * as ts9 from "@typescript/typescript6";
10486
10781
  function checkStaticImports(path, contents) {
10487
10782
  if (!/\.[cm]?[jt]sx?$/.test(path))
10488
10783
  return;
10489
- const source = ts7.createSourceFile(path, new TextDecoder().decode(contents), ts7.ScriptTarget.Latest, true);
10784
+ const source = ts9.createSourceFile(path, new TextDecoder().decode(contents), ts9.ScriptTarget.Latest, true);
10490
10785
  function visit(node) {
10491
- if (ts7.isCallExpression(node) && (node.expression.kind === ts7.SyntaxKind.ImportKeyword || ts7.isIdentifier(node.expression) && node.expression.text === "require")) {
10786
+ if (ts9.isCallExpression(node) && (node.expression.kind === ts9.SyntaxKind.ImportKeyword || ts9.isIdentifier(node.expression) && node.expression.text === "require")) {
10492
10787
  const argument = node.arguments[0];
10493
- if (!argument || !ts7.isStringLiteral(argument) && !ts7.isNoSubstitutionTemplateLiteral(argument)) {
10788
+ if (!argument || !ts9.isStringLiteral(argument) && !ts9.isNoSubstitutionTemplateLiteral(argument)) {
10494
10789
  throw new Error("Computed module loading is not supported in independent delivery bundles.");
10495
10790
  }
10496
10791
  }
10497
- ts7.forEachChild(node, visit);
10792
+ ts9.forEachChild(node, visit);
10498
10793
  }
10499
10794
  visit(source);
10500
10795
  }
@@ -10583,7 +10878,7 @@ async function buildDeliveryProject(options, delivery) {
10583
10878
  const settings = parseDeliveryOptions(delivery);
10584
10879
  if (typeof Bun === "undefined")
10585
10880
  throw new Error("Independent delivery builds require Bun.");
10586
- const configPath = ts8.findConfigFile(resolve7(options.rootDir), ts8.sys.fileExists);
10881
+ const configPath = ts10.findConfigFile(resolve7(options.rootDir), ts10.sys.fileExists);
10587
10882
  if (!configPath)
10588
10883
  throw new Error("Independent delivery builds require a project tsconfig.json.");
10589
10884
  const lexicalProject = dirname5(configPath);
@@ -10599,8 +10894,8 @@ async function buildDeliveryProject(options, delivery) {
10599
10894
  if (inside(generatedRoot, sourceRoot))
10600
10895
  throw new Error("Output must not contain the application source root.");
10601
10896
  const configInputs = new Map;
10602
- const parsedConfig = ts8.getParsedCommandLineOfConfigFile(await realpath2(configPath), {}, {
10603
- ...ts8.sys,
10897
+ const parsedConfig = ts10.getParsedCommandLineOfConfigFile(await realpath2(configPath), {}, {
10898
+ ...ts10.sys,
10604
10899
  readFile(path) {
10605
10900
  const contents = readFileSync3(path, "utf8");
10606
10901
  configInputs.set(resolve7(path), digest(contents));
@@ -10686,7 +10981,7 @@ async function buildDeliveryProject(options, delivery) {
10686
10981
  for (const [name, contents] of Object.entries(generated))
10687
10982
  await writeArtifact(stage, `generated/${name}`, contents);
10688
10983
  {
10689
- const program = ts8.createProgram({
10984
+ const program = ts10.createProgram({
10690
10985
  rootNames: [
10691
10986
  ...parsedConfig.fileNames.filter((path) => !inside(generatedRoot, path)),
10692
10987
  ...Object.keys(generated).map((name) => join6(stage, "generated", name))
@@ -10694,12 +10989,12 @@ async function buildDeliveryProject(options, delivery) {
10694
10989
  options: { ...parsedConfig.options, rootDir: project },
10695
10990
  ...parsedConfig.projectReferences ? { projectReferences: parsedConfig.projectReferences } : {}
10696
10991
  });
10697
- const diagnostics = ts8.getPreEmitDiagnostics(program);
10698
- if (diagnostics.some((item) => item.category === ts8.DiagnosticCategory.Error)) {
10699
- return failed(diagnostics.filter((item) => item.category === ts8.DiagnosticCategory.Error).map((item) => ({
10992
+ const diagnostics = ts10.getPreEmitDiagnostics(program);
10993
+ if (diagnostics.some((item) => item.category === ts10.DiagnosticCategory.Error)) {
10994
+ return failed(diagnostics.filter((item) => item.category === ts10.DiagnosticCategory.Error).map((item) => ({
10700
10995
  severity: "error",
10701
10996
  code: "delivery-generated-type-error",
10702
- message: ts8.flattenDiagnosticMessageText(item.messageText, `
10997
+ message: ts10.flattenDiagnosticMessageText(item.messageText, `
10703
10998
  `),
10704
10999
  ...item.file ? { file: item.file.fileName } : {}
10705
11000
  })));
@@ -10831,7 +11126,7 @@ async function buildDeliveryProject(options, delivery) {
10831
11126
  import { randomUUID } from "node:crypto";
10832
11127
  import { lstat as lstat2, readFile as readFile6, realpath as realpath3, rename as rename4, unlink as unlink2, writeFile as writeFile3 } from "node:fs/promises";
10833
11128
  import { dirname as dirname6, isAbsolute as isAbsolute2, relative as relative7, resolve as resolve8, sep as sep7 } from "node:path";
10834
- import * as ts9 from "@typescript/typescript6";
11129
+ import * as ts11 from "@typescript/typescript6";
10835
11130
  async function applyDiagnosticFix(fix, options = {}) {
10836
11131
  if (!fix || typeof fix.targetFile !== "string")
10837
11132
  throw new Error("Invalid DiagnosticFix");
@@ -10856,7 +11151,7 @@ async function applyDiagnosticFix(fix, options = {}) {
10856
11151
  if (!current || current.initializer.getText(source) !== fix.expectedExpression) {
10857
11152
  throw new Error("Command mode changed since diagnosis; analyze the project again");
10858
11153
  }
10859
- content = replaceProperty(source, object, fix.property, ts9.factory.createStringLiteral(fix.value));
11154
+ content = replaceProperty(source, object, fix.property, ts11.factory.createStringLiteral(fix.value));
10860
11155
  break;
10861
11156
  }
10862
11157
  case "add_module_import": {
@@ -10867,15 +11162,15 @@ async function applyDiagnosticFix(fix, options = {}) {
10867
11162
  source = parse3(file, withImport);
10868
11163
  const object = unique(moduleObjects(source).filter((candidate) => !fix.targetModule || stringProperty(candidate, "name") === fix.targetModule), "target module");
10869
11164
  const imports = property(object, "imports");
10870
- if (imports && !ts9.isArrayLiteralExpression(imports.initializer)) {
11165
+ if (imports && !ts11.isArrayLiteralExpression(imports.initializer)) {
10871
11166
  throw new Error("Module imports must be a static array");
10872
11167
  }
10873
- const values = imports && ts9.isArrayLiteralExpression(imports.initializer) ? imports.initializer.elements : [];
10874
- if (values.some(ts9.isSpreadElement))
11168
+ const values = imports && ts11.isArrayLiteralExpression(imports.initializer) ? imports.initializer.elements : [];
11169
+ if (values.some(ts11.isSpreadElement))
10875
11170
  throw new Error("Module imports cannot contain spread elements");
10876
- content = values.some((value) => ts9.isIdentifier(value) && value.text === fix.symbol) ? withImport : replaceProperty(source, object, "imports", ts9.factory.createArrayLiteralExpression([
11171
+ content = values.some((value) => ts11.isIdentifier(value) && value.text === fix.symbol) ? withImport : replaceProperty(source, object, "imports", ts11.factory.createArrayLiteralExpression([
10877
11172
  ...values,
10878
- ts9.factory.createIdentifier(fix.symbol)
11173
+ ts11.factory.createIdentifier(fix.symbol)
10879
11174
  ]));
10880
11175
  break;
10881
11176
  }
@@ -10887,24 +11182,24 @@ async function applyDiagnosticFix(fix, options = {}) {
10887
11182
  const command = findClass(source, fix.command);
10888
11183
  const object = decoratorObject(command, "Command");
10889
11184
  const current = property(object, "permission");
10890
- if (current && (!ts9.isStringLiteral(current.initializer) || current.initializer.text !== permission)) {
11185
+ if (current && (!ts11.isStringLiteral(current.initializer) || current.initializer.text !== permission)) {
10891
11186
  throw new Error("Command permission already exists with a different value");
10892
11187
  }
10893
- content = current ? original : replaceProperty(source, object, "permission", ts9.factory.createStringLiteral(permission));
11188
+ content = current ? original : replaceProperty(source, object, "permission", ts11.factory.createStringLiteral(permission));
10894
11189
  break;
10895
11190
  }
10896
11191
  case "add_route_parameter_binding": {
10897
11192
  const controller = findClass(source, fix.controller);
10898
- const method = unique(controller.members.filter((member) => ts9.isMethodDeclaration(member) && nameOf(member.name) === fix.route), "route handler");
10899
- const parameter = unique(method.parameters.filter((candidate) => ts9.isIdentifier(candidate.name) && candidate.name.text === fix.parameter), "same-named route parameter");
11193
+ const method = unique(controller.members.filter((member) => ts11.isMethodDeclaration(member) && nameOf(member.name) === fix.route), "route handler");
11194
+ const parameter = unique(method.parameters.filter((candidate) => ts11.isIdentifier(candidate.name) && candidate.name.text === fix.parameter), "same-named route parameter");
10900
11195
  const binding = fix.binding === "param" ? "Param" : fix.binding === "query" ? "Query" : undefined;
10901
11196
  if (!binding)
10902
11197
  throw new Error("Invalid route binding");
10903
- const decorators = ts9.getDecorators(parameter) ?? [];
11198
+ const decorators = ts11.getDecorators(parameter) ?? [];
10904
11199
  if (decorators.length > 0)
10905
11200
  throw new Error("Parameter already has a decorator");
10906
- const framework = unique(source.statements.filter((statement) => ts9.isImportDeclaration(statement) && statement.importClause?.namedBindings && ts9.isNamedImports(statement.importClause.namedBindings) && statement.importClause.namedBindings.elements.some((element) => ["Controller", "Get", "Post", "Put", "Patch", "Delete", "Head", "Options"].includes(element.name.text))), "framework import");
10907
- if (!ts9.isImportDeclaration(framework) || !ts9.isStringLiteral(framework.moduleSpecifier)) {
11201
+ const framework = unique(source.statements.filter((statement) => ts11.isImportDeclaration(statement) && statement.importClause?.namedBindings && ts11.isNamedImports(statement.importClause.namedBindings) && statement.importClause.namedBindings.elements.some((element) => ["Controller", "Get", "Post", "Put", "Patch", "Delete", "Head", "Options"].includes(element.name.text))), "framework import");
11202
+ if (!ts11.isImportDeclaration(framework) || !ts11.isStringLiteral(framework.moduleSpecifier)) {
10908
11203
  throw new Error("Framework import must be static");
10909
11204
  }
10910
11205
  const edited = original.slice(0, parameter.getStart(source)) + `@${binding}(${JSON.stringify(fix.parameter)}) ` + original.slice(parameter.getStart(source));
@@ -10930,15 +11225,15 @@ async function applyDiagnosticFix(fix, options = {}) {
10930
11225
  return result;
10931
11226
  }
10932
11227
  function parse3(file, text) {
10933
- const result = ts9.transpileModule(text, {
11228
+ const result = ts11.transpileModule(text, {
10934
11229
  fileName: file,
10935
11230
  reportDiagnostics: true,
10936
- compilerOptions: { target: ts9.ScriptTarget.ESNext, experimentalDecorators: true }
11231
+ compilerOptions: { target: ts11.ScriptTarget.ESNext, experimentalDecorators: true }
10937
11232
  });
10938
- if (result.diagnostics?.some((item) => item.category === ts9.DiagnosticCategory.Error)) {
11233
+ if (result.diagnostics?.some((item) => item.category === ts11.DiagnosticCategory.Error)) {
10939
11234
  throw new Error("Cannot fix syntactically invalid TypeScript");
10940
11235
  }
10941
- return ts9.createSourceFile(file, text, ts9.ScriptTarget.Latest, true, ts9.ScriptKind.TS);
11236
+ return ts11.createSourceFile(file, text, ts11.ScriptTarget.Latest, true, ts11.ScriptKind.TS);
10942
11237
  }
10943
11238
  function unique(items, description) {
10944
11239
  if (items.length !== 1)
@@ -10952,50 +11247,50 @@ function identifier(value) {
10952
11247
  function nameOf(name) {
10953
11248
  if (!name)
10954
11249
  return "";
10955
- return ts9.isIdentifier(name) || ts9.isStringLiteral(name) || ts9.isNumericLiteral(name) ? name.text : "";
11250
+ return ts11.isIdentifier(name) || ts11.isStringLiteral(name) || ts11.isNumericLiteral(name) ? name.text : "";
10956
11251
  }
10957
11252
  function property(object, key) {
10958
- if (object.properties.some((item) => !ts9.isPropertyAssignment(item) || ts9.isComputedPropertyName(item.name))) {
11253
+ if (object.properties.some((item) => !ts11.isPropertyAssignment(item) || ts11.isComputedPropertyName(item.name))) {
10959
11254
  throw new Error("Fix requires explicit static object properties");
10960
11255
  }
10961
- const values = object.properties.filter((item) => ts9.isPropertyAssignment(item) && nameOf(item.name) === key);
11256
+ const values = object.properties.filter((item) => ts11.isPropertyAssignment(item) && nameOf(item.name) === key);
10962
11257
  if (values.length > 1)
10963
11258
  throw new Error(`Duplicate '${key}' property`);
10964
11259
  return values[0];
10965
11260
  }
10966
11261
  function stringProperty(object, key) {
10967
11262
  const value = property(object, key)?.initializer;
10968
- return value && ts9.isStringLiteral(value) ? value.text : undefined;
11263
+ return value && ts11.isStringLiteral(value) ? value.text : undefined;
10969
11264
  }
10970
11265
  function replaceProperty(source, object, key, value) {
10971
11266
  const previous = property(object, key);
10972
- const replacement = ts9.factory.createPropertyAssignment(key, value);
11267
+ const replacement = ts11.factory.createPropertyAssignment(key, value);
10973
11268
  const properties = object.properties.map((item) => item === previous ? replacement : item);
10974
11269
  if (!previous)
10975
11270
  properties.push(replacement);
10976
- const updated = ts9.factory.updateObjectLiteralExpression(object, properties);
10977
- return source.text.slice(0, object.getStart(source)) + ts9.createPrinter().printNode(ts9.EmitHint.Expression, updated, source) + source.text.slice(object.end);
11271
+ const updated = ts11.factory.updateObjectLiteralExpression(object, properties);
11272
+ return source.text.slice(0, object.getStart(source)) + ts11.createPrinter().printNode(ts11.EmitHint.Expression, updated, source) + source.text.slice(object.end);
10978
11273
  }
10979
11274
  function findClass(source, name) {
10980
- return unique(source.statements.filter((statement) => ts9.isClassDeclaration(statement) && statement.name?.text === name), `class '${name}'`);
11275
+ return unique(source.statements.filter((statement) => ts11.isClassDeclaration(statement) && statement.name?.text === name), `class '${name}'`);
10981
11276
  }
10982
11277
  function decoratorObject(node, name) {
10983
- const decorator = unique((ts9.getDecorators(node) ?? []).filter((item) => ts9.isCallExpression(item.expression) && item.expression.expression.getText() === name), `@${name} decorator`);
10984
- const argument = ts9.isCallExpression(decorator.expression) ? decorator.expression.arguments[0] : undefined;
10985
- if (!argument || !ts9.isObjectLiteralExpression(argument))
11278
+ const decorator = unique((ts11.getDecorators(node) ?? []).filter((item) => ts11.isCallExpression(item.expression) && item.expression.expression.getText() === name), `@${name} decorator`);
11279
+ const argument = ts11.isCallExpression(decorator.expression) ? decorator.expression.arguments[0] : undefined;
11280
+ if (!argument || !ts11.isObjectLiteralExpression(argument))
10986
11281
  throw new Error(`@${name} requires a static object`);
10987
11282
  return argument;
10988
11283
  }
10989
11284
  function moduleObjects(source) {
10990
11285
  const result = [];
10991
11286
  for (const statement of source.statements) {
10992
- if (ts9.isClassDeclaration(statement) && (ts9.getDecorators(statement) ?? []).some((item) => ts9.isCallExpression(item.expression) && item.expression.expression.getText() === "Module")) {
11287
+ if (ts11.isClassDeclaration(statement) && (ts11.getDecorators(statement) ?? []).some((item) => ts11.isCallExpression(item.expression) && item.expression.expression.getText() === "Module")) {
10993
11288
  result.push(decoratorObject(statement, "Module"));
10994
11289
  }
10995
- if (ts9.isVariableStatement(statement)) {
11290
+ if (ts11.isVariableStatement(statement)) {
10996
11291
  for (const declaration of statement.declarationList.declarations) {
10997
11292
  const call = declaration.initializer;
10998
- if (call && ts9.isCallExpression(call) && ["defineModule", "defineFeatureSlice"].includes(call.expression.getText()) && call.arguments[0] && ts9.isObjectLiteralExpression(call.arguments[0])) {
11293
+ if (call && ts11.isCallExpression(call) && ["defineModule", "defineFeatureSlice"].includes(call.expression.getText()) && call.arguments[0] && ts11.isObjectLiteralExpression(call.arguments[0])) {
10999
11294
  result.push(call.arguments[0]);
11000
11295
  }
11001
11296
  }
@@ -11009,19 +11304,19 @@ function importSymbol(source, path, symbol) {
11009
11304
  const target = resolve8(dirname6(source.fileName), path).replace(/\.(tsx?|mts|cts)$/, "");
11010
11305
  if (current === target)
11011
11306
  return source.text;
11012
- const matches = source.statements.filter((item) => ts9.isImportDeclaration(item) && ts9.isStringLiteral(item.moduleSpecifier) && item.moduleSpecifier.text === path);
11307
+ const matches = source.statements.filter((item) => ts11.isImportDeclaration(item) && ts11.isStringLiteral(item.moduleSpecifier) && item.moduleSpecifier.text === path);
11013
11308
  if (matches.length > 1)
11014
11309
  throw new Error(`Ambiguous imports from '${path}'`);
11015
11310
  const match = matches[0];
11016
- if (match && ts9.isImportDeclaration(match) && match.importClause?.namedBindings && ts9.isNamedImports(match.importClause.namedBindings) && !match.importClause.isTypeOnly) {
11311
+ if (match && ts11.isImportDeclaration(match) && match.importClause?.namedBindings && ts11.isNamedImports(match.importClause.namedBindings) && !match.importClause.isTypeOnly) {
11017
11312
  if (match.importClause.namedBindings.elements.some((item) => item.name.text === symbol))
11018
11313
  return source.text;
11019
11314
  const bindings = match.importClause.namedBindings;
11020
- const updated = ts9.factory.updateNamedImports(bindings, [
11315
+ const updated = ts11.factory.updateNamedImports(bindings, [
11021
11316
  ...bindings.elements,
11022
- ts9.factory.createImportSpecifier(false, undefined, ts9.factory.createIdentifier(symbol))
11317
+ ts11.factory.createImportSpecifier(false, undefined, ts11.factory.createIdentifier(symbol))
11023
11318
  ]);
11024
- return source.text.slice(0, bindings.getStart(source)) + ts9.createPrinter().printNode(ts9.EmitHint.Unspecified, updated, source) + source.text.slice(bindings.end);
11319
+ return source.text.slice(0, bindings.getStart(source)) + ts11.createPrinter().printNode(ts11.EmitHint.Unspecified, updated, source) + source.text.slice(bindings.end);
11025
11320
  }
11026
11321
  if (match)
11027
11322
  throw new Error(`Import from '${path}' is not a named value import`);
@@ -11436,7 +11731,7 @@ function watchProject(options) {
11436
11731
  // src/migrations.ts
11437
11732
  import { rename as rename5, readFile as readFile9, writeFile as writeFile4, rm as rm3 } from "node:fs/promises";
11438
11733
  import { relative as relative10, resolve as resolve12 } from "node:path";
11439
- import * as ts10 from "@typescript/typescript6";
11734
+ import * as ts12 from "@typescript/typescript6";
11440
11735
 
11441
11736
  // src/migration-policy.ts
11442
11737
  import { readFile as readFile8 } from "node:fs/promises";
@@ -11457,7 +11752,7 @@ function migrationDependencies() {
11457
11752
  return {
11458
11753
  "@supacloud/app": "0.14.0",
11459
11754
  "@supacloud/compiler": compilerVersion(),
11460
- "@supacloud/elysia": "0.16.0",
11755
+ "@supacloud/elysia": "0.17.0",
11461
11756
  elysia: "1.4.30",
11462
11757
  typescript: "7.0.2"
11463
11758
  };
@@ -11480,29 +11775,29 @@ async function checkMigrationDependencies(rootDir) {
11480
11775
  // src/migrations.ts
11481
11776
  var ROUTE_DECORATORS2 = new Set(["Get", "Post", "Put", "Patch", "Delete", "Head", "Options"]);
11482
11777
  var MIGRATION_COMPILER_OPTIONS = {
11483
- target: ts10.ScriptTarget.ES2022,
11484
- module: ts10.ModuleKind.ESNext,
11485
- moduleResolution: ts10.ModuleResolutionKind.Bundler,
11778
+ target: ts12.ScriptTarget.ES2022,
11779
+ module: ts12.ModuleKind.ESNext,
11780
+ moduleResolution: ts12.ModuleResolutionKind.Bundler,
11486
11781
  noEmit: true,
11487
11782
  skipLibCheck: true
11488
11783
  };
11489
11784
  function migrationCompilerOptions(rootDir) {
11490
11785
  if (!rootDir)
11491
11786
  return MIGRATION_COMPILER_OPTIONS;
11492
- const configPath = ts10.findConfigFile(rootDir, ts10.sys.fileExists);
11787
+ const configPath = ts12.findConfigFile(rootDir, ts12.sys.fileExists);
11493
11788
  if (!configPath)
11494
11789
  return MIGRATION_COMPILER_OPTIONS;
11495
11790
  const configHost = {
11496
- ...ts10.sys,
11791
+ ...ts12.sys,
11497
11792
  onUnRecoverableConfigFileDiagnostic: (_diagnostic) => {}
11498
11793
  };
11499
- const parsed = ts10.getParsedCommandLineOfConfigFile(configPath, {}, configHost);
11794
+ const parsed = ts12.getParsedCommandLineOfConfigFile(configPath, {}, configHost);
11500
11795
  if (!parsed || parsed.errors.length > 0)
11501
11796
  return MIGRATION_COMPILER_OPTIONS;
11502
11797
  return { ...parsed.options, noEmit: true, skipLibCheck: true };
11503
11798
  }
11504
11799
  function propertyName2(property) {
11505
- if (ts10.isIdentifier(property) || ts10.isStringLiteral(property) || ts10.isNumericLiteral(property))
11800
+ if (ts12.isIdentifier(property) || ts12.isStringLiteral(property) || ts12.isNumericLiteral(property))
11506
11801
  return property.text;
11507
11802
  return;
11508
11803
  }
@@ -11512,7 +11807,7 @@ function lineOf2(sourceFile, node) {
11512
11807
  function resolveSymbol(symbol, checker) {
11513
11808
  if (!symbol)
11514
11809
  return;
11515
- for (let guard = 0;guard < 4 && (symbol.flags & ts10.SymbolFlags.Alias) !== 0; guard += 1) {
11810
+ for (let guard = 0;guard < 4 && (symbol.flags & ts12.SymbolFlags.Alias) !== 0; guard += 1) {
11516
11811
  const aliased = checker.getAliasedSymbol(symbol);
11517
11812
  if (aliased === symbol)
11518
11813
  break;
@@ -11521,12 +11816,12 @@ function resolveSymbol(symbol, checker) {
11521
11816
  return symbol;
11522
11817
  }
11523
11818
  function symbolForExpression(expression, checker) {
11524
- const location = ts10.isIdentifier(expression) ? expression : ts10.isPropertyAccessExpression(expression) ? expression.name : ts10.isElementAccessExpression(expression) && expression.argumentExpression && ts10.isStringLiteral(expression.argumentExpression) ? expression : undefined;
11819
+ const location = ts12.isIdentifier(expression) ? expression : ts12.isPropertyAccessExpression(expression) ? expression.name : ts12.isElementAccessExpression(expression) && expression.argumentExpression && ts12.isStringLiteral(expression.argumentExpression) ? expression : undefined;
11525
11820
  return location ? resolveSymbol(checker.getSymbolAtLocation(location), checker) : undefined;
11526
11821
  }
11527
11822
  function unwrapExpression(expression) {
11528
11823
  let current = expression;
11529
- while (ts10.isAsExpression(current) || ts10.isSatisfiesExpression(current) || ts10.isParenthesizedExpression(current) || ts10.isTypeAssertionExpression(current)) {
11824
+ while (ts12.isAsExpression(current) || ts12.isSatisfiesExpression(current) || ts12.isParenthesizedExpression(current) || ts12.isTypeAssertionExpression(current)) {
11530
11825
  current = current.expression;
11531
11826
  }
11532
11827
  return current;
@@ -11539,7 +11834,7 @@ function isDefineRouteContractCall(node, checker) {
11539
11834
  }
11540
11835
  function isRouteDecoratorCall(node, checker) {
11541
11836
  const name = node.expression.getText(node.getSourceFile());
11542
- if (ts10.isIdentifier(node.expression) && ROUTE_DECORATORS2.has(node.expression.text))
11837
+ if (ts12.isIdentifier(node.expression) && ROUTE_DECORATORS2.has(node.expression.text))
11543
11838
  return true;
11544
11839
  if (ROUTE_DECORATORS2.has(name))
11545
11840
  return true;
@@ -11553,14 +11848,14 @@ function resolveStaticObjectLiteral2(input, checker, seen = new Set) {
11553
11848
  if (seen.has(expression))
11554
11849
  return;
11555
11850
  seen.add(expression);
11556
- if (ts10.isObjectLiteralExpression(expression))
11851
+ if (ts12.isObjectLiteralExpression(expression))
11557
11852
  return expression;
11558
- if (ts10.isCallExpression(expression) && isDefineRouteContractCall(expression, checker)) {
11853
+ if (ts12.isCallExpression(expression) && isDefineRouteContractCall(expression, checker)) {
11559
11854
  return resolveStaticObjectLiteral2(expression.arguments[0], checker, seen);
11560
11855
  }
11561
11856
  const symbol = symbolForExpression(expression, checker);
11562
11857
  for (const declaration of symbol?.declarations ?? []) {
11563
- if (ts10.isVariableDeclaration(declaration) && declaration.initializer) {
11858
+ if (ts12.isVariableDeclaration(declaration) && declaration.initializer) {
11564
11859
  const resolved = resolveStaticObjectLiteral2(declaration.initializer, checker, seen);
11565
11860
  if (resolved)
11566
11861
  return resolved;
@@ -11574,7 +11869,7 @@ function displayFile(rootDir, fileName) {
11574
11869
  }
11575
11870
  function createMigrationProgram(fileNames, sourceOverrides, rootDir) {
11576
11871
  const compilerOptions = migrationCompilerOptions(rootDir);
11577
- const host = ts10.createCompilerHost(compilerOptions);
11872
+ const host = ts12.createCompilerHost(compilerOptions);
11578
11873
  const getSourceFile = host.getSourceFile.bind(host);
11579
11874
  const fileExists = host.fileExists.bind(host);
11580
11875
  const readFile = host.readFile.bind(host);
@@ -11583,16 +11878,16 @@ function createMigrationProgram(fileNames, sourceOverrides, rootDir) {
11583
11878
  host.readFile = (fileName) => sourceOverrides.get(resolve12(fileName)) ?? readFile(fileName);
11584
11879
  host.getSourceFile = (fileName, languageVersion, onError, shouldCreateNewSourceFile) => {
11585
11880
  const source = sourceOverrides.get(resolve12(fileName));
11586
- return source === undefined ? getSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile) : ts10.createSourceFile(fileName, source, languageVersion, true);
11881
+ return source === undefined ? getSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile) : ts12.createSourceFile(fileName, source, languageVersion, true);
11587
11882
  };
11588
11883
  host.getCurrentDirectory = () => rootDir ?? currentDirectory();
11589
- return ts10.createProgram(fileNames, compilerOptions, host);
11884
+ return ts12.createProgram(fileNames, compilerOptions, host);
11590
11885
  }
11591
11886
  function routeResponseProperties(object) {
11592
- const responseProperties = object.properties.filter((property) => ts10.isPropertyAssignment(property) && propertyName2(property.name) === "response");
11887
+ const responseProperties = object.properties.filter((property) => ts12.isPropertyAssignment(property) && propertyName2(property.name) === "response");
11593
11888
  return {
11594
11889
  response: responseProperties[0],
11595
- hasResponses: object.properties.some((property) => (ts10.isPropertyAssignment(property) || ts10.isShorthandPropertyAssignment(property)) && propertyName2(property.name) === "responses"),
11890
+ hasResponses: object.properties.some((property) => (ts12.isPropertyAssignment(property) || ts12.isShorthandPropertyAssignment(property)) && propertyName2(property.name) === "responses"),
11596
11891
  duplicateResponse: responseProperties.length > 1
11597
11892
  };
11598
11893
  }
@@ -11612,7 +11907,7 @@ function planRouteResponseMigration(sourceFiles, checker, rootDir, includedFiles
11612
11907
  if (!includedFiles.has(sourcePath))
11613
11908
  continue;
11614
11909
  const visit = (node) => {
11615
- if (ts10.isCallExpression(node) && isRouteDecoratorCall(node, checker)) {
11910
+ if (ts12.isCallExpression(node) && isRouteDecoratorCall(node, checker)) {
11616
11911
  const options = node.arguments[1];
11617
11912
  const object = options && resolveStaticObjectLiteral2(options, checker);
11618
11913
  if (object) {
@@ -11632,7 +11927,7 @@ function planRouteResponseMigration(sourceFiles, checker, rootDir, includedFiles
11632
11927
  }
11633
11928
  }
11634
11929
  }
11635
- ts10.forEachChild(node, visit);
11930
+ ts12.forEachChild(node, visit);
11636
11931
  };
11637
11932
  visit(sourceFile);
11638
11933
  }
@@ -11792,7 +12087,7 @@ async function migrateProject(options) {
11792
12087
  }
11793
12088
  }
11794
12089
  const include = options.include ?? ["**/*.ts", "**/*.tsx", "**/*.mts", "**/*.cts"];
11795
- const files = ts10.sys.readDirectory(rootDir, [".ts", ".tsx", ".mts", ".cts"], ["node_modules", "dist", "generated"], include).sort();
12090
+ const files = ts12.sys.readDirectory(rootDir, [".ts", ".tsx", ".mts", ".cts"], ["node_modules", "dist", "generated"], include).sort();
11796
12091
  const results = [];
11797
12092
  const issues = [];
11798
12093
  const pendingWrites = new Map;
@@ -12793,6 +13088,7 @@ function compileOptionsFromConfig(config, cwd = process.cwd()) {
12793
13088
 
12794
13089
  // src/index.ts
12795
13090
  init_graphql_schema();
13091
+ init_database_contracts();
12796
13092
  export {
12797
13093
  ANGULAR_ENTERPRISE_RULES,
12798
13094
  CLEAN_ARCHITECTURE_RULES,
@@ -12809,6 +13105,7 @@ export {
12809
13105
  MODULE_BOUNDARY_PROFILES,
12810
13106
  ModuleDependencyGraph,
12811
13107
  OpenApiDocumentError,
13108
+ SQL_SAFETY_DIAGNOSTIC_CODES,
12812
13109
  SUPACLOUD_MIGRATIONS,
12813
13110
  TYPE_SAFETY_DIAGNOSTIC_CODES,
12814
13111
  TraitCompiler,
@@ -12837,6 +13134,7 @@ export {
12837
13134
  formatGraph,
12838
13135
  formatOpenApiDiff,
12839
13136
  generateApplication,
13137
+ generateDatabaseContracts,
12840
13138
  generateFeatureSource,
12841
13139
  getModuleBoundaryPreset,
12842
13140
  getModuleBoundaryProfile,
@@ -12845,6 +13143,7 @@ export {
12845
13143
  loadSupacloudConfig,
12846
13144
  migrateProject,
12847
13145
  migrateRouteResponse,
13146
+ parseDatabaseContractsOptions,
12848
13147
  parseDeliveryBuildManifest,
12849
13148
  parseDeliveryBuildResult,
12850
13149
  parseDeliveryOptions,
@@ -12858,6 +13157,8 @@ export {
12858
13157
  renderOpenApi,
12859
13158
  resolveModuleBoundaries,
12860
13159
  resolveSupacloudConfig,
13160
+ runDatabaseContractsFile,
13161
+ scanDrizzleSql,
12861
13162
  scanGeneratedArtifacts,
12862
13163
  scanProductionSource,
12863
13164
  serializeOpenApiJson,