@supacloud/compiler 0.28.0 → 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1663,6 +1663,12 @@ class ModuleGenerator {
1663
1663
  }
1664
1664
  renderFactories() {
1665
1665
  const sections = [this.renderServicesFactory()];
1666
+ if (this.hasApplicationLifecycle("init")) {
1667
+ sections.push(this.renderApplicationLifecycle("init"));
1668
+ }
1669
+ if (this.hasApplicationLifecycle("destroy")) {
1670
+ sections.push(this.renderApplicationLifecycle("destroy"));
1671
+ }
1666
1672
  if (this.hasFactoryContent("request")) {
1667
1673
  sections.push(this.renderScopeFactory("request"));
1668
1674
  sections.push(this.renderScopeDestroyer("request"));
@@ -1679,6 +1685,12 @@ class ModuleGenerator {
1679
1685
  ` name: ${JSON.stringify(this.module.name)} as const,`,
1680
1686
  ` createServices: create${this.pascal}Services,`
1681
1687
  ];
1688
+ if (this.hasApplicationLifecycle("init")) {
1689
+ lines.push(` initializeServices: initialize${this.pascal}Services,`);
1690
+ }
1691
+ if (this.hasApplicationLifecycle("destroy")) {
1692
+ lines.push(` destroyServices: destroy${this.pascal}Services,`);
1693
+ }
1682
1694
  if (this.hasFactoryContent("request")) {
1683
1695
  lines.push(` createRequestScope: create${this.pascal}RequestScope,`);
1684
1696
  lines.push(` destroyRequestScope: destroy${this.pascal}RequestScope,`);
@@ -1701,6 +1713,40 @@ class ModuleGenerator {
1701
1713
  hasFactoryContent(kind) {
1702
1714
  return this.module.providers.some((p) => factoryOfScope(p.scope) === kind) || this.module.controllers.some((c) => factoryOfScope(c.scope) === kind);
1703
1715
  }
1716
+ hasApplicationLifecycle(kind) {
1717
+ return this.applicationLifecyclePlan(kind).length > 0;
1718
+ }
1719
+ applicationLifecyclePlan(kind) {
1720
+ const result = [];
1721
+ const multiIndices = new Map;
1722
+ for (const provider of orderProviders(this.module.providers.filter((p) => factoryOfScope(p.scope) === "services"))) {
1723
+ const index = provider.multi ? multiIndices.get(provider.token) ?? 0 : undefined;
1724
+ if (index !== undefined)
1725
+ multiIndices.set(provider.token, index + 1);
1726
+ const owned = provider.kind !== "existing";
1727
+ const selected = kind === "init" ? provider.hasOnInit : provider.hasOnDestroy;
1728
+ if (owned && selected)
1729
+ result.push({ key: camelName(provider.token), ...index === undefined ? {} : { index } });
1730
+ }
1731
+ for (const controller of this.module.controllers) {
1732
+ if (factoryOfScope(controller.scope) !== "services")
1733
+ continue;
1734
+ const selected = kind === "init" ? controller.hasOnInit : controller.hasOnDestroy;
1735
+ if (selected)
1736
+ result.push({ key: camelName(controller.className) });
1737
+ }
1738
+ return result;
1739
+ }
1740
+ renderApplicationLifecycle(kind) {
1741
+ const suffix = kind === "init" ? "initialize" : "destroy";
1742
+ const helper = kind === "init" ? "initializeServiceInstances" : "destroyServiceInstances";
1743
+ return [
1744
+ `async function ${suffix}${this.pascal}Services(services: Record<string, unknown>): Promise<void> {`,
1745
+ ` await ${helper}(services, ${JSON.stringify(this.applicationLifecyclePlan(kind))});`,
1746
+ `}`
1747
+ ].join(`
1748
+ `);
1749
+ }
1704
1750
  renderControllers() {
1705
1751
  if (this.module.controllers.length === 0)
1706
1752
  return "[]";
@@ -3419,6 +3465,10 @@ export interface CompiledModule {
3419
3465
  deps: Record<string, unknown>,
3420
3466
  imported: Record<string, Record<string, unknown>>,
3421
3467
  ): Record<string, unknown>;
3468
+ /** Initializes application-scoped instances owned by this module. */
3469
+ initializeServices?(services: Record<string, unknown>): Promise<void>;
3470
+ /** Destroys application-scoped instances owned by this module. */
3471
+ destroyServices?(services: Record<string, unknown>): Promise<void>;
3422
3472
  createRequestScope?(
3423
3473
  services: Record<string, unknown>,
3424
3474
  ctx: unknown,
@@ -3502,7 +3552,54 @@ function destroyScopeInstances(
3502
3552
  });
3503
3553
  scopeDestructions.set(scope, destruction);
3504
3554
  return destruction;
3505
- }`;
3555
+ }
3556
+
3557
+ type CompiledServiceLifecycleEntry = { key: string; index?: number };
3558
+
3559
+ async function initializeServiceInstances(
3560
+ services: Record<string, unknown>,
3561
+ plan: readonly CompiledServiceLifecycleEntry[],
3562
+ ): Promise<void> {
3563
+ const seen = new Set<unknown>();
3564
+ for (const entry of plan) {
3565
+ const value = services[entry.key];
3566
+ const instance = entry.index === undefined
3567
+ ? value
3568
+ : Array.isArray(value) ? value[entry.index] : undefined;
3569
+ if (seen.has(instance)) continue;
3570
+ seen.add(instance);
3571
+ if (!isRecord(instance) || !isFunction(instance.onInit)) continue;
3572
+ await instance.onInit();
3573
+ }
3574
+ }
3575
+
3576
+ async function destroyServiceInstances(
3577
+ services: Record<string, unknown>,
3578
+ plan: readonly CompiledServiceLifecycleEntry[],
3579
+ ): Promise<void> {
3580
+ const errors: unknown[] = [];
3581
+ const seen = new Set<unknown>();
3582
+ for (const entry of [...plan].reverse()) {
3583
+ const value = services[entry.key];
3584
+ const instance = entry.index === undefined
3585
+ ? value
3586
+ : Array.isArray(value) ? value[entry.index] : undefined;
3587
+ if (seen.has(instance)) continue;
3588
+ seen.add(instance);
3589
+ if (!isRecord(instance)) continue;
3590
+ const hook = isFunction(instance.onDestroy)
3591
+ ? instance.onDestroy
3592
+ : isFunction(instance.ngOnDestroy) ? instance.ngOnDestroy : undefined;
3593
+ if (!hook) continue;
3594
+ try {
3595
+ await hook.call(instance);
3596
+ } catch (error) {
3597
+ errors.push(error);
3598
+ }
3599
+ }
3600
+ if (errors.length > 0) throw new AggregateError(errors, "Application service destruction failed");
3601
+ }
3602
+ `;
3506
3603
  var init_generate = __esm(() => {
3507
3604
  init_contract_manifest();
3508
3605
  });
@@ -3724,8 +3821,8 @@ var init_graphql_options = __esm(() => {
3724
3821
  });
3725
3822
 
3726
3823
  // src/graphql-inputs.ts
3727
- import { resolve as resolve3 } from "node:path";
3728
- import * as ts7 from "@typescript/typescript6";
3824
+ import { resolve as resolve4 } from "node:path";
3825
+ import * as ts10 from "@typescript/typescript6";
3729
3826
  function graphqlInputPaths(options) {
3730
3827
  if (!options.graphql)
3731
3828
  return [];
@@ -3734,9 +3831,9 @@ function graphqlInputPaths(options) {
3734
3831
  } catch {
3735
3832
  return [];
3736
3833
  }
3737
- const root = resolve3(options.rootDir);
3738
- const schema = resolve3(root, options.graphql.schema);
3739
- 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);
3834
+ const root = resolve4(options.rootDir);
3835
+ const schema = resolve4(root, options.graphql.schema);
3836
+ const documents = ts10.sys.readDirectory(root, [".graphql", ".gql"], ["**/node_modules/**", "**/.git/**", resolve4(options.outDir)], options.graphql.documents ?? ["**/*.graphql", "**/*.gql"]).map((path) => resolve4(path)).filter((path) => path !== schema);
3740
3837
  return [schema, ...[...new Set(documents)].sort()];
3741
3838
  }
3742
3839
  var init_graphql_inputs = __esm(() => {
@@ -3744,10 +3841,10 @@ var init_graphql_inputs = __esm(() => {
3744
3841
  });
3745
3842
 
3746
3843
  // src/graphql-runtime.ts
3747
- import * as ts8 from "@typescript/typescript6";
3748
- import { resolve as resolve4 } from "node:path";
3844
+ import * as ts11 from "@typescript/typescript6";
3845
+ import { resolve as resolve5 } from "node:path";
3749
3846
  function renderGraphqlValidators(source, operationNames) {
3750
- const fileName = resolve4("/__supacloud_graphql__/contracts.ts");
3847
+ const fileName = resolve5("/__supacloud_graphql__/contracts.ts");
3751
3848
  const options = {
3752
3849
  strict: true,
3753
3850
  noUncheckedIndexedAccess: true,
@@ -3756,18 +3853,18 @@ function renderGraphqlValidators(source, operationNames) {
3756
3853
  noPropertyAccessFromIndexSignature: true,
3757
3854
  noFallthroughCasesInSwitch: true,
3758
3855
  skipLibCheck: false,
3759
- target: ts8.ScriptTarget.ES2022,
3856
+ target: ts11.ScriptTarget.ES2022,
3760
3857
  lib: ["lib.es2022.d.ts"],
3761
3858
  types: [],
3762
3859
  noEmit: true
3763
3860
  };
3764
- const host = ts8.createCompilerHost(options);
3861
+ const host = ts11.createCompilerHost(options);
3765
3862
  const getSourceFile = host.getSourceFile.bind(host);
3766
- host.getSourceFile = (path, languageVersion, onError, shouldCreateNewSourceFile) => resolve4(path) === fileName ? ts8.createSourceFile(path, source, languageVersion, true) : getSourceFile(path, languageVersion, onError, shouldCreateNewSourceFile);
3767
- const program = ts8.createProgram([fileName], options, host);
3768
- const diagnostics = ts8.getPreEmitDiagnostics(program);
3863
+ host.getSourceFile = (path, languageVersion, onError, shouldCreateNewSourceFile) => resolve5(path) === fileName ? ts11.createSourceFile(path, source, languageVersion, true) : getSourceFile(path, languageVersion, onError, shouldCreateNewSourceFile);
3864
+ const program = ts11.createProgram([fileName], options, host);
3865
+ const diagnostics = ts11.getPreEmitDiagnostics(program);
3769
3866
  if (diagnostics.length) {
3770
- throw new Error(`Generated GraphQL types cannot be validated: ${diagnostics.map((item) => ts8.flattenDiagnosticMessageText(item.messageText, `
3867
+ throw new Error(`Generated GraphQL types cannot be validated: ${diagnostics.map((item) => ts11.flattenDiagnosticMessageText(item.messageText, `
3771
3868
  `)).join("; ")}`);
3772
3869
  }
3773
3870
  const checker = program.getTypeChecker();
@@ -3797,25 +3894,25 @@ function renderGraphqlValidators(source, operationNames) {
3797
3894
  return name;
3798
3895
  }
3799
3896
  function expression(type) {
3800
- if (type.flags & ts8.TypeFlags.Any)
3897
+ if (type.flags & ts11.TypeFlags.Any)
3801
3898
  return unsupported(type);
3802
- if (type.flags & ts8.TypeFlags.Unknown)
3899
+ if (type.flags & ts11.TypeFlags.Unknown)
3803
3900
  return "true";
3804
- if (type.flags & ts8.TypeFlags.Never)
3901
+ if (type.flags & ts11.TypeFlags.Never)
3805
3902
  return "false";
3806
- if (type.flags & ts8.TypeFlags.Null)
3903
+ if (type.flags & ts11.TypeFlags.Null)
3807
3904
  return "value === null";
3808
- if (type.flags & ts8.TypeFlags.Undefined)
3905
+ if (type.flags & ts11.TypeFlags.Undefined)
3809
3906
  return "value === undefined";
3810
3907
  if (type.isStringLiteral() || type.isNumberLiteral())
3811
3908
  return `value === ${JSON.stringify(type.value)}`;
3812
- if (type.flags & ts8.TypeFlags.BooleanLiteral)
3909
+ if (type.flags & ts11.TypeFlags.BooleanLiteral)
3813
3910
  return `value === ${checker.typeToString(type)}`;
3814
- if (type.flags & ts8.TypeFlags.String)
3911
+ if (type.flags & ts11.TypeFlags.String)
3815
3912
  return 'typeof value === "string"';
3816
- if (type.flags & ts8.TypeFlags.Number)
3913
+ if (type.flags & ts11.TypeFlags.Number)
3817
3914
  return 'typeof value === "number" && Number.isFinite(value)';
3818
- if (type.flags & ts8.TypeFlags.Boolean)
3915
+ if (type.flags & ts11.TypeFlags.Boolean)
3819
3916
  return 'typeof value === "boolean"';
3820
3917
  if (type.isUnion())
3821
3918
  return type.types.map((part) => `${reference(part)}(value)`).join(" || ");
@@ -3824,16 +3921,16 @@ function renderGraphqlValidators(source, operationNames) {
3824
3921
  if (checker.isTupleType(type))
3825
3922
  return unsupported(type);
3826
3923
  if (checker.isArrayType(type)) {
3827
- const item = checker.getIndexTypeOfType(type, ts8.IndexKind.Number);
3924
+ const item = checker.getIndexTypeOfType(type, ts11.IndexKind.Number);
3828
3925
  if (!item)
3829
3926
  return unsupported(type);
3830
3927
  return `isGraphqlArray(value) && Array.from(value).every(${reference(item)})`;
3831
3928
  }
3832
- if (type.flags & ts8.TypeFlags.Object) {
3929
+ if (type.flags & ts11.TypeFlags.Object) {
3833
3930
  if (type.getCallSignatures().length || type.getConstructSignatures().length)
3834
3931
  return unsupported(type);
3835
3932
  const indexes = checker.getIndexInfosOfType(type);
3836
- if (indexes.some((index) => !(index.keyType.flags & ts8.TypeFlags.String)))
3933
+ if (indexes.some((index) => !(index.keyType.flags & ts11.TypeFlags.String)))
3837
3934
  return unsupported(type);
3838
3935
  const properties = checker.getPropertiesOfType(type).map((property) => {
3839
3936
  const declaration = property.valueDeclaration ?? property.declarations?.[0];
@@ -3842,7 +3939,7 @@ function renderGraphqlValidators(source, operationNames) {
3842
3939
  const check = reference(checker.getTypeOfSymbolAtLocation(property, declaration));
3843
3940
  const key = JSON.stringify(property.name);
3844
3941
  const present = `Object.prototype.hasOwnProperty.call(value, ${key})`;
3845
- return property.flags & ts8.SymbolFlags.Optional ? `(!${present} || ${check}(value[${key}]))` : `(${present} && ${check}(value[${key}]))`;
3942
+ return property.flags & ts11.SymbolFlags.Optional ? `(!${present} || ${check}(value[${key}]))` : `(${present} && ${check}(value[${key}]))`;
3846
3943
  });
3847
3944
  const indexedValues = indexes.map((index) => `Object.values(value).every(${reference(index.type)})`);
3848
3945
  return ["isGraphqlRecord(value)", ...properties, ...indexedValues].join(" && ");
@@ -4212,6 +4309,12 @@ function createContextPack(graph, subject) {
4212
4309
  routeContracts: inspectRouteContracts({ ...graph, modules }),
4213
4310
  ...graphql ? { graphql } : {},
4214
4311
  diagnostics: (graph.diagnostics ?? []).filter((diagnostic) => diagnostic.file === undefined || files.includes(diagnostic.file)),
4312
+ conventions: {
4313
+ singleResult: "async-await",
4314
+ eventComposition: "rxjs",
4315
+ angularHost: "@supacloud/app/angular",
4316
+ cancellation: "explicit-owner-signal"
4317
+ },
4215
4318
  relatedModules: {
4216
4319
  imports: subjectModule.imports.filter((name) => selected.has(name)),
4217
4320
  importedBy: graph.modules.filter((module) => module.imports.includes(subjectModule.name)).map((module) => module.name).sort()
@@ -15323,7 +15426,7 @@ var init_delivery_schema = __esm(() => {
15323
15426
  import { createHash as createHash6 } from "node:crypto";
15324
15427
  import { constants as constants2 } from "node:fs";
15325
15428
  import { lstat, mkdir as mkdir2, open as open3, readFile as readFile3, readdir, realpath, rename as rename2, rm, writeFile as writeFile2 } from "node:fs/promises";
15326
- import { dirname as dirname5, isAbsolute as isAbsolute2, join as join6, relative as relative6, resolve as resolve6, sep as sep6 } from "node:path";
15429
+ import { dirname as dirname5, isAbsolute as isAbsolute2, join as join6, relative as relative6, resolve as resolve7, sep as sep6 } from "node:path";
15327
15430
  function canonical2(value) {
15328
15431
  return JSON.stringify(value, (_key, item) => item !== null && typeof item === "object" && !Array.isArray(item) ? Object.fromEntries(Object.entries(item).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)) : item);
15329
15432
  }
@@ -15386,7 +15489,7 @@ async function reserveOutput(project, requested) {
15386
15489
  if (!inside(project, requested))
15387
15490
  throw new Error("Delivery output must be inside the application project.");
15388
15491
  const base = await realpath(project);
15389
- const path = resolve6(base, relative6(project, requested));
15492
+ const path = resolve7(base, relative6(project, requested));
15390
15493
  if (relative6(base, path).split(sep6).some((part) => part === ".git" || part === "node_modules")) {
15391
15494
  throw new Error("Delivery output cannot use repository or dependency internals.");
15392
15495
  }
@@ -15579,9 +15682,9 @@ var init_delivery_build_schema = __esm(() => {
15579
15682
 
15580
15683
  // node_modules/@supacloud/delivery/src/delivery-artifact.ts
15581
15684
  import { readdir as readdir2, realpath as realpath2 } from "node:fs/promises";
15582
- import { basename, dirname as dirname6, join as join7, resolve as resolve7 } from "node:path";
15685
+ import { basename, dirname as dirname6, join as join7, resolve as resolve8 } from "node:path";
15583
15686
  async function readDeliveryManifest(manifestPath) {
15584
- const selected = resolve7(manifestPath);
15687
+ const selected = resolve8(manifestPath);
15585
15688
  const root = await realpath2(dirname6(selected));
15586
15689
  const manifest = parseDeliveryBuildManifest(JSON.parse((await readBoundedOwned(root, join7(root, basename(selected)), JSON_LIMIT)).toString("utf8")));
15587
15690
  return { root, manifest };
@@ -15730,6 +15833,213 @@ var init_delivery_context = __esm(() => {
15730
15833
  };
15731
15834
  });
15732
15835
 
15836
+ // src/fixes.ts
15837
+ import { createHash as createHash8, randomUUID } from "node:crypto";
15838
+ import { lstat as lstat2, readFile as readFile5, realpath as realpath3, rename as rename3, unlink as unlink2, writeFile as writeFile3 } from "node:fs/promises";
15839
+ import { dirname as dirname8, isAbsolute as isAbsolute4, relative as relative9, resolve as resolve12, sep as sep9 } from "node:path";
15840
+ import * as ts12 from "@typescript/typescript6";
15841
+ async function applyDiagnosticFix(fix, options = {}) {
15842
+ if (!fix || typeof fix.targetFile !== "string")
15843
+ throw new Error("Invalid DiagnosticFix");
15844
+ const root = await realpath3(options.rootDir ?? process.cwd());
15845
+ const file = resolve12(root, fix.targetFile);
15846
+ const stat = await lstat2(file);
15847
+ const resolved = await realpath3(file);
15848
+ const relativePath = relative9(root, resolved);
15849
+ if (stat.isSymbolicLink() || !stat.isFile() || isAbsolute4(relativePath) || relativePath === ".." || relativePath.startsWith(`..${sep9}`)) {
15850
+ throw new Error("Fix target must be a regular file inside rootDir");
15851
+ }
15852
+ const original = await readFile5(file, "utf8");
15853
+ const sourceHash = createHash8("sha256").update(original).digest("hex");
15854
+ if (options.expectedSourceHash !== undefined && options.expectedSourceHash !== sourceHash) {
15855
+ throw new Error("Fix source changed since preview; analyze the project again");
15856
+ }
15857
+ let source = parse5(file, original);
15858
+ let content;
15859
+ switch (fix.type) {
15860
+ case "set_command_mode": {
15861
+ if (fix.property !== "transaction" && fix.property !== "idempotency" || fix.value !== "required" && fix.value !== "none") {
15862
+ throw new Error("Command mode fix requires an explicit property and policy value");
15863
+ }
15864
+ const object = decoratorObject(findClass(source, fix.command), "Command");
15865
+ const current = property(object, fix.property);
15866
+ if (!current || current.initializer.getText(source) !== fix.expectedExpression) {
15867
+ throw new Error("Command mode changed since diagnosis; analyze the project again");
15868
+ }
15869
+ content = replaceProperty(source, object, fix.property, ts12.factory.createStringLiteral(fix.value));
15870
+ break;
15871
+ }
15872
+ case "add_module_import": {
15873
+ if (!fix.importPath || !fix.symbol)
15874
+ throw new Error("Module fix requires importPath and symbol");
15875
+ identifier2(fix.symbol);
15876
+ const withImport = importSymbol(source, fix.importPath, fix.symbol);
15877
+ source = parse5(file, withImport);
15878
+ const object = unique(moduleObjects(source).filter((candidate) => !fix.targetModule || stringProperty(candidate, "name") === fix.targetModule), "target module");
15879
+ const imports = property(object, "imports");
15880
+ if (imports && !ts12.isArrayLiteralExpression(imports.initializer)) {
15881
+ throw new Error("Module imports must be a static array");
15882
+ }
15883
+ const values = imports && ts12.isArrayLiteralExpression(imports.initializer) ? imports.initializer.elements : [];
15884
+ if (values.some(ts12.isSpreadElement))
15885
+ throw new Error("Module imports cannot contain spread elements");
15886
+ content = values.some((value) => ts12.isIdentifier(value) && value.text === fix.symbol) ? withImport : replaceProperty(source, object, "imports", ts12.factory.createArrayLiteralExpression([
15887
+ ...values,
15888
+ ts12.factory.createIdentifier(fix.symbol)
15889
+ ]));
15890
+ break;
15891
+ }
15892
+ case "add_command_permission": {
15893
+ const permission = options.permission ?? fix.permission;
15894
+ if (!permission?.trim()) {
15895
+ throw new Error("Permission fix requires an explicit permission; privileges are never inferred");
15896
+ }
15897
+ const command = findClass(source, fix.command);
15898
+ const object = decoratorObject(command, "Command");
15899
+ const current = property(object, "permission");
15900
+ if (current && (!ts12.isStringLiteral(current.initializer) || current.initializer.text !== permission)) {
15901
+ throw new Error("Command permission already exists with a different value");
15902
+ }
15903
+ content = current ? original : replaceProperty(source, object, "permission", ts12.factory.createStringLiteral(permission));
15904
+ break;
15905
+ }
15906
+ case "add_route_parameter_binding": {
15907
+ const controller = findClass(source, fix.controller);
15908
+ const method = unique(controller.members.filter((member) => ts12.isMethodDeclaration(member) && nameOf(member.name) === fix.route), "route handler");
15909
+ const parameter = unique(method.parameters.filter((candidate) => ts12.isIdentifier(candidate.name) && candidate.name.text === fix.parameter), "same-named route parameter");
15910
+ const binding = fix.binding === "param" ? "Param" : fix.binding === "query" ? "Query" : undefined;
15911
+ if (!binding)
15912
+ throw new Error("Invalid route binding");
15913
+ const decorators = ts12.getDecorators(parameter) ?? [];
15914
+ if (decorators.length > 0)
15915
+ throw new Error("Parameter already has a decorator");
15916
+ const framework = unique(source.statements.filter((statement) => ts12.isImportDeclaration(statement) && statement.importClause?.namedBindings && ts12.isNamedImports(statement.importClause.namedBindings) && statement.importClause.namedBindings.elements.some((element) => ["Controller", "Get", "Post", "Put", "Patch", "Delete", "Head", "Options"].includes(element.name.text))), "framework import");
15917
+ if (!ts12.isImportDeclaration(framework) || !ts12.isStringLiteral(framework.moduleSpecifier)) {
15918
+ throw new Error("Framework import must be static");
15919
+ }
15920
+ const edited = original.slice(0, parameter.getStart(source)) + `@${binding}(${JSON.stringify(fix.parameter)}) ` + original.slice(parameter.getStart(source));
15921
+ content = importSymbol(parse5(file, edited), framework.moduleSpecifier.text, binding);
15922
+ break;
15923
+ }
15924
+ default:
15925
+ throw new Error(`Diagnostic fix '${fix.type}' requires a manual semantic decision; no files changed`);
15926
+ }
15927
+ parse5(file, content);
15928
+ const result = { file, changed: content !== original, content, sourceHash };
15929
+ if (options.dryRun === false && result.changed) {
15930
+ const temporary = `${file}.supacloud-fix-${randomUUID()}`;
15931
+ try {
15932
+ await writeFile3(temporary, content, { encoding: "utf8", flag: "wx", mode: stat.mode });
15933
+ if (await readFile5(file, "utf8") !== original)
15934
+ throw new Error("Target changed while preparing the fix");
15935
+ await rename3(temporary, file);
15936
+ } finally {
15937
+ await unlink2(temporary).catch(() => {});
15938
+ }
15939
+ }
15940
+ return result;
15941
+ }
15942
+ function parse5(file, text) {
15943
+ const result = ts12.transpileModule(text, {
15944
+ fileName: file,
15945
+ reportDiagnostics: true,
15946
+ compilerOptions: { target: ts12.ScriptTarget.ESNext, experimentalDecorators: true }
15947
+ });
15948
+ if (result.diagnostics?.some((item) => item.category === ts12.DiagnosticCategory.Error)) {
15949
+ throw new Error("Cannot fix syntactically invalid TypeScript");
15950
+ }
15951
+ return ts12.createSourceFile(file, text, ts12.ScriptTarget.Latest, true, ts12.ScriptKind.TS);
15952
+ }
15953
+ function unique(items, description) {
15954
+ if (items.length !== 1)
15955
+ throw new Error(`Expected exactly one ${description}; found ${items.length}`);
15956
+ return items[0];
15957
+ }
15958
+ function identifier2(value) {
15959
+ if (!/^[A-Za-z_$][\w$]*$/.test(value))
15960
+ throw new Error(`Invalid identifier '${value}'`);
15961
+ }
15962
+ function nameOf(name) {
15963
+ if (!name)
15964
+ return "";
15965
+ return ts12.isIdentifier(name) || ts12.isStringLiteral(name) || ts12.isNumericLiteral(name) ? name.text : "";
15966
+ }
15967
+ function property(object, key) {
15968
+ if (object.properties.some((item) => !ts12.isPropertyAssignment(item) || ts12.isComputedPropertyName(item.name))) {
15969
+ throw new Error("Fix requires explicit static object properties");
15970
+ }
15971
+ const values = object.properties.filter((item) => ts12.isPropertyAssignment(item) && nameOf(item.name) === key);
15972
+ if (values.length > 1)
15973
+ throw new Error(`Duplicate '${key}' property`);
15974
+ return values[0];
15975
+ }
15976
+ function stringProperty(object, key) {
15977
+ const value = property(object, key)?.initializer;
15978
+ return value && ts12.isStringLiteral(value) ? value.text : undefined;
15979
+ }
15980
+ function replaceProperty(source, object, key, value) {
15981
+ const previous = property(object, key);
15982
+ const replacement = ts12.factory.createPropertyAssignment(key, value);
15983
+ const properties = object.properties.map((item) => item === previous ? replacement : item);
15984
+ if (!previous)
15985
+ properties.push(replacement);
15986
+ const updated = ts12.factory.updateObjectLiteralExpression(object, properties);
15987
+ return source.text.slice(0, object.getStart(source)) + ts12.createPrinter().printNode(ts12.EmitHint.Expression, updated, source) + source.text.slice(object.end);
15988
+ }
15989
+ function findClass(source, name) {
15990
+ return unique(source.statements.filter((statement) => ts12.isClassDeclaration(statement) && statement.name?.text === name), `class '${name}'`);
15991
+ }
15992
+ function decoratorObject(node, name) {
15993
+ const decorator = unique((ts12.getDecorators(node) ?? []).filter((item) => ts12.isCallExpression(item.expression) && item.expression.expression.getText() === name), `@${name} decorator`);
15994
+ const argument = ts12.isCallExpression(decorator.expression) ? decorator.expression.arguments[0] : undefined;
15995
+ if (!argument || !ts12.isObjectLiteralExpression(argument))
15996
+ throw new Error(`@${name} requires a static object`);
15997
+ return argument;
15998
+ }
15999
+ function moduleObjects(source) {
16000
+ const result = [];
16001
+ for (const statement of source.statements) {
16002
+ if (ts12.isClassDeclaration(statement) && (ts12.getDecorators(statement) ?? []).some((item) => ts12.isCallExpression(item.expression) && item.expression.expression.getText() === "Module")) {
16003
+ result.push(decoratorObject(statement, "Module"));
16004
+ }
16005
+ if (ts12.isVariableStatement(statement)) {
16006
+ for (const declaration of statement.declarationList.declarations) {
16007
+ const call = declaration.initializer;
16008
+ if (call && ts12.isCallExpression(call) && ["defineModule", "defineFeatureSlice"].includes(call.expression.getText()) && call.arguments[0] && ts12.isObjectLiteralExpression(call.arguments[0])) {
16009
+ result.push(call.arguments[0]);
16010
+ }
16011
+ }
16012
+ }
16013
+ }
16014
+ return result;
16015
+ }
16016
+ function importSymbol(source, path, symbol) {
16017
+ identifier2(symbol);
16018
+ const current = resolve12(source.fileName).replace(/\.(tsx?|mts|cts)$/, "");
16019
+ const target = resolve12(dirname8(source.fileName), path).replace(/\.(tsx?|mts|cts)$/, "");
16020
+ if (current === target)
16021
+ return source.text;
16022
+ const matches = source.statements.filter((item) => ts12.isImportDeclaration(item) && ts12.isStringLiteral(item.moduleSpecifier) && item.moduleSpecifier.text === path);
16023
+ if (matches.length > 1)
16024
+ throw new Error(`Ambiguous imports from '${path}'`);
16025
+ const match = matches[0];
16026
+ if (match && ts12.isImportDeclaration(match) && match.importClause?.namedBindings && ts12.isNamedImports(match.importClause.namedBindings) && !match.importClause.isTypeOnly) {
16027
+ if (match.importClause.namedBindings.elements.some((item) => item.name.text === symbol))
16028
+ return source.text;
16029
+ const bindings = match.importClause.namedBindings;
16030
+ const updated = ts12.factory.updateNamedImports(bindings, [
16031
+ ...bindings.elements,
16032
+ ts12.factory.createImportSpecifier(false, undefined, ts12.factory.createIdentifier(symbol))
16033
+ ]);
16034
+ return source.text.slice(0, bindings.getStart(source)) + ts12.createPrinter().printNode(ts12.EmitHint.Unspecified, updated, source) + source.text.slice(bindings.end);
16035
+ }
16036
+ if (match)
16037
+ throw new Error(`Import from '${path}' is not a named value import`);
16038
+ return `import { ${symbol} } from ${JSON.stringify(path)};
16039
+ ${source.text}`;
16040
+ }
16041
+ var init_fixes = () => {};
16042
+
15733
16043
  // src/delivery-files.ts
15734
16044
  var init_delivery_files2 = __esm(() => {
15735
16045
  init_delivery_files();
@@ -16095,7 +16405,7 @@ var init_release_evidence = __esm(() => {
16095
16405
  });
16096
16406
 
16097
16407
  // src/release-evidence-cli.ts
16098
- import { resolve as resolve19 } from "node:path";
16408
+ import { resolve as resolve20 } from "node:path";
16099
16409
  async function runReleaseEvidenceCommand(args) {
16100
16410
  try {
16101
16411
  const values = new Map;
@@ -16119,7 +16429,7 @@ async function runReleaseEvidenceCommand(args) {
16119
16429
  if (!manifest || !target || manifest.length > 4096 || !/^[a-z][a-z0-9-]{0,62}$/.test(target)) {
16120
16430
  throw new ReleaseEvidenceError("RELEASE_EVIDENCE_INVALID");
16121
16431
  }
16122
- const evidence = await createReleaseEvidence(resolve19(manifest), target);
16432
+ const evidence = await createReleaseEvidence(resolve20(manifest), target);
16123
16433
  console.log(json ? JSON.stringify(evidence, null, 2) : formatReleaseEvidence(evidence));
16124
16434
  } catch (error) {
16125
16435
  console.error(`Error: ${error instanceof ReleaseEvidenceError ? error.code : "RELEASE_EVIDENCE_INVALID"}`);
@@ -16131,12 +16441,12 @@ var init_release_evidence_cli = __esm(() => {
16131
16441
  });
16132
16442
 
16133
16443
  // src/database-contracts.ts
16134
- import { createHash as createHash10 } from "node:crypto";
16444
+ import { createHash as createHash11 } from "node:crypto";
16135
16445
  import { mkdir as mkdir5, readFile as readFile12 } from "node:fs/promises";
16136
- import { dirname as dirname11, relative as relative12, resolve as resolve20 } from "node:path";
16137
- import * as ts14 from "@typescript/typescript6";
16446
+ import { dirname as dirname11, relative as relative12, resolve as resolve21 } from "node:path";
16447
+ import * as ts17 from "@typescript/typescript6";
16138
16448
  function hash3(value) {
16139
- return createHash10("sha256").update(value).digest("hex");
16449
+ return createHash11("sha256").update(value).digest("hex");
16140
16450
  }
16141
16451
  function importPath(out, path) {
16142
16452
  const value = relative12(out, path).replaceAll("\\", "/").replace(/\.(?:d\.)?[cm]?ts$/, "");
@@ -16161,33 +16471,33 @@ function parseDatabaseContractsOptions(value, directory) {
16161
16471
  throw new TypeError("migrations must be an ordered list of SQL files");
16162
16472
  }
16163
16473
  return {
16164
- rootDir: resolve20(directory, field("rootDir")),
16165
- outDir: resolve20(directory, field("outDir")),
16166
- postgrestTypes: resolve20(directory, field("postgrestTypes")),
16167
- drizzleSchema: resolve20(directory, field("drizzleSchema")),
16474
+ rootDir: resolve21(directory, field("rootDir")),
16475
+ outDir: resolve21(directory, field("outDir")),
16476
+ postgrestTypes: resolve21(directory, field("postgrestTypes")),
16477
+ drizzleSchema: resolve21(directory, field("drizzleSchema")),
16168
16478
  role: field("role"),
16169
- graphql: { ...graphql, schema: resolve20(directory, graphql.schema) },
16170
- migrations: migrations.map((file) => resolve20(directory, file))
16479
+ graphql: { ...graphql, schema: resolve21(directory, graphql.schema) },
16480
+ migrations: migrations.map((file) => resolve21(directory, file))
16171
16481
  };
16172
16482
  }
16173
16483
  async function generateDatabaseContracts(options, check = false) {
16174
- const rootDir = resolve20(options.rootDir), outDir = resolve20(options.outDir);
16175
- const postgrestTypes = resolve20(rootDir, options.postgrestTypes), drizzleSchema = resolve20(rootDir, options.drizzleSchema);
16484
+ const rootDir = resolve21(options.rootDir), outDir = resolve21(options.outDir);
16485
+ const postgrestTypes = resolve21(rootDir, options.postgrestTypes), drizzleSchema = resolve21(rootDir, options.drizzleSchema);
16176
16486
  const snapshot = await readFile12(postgrestTypes, "utf8");
16177
- const syntax = ts14.createSourceFile(postgrestTypes, snapshot, ts14.ScriptTarget.Latest, true);
16178
- const database = syntax.statements.find((node) => (ts14.isTypeAliasDeclaration(node) || ts14.isInterfaceDeclaration(node)) && node.name.text === "Database" && node.modifiers?.some((modifier) => modifier.kind === ts14.SyntaxKind.ExportKeyword));
16487
+ const syntax = ts17.createSourceFile(postgrestTypes, snapshot, ts17.ScriptTarget.Latest, true);
16488
+ const database = syntax.statements.find((node) => (ts17.isTypeAliasDeclaration(node) || ts17.isInterfaceDeclaration(node)) && node.name.text === "Database" && node.modifiers?.some((modifier) => modifier.kind === ts17.SyntaxKind.ExportKeyword));
16179
16489
  if (!database)
16180
16490
  throw new Error("PostgREST snapshot must export Database from the official type generator");
16181
- const program = ts14.createProgram([postgrestTypes], {
16491
+ const program = ts17.createProgram([postgrestTypes], {
16182
16492
  strict: true,
16183
16493
  noEmit: true,
16184
16494
  skipLibCheck: true,
16185
16495
  types: [],
16186
- target: ts14.ScriptTarget.ES2022,
16187
- module: ts14.ModuleKind.ESNext,
16188
- moduleResolution: ts14.ModuleResolutionKind.Bundler
16496
+ target: ts17.ScriptTarget.ES2022,
16497
+ module: ts17.ModuleKind.ESNext,
16498
+ moduleResolution: ts17.ModuleResolutionKind.Bundler
16189
16499
  });
16190
- if (ts14.getPreEmitDiagnostics(program).length)
16500
+ if (ts17.getPreEmitDiagnostics(program).length)
16191
16501
  throw new Error("PostgREST snapshot has TypeScript errors");
16192
16502
  const artifacts = await renderGraphql({
16193
16503
  rootDir,
@@ -16200,16 +16510,16 @@ async function generateDatabaseContracts(options, check = false) {
16200
16510
  }
16201
16511
  const inputs = {};
16202
16512
  const addInput = async (path) => {
16203
- const absolute = resolve20(rootDir, path);
16513
+ const absolute = resolve21(rootDir, path);
16204
16514
  inputs[relative12(rootDir, absolute).replaceAll("\\", "/")] = hash3(await readFile12(absolute, "utf8"));
16205
16515
  };
16206
16516
  await addInput(postgrestTypes);
16207
16517
  await addInput(drizzleSchema);
16208
- const drizzleProgram = ts14.createProgram([drizzleSchema], {
16518
+ const drizzleProgram = ts17.createProgram([drizzleSchema], {
16209
16519
  noEmit: true,
16210
- moduleResolution: ts14.ModuleResolutionKind.Bundler,
16211
- module: ts14.ModuleKind.ESNext,
16212
- target: ts14.ScriptTarget.ES2022,
16520
+ moduleResolution: ts17.ModuleResolutionKind.Bundler,
16521
+ module: ts17.ModuleKind.ESNext,
16522
+ target: ts17.ScriptTarget.ES2022,
16213
16523
  types: [],
16214
16524
  skipLibCheck: true
16215
16525
  });
@@ -16217,8 +16527,8 @@ async function generateDatabaseContracts(options, check = false) {
16217
16527
  if (!source.isDeclarationFile && !source.fileName.includes("/node_modules/"))
16218
16528
  await addInput(source.fileName);
16219
16529
  }
16220
- await addInput(resolve20(rootDir, options.graphql.schema));
16221
- if (new Set(options.migrations.map((path) => resolve20(rootDir, path))).size !== options.migrations.length) {
16530
+ await addInput(resolve21(rootDir, options.graphql.schema));
16531
+ if (new Set(options.migrations.map((path) => resolve21(rootDir, path))).size !== options.migrations.length) {
16222
16532
  throw new Error("Duplicate migration in database contracts configuration");
16223
16533
  }
16224
16534
  for (const path of options.migrations)
@@ -16239,14 +16549,14 @@ async function generateDatabaseContracts(options, check = false) {
16239
16549
  version: 1,
16240
16550
  role: options.role,
16241
16551
  inputs: Object.fromEntries(Object.entries(inputs).sort(([a], [b]) => a.localeCompare(b))),
16242
- migrationOrder: options.migrations.map((path) => relative12(rootDir, resolve20(rootDir, path)).replaceAll("\\", "/")),
16552
+ migrationOrder: options.migrations.map((path) => relative12(rootDir, resolve21(rootDir, path)).replaceAll("\\", "/")),
16243
16553
  outputs: Object.fromEntries(Object.entries(files).sort(([a], [b]) => a.localeCompare(b)).map(([file, text]) => [file, hash3(text)]))
16244
16554
  };
16245
16555
  files["database.manifest.json"] = JSON.stringify(manifest, null, 2) + `
16246
16556
  `;
16247
16557
  const mismatches = [];
16248
16558
  for (const [file, content] of Object.entries(files)) {
16249
- const path = resolve20(outDir, file);
16559
+ const path = resolve21(outDir, file);
16250
16560
  let current;
16251
16561
  try {
16252
16562
  current = await readFile12(path, "utf8");
@@ -16260,12 +16570,12 @@ async function generateDatabaseContracts(options, check = false) {
16260
16570
  if (!check) {
16261
16571
  await mkdir5(outDir, { recursive: true });
16262
16572
  for (const [file, content] of Object.entries(files))
16263
- await writeFileIfChanged(resolve20(outDir, file), content);
16573
+ await writeFileIfChanged(resolve21(outDir, file), content);
16264
16574
  }
16265
16575
  return { upToDate: mismatches.length === 0, mismatches, written: check ? [] : mismatches, manifest };
16266
16576
  }
16267
16577
  async function runDatabaseContractsFile(path, check = false) {
16268
- const absolute = resolve20(path);
16578
+ const absolute = resolve21(path);
16269
16579
  const value = JSON.parse(await readFile12(absolute, "utf8"));
16270
16580
  return generateDatabaseContracts(parseDatabaseContractsOptions(value, dirname11(absolute)), check);
16271
16581
  }
@@ -16277,8 +16587,8 @@ var init_database_contracts = __esm(() => {
16277
16587
 
16278
16588
  // src/graphql-schema.ts
16279
16589
  import { mkdir as mkdir6, readFile as readFile13 } from "node:fs/promises";
16280
- import { createHash as createHash11 } from "node:crypto";
16281
- import { dirname as dirname12, resolve as resolve21 } from "node:path";
16590
+ import { createHash as createHash12 } from "node:crypto";
16591
+ import { dirname as dirname12, resolve as resolve22 } from "node:path";
16282
16592
  async function pullGraphqlSchema(options) {
16283
16593
  assertGraphqlOptions({ schema: options.output });
16284
16594
  const endpoint = new URL(options.url);
@@ -16318,7 +16628,7 @@ async function pullGraphqlSchema(options) {
16318
16628
  throw new Error("GraphQL schema export failed. Verify caller grants and enable introspection only in the intended development environment.");
16319
16629
  }
16320
16630
  const schema = lexicographicSortSchema(buildClientSchema(data));
16321
- const path = resolve21(options.output);
16631
+ const path = resolve22(options.output);
16322
16632
  const content = path.endsWith(".json") ? JSON.stringify(introspectionFromSchema(schema), null, 2) + `
16323
16633
  ` : `# GENERATED BY supacloud-compiler graphql-schema. DO NOT EDIT.
16324
16634
  # Database First: change database declarations, apply migrations, then re-export for the intended role.
@@ -16332,7 +16642,7 @@ async function pullGraphqlSchema(options) {
16332
16642
  throw error;
16333
16643
  }
16334
16644
  const upToDate = previous === content;
16335
- const schemaHash = createHash11("sha256").update(content).digest("hex");
16645
+ const schemaHash = createHash12("sha256").update(content).digest("hex");
16336
16646
  if (options.check)
16337
16647
  return { path, schemaHash, upToDate, written: false };
16338
16648
  await mkdir6(dirname12(path), { recursive: true });
@@ -16345,13 +16655,13 @@ var init_graphql_schema = __esm(() => {
16345
16655
  });
16346
16656
 
16347
16657
  // src/cli.ts
16348
- import { resolve as resolve22 } from "node:path";
16658
+ import { resolve as resolve23 } from "node:path";
16349
16659
  import { readFile as readFile14 } from "node:fs/promises";
16350
16660
 
16351
16661
  // src/analyze.ts
16352
16662
  import { createHash as createHash3 } from "node:crypto";
16353
16663
  import { relative as relative2, resolve as resolvePath, sep as sep2 } from "node:path";
16354
- import * as ts4 from "@typescript/typescript6";
16664
+ import * as ts7 from "@typescript/typescript6";
16355
16665
 
16356
16666
  // src/program.ts
16357
16667
  import { createHash as createHash2 } from "node:crypto";
@@ -16687,12 +16997,258 @@ function readProjectConfig(rootDir) {
16687
16997
  init_validate();
16688
16998
 
16689
16999
  // src/static-di.ts
17000
+ import * as ts6 from "@typescript/typescript6";
17001
+
17002
+ // src/reactive-analysis.ts
17003
+ import * as ts4 from "@typescript/typescript6";
17004
+
17005
+ // src/api-source.ts
16690
17006
  import * as ts3 from "@typescript/typescript6";
17007
+ import { resolve as resolve2 } from "node:path";
17008
+ function bindApiSource(source) {
17009
+ const file = resolve2(source.fileName);
17010
+ const bound = ts3.createSourceFile(file, source.text, ts3.ScriptTarget.Latest, true);
17011
+ const options = { noLib: true, noResolve: true, target: ts3.ScriptTarget.ES2022 };
17012
+ const host = {
17013
+ getSourceFile: (name) => resolve2(name) === file ? bound : undefined,
17014
+ getDefaultLibFileName: () => "",
17015
+ writeFile: () => {},
17016
+ getCurrentDirectory: () => process.cwd(),
17017
+ getDirectories: () => [],
17018
+ fileExists: (name) => resolve2(name) === file,
17019
+ readFile: (name) => resolve2(name) === file ? source.text : undefined,
17020
+ getCanonicalFileName: (name) => name,
17021
+ useCaseSensitiveFileNames: () => true,
17022
+ getNewLine: () => `
17023
+ `
17024
+ };
17025
+ const program = ts3.createProgram([file], options, host);
17026
+ return { source: bound, checker: program.getTypeChecker() };
17027
+ }
17028
+ function importedFrom(node) {
17029
+ let current = node;
17030
+ while (current && !ts3.isImportDeclaration(current))
17031
+ current = current.parent;
17032
+ return current && ts3.isImportDeclaration(current) && ts3.isStringLiteral(current.moduleSpecifier) ? current.moduleSpecifier.text : undefined;
17033
+ }
17034
+ function apiOrigin(expression, checker, seen = new Set) {
17035
+ if (seen.has(expression))
17036
+ return;
17037
+ seen.add(expression);
17038
+ if (ts3.isParenthesizedExpression(expression) || ts3.isAsExpression(expression) || ts3.isSatisfiesExpression(expression) || ts3.isTypeAssertionExpression(expression)) {
17039
+ return apiOrigin(expression.expression, checker, seen);
17040
+ }
17041
+ if (ts3.isPropertyAccessExpression(expression) || ts3.isElementAccessExpression(expression)) {
17042
+ const name = ts3.isPropertyAccessExpression(expression) ? expression.name.text : ts3.isStringLiteral(expression.argumentExpression) ? expression.argumentExpression.text : undefined;
17043
+ const namespace = apiOrigin(expression.expression, checker, seen);
17044
+ return namespace?.name === "*" && name ? { module: namespace.module, name } : undefined;
17045
+ }
17046
+ if (!ts3.isIdentifier(expression))
17047
+ return;
17048
+ const symbol = checker.getSymbolAtLocation(expression);
17049
+ for (const declaration of symbol?.declarations ?? []) {
17050
+ if (ts3.isImportSpecifier(declaration) && !declaration.isTypeOnly && !declaration.parent.parent.isTypeOnly) {
17051
+ const module = importedFrom(declaration);
17052
+ if (module)
17053
+ return { module, name: (declaration.propertyName ?? declaration.name).text };
17054
+ }
17055
+ if (ts3.isNamespaceImport(declaration) && !declaration.parent.isTypeOnly) {
17056
+ const module = importedFrom(declaration);
17057
+ if (module)
17058
+ return { module, name: "*" };
17059
+ }
17060
+ if (ts3.isVariableDeclaration(declaration) && declaration.initializer && ts3.isVariableDeclarationList(declaration.parent) && declaration.parent.flags & ts3.NodeFlags.Const) {
17061
+ return apiOrigin(declaration.initializer, checker, seen);
17062
+ }
17063
+ }
17064
+ return;
17065
+ }
17066
+
17067
+ // src/reactive-analysis.ts
17068
+ var angularState = new Set(["@angular/core", "@supacloud/app/angular"]);
17069
+ var signalBridges = new Set(["@angular/core/rxjs-interop", "@supacloud/app/angular", "@supacloud/app/rxjs"]);
17070
+ function scanReactiveSource(input, file) {
17071
+ if (!input.statements.some((node) => ts4.isImportDeclaration(node) && ts4.isStringLiteral(node.moduleSpecifier) && (angularState.has(node.moduleSpecifier.text) || signalBridges.has(node.moduleSpecifier.text))))
17072
+ return [];
17073
+ const { source, checker } = bindApiSource(input);
17074
+ const diagnostics = [];
17075
+ const reported = new Set;
17076
+ const visit = (node, reactive) => {
17077
+ if (ts4.isCallExpression(node)) {
17078
+ const origin = apiOrigin(node.expression, checker);
17079
+ if (reactive && origin && signalBridges.has(origin.module) && ["toSignal", "toScopedSignal", "rxResource"].includes(origin.name) && !reported.has(node.pos)) {
17080
+ reported.add(node.pos);
17081
+ const start = source.getLineAndCharacterOfPosition(node.getStart(source));
17082
+ const end = source.getLineAndCharacterOfPosition(node.end);
17083
+ diagnostics.push({
17084
+ severity: "error",
17085
+ code: "reactive-subscription-in-computation",
17086
+ file,
17087
+ line: start.line + 1,
17088
+ column: start.character,
17089
+ endLine: end.line + 1,
17090
+ endColumn: end.character,
17091
+ message: `${origin.name} creates a subscription inside a reactive computation.`,
17092
+ suggestion: "Create the subscription once in its explicit owner scope, then derive state with computed. Hoisting requires ownership review; no automatic edit is safe.",
17093
+ docsUrl: "https://supacloud.dev/errors/reactive-subscription-in-computation"
17094
+ });
17095
+ }
17096
+ if (origin && angularState.has(origin.module) && ["computed", "effect", "untracked"].includes(origin.name)) {
17097
+ const callback = node.arguments[0];
17098
+ if (callback && (ts4.isArrowFunction(callback) || ts4.isFunctionExpression(callback))) {
17099
+ visit(callback.body, origin.name === "untracked" ? false : true);
17100
+ for (const argument of node.arguments.slice(1))
17101
+ visit(argument, reactive);
17102
+ return;
17103
+ }
17104
+ }
17105
+ let expression = node.expression;
17106
+ while (ts4.isParenthesizedExpression(expression))
17107
+ expression = expression.expression;
17108
+ if (ts4.isArrowFunction(expression) || ts4.isFunctionExpression(expression))
17109
+ visit(expression.body, reactive);
17110
+ }
17111
+ if (ts4.isFunctionLike(node)) {
17112
+ if (!reactive)
17113
+ ts4.forEachChild(node, (child) => visit(child, false));
17114
+ return;
17115
+ }
17116
+ ts4.forEachChild(node, (child) => visit(child, reactive));
17117
+ };
17118
+ visit(source, false);
17119
+ return diagnostics;
17120
+ }
17121
+
17122
+ // src/http-provider-migration.ts
17123
+ import * as ts5 from "@typescript/typescript6";
17124
+ function providerArgument(node, checker) {
17125
+ let current = node;
17126
+ while (ts5.isParenthesizedExpression(current.parent))
17127
+ current = current.parent;
17128
+ if (!ts5.isCallExpression(current.parent) || current.parent.expression !== current)
17129
+ return false;
17130
+ current = current.parent;
17131
+ while (ts5.isParenthesizedExpression(current.parent))
17132
+ current = current.parent;
17133
+ const parent = current.parent;
17134
+ if (!ts5.isCallExpression(parent) || !parent.arguments.some((argument) => argument === current))
17135
+ return false;
17136
+ const owner = apiOrigin(parent.expression, checker);
17137
+ return owner?.name === "provideHttpClient" && ["@supacloud/app", "@supacloud/app/http"].includes(owner.module);
17138
+ }
17139
+ function migrateHttpProviderImports(source, fileName) {
17140
+ const bound = bindApiSource(ts5.createSourceFile(fileName, source, ts5.ScriptTarget.Latest, true));
17141
+ const { source: sf, checker } = bound;
17142
+ const edits = [];
17143
+ const issues = [];
17144
+ const printer = ts5.createPrinter({ newLine: source.includes(`\r
17145
+ `) ? ts5.NewLineKind.CarriageReturnLineFeed : ts5.NewLineKind.LineFeed });
17146
+ const newline = source.includes(`\r
17147
+ `) ? `\r
17148
+ ` : `
17149
+ `;
17150
+ for (const statement of sf.statements) {
17151
+ if (!ts5.isImportDeclaration(statement) || !ts5.isStringLiteral(statement.moduleSpecifier) || statement.moduleSpecifier.text !== "@supacloud/app" || !statement.importClause || statement.importClause.isTypeOnly)
17152
+ continue;
17153
+ const named = statement.importClause.namedBindings;
17154
+ if (!named || !ts5.isNamedImports(named))
17155
+ continue;
17156
+ const specifier = named.elements.find((item) => !item.isTypeOnly && (item.propertyName ?? item.name).text === "withInterceptors");
17157
+ if (!specifier)
17158
+ continue;
17159
+ const symbol = checker.getSymbolAtLocation(specifier.name);
17160
+ if (!symbol)
17161
+ continue;
17162
+ const uses = [];
17163
+ const visit = (node) => {
17164
+ if (ts5.isImportDeclaration(node))
17165
+ return;
17166
+ if (ts5.isIdentifier(node) && checker.getSymbolAtLocation(node) === symbol)
17167
+ uses.push(node);
17168
+ ts5.forEachChild(node, visit);
17169
+ };
17170
+ visit(sf);
17171
+ if (!uses.some((node) => providerArgument(node, checker)))
17172
+ continue;
17173
+ if (!uses.every((node) => providerArgument(node, checker)) || statement.attributes) {
17174
+ issues.push({
17175
+ code: "http-provider-migration-ambiguous",
17176
+ file: fileName,
17177
+ line: sf.getLineAndCharacterOfPosition(specifier.getStart(sf)).line + 1,
17178
+ message: "withInterceptors also has non-provider uses; split the bindings manually before migration."
17179
+ });
17180
+ continue;
17181
+ }
17182
+ const remaining = named.elements.filter((item) => item !== specifier);
17183
+ if (remaining.length === 0 && !statement.importClause.name) {
17184
+ edits.push({ start: statement.moduleSpecifier.getStart(sf), end: statement.moduleSpecifier.end, text: '"@supacloud/app/http"' });
17185
+ } else {
17186
+ const clause = ts5.factory.updateImportClause(statement.importClause, false, statement.importClause.name, remaining.length ? ts5.factory.updateNamedImports(named, remaining) : undefined);
17187
+ const updated = ts5.factory.updateImportDeclaration(statement, statement.modifiers, clause, statement.moduleSpecifier, statement.attributes);
17188
+ const text = printer.printNode(ts5.EmitHint.Unspecified, updated, sf).trimStart() + newline + `import { ${specifier.getText(sf)} } from "@supacloud/app/http";`;
17189
+ const withoutLeading = text.replace(/^(?:\/\/[^\n]*\n|\/\*[\s\S]*?\*\/\s*)+/, "");
17190
+ edits.push({ start: statement.getStart(sf), end: statement.end, text: withoutLeading });
17191
+ }
17192
+ }
17193
+ const checkNamespace = (node) => {
17194
+ if ((ts5.isPropertyAccessExpression(node) || ts5.isElementAccessExpression(node)) && providerArgument(node, checker)) {
17195
+ const origin = apiOrigin(node, checker);
17196
+ if (origin?.module === "@supacloud/app" && origin.name === "withInterceptors")
17197
+ issues.push({
17198
+ code: "http-provider-migration-namespace",
17199
+ file: fileName,
17200
+ line: sf.getLineAndCharacterOfPosition(node.getStart(sf)).line + 1,
17201
+ message: "Use a dedicated named import from @supacloud/app/http; namespace rewrites require manual review."
17202
+ });
17203
+ }
17204
+ ts5.forEachChild(node, checkNamespace);
17205
+ };
17206
+ checkNamespace(sf);
17207
+ if (issues.length)
17208
+ return { changed: false, content: source, replacements: 0, issues };
17209
+ let content = source;
17210
+ for (const edit of edits.sort((a, b) => b.start - a.start))
17211
+ content = content.slice(0, edit.start) + edit.text + content.slice(edit.end);
17212
+ return { changed: edits.length > 0, content, replacements: edits.length, issues: [] };
17213
+ }
17214
+ function scanHttpProviderImports(source, file) {
17215
+ if (!source.text.includes("@supacloud/app"))
17216
+ return [];
17217
+ const { source: sf, checker } = bindApiSource(source);
17218
+ const diagnostics = [];
17219
+ const visit = (node) => {
17220
+ if (ts5.isCallExpression(node)) {
17221
+ const origin = apiOrigin(node.expression, checker);
17222
+ if (origin?.module === "@supacloud/app" && origin.name === "withInterceptors" && providerArgument(node.expression, checker)) {
17223
+ const start = sf.getLineAndCharacterOfPosition(node.getStart(sf));
17224
+ const end = sf.getLineAndCharacterOfPosition(node.end);
17225
+ diagnostics.push({
17226
+ severity: "error",
17227
+ code: "http-provider-import-mismatch",
17228
+ file,
17229
+ line: start.line + 1,
17230
+ column: start.character,
17231
+ endLine: end.line + 1,
17232
+ endColumn: end.character,
17233
+ message: "The root withInterceptors returns an interceptor array, not a provideHttpClient feature.",
17234
+ suggestion: "Import withInterceptors from @supacloud/app/http. Preview the http-provider-entrypoint source migration; mixed/namespace uses require manual review.",
17235
+ docsUrl: "https://supacloud.dev/errors/http-provider-import-mismatch"
17236
+ });
17237
+ }
17238
+ }
17239
+ ts5.forEachChild(node, visit);
17240
+ };
17241
+ visit(sf);
17242
+ return diagnostics;
17243
+ }
17244
+
17245
+ // src/static-di.ts
16691
17246
  var runtimeApis = new Set([
16692
17247
  "inject",
16693
17248
  "createEnvironmentInjector",
16694
17249
  "runInInjectionContext",
16695
17250
  "EnvironmentInjector",
17251
+ "Injector",
16696
17252
  "bootstrapBun",
16697
17253
  "runInScope",
16698
17254
  "runInRequestContext",
@@ -16702,25 +17258,33 @@ var runtimeApis = new Set([
16702
17258
  function scanRuntimeDi(source, file) {
16703
17259
  const diagnostics = [];
16704
17260
  const namespaces = new Set;
16705
- const report = (node) => diagnostics.push({
16706
- severity: "error",
16707
- code: "runtime-injection-disallowed",
16708
- errorCode: "SC2012",
16709
- docsUrl: "https://supacloud.dev/errors/SC2012",
16710
- file,
16711
- line: source.getLineAndCharacterOfPosition(node.getStart()).line + 1,
16712
- message: "Compiled applications cannot import runtime DI. Use explicit constructors and generated scope factories."
16713
- });
17261
+ const report = (node) => {
17262
+ const start = source.getLineAndCharacterOfPosition(node.getStart());
17263
+ const end = source.getLineAndCharacterOfPosition(node.end);
17264
+ diagnostics.push({
17265
+ severity: "error",
17266
+ code: "runtime-injection-disallowed",
17267
+ errorCode: "SC2012",
17268
+ docsUrl: "https://supacloud.dev/errors/SC2012",
17269
+ file,
17270
+ line: start.line + 1,
17271
+ column: start.character,
17272
+ endLine: end.line + 1,
17273
+ endColumn: end.character,
17274
+ message: "Compiled applications cannot import runtime DI. Use explicit constructors and generated scope factories.",
17275
+ suggestion: "Use constructor dependencies and generated request/job factories. Keep Angular runtime services outside the compiled application source root."
17276
+ });
17277
+ };
16714
17278
  for (const statement of source.statements) {
16715
- if (!(ts3.isImportDeclaration(statement) || ts3.isExportDeclaration(statement)) || !statement.moduleSpecifier || !ts3.isStringLiteral(statement.moduleSpecifier) || !/^@supacloud\/app(?:\/|$)/.test(statement.moduleSpecifier.text))
17279
+ if (!(ts6.isImportDeclaration(statement) || ts6.isExportDeclaration(statement)) || !statement.moduleSpecifier || !ts6.isStringLiteral(statement.moduleSpecifier) || !(/^@supacloud\/app(?:\/|$)/.test(statement.moduleSpecifier.text) || statement.moduleSpecifier.text === "@angular/core"))
16716
17280
  continue;
16717
- if (ts3.isImportDeclaration(statement)) {
17281
+ if (ts6.isImportDeclaration(statement)) {
16718
17282
  if (statement.importClause?.isTypeOnly)
16719
17283
  continue;
16720
17284
  const binding = statement.importClause?.namedBindings;
16721
- if (binding && ts3.isNamespaceImport(binding))
17285
+ if (binding && ts6.isNamespaceImport(binding))
16722
17286
  namespaces.add(binding.name.text);
16723
- if (binding && ts3.isNamedImports(binding))
17287
+ if (binding && ts6.isNamedImports(binding))
16724
17288
  for (const item of binding.elements) {
16725
17289
  if (!item.isTypeOnly && runtimeApis.has((item.propertyName ?? item.name).text))
16726
17290
  report(item);
@@ -16728,24 +17292,29 @@ function scanRuntimeDi(source, file) {
16728
17292
  } else if (!statement.isTypeOnly) {
16729
17293
  if (!statement.exportClause)
16730
17294
  report(statement);
16731
- else if (ts3.isNamedExports(statement.exportClause))
17295
+ else if (ts6.isNamedExports(statement.exportClause))
16732
17296
  for (const item of statement.exportClause.elements) {
16733
17297
  if (!item.isTypeOnly && runtimeApis.has((item.propertyName ?? item.name).text))
16734
17298
  report(item);
16735
17299
  }
16736
17300
  }
16737
17301
  }
16738
- const visit = (node) => {
16739
- if (ts3.isPropertyAccessExpression(node) && ts3.isIdentifier(node.expression) && namespaces.has(node.expression.text) && runtimeApis.has(node.name.text))
16740
- report(node);
16741
- if (ts3.isElementAccessExpression(node) && ts3.isIdentifier(node.expression) && namespaces.has(node.expression.text) && (!ts3.isStringLiteral(node.argumentExpression) || runtimeApis.has(node.argumentExpression.text)))
16742
- report(node);
16743
- if (ts3.isVariableDeclaration(node) && node.initializer && ts3.isIdentifier(node.initializer) && namespaces.has(node.initializer.text))
16744
- report(node);
16745
- ts3.forEachChild(node, visit);
16746
- };
16747
- visit(source);
16748
- return diagnostics;
17302
+ if (namespaces.size > 0) {
17303
+ const bound = bindApiSource(source);
17304
+ const protectedNamespace = (expression) => {
17305
+ const origin = apiOrigin(expression, bound.checker);
17306
+ return origin?.name === "*" && (origin.module === "@angular/core" || /^@supacloud\/app(?:\/|$)/.test(origin.module));
17307
+ };
17308
+ const visit = (node) => {
17309
+ if (ts6.isPropertyAccessExpression(node) && protectedNamespace(node.expression) && runtimeApis.has(node.name.text))
17310
+ report(node);
17311
+ if (ts6.isElementAccessExpression(node) && protectedNamespace(node.expression) && (!ts6.isStringLiteral(node.argumentExpression) || runtimeApis.has(node.argumentExpression.text)))
17312
+ report(node);
17313
+ ts6.forEachChild(node, visit);
17314
+ };
17315
+ visit(bound.source);
17316
+ }
17317
+ return [...diagnostics, ...scanReactiveSource(source, file), ...scanHttpProviderImports(source, file)];
16749
17318
  }
16750
17319
 
16751
17320
  // src/analyze.ts
@@ -16796,36 +17365,39 @@ function lineOf(node) {
16796
17365
  return sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;
16797
17366
  }
16798
17367
  function variableName(decl) {
16799
- return ts4.isIdentifier(decl.name) ? decl.name.text : nodeText(decl.name);
17368
+ return ts7.isIdentifier(decl.name) ? decl.name.text : nodeText(decl.name);
16800
17369
  }
16801
17370
  function propertyName(name) {
16802
- if (ts4.isIdentifier(name) || ts4.isPrivateIdentifier(name))
17371
+ if (ts7.isIdentifier(name) || ts7.isPrivateIdentifier(name))
16803
17372
  return name.text;
16804
- if (ts4.isStringLiteral(name) || ts4.isNumericLiteral(name))
17373
+ if (ts7.isStringLiteral(name) || ts7.isNumericLiteral(name))
16805
17374
  return name.text;
16806
17375
  return nodeText(name);
16807
17376
  }
16808
17377
  function parameterName(param) {
16809
- return ts4.isIdentifier(param.name) ? param.name.text : nodeText(param.name);
17378
+ return ts7.isIdentifier(param.name) ? param.name.text : nodeText(param.name);
16810
17379
  }
16811
17380
  function decoratorsOf(node) {
16812
- return ts4.canHaveDecorators(node) ? ts4.getDecorators(node) ?? [] : [];
17381
+ return ts7.canHaveDecorators(node) ? ts7.getDecorators(node) ?? [] : [];
16813
17382
  }
16814
17383
  function decoratorArguments(dec) {
16815
- return ts4.isCallExpression(dec.expression) ? dec.expression.arguments : [];
17384
+ return ts7.isCallExpression(dec.expression) ? dec.expression.arguments : [];
16816
17385
  }
16817
17386
  function hasMethod(cls, name) {
16818
- return cls.members.some((member) => (ts4.isMethodDeclaration(member) || ts4.isGetAccessorDeclaration(member) || ts4.isSetAccessorDeclaration(member)) && member.name !== undefined && propertyName(member.name) === name);
17387
+ return cls.members.some((member) => (ts7.isMethodDeclaration(member) || ts7.isGetAccessorDeclaration(member) || ts7.isSetAccessorDeclaration(member)) && member.name !== undefined && propertyName(member.name) === name);
16819
17388
  }
16820
17389
  function hasDestroyHook(cls) {
16821
17390
  return hasMethod(cls, "onDestroy") || hasMethod(cls, "ngOnDestroy");
16822
17391
  }
17392
+ function hasInitHook(cls) {
17393
+ return hasMethod(cls, "onInit");
17394
+ }
16823
17395
  function descendantsOfKind(root, predicate) {
16824
17396
  const result = [];
16825
17397
  const visit = (node) => {
16826
17398
  if (predicate(node))
16827
17399
  result.push(node);
16828
- ts4.forEachChild(node, visit);
17400
+ ts7.forEachChild(node, visit);
16829
17401
  };
16830
17402
  visit(root);
16831
17403
  return result;
@@ -16834,7 +17406,7 @@ async function analyzeProject(rootDir, include, cache, changedPaths) {
16834
17406
  const session = cache?.programSession ?? createIncrementalProgramSession(rootDir);
16835
17407
  if (cache)
16836
17408
  cache.programSession = session;
16837
- const rootNames = ts4.sys.readDirectory(rootDir, [".ts", ".tsx"], ["node_modules", "dist"], include ?? DEFAULT_INCLUDE);
17409
+ const rootNames = ts7.sys.readDirectory(rootDir, [".ts", ".tsx"], ["node_modules", "dist"], include ?? DEFAULT_INCLUDE);
16838
17410
  const update = session.update(rootNames, changedPaths);
16839
17411
  const program = update.program;
16840
17412
  const checker = program.getTypeChecker();
@@ -16870,7 +17442,7 @@ async function analyzeProject(rootDir, include, cache, changedPaths) {
16870
17442
  for (const sf of sourceFiles) {
16871
17443
  const traits = nativeTraitFiles.get(sf.fileName);
16872
17444
  if (!cache || traits?.has("module")) {
16873
- for (const cls of sf.statements.filter(ts4.isClassDeclaration)) {
17445
+ for (const cls of sf.statements.filter(ts7.isClassDeclaration)) {
16874
17446
  const moduleDec = findDecorator(cls, "Module");
16875
17447
  if (!moduleDec)
16876
17448
  continue;
@@ -16887,14 +17459,14 @@ async function analyzeProject(rootDir, include, cache, changedPaths) {
16887
17459
  }
16888
17460
  }
16889
17461
  if (!cache || traits?.has("defineModule") || traits?.has("defineFeatureSlice")) {
16890
- for (const call of descendantsOfKind(sf, ts4.isCallExpression)) {
17462
+ for (const call of descendantsOfKind(sf, ts7.isCallExpression)) {
16891
17463
  if (!["defineModule", "defineFeatureSlice"].includes(nodeText(call.expression)))
16892
17464
  continue;
16893
17465
  const parent = call.parent;
16894
- if (!parent || !ts4.isVariableDeclaration(parent))
17466
+ if (!parent || !ts7.isVariableDeclaration(parent))
16895
17467
  continue;
16896
17468
  const arg = call.arguments[0];
16897
- if (!arg || !ts4.isObjectLiteralExpression(arg))
17469
+ if (!arg || !ts7.isObjectLiteralExpression(arg))
16898
17470
  continue;
16899
17471
  candidates.push({
16900
17472
  node: parent,
@@ -17030,6 +17602,7 @@ async function analyzeProject(rootDir, include, cache, changedPaths) {
17030
17602
  ...functionalInjects.length > 0 ? { functionalInjects } : {},
17031
17603
  providedIn: "root",
17032
17604
  ...hasDestroyHook(classInfo.decl) ? { hasOnDestroy: true } : {},
17605
+ ...hasInitHook(classInfo.decl) ? { hasOnInit: true } : {},
17033
17606
  exported: true,
17034
17607
  file,
17035
17608
  line,
@@ -17041,7 +17614,7 @@ async function analyzeProject(rootDir, include, cache, changedPaths) {
17041
17614
  const controllerDec = findDecorator(classInfo.decl, "Controller");
17042
17615
  if (controllerDec) {
17043
17616
  const arg = decoratorArguments(controllerDec)[0];
17044
- const isStandalone = arg && ts4.isObjectLiteralExpression(arg) && booleanProp(arg, "standalone");
17617
+ const isStandalone = arg && ts7.isObjectLiteralExpression(arg) && booleanProp(arg, "standalone");
17045
17618
  if (isStandalone) {
17046
17619
  const ctrl = parseController(classInfo.decl, ctx);
17047
17620
  if (ctrl)
@@ -17201,16 +17774,16 @@ function collectModuleSourceClosure(module, ctx) {
17201
17774
  ownedFiles.add(relativeFile);
17202
17775
  for (const statement of sourceFile.statements) {
17203
17776
  let moduleName;
17204
- if (ts4.isImportDeclaration(statement) && ts4.isStringLiteral(statement.moduleSpecifier)) {
17777
+ if (ts7.isImportDeclaration(statement) && ts7.isStringLiteral(statement.moduleSpecifier)) {
17205
17778
  moduleName = statement.moduleSpecifier.text;
17206
- } else if (ts4.isExportDeclaration(statement) && statement.moduleSpecifier && ts4.isStringLiteral(statement.moduleSpecifier)) {
17779
+ } else if (ts7.isExportDeclaration(statement) && statement.moduleSpecifier && ts7.isStringLiteral(statement.moduleSpecifier)) {
17207
17780
  moduleName = statement.moduleSpecifier.text;
17208
- } else if (ts4.isImportEqualsDeclaration(statement) && ts4.isExternalModuleReference(statement.moduleReference) && ts4.isStringLiteral(statement.moduleReference.expression)) {
17781
+ } else if (ts7.isImportEqualsDeclaration(statement) && ts7.isExternalModuleReference(statement.moduleReference) && ts7.isStringLiteral(statement.moduleReference.expression)) {
17209
17782
  moduleName = statement.moduleReference.expression.text;
17210
17783
  }
17211
17784
  if (!moduleName || moduleName.startsWith("node:"))
17212
17785
  continue;
17213
- const resolved = ts4.resolveModuleName(moduleName, sourceFile.fileName, ctx.program.getCompilerOptions(), ts4.sys).resolvedModule?.resolvedFileName;
17786
+ const resolved = ts7.resolveModuleName(moduleName, sourceFile.fileName, ctx.program.getCompilerOptions(), ts7.sys).resolvedModule?.resolvedFileName;
17214
17787
  if (resolved && isProjectSourcePath(resolved, ctx.rootDir) && !enqueued.has(resolved)) {
17215
17788
  enqueued.add(resolved);
17216
17789
  queue.push(resolved);
@@ -17232,7 +17805,7 @@ function isProjectSourceFile(sourceFile, rootDir) {
17232
17805
  return isProjectSourcePath(sourceFile.fileName, rootDir) && /\.(tsx?|mts|cts)$/.test(sourceFile.fileName);
17233
17806
  }
17234
17807
  function indexFile(sf, ctx) {
17235
- for (const cls of sf.statements.filter(ts4.isClassDeclaration)) {
17808
+ for (const cls of sf.statements.filter(ts7.isClassDeclaration)) {
17236
17809
  const name = cls.name?.text;
17237
17810
  if (name && !ctx.classesByName.has(name)) {
17238
17811
  ctx.classesByName.set(name, { name, decl: cls, file: sf.fileName });
@@ -17240,9 +17813,9 @@ function indexFile(sf, ctx) {
17240
17813
  if (name)
17241
17814
  indexInfraResource(cls, name, sf, ctx);
17242
17815
  }
17243
- for (const statement of sf.statements.filter(ts4.isVariableStatement)) {
17816
+ for (const statement of sf.statements.filter(ts7.isVariableStatement)) {
17244
17817
  for (const decl of statement.declarationList.declarations) {
17245
- if (ts4.isIdentifier(decl.name) && !ctx.variablesByName.has(decl.name.text)) {
17818
+ if (ts7.isIdentifier(decl.name) && !ctx.variablesByName.has(decl.name.text)) {
17246
17819
  ctx.variablesByName.set(decl.name.text, decl);
17247
17820
  }
17248
17821
  const info = parseTokenVariable(decl, sf.fileName);
@@ -17254,16 +17827,16 @@ function indexFile(sf, ctx) {
17254
17827
  }
17255
17828
  function parseTokenVariable(decl, file) {
17256
17829
  const init = decl.initializer;
17257
- if (!init || !ts4.isNewExpression(init))
17830
+ if (!init || !ts7.isNewExpression(init))
17258
17831
  return;
17259
17832
  if (nodeText(init.expression) !== "InjectionToken")
17260
17833
  return;
17261
17834
  const [nameArg, optionsArg] = init.arguments ?? [];
17262
17835
  const info = { name: variableName(decl), file, line: lineOf(decl) };
17263
- if (nameArg && ts4.isStringLiteral(nameArg)) {
17836
+ if (nameArg && ts7.isStringLiteral(nameArg)) {
17264
17837
  info.stringName = nameArg.text;
17265
17838
  }
17266
- if (optionsArg && ts4.isObjectLiteralExpression(optionsArg)) {
17839
+ if (optionsArg && ts7.isObjectLiteralExpression(optionsArg)) {
17267
17840
  const scope = stringLiteralProp(optionsArg, "scope");
17268
17841
  if (scope && isScope(scope)) {
17269
17842
  info.scope = scope;
@@ -17283,23 +17856,23 @@ function parseModule(candidate, nameByNode, ctx) {
17283
17856
  const { options, className, file, line } = candidate;
17284
17857
  const name = nameByNode.get(candidate.node) ?? className;
17285
17858
  const featureSpec = parseFeatureSpec(getProp(options, "spec"), ctx);
17286
- const tags = arrayProp(options, "tags").map((el) => ts4.isStringLiteral(el) ? el.text : nodeText(el).replace(/['"]/g, "")).filter(Boolean);
17859
+ const tags = arrayProp(options, "tags").map((el) => ts7.isStringLiteral(el) ? el.text : nodeText(el).replace(/['"]/g, "")).filter(Boolean);
17287
17860
  const aspects = parseAspectRefs(getProp(options, "aspects"), ctx, `module ${name}`);
17288
17861
  const moduleResourceNames = parseModuleInfraResources(infraResourceProp(options, "resources", ctx), ctx, `module ${name}`, sourcePath(ctx.rootDir, file), line);
17289
17862
  const imports = arrayProp(options, "imports").map((el) => {
17290
17863
  const unwrapped = unwrapForwardRef(el);
17291
- const decl = ts4.isIdentifier(unwrapped) ? resolveDeclaration(unwrapped, ctx)[0] : undefined;
17864
+ const decl = ts7.isIdentifier(unwrapped) ? resolveDeclaration(unwrapped, ctx)[0] : undefined;
17292
17865
  if (decl) {
17293
17866
  const known = nameByNode.get(decl);
17294
17867
  if (known)
17295
17868
  return known;
17296
- if (ts4.isClassDeclaration(decl)) {
17869
+ if (ts7.isClassDeclaration(decl)) {
17297
17870
  const dec = findDecorator(decl, "Module");
17298
17871
  const decOptions = dec && decoratorObjectArg(dec);
17299
17872
  const decName = decOptions && stringLiteralProp(decOptions, "name");
17300
17873
  return decName ?? decl.name?.text ?? nodeText(el);
17301
17874
  }
17302
- if (ts4.isVariableDeclaration(decl))
17875
+ if (ts7.isVariableDeclaration(decl))
17303
17876
  return variableName(decl);
17304
17877
  }
17305
17878
  return nodeText(el);
@@ -17313,7 +17886,7 @@ function parseModule(candidate, nameByNode, ctx) {
17313
17886
  providers.push(...parsedProviders);
17314
17887
  continue;
17315
17888
  }
17316
- if (ts4.isCallExpression(el)) {
17889
+ if (ts7.isCallExpression(el)) {
17317
17890
  const helper = nodeText(el.expression).split(".").pop() ?? nodeText(el.expression);
17318
17891
  warn(ctx, "unsupported-provider-helper", `无法静态展开 provider helper '${helper}';请改用显式 Provider 或实现编译器支持的 helper`, sourcePath(ctx.rootDir, el.getSourceFile().fileName), lineOf(el));
17319
17892
  continue;
@@ -17323,10 +17896,10 @@ function parseModule(candidate, nameByNode, ctx) {
17323
17896
  providers.push(provider);
17324
17897
  }
17325
17898
  for (const el of arrayProp(options, "jobs")) {
17326
- if (!ts4.isIdentifier(el))
17899
+ if (!ts7.isIdentifier(el))
17327
17900
  continue;
17328
17901
  const decl = resolveDeclaration(el, ctx)[0];
17329
- if (!decl || !ts4.isClassDeclaration(decl))
17902
+ if (!decl || !ts7.isClassDeclaration(decl))
17330
17903
  continue;
17331
17904
  const className = decl.name?.text ?? el.text;
17332
17905
  const registeredProvider = providers.find((provider) => provider.token === className || provider.useClass === className);
@@ -17348,6 +17921,7 @@ function parseModule(candidate, nameByNode, ctx) {
17348
17921
  ...deps.hostDeps.length > 0 ? { hostDeps: deps.hostDeps } : {},
17349
17922
  ...deps.functionalInjects.length > 0 ? { functionalInjects: deps.functionalInjects } : {},
17350
17923
  ...hasDestroyHook(decl) ? { hasOnDestroy: true } : {},
17924
+ ...hasInitHook(decl) ? { hasOnInit: true } : {},
17351
17925
  exported: exportsSet.has(className),
17352
17926
  file: sourcePath(ctx.rootDir, decl.getSourceFile().fileName),
17353
17927
  line: lineOf(decl),
@@ -17363,18 +17937,18 @@ function parseModule(candidate, nameByNode, ctx) {
17363
17937
  const handlerClasses = [];
17364
17938
  const seenHandlers = new Set;
17365
17939
  const collectHandler = (expr) => {
17366
- if (!ts4.isIdentifier(expr))
17940
+ if (!ts7.isIdentifier(expr))
17367
17941
  return;
17368
17942
  const decl = resolveDeclaration(expr, ctx)[0];
17369
- if (decl && ts4.isClassDeclaration(decl) && !seenHandlers.has(decl.name?.text ?? "")) {
17943
+ if (decl && ts7.isClassDeclaration(decl) && !seenHandlers.has(decl.name?.text ?? "")) {
17370
17944
  seenHandlers.add(decl.name?.text ?? "");
17371
17945
  handlerClasses.push(decl);
17372
17946
  }
17373
17947
  };
17374
17948
  for (const el of arrayProp(options, "providers")) {
17375
- if (ts4.isIdentifier(el))
17949
+ if (ts7.isIdentifier(el))
17376
17950
  collectHandler(el);
17377
- if (ts4.isObjectLiteralExpression(el)) {
17951
+ if (ts7.isObjectLiteralExpression(el)) {
17378
17952
  const useClass = getProp(el, "useClass");
17379
17953
  if (useClass)
17380
17954
  collectHandler(useClass);
@@ -17483,17 +18057,17 @@ function parseFeatureSpec(input, ctx, seen = new Set) {
17483
18057
  if (seen.has(input))
17484
18058
  return;
17485
18059
  seen.add(input);
17486
- if (ts4.isIdentifier(input)) {
17487
- const local = input.getSourceFile().statements.flatMap((statement) => ts4.isVariableStatement(statement) ? [...statement.declarationList.declarations] : []);
18060
+ if (ts7.isIdentifier(input)) {
18061
+ const local = input.getSourceFile().statements.flatMap((statement) => ts7.isVariableStatement(statement) ? [...statement.declarationList.declarations] : []);
17488
18062
  const resolved = resolveDeclaration(input, ctx)[0];
17489
- 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);
17490
- if (decl && ts4.isVariableDeclaration(decl))
18063
+ const decl = (resolved && ts7.isVariableDeclaration(resolved) ? resolved : undefined) ?? ctx.variablesByName.get(input.text) ?? local.find((candidate) => ts7.isIdentifier(candidate.name) && candidate.name.text === input.text) ?? descendantsOfKind(input.getSourceFile(), ts7.isVariableDeclaration).find((candidate) => ts7.isIdentifier(candidate.name) && candidate.name.text === input.text);
18064
+ if (decl && ts7.isVariableDeclaration(decl))
17491
18065
  return parseFeatureSpec(decl.initializer, ctx, seen);
17492
18066
  }
17493
- if (ts4.isCallExpression(input) && nodeText(input.expression) === "defineFeatureSpec") {
18067
+ if (ts7.isCallExpression(input) && nodeText(input.expression) === "defineFeatureSpec") {
17494
18068
  return parseFeatureSpec(input.arguments[0], ctx, seen);
17495
18069
  }
17496
- if (ts4.isAsExpression(input) || ts4.isSatisfiesExpression(input) || ts4.isParenthesizedExpression(input)) {
18070
+ if (ts7.isAsExpression(input) || ts7.isSatisfiesExpression(input) || ts7.isParenthesizedExpression(input)) {
17497
18071
  return parseFeatureSpec(input.expression, ctx, seen);
17498
18072
  }
17499
18073
  const invalid = () => {
@@ -17506,28 +18080,28 @@ function parseFeatureSpec(input, ctx, seen = new Set) {
17506
18080
  });
17507
18081
  return;
17508
18082
  };
17509
- if (!ts4.isObjectLiteralExpression(input))
18083
+ if (!ts7.isObjectLiteralExpression(input))
17510
18084
  return invalid();
17511
18085
  const name = stringLiteralProp(input, "name");
17512
18086
  const statesExpr = getProp(input, "states");
17513
18087
  const transitionObject = getProp(input, "transitions");
17514
- if (!name || !statesExpr || !ts4.isArrayLiteralExpression(statesExpr) || statesExpr.elements.some((state) => !ts4.isStringLiteral(state)) || !transitionObject || !ts4.isObjectLiteralExpression(transitionObject) || input.properties.some((property) => !ts4.isPropertyAssignment(property))) {
18088
+ if (!name || !statesExpr || !ts7.isArrayLiteralExpression(statesExpr) || statesExpr.elements.some((state) => !ts7.isStringLiteral(state)) || !transitionObject || !ts7.isObjectLiteralExpression(transitionObject) || input.properties.some((property) => !ts7.isPropertyAssignment(property))) {
17515
18089
  return invalid();
17516
18090
  }
17517
18091
  const states = [];
17518
18092
  for (const state of statesExpr.elements) {
17519
- if (!ts4.isStringLiteral(state))
18093
+ if (!ts7.isStringLiteral(state))
17520
18094
  return invalid();
17521
18095
  states.push(state.text);
17522
18096
  }
17523
18097
  const transitions = [];
17524
18098
  for (const property of transitionObject.properties) {
17525
- if (!ts4.isPropertyAssignment(property) || ts4.isComputedPropertyName(property.name) || !ts4.isObjectLiteralExpression(property.initializer))
18099
+ if (!ts7.isPropertyAssignment(property) || ts7.isComputedPropertyName(property.name) || !ts7.isObjectLiteralExpression(property.initializer))
17526
18100
  return invalid();
17527
18101
  const options = property.initializer;
17528
18102
  const from = stringLiteralProp(options, "from");
17529
18103
  const to = stringLiteralProp(options, "to");
17530
- 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))) {
18104
+ if (!from || !to || options.properties.some((prop) => !ts7.isPropertyAssignment(prop)) || ["permission", "command", "route", "audit"].some((key) => getProp(options, key) && !stringLiteralProp(options, key)) || ["transaction", "idempotency"].some((key) => getProp(options, key) && !commandModeProp(options, key))) {
17531
18105
  return invalid();
17532
18106
  }
17533
18107
  const permission = stringLiteralProp(options, "permission");
@@ -17554,21 +18128,21 @@ function resolveStaticObjectLiteral(input, ctx, seen = new Set) {
17554
18128
  if (!input || seen.has(input))
17555
18129
  return;
17556
18130
  seen.add(input);
17557
- if (ts4.isAsExpression(input) || ts4.isSatisfiesExpression(input) || ts4.isParenthesizedExpression(input)) {
18131
+ if (ts7.isAsExpression(input) || ts7.isSatisfiesExpression(input) || ts7.isParenthesizedExpression(input)) {
17558
18132
  return resolveStaticObjectLiteral(input.expression, ctx, seen);
17559
18133
  }
17560
- if (ts4.isIdentifier(input)) {
17561
- const declaration = resolveDeclaration(input, ctx).find(ts4.isVariableDeclaration);
18134
+ if (ts7.isIdentifier(input)) {
18135
+ const declaration = resolveDeclaration(input, ctx).find(ts7.isVariableDeclaration);
17562
18136
  return declaration?.initializer ? resolveStaticObjectLiteral(declaration.initializer, ctx, seen) : undefined;
17563
18137
  }
17564
- if (ts4.isCallExpression(input)) {
18138
+ if (ts7.isCallExpression(input)) {
17565
18139
  const expressionName = nodeText(input.expression);
17566
18140
  if (expressionName === "defineRouteContract" || expressionName.endsWith(".defineRouteContract")) {
17567
18141
  return resolveStaticObjectLiteral(input.arguments[0], ctx, seen);
17568
18142
  }
17569
18143
  return;
17570
18144
  }
17571
- return ts4.isObjectLiteralExpression(input) ? input : undefined;
18145
+ return ts7.isObjectLiteralExpression(input) ? input : undefined;
17572
18146
  }
17573
18147
  function routePolicyProperty(object, name, ctx, seen = new Set) {
17574
18148
  if (seen.has(object))
@@ -17576,15 +18150,15 @@ function routePolicyProperty(object, name, ctx, seen = new Set) {
17576
18150
  const ancestry = new Set(seen).add(object);
17577
18151
  let result = { unresolved: false };
17578
18152
  for (const property of object.properties) {
17579
- if (ts4.isSpreadAssignment(property)) {
18153
+ if (ts7.isSpreadAssignment(property)) {
17580
18154
  const spread = resolveStaticObjectLiteral(property.expression, ctx);
17581
18155
  const nested = spread ? routePolicyProperty(spread, name, ctx, ancestry) : { unresolved: true };
17582
18156
  if (nested.unresolved || nested.value !== undefined)
17583
18157
  result = nested;
17584
- } else if (ts4.isComputedPropertyName(property.name)) {
18158
+ } else if (ts7.isComputedPropertyName(property.name)) {
17585
18159
  result = { unresolved: true };
17586
18160
  } else if (propertyName(property.name) === name) {
17587
- result = ts4.isPropertyAssignment(property) ? { value: property.initializer, unresolved: false } : { unresolved: true };
18161
+ result = ts7.isPropertyAssignment(property) ? { value: property.initializer, unresolved: false } : { unresolved: true };
17588
18162
  }
17589
18163
  }
17590
18164
  return result;
@@ -17622,9 +18196,9 @@ function parseProvider(el, exportsSet, ctx) {
17622
18196
  const file = sourcePath(ctx.rootDir, el.getSourceFile().fileName);
17623
18197
  const line = lineOf(el);
17624
18198
  const unwrappedEl = unwrapForwardRef(el);
17625
- if (ts4.isIdentifier(unwrappedEl)) {
18199
+ if (ts7.isIdentifier(unwrappedEl)) {
17626
18200
  const decl = resolveDeclaration(unwrappedEl, ctx)[0];
17627
- const cls = decl && ts4.isClassDeclaration(decl) ? decl : undefined;
18201
+ const cls = decl && ts7.isClassDeclaration(decl) ? decl : undefined;
17628
18202
  const className = cls?.name?.text ?? unwrappedEl.text;
17629
18203
  const { deps, optionalDeps, selfDeps, skipSelfDeps, hostDeps, functionalInjects, missing } = cls ? classDeps(cls, ctx) : { deps: [], optionalDeps: [], selfDeps: [], skipSelfDeps: [], hostDeps: [], functionalInjects: [], missing: false };
17630
18204
  const injectable = cls ? parseInjectableOptions(cls, ctx) : undefined;
@@ -17645,13 +18219,14 @@ function parseProvider(el, exportsSet, ctx) {
17645
18219
  ...functionalInjects.length > 0 ? { functionalInjects } : {},
17646
18220
  ...injectable?.providedIn ? { providedIn: injectable.providedIn } : {},
17647
18221
  ...cls && hasDestroyHook(cls) ? { hasOnDestroy: true } : {},
18222
+ ...cls && hasInitHook(cls) ? { hasOnInit: true } : {},
17648
18223
  exported: exportsSet.has(className),
17649
18224
  file,
17650
18225
  line,
17651
18226
  ...cls ? { importPath: modulePath(ctx.rootDir, cls.getSourceFile().fileName) } : {}
17652
18227
  };
17653
18228
  }
17654
- if (!ts4.isObjectLiteralExpression(el))
18229
+ if (!ts7.isObjectLiteralExpression(el))
17655
18230
  return;
17656
18231
  const provideExpr = getProp(el, "provide");
17657
18232
  if (!provideExpr)
@@ -17666,8 +18241,8 @@ function parseProvider(el, exportsSet, ctx) {
17666
18241
  const useExistingExpr = getProp(el, "useExisting");
17667
18242
  if (useClassExpr) {
17668
18243
  const unwrappedClass = unwrapForwardRef(useClassExpr);
17669
- const decl = ts4.isIdentifier(unwrappedClass) ? resolveDeclaration(unwrappedClass, ctx)[0] : undefined;
17670
- const cls = decl && ts4.isClassDeclaration(decl) ? decl : undefined;
18244
+ const decl = ts7.isIdentifier(unwrappedClass) ? resolveDeclaration(unwrappedClass, ctx)[0] : undefined;
18245
+ const cls = decl && ts7.isClassDeclaration(decl) ? decl : undefined;
17671
18246
  const useClass = cls?.name?.text ?? nodeText(unwrappedClass);
17672
18247
  let deps = explicitDeps;
17673
18248
  let optionalDeps = [];
@@ -17715,6 +18290,7 @@ function parseProvider(el, exportsSet, ctx) {
17715
18290
  ...multi === undefined ? {} : { multi },
17716
18291
  ...injectable?.providedIn ? { providedIn: injectable.providedIn } : {},
17717
18292
  ...cls && hasMethod(cls, "onDestroy") ? { hasOnDestroy: true } : {},
18293
+ ...cls && hasInitHook(cls) ? { hasOnInit: true } : {},
17718
18294
  exported: exportsSet.has(token),
17719
18295
  file,
17720
18296
  line,
@@ -17723,7 +18299,7 @@ function parseProvider(el, exportsSet, ctx) {
17723
18299
  }
17724
18300
  if (useValueExpr) {
17725
18301
  validateProviderCompatibility(provideExpr, useValueExpr, "value", token, ctx, file, line);
17726
- const importPath = ts4.isIdentifier(useValueExpr) ? importPathOf(useValueExpr, ctx) : undefined;
18302
+ const importPath = ts7.isIdentifier(useValueExpr) ? importPathOf(useValueExpr, ctx) : undefined;
17727
18303
  return {
17728
18304
  token,
17729
18305
  tokenKind,
@@ -17739,12 +18315,12 @@ function parseProvider(el, exportsSet, ctx) {
17739
18315
  };
17740
18316
  }
17741
18317
  if (useFactoryExpr) {
17742
- const factoryName = ts4.isIdentifier(useFactoryExpr) ? (() => {
18318
+ const factoryName = ts7.isIdentifier(useFactoryExpr) ? (() => {
17743
18319
  const decl = resolveDeclaration(useFactoryExpr, ctx)[0];
17744
- return decl && (ts4.isFunctionDeclaration(decl) || ts4.isVariableDeclaration(decl)) ? (ts4.isFunctionDeclaration(decl) ? decl.name?.text : variableName(decl)) ?? useFactoryExpr.text : useFactoryExpr.text;
18320
+ return decl && (ts7.isFunctionDeclaration(decl) || ts7.isVariableDeclaration(decl)) ? (ts7.isFunctionDeclaration(decl) ? decl.name?.text : variableName(decl)) ?? useFactoryExpr.text : useFactoryExpr.text;
17745
18321
  })() : nodeText(useFactoryExpr);
17746
18322
  validateProviderCompatibility(provideExpr, useFactoryExpr, "factory", token, ctx, file, line);
17747
- const importPath = ts4.isIdentifier(useFactoryExpr) ? importPathOf(useFactoryExpr, ctx) : undefined;
18323
+ const importPath = ts7.isIdentifier(useFactoryExpr) ? importPathOf(useFactoryExpr, ctx) : undefined;
17748
18324
  return {
17749
18325
  token,
17750
18326
  tokenKind,
@@ -17780,20 +18356,20 @@ function parseProvider(el, exportsSet, ctx) {
17780
18356
  function expandProviderExpressions(expressions, ctx, seen = new Set) {
17781
18357
  const result = [];
17782
18358
  for (const expression of expressions) {
17783
- if (ts4.isSpreadElement(expression)) {
18359
+ if (ts7.isSpreadElement(expression)) {
17784
18360
  result.push(...expandProviderExpressions([expression.expression], ctx, seen));
17785
18361
  continue;
17786
18362
  }
17787
- if (ts4.isIdentifier(expression)) {
18363
+ if (ts7.isIdentifier(expression)) {
17788
18364
  const declaration = resolveDeclaration(expression, ctx)[0];
17789
- if (declaration && ts4.isVariableDeclaration(declaration) && declaration.initializer) {
18365
+ if (declaration && ts7.isVariableDeclaration(declaration) && declaration.initializer) {
17790
18366
  const key = `${declaration.getSourceFile().fileName}:${declaration.pos}`;
17791
18367
  if (seen.has(key))
17792
18368
  continue;
17793
18369
  const initializer = declaration.initializer;
17794
- if (ts4.isCallExpression(initializer) && isProviderHelper(initializer, "makeEnvironmentProviders")) {
18370
+ if (ts7.isCallExpression(initializer) && isProviderHelper(initializer, "makeEnvironmentProviders")) {
17795
18371
  const nested = initializer.arguments[0];
17796
- if (nested && ts4.isArrayLiteralExpression(nested)) {
18372
+ if (nested && ts7.isArrayLiteralExpression(nested)) {
17797
18373
  seen.add(key);
17798
18374
  result.push(...expandProviderExpressions([...nested.elements], ctx, seen));
17799
18375
  seen.delete(key);
@@ -17802,9 +18378,9 @@ function expandProviderExpressions(expressions, ctx, seen = new Set) {
17802
18378
  }
17803
18379
  }
17804
18380
  }
17805
- if (ts4.isCallExpression(expression) && isProviderHelper(expression, "makeEnvironmentProviders")) {
18381
+ if (ts7.isCallExpression(expression) && isProviderHelper(expression, "makeEnvironmentProviders")) {
17806
18382
  const nested = expression.arguments[0];
17807
- if (nested && ts4.isArrayLiteralExpression(nested)) {
18383
+ if (nested && ts7.isArrayLiteralExpression(nested)) {
17808
18384
  result.push(...expandProviderExpressions([...nested.elements], ctx, seen));
17809
18385
  continue;
17810
18386
  }
@@ -17817,7 +18393,7 @@ function isProviderHelper(expression, name) {
17817
18393
  return nodeText(expression.expression).split(".").pop() === name;
17818
18394
  }
17819
18395
  function parseFunctionalProvider(expression, exportsSet, ctx) {
17820
- if (!ts4.isCallExpression(expression))
18396
+ if (!ts7.isCallExpression(expression))
17821
18397
  return;
17822
18398
  const helper = nodeText(expression.expression).split(".").pop();
17823
18399
  const args = expression.arguments;
@@ -17830,7 +18406,7 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
17830
18406
  return [];
17831
18407
  const { name: token, kind: tokenKind } = tokenNameOf(tokenExpr, ctx);
17832
18408
  validateProviderCompatibility(tokenExpr, valueExpr, "value", token, ctx, file, line);
17833
- const importPath = ts4.isIdentifier(valueExpr) ? importPathOf(valueExpr, ctx) : undefined;
18409
+ const importPath = ts7.isIdentifier(valueExpr) ? importPathOf(valueExpr, ctx) : undefined;
17834
18410
  return [{
17835
18411
  token,
17836
18412
  tokenKind,
@@ -17849,7 +18425,7 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
17849
18425
  if (!initializer)
17850
18426
  return [];
17851
18427
  const token = helper === "provideAppInitializer" ? "APP_INITIALIZER" : "ENVIRONMENT_INITIALIZER";
17852
- const importPath = ts4.isIdentifier(initializer) ? importPathOf(initializer, ctx) : undefined;
18428
+ const importPath = ts7.isIdentifier(initializer) ? importPathOf(initializer, ctx) : undefined;
17853
18429
  return [{
17854
18430
  token,
17855
18431
  tokenKind: "injection-token",
@@ -17868,7 +18444,7 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
17868
18444
  const providers = [];
17869
18445
  const routes = args[0];
17870
18446
  if (routes) {
17871
- const importPath = ts4.isIdentifier(routes) ? importPathOf(routes, ctx) : undefined;
18447
+ const importPath = ts7.isIdentifier(routes) ? importPathOf(routes, ctx) : undefined;
17872
18448
  providers.push({
17873
18449
  token: "ROUTE_CONFIG",
17874
18450
  tokenKind: "injection-token",
@@ -17883,7 +18459,7 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
17883
18459
  });
17884
18460
  }
17885
18461
  for (const feature of args.slice(1)) {
17886
- if (!ts4.isCallExpression(feature))
18462
+ if (!ts7.isCallExpression(feature))
17887
18463
  continue;
17888
18464
  const featureName = nodeText(feature.expression).split(".").pop();
17889
18465
  if (featureName === "withRouterConfig" && feature.arguments[0]) {
@@ -17900,8 +18476,8 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
17900
18476
  });
17901
18477
  } else if (featureName === "withTitleStrategy" && feature.arguments[0]) {
17902
18478
  const strategy = feature.arguments[0];
17903
- const isClass = ts4.isIdentifier(strategy) && Boolean(resolveDeclaration(strategy, ctx).find((declaration) => ts4.isClassDeclaration(declaration)));
17904
- const importPath = ts4.isIdentifier(strategy) ? importPathOf(strategy, ctx) : undefined;
18479
+ const isClass = ts7.isIdentifier(strategy) && Boolean(resolveDeclaration(strategy, ctx).find((declaration) => ts7.isClassDeclaration(declaration)));
18480
+ const importPath = ts7.isIdentifier(strategy) ? importPathOf(strategy, ctx) : undefined;
17905
18481
  providers.push({
17906
18482
  token: "TITLE_STRATEGY",
17907
18483
  tokenKind: "injection-token",
@@ -17933,14 +18509,14 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
17933
18509
  importModule: "@supacloud/app"
17934
18510
  }];
17935
18511
  for (const feature of args) {
17936
- if (!ts4.isCallExpression(feature))
18512
+ if (!ts7.isCallExpression(feature))
17937
18513
  continue;
17938
18514
  const featureName = nodeText(feature.expression).split(".").pop();
17939
18515
  if (featureName === "withInterceptors") {
17940
18516
  for (const interceptorArg of feature.arguments) {
17941
- const values = ts4.isArrayLiteralExpression(interceptorArg) ? [...interceptorArg.elements] : [interceptorArg];
18517
+ const values = ts7.isArrayLiteralExpression(interceptorArg) ? [...interceptorArg.elements] : [interceptorArg];
17942
18518
  for (const value of values) {
17943
- const importPath = ts4.isIdentifier(value) ? importPathOf(value, ctx) : undefined;
18519
+ const importPath = ts7.isIdentifier(value) ? importPathOf(value, ctx) : undefined;
17944
18520
  providers.push({
17945
18521
  token: "HTTP_INTERCEPTORS",
17946
18522
  tokenKind: "injection-token",
@@ -17987,9 +18563,9 @@ function providerTokenValueType(expr, ctx) {
17987
18563
  const typeArguments = typeArgumentsOf(type, ctx);
17988
18564
  if (typeArguments.length > 0)
17989
18565
  return typeArguments[0];
17990
- if (ts4.isIdentifier(expr)) {
18566
+ if (ts7.isIdentifier(expr)) {
17991
18567
  const declaration = resolveDeclaration(expr, ctx)[0];
17992
- if (declaration && ts4.isClassDeclaration(declaration)) {
18568
+ if (declaration && ts7.isClassDeclaration(declaration)) {
17993
18569
  return declaredClassType(declaration, ctx);
17994
18570
  }
17995
18571
  }
@@ -17997,9 +18573,9 @@ function providerTokenValueType(expr, ctx) {
17997
18573
  }
17998
18574
  function providerImplementationType(expr, kind, ctx) {
17999
18575
  if (kind === "class" || kind === "existing") {
18000
- if (ts4.isIdentifier(expr)) {
18576
+ if (ts7.isIdentifier(expr)) {
18001
18577
  const declaration = resolveDeclaration(expr, ctx)[0];
18002
- if (declaration && ts4.isClassDeclaration(declaration)) {
18578
+ if (declaration && ts7.isClassDeclaration(declaration)) {
18003
18579
  return declaredClassType(declaration, ctx);
18004
18580
  }
18005
18581
  }
@@ -18009,7 +18585,7 @@ function providerImplementationType(expr, kind, ctx) {
18009
18585
  }
18010
18586
  if (kind === "factory") {
18011
18587
  const type = ctx.checker.getTypeAtLocation(expr);
18012
- const signature = ctx.checker.getSignaturesOfType(type, ts4.SignatureKind.Call)[0];
18588
+ const signature = ctx.checker.getSignaturesOfType(type, ts7.SignatureKind.Call)[0];
18013
18589
  return signature?.getReturnType();
18014
18590
  }
18015
18591
  return ctx.checker.getTypeAtLocation(expr);
@@ -18028,16 +18604,16 @@ function isTypeReference(type) {
18028
18604
  return "target" in type;
18029
18605
  }
18030
18606
  function isUnknownOrAny(type) {
18031
- return (type.flags & (ts4.TypeFlags.Any | ts4.TypeFlags.Unknown)) !== 0;
18607
+ return (type.flags & (ts7.TypeFlags.Any | ts7.TypeFlags.Unknown)) !== 0;
18032
18608
  }
18033
18609
  function parseController(input, ctx) {
18034
18610
  let decl;
18035
- if (ts4.isClassDeclaration(input)) {
18611
+ if (ts7.isClassDeclaration(input)) {
18036
18612
  decl = input;
18037
18613
  } else {
18038
18614
  const unwrapped = unwrapForwardRef(input);
18039
- const resolved = ts4.isIdentifier(unwrapped) ? resolveDeclaration(unwrapped, ctx)[0] : undefined;
18040
- if (resolved && ts4.isClassDeclaration(resolved)) {
18615
+ const resolved = ts7.isIdentifier(unwrapped) ? resolveDeclaration(unwrapped, ctx)[0] : undefined;
18616
+ if (resolved && ts7.isClassDeclaration(resolved)) {
18041
18617
  decl = resolved;
18042
18618
  }
18043
18619
  }
@@ -18050,9 +18626,9 @@ function parseController(input, ctx) {
18050
18626
  let standalone;
18051
18627
  const pathArg = decoratorArguments(controllerDec)[0];
18052
18628
  if (pathArg) {
18053
- if (ts4.isStringLiteral(pathArg)) {
18629
+ if (ts7.isStringLiteral(pathArg)) {
18054
18630
  path = pathArg.text;
18055
- } else if (ts4.isObjectLiteralExpression(pathArg)) {
18631
+ } else if (ts7.isObjectLiteralExpression(pathArg)) {
18056
18632
  const p = stringLiteralProp(pathArg, "path");
18057
18633
  if (p)
18058
18634
  path = p;
@@ -18075,7 +18651,7 @@ function parseController(input, ctx) {
18075
18651
  }
18076
18652
  }
18077
18653
  }
18078
- for (const method of decl.members.filter(ts4.isMethodDeclaration)) {
18654
+ for (const method of decl.members.filter(ts7.isMethodDeclaration)) {
18079
18655
  for (const dec of decoratorsOf(method)) {
18080
18656
  const name = decoratorName2(dec);
18081
18657
  const httpMethod = name ? ROUTE_DECORATORS[name] : undefined;
@@ -18083,7 +18659,7 @@ function parseController(input, ctx) {
18083
18659
  continue;
18084
18660
  const args = decoratorArguments(dec);
18085
18661
  const pathArg = args[0];
18086
- const routePath = pathArg && ts4.isStringLiteral(pathArg) ? pathArg.text : "/";
18662
+ const routePath = pathArg && ts7.isStringLiteral(pathArg) ? pathArg.text : "/";
18087
18663
  const route = {
18088
18664
  method: httpMethod,
18089
18665
  path: routePath,
@@ -18157,12 +18733,12 @@ function parseController(input, ctx) {
18157
18733
  } else if (dName === "Headers") {
18158
18734
  hasBindingDecorator = true;
18159
18735
  const argument = dArgs[0];
18160
- const bindingName = argument !== undefined && ts4.isStringLiteral(argument) ? argument.text : undefined;
18736
+ const bindingName = argument !== undefined && ts7.isStringLiteral(argument) ? argument.text : undefined;
18161
18737
  paramNode = { name: pName, kind: "headers", ...bindingName === undefined ? {} : { bindingName } };
18162
18738
  } else if (dName === "Cookie") {
18163
18739
  hasBindingDecorator = true;
18164
18740
  const argument = dArgs[0];
18165
- const bindingName = argument !== undefined && ts4.isStringLiteral(argument) ? argument.text : undefined;
18741
+ const bindingName = argument !== undefined && ts7.isStringLiteral(argument) ? argument.text : undefined;
18166
18742
  paramNode = { name: pName, kind: "cookie", ...bindingName === undefined ? {} : { bindingName } };
18167
18743
  }
18168
18744
  }
@@ -18224,20 +18800,20 @@ function parseController(input, ctx) {
18224
18800
  }
18225
18801
  } else if (dName === "Title") {
18226
18802
  const tArg = mArgs[0];
18227
- if (tArg && ts4.isStringLiteral(tArg)) {
18803
+ if (tArg && ts7.isStringLiteral(tArg)) {
18228
18804
  route.title = tArg.text;
18229
18805
  }
18230
18806
  } else if (dName === "Data") {
18231
18807
  const dArg = mArgs[0];
18232
- if (dArg && ts4.isObjectLiteralExpression(dArg)) {
18808
+ if (dArg && ts7.isObjectLiteralExpression(dArg)) {
18233
18809
  route.data = { ...route.data, ...parseObjectLiteralValues(dArg) };
18234
18810
  }
18235
18811
  } else if (dName === "Resolve") {
18236
18812
  const rArg = mArgs[0];
18237
- if (rArg && ts4.isObjectLiteralExpression(rArg)) {
18813
+ if (rArg && ts7.isObjectLiteralExpression(rArg)) {
18238
18814
  const resolvers = route.resolvers ?? {};
18239
18815
  for (const prop of rArg.properties) {
18240
- if (ts4.isPropertyAssignment(prop)) {
18816
+ if (ts7.isPropertyAssignment(prop)) {
18241
18817
  const rName = propertyName(prop.name);
18242
18818
  const init = prop.initializer;
18243
18819
  if (init)
@@ -18265,7 +18841,7 @@ function parseController(input, ctx) {
18265
18841
  }
18266
18842
  const parse = parsePolicy.value;
18267
18843
  if (parse) {
18268
- if (ts4.isStringLiteral(parse) && parse.text === "none")
18844
+ if (ts7.isStringLiteral(parse) && parse.text === "none")
18269
18845
  route.parse = "none";
18270
18846
  else
18271
18847
  ctx.diagnostics.push({
@@ -18277,7 +18853,7 @@ function parseController(input, ctx) {
18277
18853
  }
18278
18854
  const allowDeleteBody = deletePolicy.value;
18279
18855
  if (allowDeleteBody) {
18280
- if (allowDeleteBody.kind === ts4.SyntaxKind.TrueKeyword)
18856
+ if (allowDeleteBody.kind === ts7.SyntaxKind.TrueKeyword)
18281
18857
  route.allowDeleteBody = true;
18282
18858
  else
18283
18859
  ctx.diagnostics.push({
@@ -18302,7 +18878,7 @@ function parseController(input, ctx) {
18302
18878
  });
18303
18879
  }
18304
18880
  const contract = getProp(optionsObject, "contract");
18305
- if (contract && ts4.isObjectLiteralExpression(contract)) {
18881
+ if (contract && ts7.isObjectLiteralExpression(contract)) {
18306
18882
  route.contract = {};
18307
18883
  for (const field of ["body", "response", "evidence"]) {
18308
18884
  const value = stringLiteralProp(contract, field);
@@ -18320,7 +18896,7 @@ function parseController(input, ctx) {
18320
18896
  }
18321
18897
  for (const field of ["body", "params", "query", "headers", "cookie", "response"]) {
18322
18898
  const schemaExpr = getProp(optionsObject, field);
18323
- if (schemaExpr && ts4.isIdentifier(schemaExpr)) {
18899
+ if (schemaExpr && ts7.isIdentifier(schemaExpr)) {
18324
18900
  route[field] = nodeText(schemaExpr);
18325
18901
  const importPath = importPathOf(schemaExpr, ctx);
18326
18902
  if (importPath)
@@ -18335,7 +18911,7 @@ function parseController(input, ctx) {
18335
18911
  const responses = {};
18336
18912
  const selectors = new Map;
18337
18913
  for (const property of responsesObject.properties) {
18338
- if (!ts4.isPropertyAssignment(property) || ts4.isComputedPropertyName(property.name))
18914
+ if (!ts7.isPropertyAssignment(property) || ts7.isComputedPropertyName(property.name))
18339
18915
  continue;
18340
18916
  const status = propertyName(property.name);
18341
18917
  if (!isRouteResponseSelector(status)) {
@@ -18367,7 +18943,7 @@ function parseController(input, ctx) {
18367
18943
  }
18368
18944
  selectors.set(canonical, status);
18369
18945
  const schemaExpr = property.initializer;
18370
- if (!ts4.isIdentifier(schemaExpr)) {
18946
+ if (!ts7.isIdentifier(schemaExpr)) {
18371
18947
  ctx.diagnostics.push({
18372
18948
  severity: "error",
18373
18949
  code: "invalid-route-response-map",
@@ -18389,18 +18965,18 @@ function parseController(input, ctx) {
18389
18965
  route.responses = responses;
18390
18966
  }
18391
18967
  const commandExpr = getProp(optionsObject, "command");
18392
- if (commandExpr && ts4.isIdentifier(commandExpr)) {
18968
+ if (commandExpr && ts7.isIdentifier(commandExpr)) {
18393
18969
  const commandDecl = resolveDeclaration(commandExpr, ctx)[0];
18394
- route.command = commandDecl && ts4.isClassDeclaration(commandDecl) ? commandDecl.name?.text ?? commandExpr.text : commandExpr.text;
18970
+ route.command = commandDecl && ts7.isClassDeclaration(commandDecl) ? commandDecl.name?.text ?? commandExpr.text : commandExpr.text;
18395
18971
  }
18396
18972
  const guardsExpr = getProp(optionsObject, "guards");
18397
- if (guardsExpr && ts4.isArrayLiteralExpression(guardsExpr)) {
18973
+ if (guardsExpr && ts7.isArrayLiteralExpression(guardsExpr)) {
18398
18974
  for (const el of guardsExpr.elements) {
18399
18975
  routeGuards.push(tokenText(el, ctx));
18400
18976
  }
18401
18977
  }
18402
18978
  const canMatchExpr = getProp(optionsObject, "canMatch");
18403
- if (canMatchExpr && ts4.isArrayLiteralExpression(canMatchExpr)) {
18979
+ if (canMatchExpr && ts7.isArrayLiteralExpression(canMatchExpr)) {
18404
18980
  const canMatchList = [];
18405
18981
  for (const el of canMatchExpr.elements) {
18406
18982
  canMatchList.push(tokenText(el, ctx));
@@ -18410,16 +18986,16 @@ function parseController(input, ctx) {
18410
18986
  }
18411
18987
  }
18412
18988
  const canDeactivateExpr = getProp(optionsObject, "canDeactivate");
18413
- if (canDeactivateExpr && ts4.isArrayLiteralExpression(canDeactivateExpr)) {
18989
+ if (canDeactivateExpr && ts7.isArrayLiteralExpression(canDeactivateExpr)) {
18414
18990
  for (const el of canDeactivateExpr.elements) {
18415
18991
  routeCanDeactivate.push(tokenText(el, ctx));
18416
18992
  }
18417
18993
  }
18418
18994
  const resolversExpr = getProp(optionsObject, "resolvers");
18419
- if (resolversExpr && ts4.isObjectLiteralExpression(resolversExpr)) {
18995
+ if (resolversExpr && ts7.isObjectLiteralExpression(resolversExpr)) {
18420
18996
  const resolvers = {};
18421
18997
  for (const prop of resolversExpr.properties) {
18422
- if (ts4.isPropertyAssignment(prop)) {
18998
+ if (ts7.isPropertyAssignment(prop)) {
18423
18999
  const rName = propertyName(prop.name);
18424
19000
  const init = prop.initializer;
18425
19001
  if (init)
@@ -18431,22 +19007,22 @@ function parseController(input, ctx) {
18431
19007
  }
18432
19008
  }
18433
19009
  const redirectToExpr = getProp(optionsObject, "redirectTo");
18434
- if (redirectToExpr && ts4.isStringLiteral(redirectToExpr)) {
19010
+ if (redirectToExpr && ts7.isStringLiteral(redirectToExpr)) {
18435
19011
  route.redirectTo = redirectToExpr.text;
18436
19012
  }
18437
19013
  const pathMatchExpr = getProp(optionsObject, "pathMatch");
18438
- if (pathMatchExpr && ts4.isStringLiteral(pathMatchExpr)) {
19014
+ if (pathMatchExpr && ts7.isStringLiteral(pathMatchExpr)) {
18439
19015
  const val = pathMatchExpr.text;
18440
19016
  if (val === "full" || val === "prefix") {
18441
19017
  route.pathMatch = val;
18442
19018
  }
18443
19019
  }
18444
19020
  const titleExpr = getProp(optionsObject, "title");
18445
- if (titleExpr && ts4.isStringLiteral(titleExpr)) {
19021
+ if (titleExpr && ts7.isStringLiteral(titleExpr)) {
18446
19022
  route.title = titleExpr.text;
18447
19023
  }
18448
19024
  const dataExpr = getProp(optionsObject, "data");
18449
- if (dataExpr && ts4.isObjectLiteralExpression(dataExpr)) {
19025
+ if (dataExpr && ts7.isObjectLiteralExpression(dataExpr)) {
18450
19026
  route.data = { ...route.data, ...parseObjectLiteralValues(dataExpr) };
18451
19027
  }
18452
19028
  const aspects = parseAspectRefs(getProp(optionsObject, "aspects"), ctx, `route ${httpMethod} ${routePath}`);
@@ -18468,6 +19044,7 @@ function parseController(input, ctx) {
18468
19044
  scope: injectable?.scope ?? "request",
18469
19045
  deps,
18470
19046
  ...hasDestroyHook(decl) ? { hasOnDestroy: true } : {},
19047
+ ...hasInitHook(decl) ? { hasOnInit: true } : {},
18471
19048
  ...optionalDeps.length > 0 ? { optionalDeps } : {},
18472
19049
  ...selfDeps.length > 0 ? { selfDeps } : {},
18473
19050
  ...skipSelfDeps.length > 0 ? { skipSelfDeps } : {},
@@ -18501,7 +19078,7 @@ function parseJobOptions(meta, owner, ctx) {
18501
19078
  const expression = getProp(meta, field);
18502
19079
  if (!expression)
18503
19080
  continue;
18504
- if (!ts4.isIdentifier(expression)) {
19081
+ if (!ts7.isIdentifier(expression)) {
18505
19082
  jobOptionError(ctx, "invalid-job-schema", `${owner} 的 ${field} schema 必须是可静态解析的标识符引用,不能使用内联调用或动态表达式`, expression, "SC4019", `将 schema 提取为命名导出,例如 ${field}: ${field === "input" ? "JobInput" : "JobOutput"}。`);
18506
19083
  continue;
18507
19084
  }
@@ -18525,7 +19102,7 @@ function parseJobEnum(meta, field, allowed, owner, ctx, code, errorCode) {
18525
19102
  const expression = getProp(meta, field);
18526
19103
  if (!expression)
18527
19104
  return;
18528
- if (!ts4.isStringLiteral(expression) || !allowed.includes(expression.text)) {
19105
+ if (!ts7.isStringLiteral(expression) || !allowed.includes(expression.text)) {
18529
19106
  jobOptionError(ctx, code, `${owner} 的 ${field} 必须是 ${allowed.map((value) => JSON.stringify(value)).join(" 或 ")} 字符串字面量`, expression, errorCode);
18530
19107
  return;
18531
19108
  }
@@ -18535,7 +19112,7 @@ function parseJobInteger(meta, field, min, max, owner, ctx, code, errorCode) {
18535
19112
  const expression = getProp(meta, field);
18536
19113
  if (!expression)
18537
19114
  return;
18538
- const value = ts4.isNumericLiteral(expression) ? Number(expression.text) : Number.NaN;
19115
+ const value = ts7.isNumericLiteral(expression) ? Number(expression.text) : Number.NaN;
18539
19116
  if (!Number.isSafeInteger(value) || value < min || value > max) {
18540
19117
  jobOptionError(ctx, code, `${owner} 的 ${field} 必须是 ${min} 到 ${max} 之间的安全整数`, expression, errorCode);
18541
19118
  return;
@@ -18571,7 +19148,7 @@ function isOpaqueSchema(identifier, declaration, ctx) {
18571
19148
  const property = type.getProperty(kind.value === "Union" ? "anyOf" : "allOf");
18572
19149
  if (!property)
18573
19150
  return true;
18574
- const members = ctx.checker.getIndexTypeOfType(ctx.checker.getTypeOfSymbolAtLocation(property, identifier), ts4.IndexKind.Number);
19151
+ const members = ctx.checker.getIndexTypeOfType(ctx.checker.getTypeOfSymbolAtLocation(property, identifier), ts7.IndexKind.Number);
18575
19152
  if (!members)
18576
19153
  return true;
18577
19154
  const branches = members.isUnion() ? members.types : [members];
@@ -18583,8 +19160,8 @@ function isOpaqueSchema(identifier, declaration, ctx) {
18583
19160
  }
18584
19161
  if (opaque(ctx.checker.getTypeAtLocation(identifier), new Set))
18585
19162
  return true;
18586
- const initializer = declaration && ts4.isVariableDeclaration(declaration) ? declaration.initializer : undefined;
18587
- return Boolean(initializer && ts4.isCallExpression(initializer) && ts4.isPropertyAccessExpression(initializer.expression) && ["Unknown", "Any"].includes(initializer.expression.name.text));
19163
+ const initializer = declaration && ts7.isVariableDeclaration(declaration) ? declaration.initializer : undefined;
19164
+ return Boolean(initializer && ts7.isCallExpression(initializer) && ts7.isPropertyAccessExpression(initializer.expression) && ["Unknown", "Any"].includes(initializer.expression.name.text));
18588
19165
  }
18589
19166
  function checkedRpc(meta, ctx) {
18590
19167
  const expression = getProp(meta, "rpc");
@@ -18605,7 +19182,7 @@ function checkedRpc(meta, ctx) {
18605
19182
  }
18606
19183
  function classDeps(cls, ctx) {
18607
19184
  const injectable = parseInjectableOptions(cls, ctx);
18608
- const ctor = cls.members.find(ts4.isConstructorDeclaration);
19185
+ const ctor = cls.members.find(ts7.isConstructorDeclaration);
18609
19186
  const deps = injectable?.deps ? [...injectable.deps] : [];
18610
19187
  const optionalDeps = [];
18611
19188
  const selfDeps = [];
@@ -18639,23 +19216,23 @@ function classDeps(cls, ctx) {
18639
19216
  }
18640
19217
  });
18641
19218
  }
18642
- for (const prop of cls.members.filter(ts4.isPropertyDeclaration)) {
19219
+ for (const prop of cls.members.filter(ts7.isPropertyDeclaration)) {
18643
19220
  const init = prop.initializer;
18644
- if (init && ts4.isCallExpression(init)) {
19221
+ if (init && ts7.isCallExpression(init)) {
18645
19222
  const callName = nodeText(init.expression).split(".").pop();
18646
19223
  if (callName === "inject") {
18647
19224
  const [tokenArg, optionsArg] = init.arguments;
18648
19225
  if (tokenArg) {
18649
19226
  const tokenName = tokenText(tokenArg, ctx);
18650
19227
  const unwrappedToken = unwrapForwardRef(tokenArg);
18651
- const known = ts4.isStringLiteral(unwrappedToken) || ts4.isIdentifier(unwrappedToken) && (ctx.tokensByName.has(tokenName) || ctx.classesByName.has(tokenName));
19228
+ const known = ts7.isStringLiteral(unwrappedToken) || ts7.isIdentifier(unwrappedToken) && (ctx.tokensByName.has(tokenName) || ctx.classesByName.has(tokenName));
18652
19229
  if (!known) {
18653
19230
  missing = true;
18654
19231
  continue;
18655
19232
  }
18656
19233
  if (!deps.includes(tokenName))
18657
19234
  deps.push(tokenName);
18658
- const options = optionsArg && ts4.isObjectLiteralExpression(optionsArg) ? {
19235
+ const options = optionsArg && ts7.isObjectLiteralExpression(optionsArg) ? {
18659
19236
  optional: booleanProp(optionsArg, "optional") ?? false,
18660
19237
  self: booleanProp(optionsArg, "self") ?? false,
18661
19238
  skipSelf: booleanProp(optionsArg, "skipSelf") ?? false,
@@ -18670,9 +19247,9 @@ function classDeps(cls, ctx) {
18670
19247
  if (options.host && !hostDeps.includes(tokenName))
18671
19248
  hostDeps.push(tokenName);
18672
19249
  if (!functionalInjects.some((entry) => entry.token === tokenName)) {
18673
- const declaration = ts4.isIdentifier(unwrappedToken) ? resolveDeclaration(unwrappedToken, ctx)[0] : undefined;
19250
+ const declaration = ts7.isIdentifier(unwrappedToken) ? resolveDeclaration(unwrappedToken, ctx)[0] : undefined;
18674
19251
  const localFile = declaration && isProjectSourcePath(declaration.getSourceFile().fileName, ctx.rootDir) ? declaration.getSourceFile().fileName : undefined;
18675
- const importModule = declaration && !localFile && ts4.isIdentifier(unwrappedToken) ? importModuleOf(unwrappedToken, ctx) : undefined;
19252
+ const importModule = declaration && !localFile && ts7.isIdentifier(unwrappedToken) ? importModuleOf(unwrappedToken, ctx) : undefined;
18676
19253
  functionalInjects.push({
18677
19254
  token: tokenName,
18678
19255
  expression: nodeText(unwrappedToken),
@@ -18716,7 +19293,7 @@ function parseInjectableOptions(cls, ctx) {
18716
19293
  }
18717
19294
  function parseInjectParams(cls, ctx) {
18718
19295
  const result = new Map;
18719
- const ctor = cls.members.find(ts4.isConstructorDeclaration);
19296
+ const ctor = cls.members.find(ts7.isConstructorDeclaration);
18720
19297
  if (!ctor)
18721
19298
  return result;
18722
19299
  ctor.parameters.forEach((param, index) => {
@@ -18732,7 +19309,7 @@ function parseInjectParams(cls, ctx) {
18732
19309
  }
18733
19310
  function parseOptionalParams(cls) {
18734
19311
  const result = new Set;
18735
- const ctor = cls.members.find(ts4.isConstructorDeclaration);
19312
+ const ctor = cls.members.find(ts7.isConstructorDeclaration);
18736
19313
  if (!ctor)
18737
19314
  return result;
18738
19315
  ctor.parameters.forEach((param, index) => {
@@ -18747,7 +19324,7 @@ function parseOptionalParams(cls) {
18747
19324
  }
18748
19325
  function parseModifierParams(cls, modifierName) {
18749
19326
  const result = new Set;
18750
- const ctor = cls.members.find(ts4.isConstructorDeclaration);
19327
+ const ctor = cls.members.find(ts7.isConstructorDeclaration);
18751
19328
  if (!ctor)
18752
19329
  return result;
18753
19330
  ctor.parameters.forEach((param, index) => {
@@ -18759,13 +19336,13 @@ function parseModifierParams(cls, modifierName) {
18759
19336
  return result;
18760
19337
  }
18761
19338
  function unwrapForwardRef(expr) {
18762
- if (ts4.isCallExpression(expr)) {
19339
+ if (ts7.isCallExpression(expr)) {
18763
19340
  const exprText = nodeText(expr.expression);
18764
19341
  if (exprText === "forwardRef" || exprText.endsWith(".forwardRef")) {
18765
19342
  const arg = expr.arguments[0];
18766
- if (arg && (ts4.isArrowFunction(arg) || ts4.isFunctionExpression(arg))) {
19343
+ if (arg && (ts7.isArrowFunction(arg) || ts7.isFunctionExpression(arg))) {
18767
19344
  const body = arg.body;
18768
- if (body && ts4.isExpression(body)) {
19345
+ if (body && ts7.isExpression(body)) {
18769
19346
  return unwrapForwardRef(body);
18770
19347
  }
18771
19348
  }
@@ -18775,13 +19352,13 @@ function unwrapForwardRef(expr) {
18775
19352
  }
18776
19353
  function tokenText(expr, ctx) {
18777
19354
  const unwrapped = unwrapForwardRef(expr);
18778
- if (ts4.isStringLiteral(unwrapped))
19355
+ if (ts7.isStringLiteral(unwrapped))
18779
19356
  return unwrapped.text;
18780
- if (ts4.isIdentifier(unwrapped)) {
19357
+ if (ts7.isIdentifier(unwrapped)) {
18781
19358
  const decl = resolveDeclaration(unwrapped, ctx)[0];
18782
- if (decl && ts4.isClassDeclaration(decl))
19359
+ if (decl && ts7.isClassDeclaration(decl))
18783
19360
  return decl.name?.text ?? unwrapped.text;
18784
- if (decl && ts4.isVariableDeclaration(decl))
19361
+ if (decl && ts7.isVariableDeclaration(decl))
18785
19362
  return variableName(decl);
18786
19363
  }
18787
19364
  return nodeText(unwrapped);
@@ -18801,12 +19378,12 @@ function resolveScope(input, ctx) {
18801
19378
  }
18802
19379
  function tokenNameOf(expr, ctx) {
18803
19380
  const unwrapped = unwrapForwardRef(expr);
18804
- if (ts4.isIdentifier(unwrapped)) {
19381
+ if (ts7.isIdentifier(unwrapped)) {
18805
19382
  const decl = resolveDeclaration(unwrapped, ctx)[0];
18806
- if (decl && ts4.isClassDeclaration(decl)) {
19383
+ if (decl && ts7.isClassDeclaration(decl)) {
18807
19384
  return { name: decl.name?.text ?? nodeText(expr), kind: "class" };
18808
19385
  }
18809
- if (decl && ts4.isVariableDeclaration(decl)) {
19386
+ if (decl && ts7.isVariableDeclaration(decl)) {
18810
19387
  const name = variableName(decl);
18811
19388
  return { name, kind: ctx.tokensByName.has(name) ? "injection-token" : "class" };
18812
19389
  }
@@ -18822,10 +19399,10 @@ function resolveDeclaration(id, ctx) {
18822
19399
  return [];
18823
19400
  let declarations = symbol.declarations ?? [];
18824
19401
  for (let guard = 0;guard < 4; guard += 1) {
18825
- const isAlias = declarations.some((d) => ts4.isImportSpecifier(d) || ts4.isImportClause(d) || ts4.isNamespaceImport(d));
19402
+ const isAlias = declarations.some((d) => ts7.isImportSpecifier(d) || ts7.isImportClause(d) || ts7.isNamespaceImport(d));
18826
19403
  if (!isAlias)
18827
19404
  break;
18828
- if (!(symbol.flags & ts4.SymbolFlags.Alias))
19405
+ if (!(symbol.flags & ts7.SymbolFlags.Alias))
18829
19406
  break;
18830
19407
  const aliased = ctx.checker.getAliasedSymbol(symbol);
18831
19408
  symbol = aliased;
@@ -18845,9 +19422,9 @@ function importModuleOf(id, ctx) {
18845
19422
  for (const declaration of declarations) {
18846
19423
  let current = declaration;
18847
19424
  while (current) {
18848
- if (ts4.isImportDeclaration(current)) {
19425
+ if (ts7.isImportDeclaration(current)) {
18849
19426
  const moduleSpecifier = current.moduleSpecifier;
18850
- return ts4.isStringLiteral(moduleSpecifier) ? moduleSpecifier.text : undefined;
19427
+ return ts7.isStringLiteral(moduleSpecifier) ? moduleSpecifier.text : undefined;
18851
19428
  }
18852
19429
  current = current.parent;
18853
19430
  }
@@ -18859,27 +19436,27 @@ function findDecorator(cls, name) {
18859
19436
  }
18860
19437
  function decoratorName2(dec) {
18861
19438
  const expr = dec.expression;
18862
- if (ts4.isCallExpression(expr)) {
19439
+ if (ts7.isCallExpression(expr)) {
18863
19440
  return nodeText(expr.expression).split(".").pop();
18864
19441
  }
18865
- if (ts4.isIdentifier(expr))
19442
+ if (ts7.isIdentifier(expr))
18866
19443
  return expr.text;
18867
19444
  return;
18868
19445
  }
18869
19446
  function decoratorObjectArg(dec) {
18870
19447
  const expr = dec.expression;
18871
- if (!ts4.isCallExpression(expr))
19448
+ if (!ts7.isCallExpression(expr))
18872
19449
  return;
18873
19450
  const arg = expr.arguments[0];
18874
- return arg && ts4.isObjectLiteralExpression(arg) ? arg : undefined;
19451
+ return arg && ts7.isObjectLiteralExpression(arg) ? arg : undefined;
18875
19452
  }
18876
19453
  function getProp(obj, name) {
18877
- const prop = obj.properties.find((item) => (ts4.isPropertyAssignment(item) || ts4.isShorthandPropertyAssignment(item)) && propertyName(item.name) === name);
19454
+ const prop = obj.properties.find((item) => (ts7.isPropertyAssignment(item) || ts7.isShorthandPropertyAssignment(item)) && propertyName(item.name) === name);
18878
19455
  if (!prop)
18879
19456
  return;
18880
- if (ts4.isPropertyAssignment(prop))
19457
+ if (ts7.isPropertyAssignment(prop))
18881
19458
  return prop.initializer;
18882
- if (ts4.isShorthandPropertyAssignment(prop))
19459
+ if (ts7.isShorthandPropertyAssignment(prop))
18883
19460
  return prop.name;
18884
19461
  return;
18885
19462
  }
@@ -18887,10 +19464,10 @@ function toCompilerDiagnostic(diagnostic, rootDir) {
18887
19464
  const file = diagnostic.file;
18888
19465
  const position = file && diagnostic.start !== undefined ? file.getLineAndCharacterOfPosition(diagnostic.start) : undefined;
18889
19466
  return {
18890
- severity: diagnostic.category === ts4.DiagnosticCategory.Error ? "error" : "warn",
19467
+ severity: diagnostic.category === ts7.DiagnosticCategory.Error ? "error" : "warn",
18891
19468
  code: `typescript-${diagnostic.code}`,
18892
19469
  errorCode: `TS${diagnostic.code}`,
18893
- message: ts4.flattenDiagnosticMessageText(diagnostic.messageText, `
19470
+ message: ts7.flattenDiagnosticMessageText(diagnostic.messageText, `
18894
19471
  `),
18895
19472
  ...file ? { file: sourcePath(rootDir, file.fileName) } : {},
18896
19473
  ...position ? { line: position.line + 1 } : {}
@@ -18898,16 +19475,16 @@ function toCompilerDiagnostic(diagnostic, rootDir) {
18898
19475
  }
18899
19476
  function stringLiteralProp(obj, name) {
18900
19477
  const expr = getProp(obj, name);
18901
- return expr && ts4.isStringLiteral(expr) ? expr.text : undefined;
19478
+ return expr && ts7.isStringLiteral(expr) ? expr.text : undefined;
18902
19479
  }
18903
19480
  function arrayProp(obj, name) {
18904
19481
  const expr = getProp(obj, name);
18905
- return expr && ts4.isArrayLiteralExpression(expr) ? [...expr.elements] : [];
19482
+ return expr && ts7.isArrayLiteralExpression(expr) ? [...expr.elements] : [];
18906
19483
  }
18907
19484
  function parseAspectRefs(expression, ctx, owner) {
18908
19485
  if (!expression)
18909
19486
  return [];
18910
- if (!ts4.isArrayLiteralExpression(expression)) {
19487
+ if (!ts7.isArrayLiteralExpression(expression)) {
18911
19488
  ctx.diagnostics.push({
18912
19489
  severity: "error",
18913
19490
  code: "dynamic-aspect-reference",
@@ -18922,7 +19499,7 @@ function parseAspectRefs(expression, ctx, owner) {
18922
19499
  }
18923
19500
  const refs = [];
18924
19501
  for (const element of expression.elements) {
18925
- if (ts4.isSpreadElement(element) || !ts4.isIdentifier(element)) {
19502
+ if (ts7.isSpreadElement(element) || !ts7.isIdentifier(element)) {
18926
19503
  ctx.diagnostics.push({
18927
19504
  severity: "error",
18928
19505
  code: "dynamic-aspect-reference",
@@ -18935,7 +19512,7 @@ function parseAspectRefs(expression, ctx, owner) {
18935
19512
  });
18936
19513
  continue;
18937
19514
  }
18938
- const declaration = resolveDeclaration(element, ctx).find((candidate) => ts4.isFunctionDeclaration(candidate) || ts4.isVariableDeclaration(candidate) && candidate.initializer !== undefined && (ts4.isArrowFunction(candidate.initializer) || ts4.isFunctionExpression(candidate.initializer)));
19515
+ const declaration = resolveDeclaration(element, ctx).find((candidate) => ts7.isFunctionDeclaration(candidate) || ts7.isVariableDeclaration(candidate) && candidate.initializer !== undefined && (ts7.isArrowFunction(candidate.initializer) || ts7.isFunctionExpression(candidate.initializer)));
18939
19516
  if (!declaration) {
18940
19517
  ctx.diagnostics.push({
18941
19518
  severity: "error",
@@ -18949,7 +19526,7 @@ function parseAspectRefs(expression, ctx, owner) {
18949
19526
  });
18950
19527
  continue;
18951
19528
  }
18952
- const name = ts4.isFunctionDeclaration(declaration) ? declaration.name?.text : ts4.isVariableDeclaration(declaration) ? variableName(declaration) : undefined;
19529
+ const name = ts7.isFunctionDeclaration(declaration) ? declaration.name?.text : ts7.isVariableDeclaration(declaration) ? variableName(declaration) : undefined;
18953
19530
  if (!name)
18954
19531
  continue;
18955
19532
  const declaredFile = declaration.getSourceFile().fileName;
@@ -18969,9 +19546,9 @@ function booleanProp(obj, name) {
18969
19546
  const expr = getProp(obj, name);
18970
19547
  if (!expr)
18971
19548
  return;
18972
- if (expr.kind === ts4.SyntaxKind.TrueKeyword)
19549
+ if (expr.kind === ts7.SyntaxKind.TrueKeyword)
18973
19550
  return true;
18974
- if (expr.kind === ts4.SyntaxKind.FalseKeyword)
19551
+ if (expr.kind === ts7.SyntaxKind.FalseKeyword)
18975
19552
  return false;
18976
19553
  return;
18977
19554
  }
@@ -18985,15 +19562,15 @@ function parseBindingOptions(args, defaultName) {
18985
19562
  let defaultValue;
18986
19563
  const first = args[0];
18987
19564
  const second = args[1];
18988
- if (first && ts4.isStringLiteral(first)) {
19565
+ if (first && ts7.isStringLiteral(first)) {
18989
19566
  name = first.text;
18990
- } else if (first && ts4.isObjectLiteralExpression(first)) {
19567
+ } else if (first && ts7.isObjectLiteralExpression(first)) {
18991
19568
  const nameProp = getProp(first, "name");
18992
- if (nameProp && ts4.isStringLiteral(nameProp)) {
19569
+ if (nameProp && ts7.isStringLiteral(nameProp)) {
18993
19570
  name = nameProp.text;
18994
19571
  }
18995
19572
  const trProp = getProp(first, "transform");
18996
- if (trProp && ts4.isStringLiteral(trProp)) {
19573
+ if (trProp && ts7.isStringLiteral(trProp)) {
18997
19574
  const val = trProp.text;
18998
19575
  if (val === "number" || val === "boolean" || val === "string") {
18999
19576
  transform = val;
@@ -19004,9 +19581,9 @@ function parseBindingOptions(args, defaultName) {
19004
19581
  defaultValue = parseLiteralValue(defProp);
19005
19582
  }
19006
19583
  }
19007
- if (second && ts4.isObjectLiteralExpression(second)) {
19584
+ if (second && ts7.isObjectLiteralExpression(second)) {
19008
19585
  const trProp = getProp(second, "transform");
19009
- if (trProp && ts4.isStringLiteral(trProp)) {
19586
+ if (trProp && ts7.isStringLiteral(trProp)) {
19010
19587
  const val = trProp.text;
19011
19588
  if (val === "number" || val === "boolean" || val === "string") {
19012
19589
  transform = val;
@@ -19020,18 +19597,18 @@ function parseBindingOptions(args, defaultName) {
19020
19597
  return { name, ...transform ? { transform } : {}, default: defaultValue };
19021
19598
  }
19022
19599
  function parseLiteralValue(node) {
19023
- if (ts4.isStringLiteral(node))
19600
+ if (ts7.isStringLiteral(node))
19024
19601
  return node.text;
19025
- if (ts4.isNumericLiteral(node))
19602
+ if (ts7.isNumericLiteral(node))
19026
19603
  return Number(node.text);
19027
- if (node.kind === ts4.SyntaxKind.TrueKeyword)
19604
+ if (node.kind === ts7.SyntaxKind.TrueKeyword)
19028
19605
  return true;
19029
- if (node.kind === ts4.SyntaxKind.FalseKeyword)
19606
+ if (node.kind === ts7.SyntaxKind.FalseKeyword)
19030
19607
  return false;
19031
- if (ts4.isArrayLiteralExpression(node)) {
19608
+ if (ts7.isArrayLiteralExpression(node)) {
19032
19609
  return node.elements.map(parseLiteralValue);
19033
19610
  }
19034
- if (ts4.isObjectLiteralExpression(node)) {
19611
+ if (ts7.isObjectLiteralExpression(node)) {
19035
19612
  return parseObjectLiteralValues(node);
19036
19613
  }
19037
19614
  return;
@@ -19039,7 +19616,7 @@ function parseLiteralValue(node) {
19039
19616
  function parseObjectLiteralValues(obj) {
19040
19617
  const result = {};
19041
19618
  for (const prop of obj.properties) {
19042
- if (ts4.isPropertyAssignment(prop)) {
19619
+ if (ts7.isPropertyAssignment(prop)) {
19043
19620
  const name = propertyName(prop.name);
19044
19621
  const init = prop.initializer;
19045
19622
  if (init) {
@@ -19056,7 +19633,7 @@ function sourcePath(rootDir, absFile) {
19056
19633
  return relative2(rootDir, absFile).split(sep2).join("/");
19057
19634
  }
19058
19635
  function unwrapInfraResourceExpression(value) {
19059
- while (ts4.isParenthesizedExpression(value) || ts4.isAsExpression(value) || ts4.isTypeAssertionExpression(value) || ts4.isSatisfiesExpression(value) || ts4.isNonNullExpression(value)) {
19636
+ while (ts7.isParenthesizedExpression(value) || ts7.isAsExpression(value) || ts7.isTypeAssertionExpression(value) || ts7.isSatisfiesExpression(value) || ts7.isNonNullExpression(value)) {
19060
19637
  value = value.expression;
19061
19638
  }
19062
19639
  return value;
@@ -19066,7 +19643,7 @@ function infraResourceProp(obj, name, ctx) {
19066
19643
  if (members.length === 0)
19067
19644
  return;
19068
19645
  const member = members[0];
19069
- if (members.length !== 1 || !ts4.isPropertyAssignment(member) || ts4.isComputedPropertyName(member.name) || obj.properties.some(ts4.isSpreadAssignment)) {
19646
+ if (members.length !== 1 || !ts7.isPropertyAssignment(member) || ts7.isComputedPropertyName(member.name) || obj.properties.some(ts7.isSpreadAssignment)) {
19070
19647
  pushResourceError(ctx, "unknown-resource", `${name} 必须是唯一、显式的静态属性,且不能被对象展开覆盖`, sourcePath(ctx.rootDir, obj.getSourceFile().fileName), lineOf(member), `使用 ${name}: [...],不要使用简写属性、计算属性或对象展开。`);
19071
19648
  return;
19072
19649
  }
@@ -19079,7 +19656,7 @@ function indexInfraResource(cls, className, sf, ctx) {
19079
19656
  const file = sourcePath(ctx.rootDir, sf.fileName);
19080
19657
  const line = lineOf(cls);
19081
19658
  const options = decoratorObjectArg(decorator);
19082
- if (!options || options.properties.some((property) => !ts4.isPropertyAssignment(property) || ts4.isComputedPropertyName(property.name)) || new Set(options.properties.map((property) => property.name && propertyName(property.name))).size !== options.properties.length) {
19659
+ if (!options || options.properties.some((property) => !ts7.isPropertyAssignment(property) || ts7.isComputedPropertyName(property.name)) || new Set(options.properties.map((property) => property.name && propertyName(property.name))).size !== options.properties.length) {
19083
19660
  pushResourceError(ctx, "invalid-resource-kind", "@InfraResource 需要静态的 { name, kind } 对象参数", file, line, '使用 @InfraResource({ name: "orders-db", kind: "database" }),不要使用对象展开或重复属性。');
19084
19661
  return;
19085
19662
  }
@@ -19110,14 +19687,14 @@ function indexInfraResource(cls, className, sf, ctx) {
19110
19687
  }
19111
19688
  function resolveInfraResourceRef(el, ctx, owner, file, line) {
19112
19689
  const unwrapped = unwrapInfraResourceExpression(unwrapForwardRef(unwrapInfraResourceExpression(el)));
19113
- const identifier = ts4.isIdentifier(unwrapped) ? unwrapped : ts4.isPropertyAccessExpression(unwrapped) && ts4.isIdentifier(unwrapped.name) ? unwrapped.name : undefined;
19690
+ const identifier = ts7.isIdentifier(unwrapped) ? unwrapped : ts7.isPropertyAccessExpression(unwrapped) && ts7.isIdentifier(unwrapped.name) ? unwrapped.name : undefined;
19114
19691
  let symbol = identifier ? ctx.checker.getSymbolAtLocation(identifier) : undefined;
19115
19692
  const visited = new Set;
19116
- while (symbol && symbol.flags & ts4.SymbolFlags.Alias && !visited.has(symbol)) {
19693
+ while (symbol && symbol.flags & ts7.SymbolFlags.Alias && !visited.has(symbol)) {
19117
19694
  visited.add(symbol);
19118
19695
  symbol = ctx.checker.getAliasedSymbol(symbol);
19119
19696
  }
19120
- const declaration = symbol?.declarations?.find(ts4.isClassDeclaration);
19697
+ const declaration = symbol?.declarations?.find(ts7.isClassDeclaration);
19121
19698
  const resource = declaration ? ctx.infraResources.get(declaration) : undefined;
19122
19699
  if (!resource) {
19123
19700
  pushResourceError(ctx, "unknown-resource", `${owner} 引用的资源 '${nodeText(el)}' 未声明为 @InfraResource`, file, line, "引用实际声明了 @InfraResource({ name, kind }) 的类,不能依赖其他文件的同名类。");
@@ -19130,7 +19707,7 @@ function parseModuleInfraResources(value, ctx, owner, file, line) {
19130
19707
  if (!value)
19131
19708
  return names;
19132
19709
  const array = unwrapInfraResourceExpression(value);
19133
- if (!ts4.isArrayLiteralExpression(array)) {
19710
+ if (!ts7.isArrayLiteralExpression(array)) {
19134
19711
  pushResourceError(ctx, "unknown-resource", `${owner} 的 resources 必须是静态数组`, file, line, "使用 resources: [ResourceClass];省略该属性表示不声明资源。");
19135
19712
  return names;
19136
19713
  }
@@ -19145,14 +19722,14 @@ function parseInfraResourceUseRefs(value, ctx, owner, file, line) {
19145
19722
  if (!value)
19146
19723
  return [];
19147
19724
  const array = unwrapInfraResourceExpression(value);
19148
- if (!ts4.isArrayLiteralExpression(array)) {
19725
+ if (!ts7.isArrayLiteralExpression(array)) {
19149
19726
  pushResourceError(ctx, "unknown-resource", `${owner} 的 uses 必须是静态数组`, file, line, '使用 uses: [{ resource: ResourceClass, operations: ["read"] }]。');
19150
19727
  return [];
19151
19728
  }
19152
19729
  const uses = new Map;
19153
19730
  for (const element of array.elements) {
19154
19731
  const entry = unwrapInfraResourceExpression(element);
19155
- if (!ts4.isObjectLiteralExpression(entry) || entry.properties.some((property) => !ts4.isPropertyAssignment(property) || ts4.isComputedPropertyName(property.name) || !["resource", "operations"].includes(propertyName(property.name))) || new Set(entry.properties.map((property) => property.name && propertyName(property.name))).size !== entry.properties.length) {
19732
+ if (!ts7.isObjectLiteralExpression(entry) || entry.properties.some((property) => !ts7.isPropertyAssignment(property) || ts7.isComputedPropertyName(property.name) || !["resource", "operations"].includes(propertyName(property.name))) || new Set(entry.properties.map((property) => property.name && propertyName(property.name))).size !== entry.properties.length) {
19156
19733
  pushResourceError(ctx, "unknown-resource", `${owner} 的 uses 项必须是显式的 { resource, operations } 对象`, file, lineOf(element), "使用显式属性,不要使用对象/数组展开、简写、计算属性或重复属性。");
19157
19734
  continue;
19158
19735
  }
@@ -19170,14 +19747,14 @@ function parseInfraResourceUseRefs(value, ctx, owner, file, line) {
19170
19747
  operations.add("read");
19171
19748
  } else {
19172
19749
  const operationArray = unwrapInfraResourceExpression(operationsEl);
19173
- if (!ts4.isArrayLiteralExpression(operationArray) || operationArray.elements.length === 0) {
19750
+ if (!ts7.isArrayLiteralExpression(operationArray) || operationArray.elements.length === 0) {
19174
19751
  pushResourceError(ctx, "invalid-resource-operation", `${owner} 对资源 '${resource}' 的 operations 必须是非空静态数组`, file, lineOf(operationsEl), "仅省略 operations 时默认 read;显式填写时必须包含有效操作。");
19175
19752
  continue;
19176
19753
  }
19177
19754
  let invalid = false;
19178
19755
  for (const operationEl of operationArray.elements) {
19179
19756
  const operation = unwrapInfraResourceExpression(operationEl);
19180
- if (!ts4.isStringLiteral(operation) || !isInfraResourceOperation(operation.text)) {
19757
+ if (!ts7.isStringLiteral(operation) || !isInfraResourceOperation(operation.text)) {
19181
19758
  pushResourceError(ctx, "invalid-resource-operation", `${owner} 对资源 '${resource}' 声明了无效操作 '${nodeText(operationEl)}'`, file, lineOf(operationEl), `operations 只能包含字符串字面量 ${INFRA_RESOURCE_OPERATIONS.join(" | ")}。`);
19182
19759
  invalid = true;
19183
19760
  continue;
@@ -19222,11 +19799,11 @@ import { join as join4 } from "node:path";
19222
19799
 
19223
19800
  // src/type-safety.ts
19224
19801
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
19225
- import { dirname as dirname3, join as join3, relative as relative3, resolve as resolve2, sep as sep3 } from "node:path";
19226
- import * as ts6 from "@typescript/typescript6";
19802
+ import { dirname as dirname3, join as join3, relative as relative3, resolve as resolve3, sep as sep3 } from "node:path";
19803
+ import * as ts9 from "@typescript/typescript6";
19227
19804
 
19228
19805
  // src/sql-safety.ts
19229
- import * as ts5 from "@typescript/typescript6";
19806
+ import * as ts8 from "@typescript/typescript6";
19230
19807
  var SQL_SAFETY_DIAGNOSTIC_CODES = {
19231
19808
  "sql-result-assertion": { errorCode: "SC6007", docsUrl: "https://supacloud.dev/errors/SC6007" },
19232
19809
  "sql-raw-dynamic": { errorCode: "SC6008", docsUrl: "https://supacloud.dev/errors/SC6008" }
@@ -19234,10 +19811,10 @@ var SQL_SAFETY_DIAGNOSTIC_CODES = {
19234
19811
  function scanDrizzleSql(sourceFile, checker, file, strict) {
19235
19812
  const diagnostics = [];
19236
19813
  const importedSql = (expression) => {
19237
- const symbol = checker.getSymbolAtLocation(ts5.isPropertyAccessExpression(expression) ? expression.name : expression);
19814
+ const symbol = checker.getSymbolAtLocation(ts8.isPropertyAccessExpression(expression) ? expression.name : expression);
19238
19815
  if (!symbol)
19239
19816
  return false;
19240
- const target = symbol.flags & ts5.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
19817
+ const target = symbol.flags & ts8.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
19241
19818
  return target.name === "sql" && (target.declarations ?? []).some((declaration) => /(?:^|\/)node_modules\/drizzle-orm\//.test(declaration.getSourceFile().fileName.replaceAll("\\", "/")));
19242
19819
  };
19243
19820
  const report = (code, node, message) => {
@@ -19251,16 +19828,16 @@ function scanDrizzleSql(sourceFile, checker, file, strict) {
19251
19828
  });
19252
19829
  };
19253
19830
  const visit = (node) => {
19254
- if (ts5.isTaggedTemplateExpression(node) && importedSql(node.tag) && node.typeArguments?.some((type) => type.kind !== ts5.SyntaxKind.UnknownKeyword)) {
19831
+ if (ts8.isTaggedTemplateExpression(node) && importedSql(node.tag) && node.typeArguments?.some((type) => type.kind !== ts8.SyntaxKind.UnknownKeyword)) {
19255
19832
  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.");
19256
19833
  }
19257
- if (ts5.isCallExpression(node) && ts5.isPropertyAccessExpression(node.expression) && node.expression.name.text === "raw" && importedSql(node.expression.expression)) {
19834
+ if (ts8.isCallExpression(node) && ts8.isPropertyAccessExpression(node.expression) && node.expression.name.text === "raw" && importedSql(node.expression.expression)) {
19258
19835
  const argument = node.arguments[0];
19259
- if (!argument || !ts5.isStringLiteral(argument) && !ts5.isNoSubstitutionTemplateLiteral(argument)) {
19836
+ if (!argument || !ts8.isStringLiteral(argument) && !ts8.isNoSubstitutionTemplateLiteral(argument)) {
19260
19837
  report("sql-raw-dynamic", node, "Dynamic sql.raw bypasses parameter binding. Interpolate values with sql templates; keep reviewed static DDL in migrations.");
19261
19838
  }
19262
19839
  }
19263
- ts5.forEachChild(node, visit);
19840
+ ts8.forEachChild(node, visit);
19264
19841
  };
19265
19842
  visit(sourceFile);
19266
19843
  return diagnostics;
@@ -19292,7 +19869,7 @@ function scanGeneratedArtifacts(artifacts, strict = true) {
19292
19869
  for (const [file, content] of Object.entries(artifacts)) {
19293
19870
  if (content === undefined)
19294
19871
  continue;
19295
- const sourceFile = ts6.createSourceFile(file, content, ts6.ScriptTarget.Latest, true, ts6.ScriptKind.TS);
19872
+ const sourceFile = ts9.createSourceFile(file, content, ts9.ScriptTarget.Latest, true, ts9.ScriptKind.TS);
19296
19873
  for (const node of descendantsOfKind2(sourceFile, isAnyKeyword)) {
19297
19874
  diagnostics.push(makeDiagnostic("generated-any", `生成产物 ${file} 包含 any;严格生成模式要求使用 unknown、具体接口或泛型约束。`, sourceFile, node, strict));
19298
19875
  }
@@ -19300,31 +19877,31 @@ function scanGeneratedArtifacts(artifacts, strict = true) {
19300
19877
  return diagnostics;
19301
19878
  }
19302
19879
  function scanProductionSource(options) {
19303
- const rootDir = resolve2(options.rootDir);
19304
- const configPath = ts6.findConfigFile(rootDir, ts6.sys.fileExists) ?? join3(rootDir, "tsconfig.json");
19880
+ const rootDir = resolve3(options.rootDir);
19881
+ const configPath = ts9.findConfigFile(rootDir, ts9.sys.fileExists) ?? join3(rootDir, "tsconfig.json");
19305
19882
  const projectConfig = existsSync2(configPath) ? readProjectConfig2(configPath) : {
19306
19883
  options: {
19307
19884
  strict: true,
19308
19885
  skipLibCheck: true,
19309
- target: ts6.ScriptTarget.ES2022,
19310
- module: ts6.ModuleKind.ESNext,
19311
- moduleResolution: ts6.ModuleResolutionKind.Bundler
19886
+ target: ts9.ScriptTarget.ES2022,
19887
+ module: ts9.ModuleKind.ESNext,
19888
+ moduleResolution: ts9.ModuleResolutionKind.Bundler
19312
19889
  },
19313
19890
  errors: []
19314
19891
  };
19315
19892
  const include = options.include ?? ["**/*.ts", "**/*.tsx", "**/*.mts", "**/*.cts"];
19316
- const rootNames = ts6.sys.readDirectory(rootDir, [".ts", ".tsx", ".mts", ".cts"], ["node_modules", "dist"], include).filter((file) => isProductionSourcePath(rootDir, file, [...DEFAULT_EXCLUDES, ...options.exclude ?? []]));
19893
+ const rootNames = ts9.sys.readDirectory(rootDir, [".ts", ".tsx", ".mts", ".cts"], ["node_modules", "dist"], include).filter((file) => isProductionSourcePath(rootDir, file, [...DEFAULT_EXCLUDES, ...options.exclude ?? []]));
19317
19894
  const compilerOptions = { ...projectConfig.options, noEmit: true };
19318
- const host = ts6.createCompilerHost(compilerOptions);
19895
+ const host = ts9.createCompilerHost(compilerOptions);
19319
19896
  host.getCurrentDirectory = () => dirname3(configPath);
19320
- const program = ts6.createProgram(rootNames, compilerOptions, host);
19897
+ const program = ts9.createProgram(rootNames, compilerOptions, host);
19321
19898
  const outDir = options.outDir ? normalizeRelative(rootDir, options.outDir) : undefined;
19322
19899
  const excludes = [...DEFAULT_EXCLUDES, ...options.exclude ?? []];
19323
19900
  const sourceFiles = program.getSourceFiles().filter((sourceFile) => isProductionSource(rootDir, sourceFile, excludes, outDir));
19324
19901
  const diagnostics = [...projectConfig.errors, ...program.getOptionsDiagnostics()].map((diagnostic) => ({
19325
19902
  severity: "error",
19326
19903
  code: "source-config",
19327
- message: ts6.flattenDiagnosticMessageText(diagnostic.messageText, `
19904
+ message: ts9.flattenDiagnosticMessageText(diagnostic.messageText, `
19328
19905
  `),
19329
19906
  file: diagnostic.file ? normalizeRelative(rootDir, diagnostic.file.fileName) : normalizeRelative(rootDir, configPath),
19330
19907
  ...diagnostic.file && diagnostic.start !== undefined ? { line: diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start).line + 1 } : {},
@@ -19341,7 +19918,7 @@ function scanProductionSource(options) {
19341
19918
  diagnostics.push({
19342
19919
  severity: "error",
19343
19920
  code: "source-typescript",
19344
- message: ts6.flattenDiagnosticMessageText(diagnostic.messageText, `
19921
+ message: ts9.flattenDiagnosticMessageText(diagnostic.messageText, `
19345
19922
  `),
19346
19923
  ...diagnostic.file ? { file: normalizeRelative(rootDir, diagnostic.file.fileName) } : {},
19347
19924
  ...diagnostic.file && diagnostic.start !== undefined ? { line: diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start).line + 1 } : {},
@@ -19351,9 +19928,9 @@ function scanProductionSource(options) {
19351
19928
  for (const sourceFile of sourceFiles) {
19352
19929
  scanSourceFile(sourceFile, checker, rootDir, diagnostics, options.strict ?? false);
19353
19930
  diagnostics.push(...scanDrizzleSql(sourceFile, checker, normalizeRelative(rootDir, sourceFile.fileName), options.strict ?? false));
19354
- const scanner = ts6.createScanner(ts6.ScriptTarget.Latest, false, sourceFile.languageVariant, sourceFile.text);
19355
- for (let kind = scanner.scan();kind !== ts6.SyntaxKind.EndOfFileToken; kind = scanner.scan()) {
19356
- if ((kind === ts6.SyntaxKind.SingleLineCommentTrivia || kind === ts6.SyntaxKind.MultiLineCommentTrivia) && /@ts-(?:ignore|nocheck|expect-error)\b/.test(scanner.getTokenText())) {
19931
+ const scanner = ts9.createScanner(ts9.ScriptTarget.Latest, false, sourceFile.languageVariant, sourceFile.text);
19932
+ for (let kind = scanner.scan();kind !== ts9.SyntaxKind.EndOfFileToken; kind = scanner.scan()) {
19933
+ if ((kind === ts9.SyntaxKind.SingleLineCommentTrivia || kind === ts9.SyntaxKind.MultiLineCommentTrivia) && /@ts-(?:ignore|nocheck|expect-error)\b/.test(scanner.getTokenText())) {
19357
19934
  diagnostics.push({
19358
19935
  severity: "error",
19359
19936
  code: "source-type-suppression",
@@ -19373,22 +19950,22 @@ function scanSourceFile(sourceFile, checker, rootDir, diagnostics, strict) {
19373
19950
  diagnostics.push(makeDiagnostic("source-any", "生产源码使用了显式 any;请改用 unknown、具体接口或泛型约束。", sourceFile, node, strict, rootDir));
19374
19951
  }
19375
19952
  for (const node of descendants(sourceFile)) {
19376
- if (ts6.isAsExpression(node)) {
19377
- if (ts6.isAsExpression(node.parent) || ts6.isTypeAssertionExpression(node.parent))
19953
+ if (ts9.isAsExpression(node)) {
19954
+ if (ts9.isAsExpression(node.parent) || ts9.isTypeAssertionExpression(node.parent))
19378
19955
  continue;
19379
19956
  const assertedType = node.type.getText(sourceFile);
19380
19957
  if (assertedType === "const")
19381
19958
  continue;
19382
19959
  diagnostics.push(makeDiagnostic("source-type-assertion", `生产源码包含类型断言 ${node.getText(sourceFile)};请优先使用类型守卫、satisfies 或显式边界解析。`, sourceFile, node, strict, rootDir));
19383
- } else if (ts6.isTypeAssertionExpression(node)) {
19384
- if (ts6.isAsExpression(node.parent) || ts6.isTypeAssertionExpression(node.parent))
19960
+ } else if (ts9.isTypeAssertionExpression(node)) {
19961
+ if (ts9.isAsExpression(node.parent) || ts9.isTypeAssertionExpression(node.parent))
19385
19962
  continue;
19386
19963
  diagnostics.push(makeDiagnostic("source-type-assertion", `生产源码包含类型断言 ${node.getText(sourceFile)};请优先使用类型守卫、satisfies 或显式边界解析。`, sourceFile, node, strict, rootDir));
19387
- } else if (ts6.isNonNullExpression(node)) {
19964
+ } else if (ts9.isNonNullExpression(node)) {
19388
19965
  diagnostics.push(makeDiagnostic("source-non-null-assertion", `生产源码包含非空断言 ${node.getText(sourceFile)};请显式处理 null/undefined。`, sourceFile, node, strict, rootDir));
19389
19966
  }
19390
19967
  }
19391
- for (const declaration of descendantsOfKind2(sourceFile, ts6.isVariableDeclaration)) {
19968
+ for (const declaration of descendantsOfKind2(sourceFile, ts9.isVariableDeclaration)) {
19392
19969
  const initializer = declaration.initializer;
19393
19970
  if (!initializer || declaration.type)
19394
19971
  continue;
@@ -19404,11 +19981,11 @@ function scanSourceFile(sourceFile, checker, rootDir, diagnostics, strict) {
19404
19981
  if (isLetDeclaration(declaration) && isLiteralSyntax(initializer) && !isLiteralType(declarationType)) {
19405
19982
  diagnostics.push(makeDiagnostic("source-implicit-widening", `变量 ${declaration.name.getText(sourceFile)} 的字面量类型从 ${checker.typeToString(initializerType, initializer)} 隐式宽化为 ${checker.typeToString(declarationType, declaration)};请补充类型或使用 const。`, sourceFile, declaration, strict, rootDir));
19406
19983
  }
19407
- 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))) {
19984
+ if (ts9.isObjectLiteralExpression(initializer) && isConstDeclaration(declaration) && initializer.getText(sourceFile).length > 0 && initializer.properties.some((property) => ts9.isPropertyAssignment(property) && property.initializer !== undefined && !ts9.isAsExpression(property.initializer) && isLiteralExpression(property.initializer))) {
19408
19985
  diagnostics.push(makeDiagnostic("source-implicit-widening", `常量对象 ${declaration.name.getText(sourceFile)} 的字面量属性会隐式宽化;请补充对象类型或使用 as const。`, sourceFile, declaration, strict, rootDir));
19409
19986
  }
19410
19987
  }
19411
- for (const parameter of descendantsOfKind2(sourceFile, ts6.isParameter)) {
19988
+ for (const parameter of descendantsOfKind2(sourceFile, ts9.isParameter)) {
19412
19989
  if (parameter.type)
19413
19990
  continue;
19414
19991
  for (const name of bindingNames(parameter.name)) {
@@ -19419,10 +19996,10 @@ function scanSourceFile(sourceFile, checker, rootDir, diagnostics, strict) {
19419
19996
  }
19420
19997
  }
19421
19998
  function readProjectConfig2(configPath) {
19422
- const config = ts6.readConfigFile(configPath, (file) => readFileSync2(file, "utf8"));
19999
+ const config = ts9.readConfigFile(configPath, (file) => readFileSync2(file, "utf8"));
19423
20000
  if (config.error)
19424
20001
  return { options: {}, errors: [config.error] };
19425
- const parsed = ts6.parseJsonConfigFileContent(config.config, ts6.sys, dirname3(configPath));
20002
+ const parsed = ts9.parseJsonConfigFileContent(config.config, ts9.sys, dirname3(configPath));
19426
20003
  return { options: parsed.options, errors: parsed.errors };
19427
20004
  }
19428
20005
  function isProductionSource(rootDir, sourceFile, excludes, outDir) {
@@ -19442,42 +20019,42 @@ function globMatches(value, pattern) {
19442
20019
  return new RegExp(`^${escaped}$`).test(value);
19443
20020
  }
19444
20021
  function bindingNames(name) {
19445
- if (ts6.isIdentifier(name))
20022
+ if (ts9.isIdentifier(name))
19446
20023
  return [name];
19447
- return name.elements.flatMap((element) => ts6.isBindingElement(element) ? bindingNames(element.name) : []);
20024
+ return name.elements.flatMap((element) => ts9.isBindingElement(element) ? bindingNames(element.name) : []);
19448
20025
  }
19449
20026
  function isLiteralExpression(node) {
19450
20027
  if (!node)
19451
20028
  return false;
19452
20029
  return [
19453
- ts6.SyntaxKind.StringLiteral,
19454
- ts6.SyntaxKind.NumericLiteral,
19455
- ts6.SyntaxKind.TrueKeyword,
19456
- ts6.SyntaxKind.FalseKeyword
20030
+ ts9.SyntaxKind.StringLiteral,
20031
+ ts9.SyntaxKind.NumericLiteral,
20032
+ ts9.SyntaxKind.TrueKeyword,
20033
+ ts9.SyntaxKind.FalseKeyword
19457
20034
  ].includes(node.kind);
19458
20035
  }
19459
20036
  function isLiteralSyntax(node) {
19460
- return ts6.isStringLiteral(node) || ts6.isNumericLiteral(node) || node.kind === ts6.SyntaxKind.TrueKeyword || node.kind === ts6.SyntaxKind.FalseKeyword;
20037
+ return ts9.isStringLiteral(node) || ts9.isNumericLiteral(node) || node.kind === ts9.SyntaxKind.TrueKeyword || node.kind === ts9.SyntaxKind.FalseKeyword;
19461
20038
  }
19462
20039
  function isLiteralType(type) {
19463
- return (type.flags & (ts6.TypeFlags.StringLiteral | ts6.TypeFlags.NumberLiteral | ts6.TypeFlags.BooleanLiteral | ts6.TypeFlags.BigIntLiteral)) !== 0;
20040
+ return (type.flags & (ts9.TypeFlags.StringLiteral | ts9.TypeFlags.NumberLiteral | ts9.TypeFlags.BooleanLiteral | ts9.TypeFlags.BigIntLiteral)) !== 0;
19464
20041
  }
19465
20042
  function isAnyType(type) {
19466
- return (type.flags & ts6.TypeFlags.Any) !== 0;
20043
+ return (type.flags & ts9.TypeFlags.Any) !== 0;
19467
20044
  }
19468
20045
  function isLetDeclaration(declaration) {
19469
- return ts6.isVariableDeclarationList(declaration.parent) && (declaration.parent.flags & ts6.NodeFlags.Let) !== 0;
20046
+ return ts9.isVariableDeclarationList(declaration.parent) && (declaration.parent.flags & ts9.NodeFlags.Let) !== 0;
19470
20047
  }
19471
20048
  function isConstDeclaration(declaration) {
19472
- return ts6.isVariableDeclarationList(declaration.parent) && (declaration.parent.flags & ts6.NodeFlags.Const) !== 0;
20049
+ return ts9.isVariableDeclarationList(declaration.parent) && (declaration.parent.flags & ts9.NodeFlags.Const) !== 0;
19473
20050
  }
19474
20051
  function descendants(root) {
19475
20052
  const result = [];
19476
20053
  const visit = (node) => {
19477
20054
  result.push(node);
19478
- ts6.forEachChild(node, visit);
20055
+ ts9.forEachChild(node, visit);
19479
20056
  };
19480
- ts6.forEachChild(root, visit);
20057
+ ts9.forEachChild(root, visit);
19481
20058
  return result;
19482
20059
  }
19483
20060
  function descendantsOfKind2(root, predicate) {
@@ -19485,9 +20062,9 @@ function descendantsOfKind2(root, predicate) {
19485
20062
  const visit = (node) => {
19486
20063
  if (predicate(node))
19487
20064
  result.push(node);
19488
- ts6.forEachChild(node, visit);
20065
+ ts9.forEachChild(node, visit);
19489
20066
  };
19490
- ts6.forEachChild(root, visit);
20067
+ ts9.forEachChild(root, visit);
19491
20068
  return result;
19492
20069
  }
19493
20070
  function makeDiagnostic(code, message, fileOrSourceFile, node, strict, rootDir) {
@@ -19508,7 +20085,7 @@ function normalizeRelative(rootDir, filePath) {
19508
20085
  return relative3(rootDir, filePath).split(sep3).join("/").replace(/^\.\//, "");
19509
20086
  }
19510
20087
  function isAnyKeyword(node) {
19511
- return node.kind === ts6.SyntaxKind.AnyKeyword;
20088
+ return node.kind === ts9.SyntaxKind.AnyKeyword;
19512
20089
  }
19513
20090
 
19514
20091
  // src/compile.ts
@@ -19927,12 +20504,12 @@ init_delivery_context();
19927
20504
 
19928
20505
  // src/watch.ts
19929
20506
  import { existsSync as existsSync4, watch } from "node:fs";
19930
- import { dirname as dirname7, relative as relative8, resolve as resolve9, sep as sep8 } from "node:path";
20507
+ import { dirname as dirname7, relative as relative8, resolve as resolve10, sep as sep8 } from "node:path";
19931
20508
 
19932
20509
  // src/incremental.ts
19933
20510
  import { createHash as createHash7 } from "node:crypto";
19934
20511
  import { access as access3, readdir as readdir3, readFile as readFile4 } from "node:fs/promises";
19935
- import { isAbsolute as isAbsolute3, relative as relative7, resolve as resolve8, sep as sep7 } from "node:path";
20512
+ import { isAbsolute as isAbsolute3, relative as relative7, resolve as resolve9, sep as sep7 } from "node:path";
19936
20513
  init_graphql_inputs();
19937
20514
  function createDependencyGraphCache() {
19938
20515
  return {
@@ -20013,11 +20590,11 @@ async function readSourceBytes(path) {
20013
20590
  return readFile4(path);
20014
20591
  }
20015
20592
  async function updateSnapshot(previous, options, changedPaths) {
20016
- const rootDir = resolve8(options.rootDir);
20017
- const outDir = resolve8(options.outDir);
20593
+ const rootDir = resolve9(options.rootDir);
20594
+ const outDir = resolve9(options.outDir);
20018
20595
  const files = { ...previous.files };
20019
20596
  await Promise.all(changedPaths.map(async (changedPath) => {
20020
- const absolutePath = isAbsolute3(changedPath) ? resolve8(changedPath) : resolve8(rootDir, changedPath);
20597
+ const absolutePath = isAbsolute3(changedPath) ? resolve9(changedPath) : resolve9(rootDir, changedPath);
20021
20598
  const relativeChangedPath = relative7(rootDir, absolutePath);
20022
20599
  if (relativeChangedPath === ".." || relativeChangedPath.startsWith(`..${sep7}`))
20023
20600
  return;
@@ -20035,8 +20612,8 @@ async function updateSnapshot(previous, options, changedPaths) {
20035
20612
  return { files, optionsKey: optionsKeyOf(options) };
20036
20613
  }
20037
20614
  async function createSnapshot(options) {
20038
- const rootDir = resolve8(options.rootDir);
20039
- const outDir = resolve8(options.outDir);
20615
+ const rootDir = resolve9(options.rootDir);
20616
+ const outDir = resolve9(options.outDir);
20040
20617
  const paths = await listSourceFiles(rootDir, outDir);
20041
20618
  const files = {};
20042
20619
  const entries = await Promise.all(paths.map(async (path) => {
@@ -20059,8 +20636,8 @@ async function createSnapshot(options) {
20059
20636
  }
20060
20637
  function optionsKeyOf(options) {
20061
20638
  return JSON.stringify({
20062
- rootDir: resolve8(options.rootDir),
20063
- outDir: resolve8(options.outDir),
20639
+ rootDir: resolve9(options.rootDir),
20640
+ outDir: resolve9(options.outDir),
20064
20641
  include: options.include,
20065
20642
  strict: options.strict,
20066
20643
  writeOnError: options.writeOnError,
@@ -20084,7 +20661,7 @@ async function listSourceFiles(rootDir, outDir) {
20084
20661
  const result = [];
20085
20662
  const visit = async (directory) => {
20086
20663
  for (const entry of await readdir3(directory, { withFileTypes: true })) {
20087
- const path = resolve8(directory, entry.name);
20664
+ const path = resolve9(directory, entry.name);
20088
20665
  if (entry.isDirectory()) {
20089
20666
  if (entry.name === "node_modules" || entry.name === ".git" || path === outDir)
20090
20667
  continue;
@@ -20219,8 +20796,8 @@ function isCompilerConfigurationPath(rootDir, changedPath) {
20219
20796
  ].includes(relativePath) || /^tsconfig\.[^/]+\.json$/.test(relativePath);
20220
20797
  }
20221
20798
  function watchProject(options) {
20222
- const rootDir = resolve9(options.rootDir);
20223
- const outDir = resolve9(options.outDir);
20799
+ const rootDir = resolve10(options.rootDir);
20800
+ const outDir = resolve10(options.outDir);
20224
20801
  const debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;
20225
20802
  let timer;
20226
20803
  let closed = false;
@@ -20230,7 +20807,7 @@ function watchProject(options) {
20230
20807
  const pendingPaths = new Set;
20231
20808
  let watcher;
20232
20809
  let schemaWatcher;
20233
- const schemaPath = options.graphql ? resolve9(rootDir, options.graphql.schema) : undefined;
20810
+ const schemaPath = options.graphql ? resolve10(rootDir, options.graphql.schema) : undefined;
20234
20811
  const incremental = createIncrementalCompiler();
20235
20812
  let initialEvent;
20236
20813
  let resolveReady = () => {
@@ -20340,7 +20917,7 @@ function watchProject(options) {
20340
20917
  watcher = watch(rootDir, { recursive: true }, (_eventType, filename) => {
20341
20918
  if (!filename)
20342
20919
  return schedule();
20343
- const changedPath = resolve9(rootDir, filename.toString());
20920
+ const changedPath = resolve10(rootDir, filename.toString());
20344
20921
  const relativePath = relative8(outDir, changedPath);
20345
20922
  if (!relativePath.startsWith("..") && relativePath !== "")
20346
20923
  return;
@@ -20353,7 +20930,7 @@ function watchProject(options) {
20353
20930
  while (!existsSync4(directory) && dirname7(directory) !== directory)
20354
20931
  directory = dirname7(directory);
20355
20932
  schemaWatcher = watch(directory, { recursive: true }, (_eventType, filename) => {
20356
- if (!filename || resolve9(directory, filename.toString()) === schemaPath)
20933
+ if (!filename || resolve10(directory, filename.toString()) === schemaPath)
20357
20934
  schedule(schemaPath);
20358
20935
  });
20359
20936
  }
@@ -20378,7 +20955,7 @@ function watchProject(options) {
20378
20955
  // src/config.ts
20379
20956
  init_graphql_options();
20380
20957
  import { existsSync as existsSync5 } from "node:fs";
20381
- import { join as join8, resolve as resolve10 } from "node:path";
20958
+ import { join as join8, resolve as resolve11 } from "node:path";
20382
20959
  import { pathToFileURL } from "node:url";
20383
20960
 
20384
20961
  // src/delivery-schema.ts
@@ -20476,8 +21053,8 @@ function validateGovernanceConfig(config) {
20476
21053
  function resolveSupacloudConfig(config = {}, cwd = process.cwd()) {
20477
21054
  const resolved = defineSupacloudConfig(config);
20478
21055
  return {
20479
- rootDir: resolve10(cwd, resolved.root ?? DEFAULT_SUPACLOUD_CONFIG.root),
20480
- outDir: resolve10(cwd, resolved.outDir ?? DEFAULT_SUPACLOUD_CONFIG.outDir),
21056
+ rootDir: resolve11(cwd, resolved.root ?? DEFAULT_SUPACLOUD_CONFIG.root),
21057
+ outDir: resolve11(cwd, resolved.outDir ?? DEFAULT_SUPACLOUD_CONFIG.outDir),
20481
21058
  include: resolved.include ?? [...DEFAULT_SUPACLOUD_CONFIG.include],
20482
21059
  strict: resolved.strict ?? DEFAULT_SUPACLOUD_CONFIG.strict,
20483
21060
  requireRouteContracts: resolved.requireRouteContracts ?? DEFAULT_SUPACLOUD_CONFIG.requireRouteContracts,
@@ -20495,7 +21072,7 @@ function resolveSupacloudConfig(config = {}, cwd = process.cwd()) {
20495
21072
  treeShakeUnusedProviders: resolved.treeShakeUnusedProviders ?? DEFAULT_SUPACLOUD_CONFIG.treeShakeUnusedProviders,
20496
21073
  graphql: resolved.graphql ? {
20497
21074
  ...resolved.graphql,
20498
- schema: resolve10(cwd, resolved.graphql.schema)
21075
+ schema: resolve11(cwd, resolved.graphql.schema)
20499
21076
  } : undefined
20500
21077
  };
20501
21078
  }
@@ -20516,213 +21093,67 @@ function compileOptionsFromConfig(config, cwd = process.cwd()) {
20516
21093
  return resolveSupacloudConfig(config, cwd);
20517
21094
  }
20518
21095
 
20519
- // src/fixes.ts
20520
- import { randomUUID } from "node:crypto";
20521
- import { lstat as lstat2, readFile as readFile5, realpath as realpath3, rename as rename3, unlink as unlink2, writeFile as writeFile3 } from "node:fs/promises";
20522
- import { dirname as dirname8, isAbsolute as isAbsolute4, relative as relative9, resolve as resolve11, sep as sep9 } from "node:path";
20523
- import * as ts9 from "@typescript/typescript6";
20524
- async function applyDiagnosticFix(fix, options = {}) {
20525
- if (!fix || typeof fix.targetFile !== "string")
20526
- throw new Error("Invalid DiagnosticFix");
20527
- const root = await realpath3(options.rootDir ?? process.cwd());
20528
- const file = resolve11(root, fix.targetFile);
20529
- const stat = await lstat2(file);
20530
- const resolved = await realpath3(file);
20531
- const relativePath = relative9(root, resolved);
20532
- if (stat.isSymbolicLink() || !stat.isFile() || isAbsolute4(relativePath) || relativePath === ".." || relativePath.startsWith(`..${sep9}`)) {
20533
- throw new Error("Fix target must be a regular file inside rootDir");
20534
- }
20535
- const original = await readFile5(file, "utf8");
20536
- let source = parse5(file, original);
20537
- let content;
20538
- switch (fix.type) {
20539
- case "set_command_mode": {
20540
- if (fix.property !== "transaction" && fix.property !== "idempotency" || fix.value !== "required" && fix.value !== "none") {
20541
- throw new Error("Command mode fix requires an explicit property and policy value");
20542
- }
20543
- const object = decoratorObject(findClass(source, fix.command), "Command");
20544
- const current = property(object, fix.property);
20545
- if (!current || current.initializer.getText(source) !== fix.expectedExpression) {
20546
- throw new Error("Command mode changed since diagnosis; analyze the project again");
20547
- }
20548
- content = replaceProperty(source, object, fix.property, ts9.factory.createStringLiteral(fix.value));
20549
- break;
20550
- }
20551
- case "add_module_import": {
20552
- if (!fix.importPath || !fix.symbol)
20553
- throw new Error("Module fix requires importPath and symbol");
20554
- identifier2(fix.symbol);
20555
- const withImport = importSymbol(source, fix.importPath, fix.symbol);
20556
- source = parse5(file, withImport);
20557
- const object = unique(moduleObjects(source).filter((candidate) => !fix.targetModule || stringProperty(candidate, "name") === fix.targetModule), "target module");
20558
- const imports = property(object, "imports");
20559
- if (imports && !ts9.isArrayLiteralExpression(imports.initializer)) {
20560
- throw new Error("Module imports must be a static array");
20561
- }
20562
- const values = imports && ts9.isArrayLiteralExpression(imports.initializer) ? imports.initializer.elements : [];
20563
- if (values.some(ts9.isSpreadElement))
20564
- throw new Error("Module imports cannot contain spread elements");
20565
- content = values.some((value) => ts9.isIdentifier(value) && value.text === fix.symbol) ? withImport : replaceProperty(source, object, "imports", ts9.factory.createArrayLiteralExpression([
20566
- ...values,
20567
- ts9.factory.createIdentifier(fix.symbol)
20568
- ]));
20569
- break;
20570
- }
20571
- case "add_command_permission": {
20572
- const permission = options.permission ?? fix.permission;
20573
- if (!permission?.trim()) {
20574
- throw new Error("Permission fix requires an explicit permission; privileges are never inferred");
20575
- }
20576
- const command = findClass(source, fix.command);
20577
- const object = decoratorObject(command, "Command");
20578
- const current = property(object, "permission");
20579
- if (current && (!ts9.isStringLiteral(current.initializer) || current.initializer.text !== permission)) {
20580
- throw new Error("Command permission already exists with a different value");
20581
- }
20582
- content = current ? original : replaceProperty(source, object, "permission", ts9.factory.createStringLiteral(permission));
20583
- break;
20584
- }
20585
- case "add_route_parameter_binding": {
20586
- const controller = findClass(source, fix.controller);
20587
- const method = unique(controller.members.filter((member) => ts9.isMethodDeclaration(member) && nameOf(member.name) === fix.route), "route handler");
20588
- const parameter = unique(method.parameters.filter((candidate) => ts9.isIdentifier(candidate.name) && candidate.name.text === fix.parameter), "same-named route parameter");
20589
- const binding = fix.binding === "param" ? "Param" : fix.binding === "query" ? "Query" : undefined;
20590
- if (!binding)
20591
- throw new Error("Invalid route binding");
20592
- const decorators = ts9.getDecorators(parameter) ?? [];
20593
- if (decorators.length > 0)
20594
- throw new Error("Parameter already has a decorator");
20595
- 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");
20596
- if (!ts9.isImportDeclaration(framework) || !ts9.isStringLiteral(framework.moduleSpecifier)) {
20597
- throw new Error("Framework import must be static");
20598
- }
20599
- const edited = original.slice(0, parameter.getStart(source)) + `@${binding}(${JSON.stringify(fix.parameter)}) ` + original.slice(parameter.getStart(source));
20600
- content = importSymbol(parse5(file, edited), framework.moduleSpecifier.text, binding);
20601
- break;
20602
- }
20603
- default:
20604
- throw new Error(`Diagnostic fix '${fix.type}' requires a manual semantic decision; no files changed`);
20605
- }
20606
- parse5(file, content);
20607
- const result = { file, changed: content !== original, content };
20608
- if (options.dryRun === false && result.changed) {
20609
- const temporary = `${file}.supacloud-fix-${randomUUID()}`;
20610
- try {
20611
- await writeFile3(temporary, content, { encoding: "utf8", flag: "wx", mode: stat.mode });
20612
- if (await readFile5(file, "utf8") !== original)
20613
- throw new Error("Target changed while preparing the fix");
20614
- await rename3(temporary, file);
20615
- } finally {
20616
- await unlink2(temporary).catch(() => {});
20617
- }
20618
- }
20619
- return result;
20620
- }
20621
- function parse5(file, text) {
20622
- const result = ts9.transpileModule(text, {
20623
- fileName: file,
20624
- reportDiagnostics: true,
20625
- compilerOptions: { target: ts9.ScriptTarget.ESNext, experimentalDecorators: true }
20626
- });
20627
- if (result.diagnostics?.some((item) => item.category === ts9.DiagnosticCategory.Error)) {
20628
- throw new Error("Cannot fix syntactically invalid TypeScript");
20629
- }
20630
- return ts9.createSourceFile(file, text, ts9.ScriptTarget.Latest, true, ts9.ScriptKind.TS);
20631
- }
20632
- function unique(items, description) {
20633
- if (items.length !== 1)
20634
- throw new Error(`Expected exactly one ${description}; found ${items.length}`);
20635
- return items[0];
20636
- }
20637
- function identifier2(value) {
20638
- if (!/^[A-Za-z_$][\w$]*$/.test(value))
20639
- throw new Error(`Invalid identifier '${value}'`);
20640
- }
20641
- function nameOf(name) {
20642
- if (!name)
20643
- return "";
20644
- return ts9.isIdentifier(name) || ts9.isStringLiteral(name) || ts9.isNumericLiteral(name) ? name.text : "";
20645
- }
20646
- function property(object, key) {
20647
- if (object.properties.some((item) => !ts9.isPropertyAssignment(item) || ts9.isComputedPropertyName(item.name))) {
20648
- throw new Error("Fix requires explicit static object properties");
20649
- }
20650
- const values = object.properties.filter((item) => ts9.isPropertyAssignment(item) && nameOf(item.name) === key);
20651
- if (values.length > 1)
20652
- throw new Error(`Duplicate '${key}' property`);
20653
- return values[0];
20654
- }
20655
- function stringProperty(object, key) {
20656
- const value = property(object, key)?.initializer;
20657
- return value && ts9.isStringLiteral(value) ? value.text : undefined;
20658
- }
20659
- function replaceProperty(source, object, key, value) {
20660
- const previous = property(object, key);
20661
- const replacement = ts9.factory.createPropertyAssignment(key, value);
20662
- const properties = object.properties.map((item) => item === previous ? replacement : item);
20663
- if (!previous)
20664
- properties.push(replacement);
20665
- const updated = ts9.factory.updateObjectLiteralExpression(object, properties);
20666
- return source.text.slice(0, object.getStart(source)) + ts9.createPrinter().printNode(ts9.EmitHint.Expression, updated, source) + source.text.slice(object.end);
20667
- }
20668
- function findClass(source, name) {
20669
- return unique(source.statements.filter((statement) => ts9.isClassDeclaration(statement) && statement.name?.text === name), `class '${name}'`);
20670
- }
20671
- function decoratorObject(node, name) {
20672
- const decorator = unique((ts9.getDecorators(node) ?? []).filter((item) => ts9.isCallExpression(item.expression) && item.expression.expression.getText() === name), `@${name} decorator`);
20673
- const argument = ts9.isCallExpression(decorator.expression) ? decorator.expression.arguments[0] : undefined;
20674
- if (!argument || !ts9.isObjectLiteralExpression(argument))
20675
- throw new Error(`@${name} requires a static object`);
20676
- return argument;
20677
- }
20678
- function moduleObjects(source) {
20679
- const result = [];
20680
- for (const statement of source.statements) {
20681
- if (ts9.isClassDeclaration(statement) && (ts9.getDecorators(statement) ?? []).some((item) => ts9.isCallExpression(item.expression) && item.expression.expression.getText() === "Module")) {
20682
- result.push(decoratorObject(statement, "Module"));
20683
- }
20684
- if (ts9.isVariableStatement(statement)) {
20685
- for (const declaration of statement.declarationList.declarations) {
20686
- const call = declaration.initializer;
20687
- if (call && ts9.isCallExpression(call) && ["defineModule", "defineFeatureSlice"].includes(call.expression.getText()) && call.arguments[0] && ts9.isObjectLiteralExpression(call.arguments[0])) {
20688
- result.push(call.arguments[0]);
20689
- }
21096
+ // src/cli.ts
21097
+ init_fixes();
21098
+
21099
+ // src/diagnostics.ts
21100
+ function createDiagnosticReport(diagnostics) {
21101
+ return { format: 1, entries: diagnostics.map((diagnostic) => {
21102
+ const repair = createDiagnosticRepairPlan([diagnostic])[0];
21103
+ return {
21104
+ diagnostic: { ...diagnostic },
21105
+ ...repair ? { repair } : {},
21106
+ ...diagnostic.suggestion ? { guidance: diagnostic.suggestion } : {}
21107
+ };
21108
+ }) };
21109
+ }
21110
+ function toEditorDiagnostics(diagnostics) {
21111
+ return createDiagnosticReport(diagnostics).entries.map((entry) => ({
21112
+ range: {
21113
+ start: {
21114
+ line: Math.max(0, (entry.diagnostic.line ?? 1) - 1),
21115
+ character: Math.max(0, entry.diagnostic.column ?? 0)
21116
+ },
21117
+ end: {
21118
+ line: Math.max(0, (entry.diagnostic.endLine ?? entry.diagnostic.line ?? 1) - 1),
21119
+ character: Math.max(0, entry.diagnostic.endColumn ?? entry.diagnostic.column ?? 0)
20690
21120
  }
20691
- }
20692
- }
20693
- return result;
21121
+ },
21122
+ severity: entry.diagnostic.severity === "error" ? 1 : 2,
21123
+ source: "supacloud",
21124
+ code: entry.diagnostic.errorCode ?? entry.diagnostic.code,
21125
+ ...entry.diagnostic.docsUrl ? { codeDescription: { href: entry.diagnostic.docsUrl } } : {},
21126
+ message: entry.diagnostic.message + (entry.guidance ? `
21127
+ ${entry.guidance}` : ""),
21128
+ data: { format: 1, ...entry }
21129
+ }));
20694
21130
  }
20695
- function importSymbol(source, path, symbol) {
20696
- identifier2(symbol);
20697
- const current = resolve11(source.fileName).replace(/\.(tsx?|mts|cts)$/, "");
20698
- const target = resolve11(dirname8(source.fileName), path).replace(/\.(tsx?|mts|cts)$/, "");
20699
- if (current === target)
20700
- return source.text;
20701
- const matches = source.statements.filter((item) => ts9.isImportDeclaration(item) && ts9.isStringLiteral(item.moduleSpecifier) && item.moduleSpecifier.text === path);
20702
- if (matches.length > 1)
20703
- throw new Error(`Ambiguous imports from '${path}'`);
20704
- const match = matches[0];
20705
- if (match && ts9.isImportDeclaration(match) && match.importClause?.namedBindings && ts9.isNamedImports(match.importClause.namedBindings) && !match.importClause.isTypeOnly) {
20706
- if (match.importClause.namedBindings.elements.some((item) => item.name.text === symbol))
20707
- return source.text;
20708
- const bindings = match.importClause.namedBindings;
20709
- const updated = ts9.factory.updateNamedImports(bindings, [
20710
- ...bindings.elements,
20711
- ts9.factory.createImportSpecifier(false, undefined, ts9.factory.createIdentifier(symbol))
20712
- ]);
20713
- return source.text.slice(0, bindings.getStart(source)) + ts9.createPrinter().printNode(ts9.EmitHint.Unspecified, updated, source) + source.text.slice(bindings.end);
21131
+ async function createEditorCodeActions(diagnostics, options = {}) {
21132
+ await Promise.resolve().then(() => init_fixes());
21133
+ const actions = [];
21134
+ for (const entry of createDiagnosticReport(diagnostics).entries) {
21135
+ if (entry.repair?.readiness !== "preview")
21136
+ continue;
21137
+ try {
21138
+ const preview = await applyDiagnosticFix(entry.repair.fix, { ...options, dryRun: true });
21139
+ if (!preview.changed)
21140
+ continue;
21141
+ const title = `Apply ${entry.repair.type}`;
21142
+ actions.push({ title, kind: "quickfix", command: {
21143
+ title,
21144
+ command: "supacloud.applyDiagnosticFix",
21145
+ arguments: [{ fix: entry.repair.fix, expectedSourceHash: preview.sourceHash }]
21146
+ }, data: { file: preview.file, preview: preview.content } });
21147
+ } catch {}
20714
21148
  }
20715
- if (match)
20716
- throw new Error(`Import from '${path}' is not a named value import`);
20717
- return `import { ${symbol} } from ${JSON.stringify(path)};
20718
- ${source.text}`;
21149
+ return actions;
20719
21150
  }
20720
21151
 
20721
21152
  // src/cli.ts
20722
21153
  init_graphql_options();
20723
21154
 
20724
21155
  // src/delivery-plan.ts
20725
- import { createHash as createHash8 } from "node:crypto";
21156
+ import { createHash as createHash9 } from "node:crypto";
20726
21157
  init_validate();
20727
21158
  var compare2 = (a, b) => a < b ? -1 : a > b ? 1 : 0;
20728
21159
  var sorted = (values) => [...new Set(values)].sort(compare2);
@@ -20920,7 +21351,7 @@ function createDeliveryPlan(graph, input) {
20920
21351
  deploymentReady: false,
20921
21352
  targets: [...targets.values()].sort((a, b) => compare2(a.name, b.name))
20922
21353
  };
20923
- const topologyDigest = createHash8("sha256").update(JSON.stringify(topology)).digest("hex");
21354
+ const topologyDigest = createHash9("sha256").update(JSON.stringify(topology)).digest("hex");
20924
21355
  return parseDeliveryPlanResult({
20925
21356
  ok: true,
20926
21357
  plan: { ...topology, topologyDigest },
@@ -20957,8 +21388,8 @@ function formatDeliveryPlan(result) {
20957
21388
  // src/delivery-build.ts
20958
21389
  import { mkdir as mkdir3, mkdtemp, readFile as readFile7, realpath as realpath4, rename as rename4, rm as rm2 } from "node:fs/promises";
20959
21390
  import { readFileSync as readFileSync3 } from "node:fs";
20960
- import { dirname as dirname9, join as join10, relative as relative10, resolve as resolve14, sep as sep10 } from "node:path";
20961
- import * as ts12 from "@typescript/typescript6";
21391
+ import { dirname as dirname9, join as join10, relative as relative10, resolve as resolve15, sep as sep10 } from "node:path";
21392
+ import * as ts15 from "@typescript/typescript6";
20962
21393
 
20963
21394
  // src/delivery-build-schema.ts
20964
21395
  init_delivery_build_schema();
@@ -20999,23 +21430,23 @@ function renderDeliveryTarget(graph, target, options) {
20999
21430
  init_delivery_files2();
21000
21431
  import { isBuiltin } from "node:module";
21001
21432
  import { readFile as readFile6 } from "node:fs/promises";
21002
- import { join as join9, resolve as resolve12 } from "node:path";
21003
- import * as ts11 from "@typescript/typescript6";
21433
+ import { join as join9, resolve as resolve13 } from "node:path";
21434
+ import * as ts14 from "@typescript/typescript6";
21004
21435
 
21005
21436
  // src/delivery-imports.ts
21006
- import * as ts10 from "@typescript/typescript6";
21437
+ import * as ts13 from "@typescript/typescript6";
21007
21438
  function staticDeliveryImports(path, contents) {
21008
21439
  if (!/\.[cm]?[jt]sx?$/.test(path))
21009
21440
  return contents;
21010
- const source = ts10.createSourceFile(path, new TextDecoder().decode(contents), ts10.ScriptTarget.Latest, true);
21441
+ const source = ts13.createSourceFile(path, new TextDecoder().decode(contents), ts13.ScriptTarget.Latest, true);
21011
21442
  const computed = [];
21012
21443
  function scan(node) {
21013
- if (ts10.isCallExpression(node) && (node.expression.kind === ts10.SyntaxKind.ImportKeyword || ts10.isIdentifier(node.expression) && node.expression.text === "require")) {
21444
+ if (ts13.isCallExpression(node) && (node.expression.kind === ts13.SyntaxKind.ImportKeyword || ts13.isIdentifier(node.expression) && node.expression.text === "require")) {
21014
21445
  const argument = node.arguments[0];
21015
- if (!argument || !ts10.isStringLiteral(argument) && !ts10.isNoSubstitutionTemplateLiteral(argument))
21446
+ if (!argument || !ts13.isStringLiteral(argument) && !ts13.isNoSubstitutionTemplateLiteral(argument))
21016
21447
  computed.push(node);
21017
21448
  }
21018
- ts10.forEachChild(node, scan);
21449
+ ts13.forEachChild(node, scan);
21019
21450
  }
21020
21451
  scan(source);
21021
21452
  if (computed.length === 0)
@@ -21023,36 +21454,36 @@ function staticDeliveryImports(path, contents) {
21023
21454
  const reject = () => {
21024
21455
  throw new Error("Computed module loading is not supported in independent delivery bundles.");
21025
21456
  };
21026
- if (!ts10.isExternalModule(source))
21457
+ if (!ts13.isExternalModule(source))
21027
21458
  return reject();
21028
- const host = ts10.createCompilerHost({ noLib: true, noResolve: true, allowJs: true });
21459
+ const host = ts13.createCompilerHost({ noLib: true, noResolve: true, allowJs: true });
21029
21460
  host.getSourceFile = (name) => name === path ? source : undefined;
21030
- const checker = ts10.createProgram([path], { noLib: true, noResolve: true, allowJs: true }, host).getTypeChecker();
21461
+ const checker = ts13.createProgram([path], { noLib: true, noResolve: true, allowJs: true }, host).getTypeChecker();
21031
21462
  const replacements = new Map;
21032
21463
  const removed = new Set;
21033
21464
  for (const call of computed) {
21034
21465
  let visit = function(node) {
21035
- const referenced = ts10.isIdentifier(node) ? ts10.isShorthandPropertyAssignment(node.parent) ? checker.getShorthandAssignmentValueSymbol(node.parent) : ts10.isExportSpecifier(node.parent) ? checker.getExportSpecifierLocalTargetSymbol(node.parent) : checker.getSymbolAtLocation(node) : undefined;
21036
- if (ts10.isIdentifier(node) && node !== declarationName && referenced === symbol) {
21466
+ const referenced = ts13.isIdentifier(node) ? ts13.isShorthandPropertyAssignment(node.parent) ? checker.getShorthandAssignmentValueSymbol(node.parent) : ts13.isExportSpecifier(node.parent) ? checker.getExportSpecifierLocalTargetSymbol(node.parent) : checker.getSymbolAtLocation(node) : undefined;
21467
+ if (ts13.isIdentifier(node) && node !== declarationName && referenced === symbol) {
21037
21468
  const use = node.parent;
21038
- if (!ts10.isCallExpression(use) || use.expression !== node || use.arguments.length !== 1 || use.questionDotToken || use.typeArguments?.length)
21469
+ if (!ts13.isCallExpression(use) || use.expression !== node || use.arguments.length !== 1 || use.questionDotToken || use.typeArguments?.length)
21039
21470
  return reject();
21040
21471
  const value = use.arguments[0];
21041
- if (!value || !ts10.isStringLiteral(value) && !ts10.isNoSubstitutionTemplateLiteral(value))
21472
+ if (!value || !ts13.isStringLiteral(value) && !ts13.isNoSubstitutionTemplateLiteral(value))
21042
21473
  return reject();
21043
21474
  references++;
21044
- replacements.set(use, ts10.factory.createCallExpression(call.expression, undefined, [value]));
21475
+ replacements.set(use, ts13.factory.createCallExpression(call.expression, undefined, [value]));
21045
21476
  }
21046
- ts10.forEachChild(node, visit);
21477
+ ts13.forEachChild(node, visit);
21047
21478
  };
21048
21479
  const statement = call.parent;
21049
21480
  const block = statement.parent;
21050
21481
  const declaration = block.parent;
21051
- if (call.expression.kind !== ts10.SyntaxKind.ImportKeyword || call.arguments.length !== 1 || !ts10.isReturnStatement(statement) || !ts10.isBlock(block) || block.statements.length !== 1 || !ts10.isFunctionDeclaration(declaration) || declaration.parent !== source || !declaration.name || declaration.modifiers?.length || declaration.asteriskToken || declaration.typeParameters?.length || declaration.parameters.length !== 1)
21482
+ if (call.expression.kind !== ts13.SyntaxKind.ImportKeyword || call.arguments.length !== 1 || !ts13.isReturnStatement(statement) || !ts13.isBlock(block) || block.statements.length !== 1 || !ts13.isFunctionDeclaration(declaration) || declaration.parent !== source || !declaration.name || declaration.modifiers?.length || declaration.asteriskToken || declaration.typeParameters?.length || declaration.parameters.length !== 1)
21052
21483
  return reject();
21053
21484
  const parameter = declaration.parameters[0];
21054
21485
  const argument = call.arguments[0];
21055
- if (!parameter || !ts10.isIdentifier(parameter.name) || parameter.initializer || parameter.dotDotDotToken || !argument || !ts10.isIdentifier(argument) || checker.getSymbolAtLocation(argument) !== checker.getSymbolAtLocation(parameter.name))
21486
+ if (!parameter || !ts13.isIdentifier(parameter.name) || parameter.initializer || parameter.dotDotDotToken || !argument || !ts13.isIdentifier(argument) || checker.getSymbolAtLocation(argument) !== checker.getSymbolAtLocation(parameter.name))
21056
21487
  return reject();
21057
21488
  const symbol = checker.getSymbolAtLocation(declaration.name);
21058
21489
  if (!symbol || symbol.declarations?.length !== 1)
@@ -21064,22 +21495,22 @@ function staticDeliveryImports(path, contents) {
21064
21495
  return reject();
21065
21496
  removed.add(declaration);
21066
21497
  }
21067
- const transformed = ts10.transform(source, [(context) => {
21498
+ const transformed = ts13.transform(source, [(context) => {
21068
21499
  const visit = (node) => {
21069
- if (ts10.isFunctionDeclaration(node) && removed.has(node))
21500
+ if (ts13.isFunctionDeclaration(node) && removed.has(node))
21070
21501
  return;
21071
- const replacement = ts10.isCallExpression(node) ? replacements.get(node) : undefined;
21502
+ const replacement = ts13.isCallExpression(node) ? replacements.get(node) : undefined;
21072
21503
  if (replacement)
21073
21504
  return replacement;
21074
- return ts10.visitEachChild(node, visit, context);
21505
+ return ts13.visitEachChild(node, visit, context);
21075
21506
  };
21076
- return (node) => ts10.visitNode(node, visit, ts10.isSourceFile) ?? node;
21507
+ return (node) => ts13.visitNode(node, visit, ts13.isSourceFile) ?? node;
21077
21508
  }]);
21078
21509
  try {
21079
21510
  const transformedSource = transformed.transformed[0];
21080
21511
  if (!transformedSource)
21081
21512
  return reject();
21082
- return new TextEncoder().encode(ts10.createPrinter().printFile(transformedSource));
21513
+ return new TextEncoder().encode(ts13.createPrinter().printFile(transformedSource));
21083
21514
  } finally {
21084
21515
  transformed.dispose();
21085
21516
  }
@@ -21176,7 +21607,7 @@ async function bundleDeliveryTarget(name, code, project, generatedDirectory, opt
21176
21607
  async function bundleDeliveryTargetInProcess(name, code, project, generatedDirectory, options) {
21177
21608
  const inputs = new Map;
21178
21609
  const workingDirectory = process.cwd();
21179
- const entry = resolve12(generatedDirectory, `delivery-${name}.ts`);
21610
+ const entry = resolve13(generatedDirectory, `delivery-${name}.ts`);
21180
21611
  const entryPattern = new RegExp(`^${entry.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}$`);
21181
21612
  const result = await Bun.build({
21182
21613
  entrypoints: [entry],
@@ -21199,7 +21630,7 @@ async function bundleDeliveryTargetInProcess(name, code, project, generatedDirec
21199
21630
  if (args.path === entry)
21200
21631
  return { contents: code, loader: "ts" };
21201
21632
  const bytes = await readFile6(args.path);
21202
- inputs.set(resolve12(args.path), digest(bytes));
21633
+ inputs.set(resolve13(args.path), digest(bytes));
21203
21634
  return { contents: staticDeliveryImports(args.path, bytes), loader: args.loader };
21204
21635
  });
21205
21636
  }
@@ -21209,7 +21640,7 @@ async function bundleDeliveryTargetInProcess(name, code, project, generatedDirec
21209
21640
  throw new Error("Independent bundle failed or has no dependency metadata.");
21210
21641
  const runtimeImports = new Set;
21211
21642
  for (const [path, metadata] of Object.entries(result.metafile.inputs)) {
21212
- if (resolve12(workingDirectory, path) !== entry && !inputs.has(resolve12(workingDirectory, path))) {
21643
+ if (resolve13(workingDirectory, path) !== entry && !inputs.has(resolve13(workingDirectory, path))) {
21213
21644
  throw new Error("Bundler reported an input that was not captured by the delivery snapshot.");
21214
21645
  }
21215
21646
  for (const imported of metadata.imports) {
@@ -21227,16 +21658,16 @@ async function bundleDeliveryTargetInProcess(name, code, project, generatedDirec
21227
21658
  const bytes = new Uint8Array(await output.arrayBuffer());
21228
21659
  if (/\.[cm]?js$/.test(path)) {
21229
21660
  let check = function(node) {
21230
- const specifier = ts11.isImportDeclaration(node) || ts11.isExportDeclaration(node) ? node.moduleSpecifier : ts11.isCallExpression(node) && (node.expression.kind === ts11.SyntaxKind.ImportKeyword || ts11.isIdentifier(node.expression) && /^(?:__)?require$/.test(node.expression.text) || ts11.isPropertyAccessExpression(node.expression) && node.expression.name.text === "require" && ts11.isMetaProperty(node.expression.expression) && node.expression.expression.keywordToken === ts11.SyntaxKind.ImportKeyword) ? node.arguments[0] : undefined;
21231
- if (specifier && ts11.isStringLiteralLike(specifier)) {
21661
+ const specifier = ts14.isImportDeclaration(node) || ts14.isExportDeclaration(node) ? node.moduleSpecifier : ts14.isCallExpression(node) && (node.expression.kind === ts14.SyntaxKind.ImportKeyword || ts14.isIdentifier(node.expression) && /^(?:__)?require$/.test(node.expression.text) || ts14.isPropertyAccessExpression(node.expression) && node.expression.name.text === "require" && ts14.isMetaProperty(node.expression.expression) && node.expression.expression.keywordToken === ts14.SyntaxKind.ImportKeyword) ? node.arguments[0] : undefined;
21662
+ if (specifier && ts14.isStringLiteralLike(specifier)) {
21232
21663
  if (!isBuiltin(specifier.text) && specifier.text !== "bun" && !specifier.text.startsWith("bun:")) {
21233
21664
  throw new Error("Independent bundles cannot retain external package imports.");
21234
21665
  }
21235
21666
  runtimeImports.add(specifier.text);
21236
21667
  }
21237
- ts11.forEachChild(node, check);
21668
+ ts14.forEachChild(node, check);
21238
21669
  };
21239
- const source = ts11.createSourceFile(path, new TextDecoder().decode(bytes), ts11.ScriptTarget.Latest, true);
21670
+ const source = ts14.createSourceFile(path, new TextDecoder().decode(bytes), ts14.ScriptTarget.Latest, true);
21240
21671
  check(source);
21241
21672
  }
21242
21673
  files.set(`bundle/${path}`, bytes);
@@ -21526,14 +21957,14 @@ interface DeliveryWorkerHost {
21526
21957
 
21527
21958
  // src/delivery-migrations.ts
21528
21959
  init_delivery_files2();
21529
- import { resolve as resolve13 } from "node:path";
21960
+ import { resolve as resolve14 } from "node:path";
21530
21961
  async function prepareDeliveryMigrations(project, generatedRoot, declarations = []) {
21531
21962
  const entries = [];
21532
21963
  const files = new Map;
21533
21964
  const inputs = new Map;
21534
21965
  let totalBytes = 0;
21535
21966
  for (const declaration of [...declarations].sort((a, b) => BigInt(a.version) < BigInt(b.version) ? -1 : BigInt(a.version) > BigInt(b.version) ? 1 : 0)) {
21536
- const source = resolve13(project, declaration.source);
21967
+ const source = resolve14(project, declaration.source);
21537
21968
  if (!inside(project, source) || inside(generatedRoot, source))
21538
21969
  throw new Error("Invalid migration source.");
21539
21970
  const bytes = await readBoundedOwned(project, source, 1048576);
@@ -21584,7 +22015,7 @@ async function buildDeliveryProject(options, delivery) {
21584
22015
  const settings = parseDeliveryOptions(delivery);
21585
22016
  if (typeof Bun === "undefined")
21586
22017
  throw new Error("Independent delivery builds require Bun.");
21587
- const configPath = ts12.findConfigFile(resolve14(options.rootDir), ts12.sys.fileExists);
22018
+ const configPath = ts15.findConfigFile(resolve15(options.rootDir), ts15.sys.fileExists);
21588
22019
  if (!configPath)
21589
22020
  throw new Error("Independent delivery builds require a project tsconfig.json.");
21590
22021
  const lexicalProject = dirname9(configPath);
@@ -21592,19 +22023,19 @@ async function buildDeliveryProject(options, delivery) {
21592
22023
  const sourceRoot = await realpath4(options.rootDir);
21593
22024
  if (!inside(project, sourceRoot))
21594
22025
  throw new Error("Application sources must be inside the project.");
21595
- const requested = resolve14(options.outDir, "delivery");
22026
+ const requested = resolve15(options.outDir, "delivery");
21596
22027
  if (!inside(lexicalProject, requested))
21597
22028
  throw new Error("Output must be inside the application project.");
21598
- const buildRoot = resolve14(project, relative10(lexicalProject, requested));
21599
- const generatedRoot = resolve14(project, relative10(lexicalProject, options.outDir));
22029
+ const buildRoot = resolve15(project, relative10(lexicalProject, requested));
22030
+ const generatedRoot = resolve15(project, relative10(lexicalProject, options.outDir));
21600
22031
  if (inside(generatedRoot, sourceRoot))
21601
22032
  throw new Error("Output must not contain the application source root.");
21602
22033
  const configInputs = new Map;
21603
- const parsedConfig = ts12.getParsedCommandLineOfConfigFile(await realpath4(configPath), {}, {
21604
- ...ts12.sys,
22034
+ const parsedConfig = ts15.getParsedCommandLineOfConfigFile(await realpath4(configPath), {}, {
22035
+ ...ts15.sys,
21605
22036
  readFile(path) {
21606
22037
  const contents = readFileSync3(path, "utf8");
21607
- configInputs.set(resolve14(path), digest(contents));
22038
+ configInputs.set(resolve15(path), digest(contents));
21608
22039
  return contents;
21609
22040
  },
21610
22041
  onUnRecoverableConfigFileDiagnostic() {
@@ -21642,7 +22073,7 @@ async function buildDeliveryProject(options, delivery) {
21642
22073
  if (!target || (kind === "worker" ? target.kind !== "jobs" : target.kind === "jobs")) {
21643
22074
  throw new Error("Delivery host kind does not match its target.");
21644
22075
  }
21645
- const path = resolve14(sourceRoot, app.source);
22076
+ const path = resolve15(sourceRoot, app.source);
21646
22077
  if (inside(generatedRoot, path) || !/\.[cm]?ts$/.test(path))
21647
22078
  throw new Error("Hosts require application TypeScript source.");
21648
22079
  hosts.set(app.target, { path, kind, hash: digest(await readOwned(sourceRoot, path)) });
@@ -21721,7 +22152,7 @@ async function buildDeliveryProject(options, delivery) {
21721
22152
  for (const [name, contents] of Object.entries(generated))
21722
22153
  await writeArtifact(stage, `generated/${name}`, contents);
21723
22154
  {
21724
- const program = ts12.createProgram({
22155
+ const program = ts15.createProgram({
21725
22156
  rootNames: [
21726
22157
  ...parsedConfig.fileNames.filter((path) => !inside(generatedRoot, path)),
21727
22158
  ...Object.keys(generated).map((name) => join10(stage, "generated", name))
@@ -21729,12 +22160,12 @@ async function buildDeliveryProject(options, delivery) {
21729
22160
  options: { ...parsedConfig.options, rootDir: project },
21730
22161
  ...parsedConfig.projectReferences ? { projectReferences: parsedConfig.projectReferences } : {}
21731
22162
  });
21732
- const diagnostics = ts12.getPreEmitDiagnostics(program);
21733
- if (diagnostics.some((item) => item.category === ts12.DiagnosticCategory.Error)) {
21734
- return failed(diagnostics.filter((item) => item.category === ts12.DiagnosticCategory.Error).map((item) => ({
22163
+ const diagnostics = ts15.getPreEmitDiagnostics(program);
22164
+ if (diagnostics.some((item) => item.category === ts15.DiagnosticCategory.Error)) {
22165
+ return failed(diagnostics.filter((item) => item.category === ts15.DiagnosticCategory.Error).map((item) => ({
21735
22166
  severity: "error",
21736
22167
  code: "delivery-generated-type-error",
21737
- message: ts12.flattenDiagnosticMessageText(item.messageText, `
22168
+ message: ts15.flattenDiagnosticMessageText(item.messageText, `
21738
22169
  `),
21739
22170
  ...item.file ? { file: item.file.fileName } : {}
21740
22171
  })));
@@ -21769,7 +22200,7 @@ async function buildDeliveryProject(options, delivery) {
21769
22200
  }));
21770
22201
  const assetInputs = {};
21771
22202
  for (const asset of assets.filter((asset) => asset.target === target.name)) {
21772
- const path = resolve14(sourceRoot, asset.source);
22203
+ const path = resolve15(sourceRoot, asset.source);
21773
22204
  const bytes = await readOwned(sourceRoot, path);
21774
22205
  const hash = digest(bytes);
21775
22206
  const previousHash = snapshots.get(path);
@@ -21879,13 +22310,13 @@ async function buildDeliveryProject(options, delivery) {
21879
22310
 
21880
22311
  // src/migrations.ts
21881
22312
  import { rename as rename5, readFile as readFile9, writeFile as writeFile4, rm as rm3 } from "node:fs/promises";
21882
- import { relative as relative11, resolve as resolve16 } from "node:path";
21883
- import * as ts13 from "@typescript/typescript6";
22313
+ import { relative as relative11, resolve as resolve17 } from "node:path";
22314
+ import * as ts16 from "@typescript/typescript6";
21884
22315
 
21885
22316
  // src/migration-policy.ts
21886
22317
  import { readFile as readFile8 } from "node:fs/promises";
21887
22318
  import { readFileSync as readFileSync4 } from "node:fs";
21888
- import { resolve as resolve15 } from "node:path";
22319
+ import { resolve as resolve16 } from "node:path";
21889
22320
  var cachedCompilerVersion;
21890
22321
  function compilerVersion() {
21891
22322
  if (cachedCompilerVersion !== undefined)
@@ -21899,9 +22330,9 @@ function compilerVersion() {
21899
22330
  }
21900
22331
  function migrationDependencies() {
21901
22332
  return {
21902
- "@supacloud/app": "0.19.0",
22333
+ "@supacloud/app": "0.21.0",
21903
22334
  "@supacloud/compiler": compilerVersion(),
21904
- "@supacloud/elysia": "0.21.0",
22335
+ "@supacloud/elysia": "0.23.0",
21905
22336
  elysia: "2.0.0-beta.19",
21906
22337
  typescript: "7.0.2"
21907
22338
  };
@@ -21910,7 +22341,7 @@ async function checkMigrationDependencies(rootDir) {
21910
22341
  const problems = [];
21911
22342
  for (const [name, expected] of Object.entries(migrationDependencies())) {
21912
22343
  try {
21913
- const manifest = JSON.parse(await readFile8(resolve15(rootDir, "node_modules", name, "package.json"), "utf8"));
22344
+ const manifest = JSON.parse(await readFile8(resolve16(rootDir, "node_modules", name, "package.json"), "utf8"));
21914
22345
  if (!manifest || typeof manifest !== "object" || !("name" in manifest) || manifest.name !== name || !("version" in manifest) || manifest.version !== expected) {
21915
22346
  problems.push(`${name}: requires tested installed version ${expected}`);
21916
22347
  }
@@ -21924,29 +22355,29 @@ async function checkMigrationDependencies(rootDir) {
21924
22355
  // src/migrations.ts
21925
22356
  var ROUTE_DECORATORS2 = new Set(["Get", "Post", "Put", "Patch", "Delete", "Head", "Options"]);
21926
22357
  var MIGRATION_COMPILER_OPTIONS = {
21927
- target: ts13.ScriptTarget.ES2022,
21928
- module: ts13.ModuleKind.ESNext,
21929
- moduleResolution: ts13.ModuleResolutionKind.Bundler,
22358
+ target: ts16.ScriptTarget.ES2022,
22359
+ module: ts16.ModuleKind.ESNext,
22360
+ moduleResolution: ts16.ModuleResolutionKind.Bundler,
21930
22361
  noEmit: true,
21931
22362
  skipLibCheck: true
21932
22363
  };
21933
22364
  function migrationCompilerOptions(rootDir) {
21934
22365
  if (!rootDir)
21935
22366
  return MIGRATION_COMPILER_OPTIONS;
21936
- const configPath = ts13.findConfigFile(rootDir, ts13.sys.fileExists);
22367
+ const configPath = ts16.findConfigFile(rootDir, ts16.sys.fileExists);
21937
22368
  if (!configPath)
21938
22369
  return MIGRATION_COMPILER_OPTIONS;
21939
22370
  const configHost = {
21940
- ...ts13.sys,
22371
+ ...ts16.sys,
21941
22372
  onUnRecoverableConfigFileDiagnostic: (_diagnostic) => {}
21942
22373
  };
21943
- const parsed = ts13.getParsedCommandLineOfConfigFile(configPath, {}, configHost);
22374
+ const parsed = ts16.getParsedCommandLineOfConfigFile(configPath, {}, configHost);
21944
22375
  if (!parsed || parsed.errors.length > 0)
21945
22376
  return MIGRATION_COMPILER_OPTIONS;
21946
22377
  return { ...parsed.options, noEmit: true, skipLibCheck: true };
21947
22378
  }
21948
22379
  function propertyName2(property) {
21949
- if (ts13.isIdentifier(property) || ts13.isStringLiteral(property) || ts13.isNumericLiteral(property))
22380
+ if (ts16.isIdentifier(property) || ts16.isStringLiteral(property) || ts16.isNumericLiteral(property))
21950
22381
  return property.text;
21951
22382
  return;
21952
22383
  }
@@ -21956,7 +22387,7 @@ function lineOf2(sourceFile, node) {
21956
22387
  function resolveSymbol(symbol, checker) {
21957
22388
  if (!symbol)
21958
22389
  return;
21959
- for (let guard = 0;guard < 4 && (symbol.flags & ts13.SymbolFlags.Alias) !== 0; guard += 1) {
22390
+ for (let guard = 0;guard < 4 && (symbol.flags & ts16.SymbolFlags.Alias) !== 0; guard += 1) {
21960
22391
  const aliased = checker.getAliasedSymbol(symbol);
21961
22392
  if (aliased === symbol)
21962
22393
  break;
@@ -21965,12 +22396,12 @@ function resolveSymbol(symbol, checker) {
21965
22396
  return symbol;
21966
22397
  }
21967
22398
  function symbolForExpression(expression, checker) {
21968
- const location = ts13.isIdentifier(expression) ? expression : ts13.isPropertyAccessExpression(expression) ? expression.name : ts13.isElementAccessExpression(expression) && expression.argumentExpression && ts13.isStringLiteral(expression.argumentExpression) ? expression : undefined;
22399
+ const location = ts16.isIdentifier(expression) ? expression : ts16.isPropertyAccessExpression(expression) ? expression.name : ts16.isElementAccessExpression(expression) && expression.argumentExpression && ts16.isStringLiteral(expression.argumentExpression) ? expression : undefined;
21969
22400
  return location ? resolveSymbol(checker.getSymbolAtLocation(location), checker) : undefined;
21970
22401
  }
21971
22402
  function unwrapExpression(expression) {
21972
22403
  let current = expression;
21973
- while (ts13.isAsExpression(current) || ts13.isSatisfiesExpression(current) || ts13.isParenthesizedExpression(current) || ts13.isTypeAssertionExpression(current)) {
22404
+ while (ts16.isAsExpression(current) || ts16.isSatisfiesExpression(current) || ts16.isParenthesizedExpression(current) || ts16.isTypeAssertionExpression(current)) {
21974
22405
  current = current.expression;
21975
22406
  }
21976
22407
  return current;
@@ -21985,7 +22416,7 @@ function isRouteDecoratorCall(node, checker) {
21985
22416
  if (node.arguments.length < 2)
21986
22417
  return false;
21987
22418
  const name = node.expression.getText(node.getSourceFile());
21988
- if (ts13.isIdentifier(node.expression) && ROUTE_DECORATORS2.has(node.expression.text))
22419
+ if (ts16.isIdentifier(node.expression) && ROUTE_DECORATORS2.has(node.expression.text))
21989
22420
  return true;
21990
22421
  if (ROUTE_DECORATORS2.has(name))
21991
22422
  return true;
@@ -21999,14 +22430,14 @@ function resolveStaticObjectLiteral2(input, checker, seen = new Set) {
21999
22430
  if (seen.has(expression))
22000
22431
  return;
22001
22432
  seen.add(expression);
22002
- if (ts13.isObjectLiteralExpression(expression))
22433
+ if (ts16.isObjectLiteralExpression(expression))
22003
22434
  return expression;
22004
- if (ts13.isCallExpression(expression) && isDefineRouteContractCall(expression, checker)) {
22435
+ if (ts16.isCallExpression(expression) && isDefineRouteContractCall(expression, checker)) {
22005
22436
  return resolveStaticObjectLiteral2(expression.arguments[0], checker, seen);
22006
22437
  }
22007
22438
  const symbol = symbolForExpression(expression, checker);
22008
22439
  for (const declaration of symbol?.declarations ?? []) {
22009
- if (ts13.isVariableDeclaration(declaration) && declaration.initializer) {
22440
+ if (ts16.isVariableDeclaration(declaration) && declaration.initializer) {
22010
22441
  const resolved = resolveStaticObjectLiteral2(declaration.initializer, checker, seen);
22011
22442
  if (resolved)
22012
22443
  return resolved;
@@ -22020,25 +22451,25 @@ function displayFile(rootDir, fileName) {
22020
22451
  }
22021
22452
  function createMigrationProgram(fileNames, sourceOverrides, rootDir) {
22022
22453
  const compilerOptions = migrationCompilerOptions(rootDir);
22023
- const host = ts13.createCompilerHost(compilerOptions);
22454
+ const host = ts16.createCompilerHost(compilerOptions);
22024
22455
  const getSourceFile = host.getSourceFile.bind(host);
22025
22456
  const fileExists = host.fileExists.bind(host);
22026
22457
  const readFile = host.readFile.bind(host);
22027
22458
  const currentDirectory = host.getCurrentDirectory.bind(host);
22028
- host.fileExists = (fileName) => sourceOverrides.has(resolve16(fileName)) || fileExists(fileName);
22029
- host.readFile = (fileName) => sourceOverrides.get(resolve16(fileName)) ?? readFile(fileName);
22459
+ host.fileExists = (fileName) => sourceOverrides.has(resolve17(fileName)) || fileExists(fileName);
22460
+ host.readFile = (fileName) => sourceOverrides.get(resolve17(fileName)) ?? readFile(fileName);
22030
22461
  host.getSourceFile = (fileName, languageVersion, onError, shouldCreateNewSourceFile) => {
22031
- const source = sourceOverrides.get(resolve16(fileName));
22032
- return source === undefined ? getSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile) : ts13.createSourceFile(fileName, source, languageVersion, true);
22462
+ const source = sourceOverrides.get(resolve17(fileName));
22463
+ return source === undefined ? getSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile) : ts16.createSourceFile(fileName, source, languageVersion, true);
22033
22464
  };
22034
22465
  host.getCurrentDirectory = () => rootDir ?? currentDirectory();
22035
- return ts13.createProgram(fileNames, compilerOptions, host);
22466
+ return ts16.createProgram(fileNames, compilerOptions, host);
22036
22467
  }
22037
22468
  function routeResponseProperties(object) {
22038
- const responseProperties = object.properties.filter((property) => ts13.isPropertyAssignment(property) && propertyName2(property.name) === "response");
22469
+ const responseProperties = object.properties.filter((property) => ts16.isPropertyAssignment(property) && propertyName2(property.name) === "response");
22039
22470
  return {
22040
22471
  response: responseProperties[0],
22041
- hasResponses: object.properties.some((property) => (ts13.isPropertyAssignment(property) || ts13.isShorthandPropertyAssignment(property)) && propertyName2(property.name) === "responses"),
22472
+ hasResponses: object.properties.some((property) => (ts16.isPropertyAssignment(property) || ts16.isShorthandPropertyAssignment(property)) && propertyName2(property.name) === "responses"),
22042
22473
  duplicateResponse: responseProperties.length > 1
22043
22474
  };
22044
22475
  }
@@ -22054,15 +22485,15 @@ function planRouteResponseMigration(sourceFiles, checker, rootDir, includedFiles
22054
22485
  issues.push(issue);
22055
22486
  };
22056
22487
  for (const sourceFile of sourceFiles) {
22057
- const sourcePath = resolve16(sourceFile.fileName);
22488
+ const sourcePath = resolve17(sourceFile.fileName);
22058
22489
  if (!includedFiles.has(sourcePath))
22059
22490
  continue;
22060
22491
  const visit = (node) => {
22061
- if (ts13.isCallExpression(node) && isRouteDecoratorCall(node, checker)) {
22492
+ if (ts16.isCallExpression(node) && isRouteDecoratorCall(node, checker)) {
22062
22493
  const options = node.arguments[1];
22063
22494
  const object = options && resolveStaticObjectLiteral2(options, checker);
22064
22495
  if (object) {
22065
- const objectPath = resolve16(object.getSourceFile().fileName);
22496
+ const objectPath = resolve17(object.getSourceFile().fileName);
22066
22497
  const properties = routeResponseProperties(object);
22067
22498
  if (properties.response) {
22068
22499
  if (!includedFiles.has(objectPath)) {
@@ -22078,7 +22509,7 @@ function planRouteResponseMigration(sourceFiles, checker, rootDir, includedFiles
22078
22509
  }
22079
22510
  }
22080
22511
  }
22081
- ts13.forEachChild(node, visit);
22512
+ ts16.forEachChild(node, visit);
22082
22513
  };
22083
22514
  visit(sourceFile);
22084
22515
  }
@@ -22105,13 +22536,13 @@ function planRouteResponseMigration(sourceFiles, checker, rootDir, includedFiles
22105
22536
  line: lineOf2(sourceFile, response)
22106
22537
  });
22107
22538
  } else {
22108
- const replacements = replacementsByFile.get(resolve16(sourceFile.fileName)) ?? [];
22539
+ const replacements = replacementsByFile.get(resolve17(sourceFile.fileName)) ?? [];
22109
22540
  replacements.push({
22110
22541
  start: response.getStart(sourceFile),
22111
22542
  end: response.getEnd(),
22112
22543
  text: `responses: { 200: ${response.initializer.getText(sourceFile)} }`
22113
22544
  });
22114
- replacementsByFile.set(resolve16(sourceFile.fileName), replacements);
22545
+ replacementsByFile.set(resolve17(sourceFile.fileName), replacements);
22115
22546
  }
22116
22547
  }
22117
22548
  return { replacementsByFile, issues };
@@ -22124,7 +22555,7 @@ function applyReplacements(source, replacements) {
22124
22555
  return content;
22125
22556
  }
22126
22557
  function migrateRouteResponse(source, fileName) {
22127
- const absoluteFile = resolve16(fileName);
22558
+ const absoluteFile = resolve17(fileName);
22128
22559
  const sourceOverrides = new Map([[absoluteFile, source]]);
22129
22560
  const program = createMigrationProgram([absoluteFile], sourceOverrides);
22130
22561
  const sourceFile = program.getSourceFile(absoluteFile);
@@ -22140,7 +22571,7 @@ function migrateRouteResponse(source, fileName) {
22140
22571
  }]
22141
22572
  };
22142
22573
  }
22143
- const plan = planRouteResponseMigration([sourceFile], program.getTypeChecker(), resolve16("."), new Set([absoluteFile]));
22574
+ const plan = planRouteResponseMigration([sourceFile], program.getTypeChecker(), resolve17("."), new Set([absoluteFile]));
22144
22575
  const replacements = plan.replacementsByFile.get(absoluteFile) ?? [];
22145
22576
  return {
22146
22577
  changed: replacements.length > 0,
@@ -22150,7 +22581,7 @@ function migrateRouteResponse(source, fileName) {
22150
22581
  };
22151
22582
  }
22152
22583
  function migrateRouteResponseProject(files, rootDir, sourceByPath) {
22153
- const absoluteFiles = files.map((file) => resolve16(file));
22584
+ const absoluteFiles = files.map((file) => resolve17(file));
22154
22585
  const program = createMigrationProgram(absoluteFiles, sourceByPath, rootDir);
22155
22586
  const sourceFiles = absoluteFiles.map((file) => program.getSourceFile(file)).filter((file) => file !== undefined);
22156
22587
  const plan = planRouteResponseMigration(sourceFiles, program.getTypeChecker(), rootDir, new Set(absoluteFiles));
@@ -22163,11 +22594,11 @@ function migrateRouteResponseProject(files, rootDir, sourceByPath) {
22163
22594
  changed: replacements.length > 0,
22164
22595
  content: applyReplacements(source, replacements),
22165
22596
  replacements: replacements.length,
22166
- issues: plan.issues.filter((issue) => resolve16(rootDir, issue.file) === file)
22597
+ issues: plan.issues.filter((issue) => resolve17(rootDir, issue.file) === file)
22167
22598
  });
22168
22599
  }
22169
22600
  for (const issue of plan.issues) {
22170
- const path = resolve16(rootDir, issue.file);
22601
+ const path = resolve17(rootDir, issue.file);
22171
22602
  if (!results.has(path) && sourceByPath.has(path)) {
22172
22603
  results.set(path, {
22173
22604
  changed: false,
@@ -22186,6 +22617,13 @@ var SUPACLOUD_MIGRATIONS = [
22186
22617
  to: "0.12.0",
22187
22618
  description: "Replace deprecated route response schemas with explicit HTTP status maps.",
22188
22619
  apply: migrateRouteResponse
22620
+ },
22621
+ {
22622
+ id: "http-provider-entrypoint",
22623
+ from: "0.12.0",
22624
+ to: "0.13.0",
22625
+ description: "Move provider-only withInterceptors imports to the shared HTTP feature entry; reject ambiguous uses.",
22626
+ apply: migrateHttpProviderImports
22189
22627
  }
22190
22628
  ];
22191
22629
  async function writeAtomically(path, content) {
@@ -22198,7 +22636,7 @@ async function writeAtomically(path, content) {
22198
22636
  }
22199
22637
  }
22200
22638
  async function migrateProject(options) {
22201
- const rootDir = resolve16(options.rootDir);
22639
+ const rootDir = resolve17(options.rootDir);
22202
22640
  let migrations = SUPACLOUD_MIGRATIONS;
22203
22641
  const preflightIssues = [];
22204
22642
  if (options.fromVersion !== undefined || options.toVersion !== undefined) {
@@ -22238,7 +22676,7 @@ async function migrateProject(options) {
22238
22676
  }
22239
22677
  }
22240
22678
  const include = options.include ?? ["**/*.ts", "**/*.tsx", "**/*.mts", "**/*.cts"];
22241
- const files = ts13.sys.readDirectory(rootDir, [".ts", ".tsx", ".mts", ".cts"], ["node_modules", "dist", "generated"], include).sort();
22679
+ const files = ts16.sys.readDirectory(rootDir, [".ts", ".tsx", ".mts", ".cts"], ["node_modules", "dist", "generated"], include).sort();
22242
22680
  const results = [];
22243
22681
  const issues = [];
22244
22682
  const pendingWrites = new Map;
@@ -22254,7 +22692,7 @@ async function migrateProject(options) {
22254
22692
  }
22255
22693
  };
22256
22694
  for (const filePath of files) {
22257
- sourceByPath.set(resolve16(filePath), await readFile9(filePath, "utf8"));
22695
+ sourceByPath.set(resolve17(filePath), await readFile9(filePath, "utf8"));
22258
22696
  }
22259
22697
  const originalSources = new Map(sourceByPath);
22260
22698
  const writtenFiles = new Set;
@@ -22263,7 +22701,7 @@ async function migrateProject(options) {
22263
22701
  if (projectResults)
22264
22702
  appendIssues(projectResults.issues);
22265
22703
  for (const filePath of files) {
22266
- const absoluteFile = resolve16(filePath);
22704
+ const absoluteFile = resolve17(filePath);
22267
22705
  const file = relative11(rootDir, absoluteFile) || absoluteFile;
22268
22706
  const before = sourceByPath.get(absoluteFile);
22269
22707
  if (before === undefined)
@@ -22323,13 +22761,13 @@ async function migrateProject(options) {
22323
22761
  }
22324
22762
 
22325
22763
  // src/migration-assess.ts
22326
- import { createHash as createHash9 } from "node:crypto";
22764
+ import { createHash as createHash10 } from "node:crypto";
22327
22765
  import { readFile as readFile11 } from "node:fs/promises";
22328
- import { join as join11, resolve as resolve18 } from "node:path";
22766
+ import { join as join11, resolve as resolve19 } from "node:path";
22329
22767
 
22330
22768
  // src/openapi-tools.ts
22331
22769
  import { mkdir as mkdir4, readFile as readFile10, rename as rename6, unlink as unlink3, writeFile as writeFile5 } from "node:fs/promises";
22332
- import { dirname as dirname10, resolve as resolve17 } from "node:path";
22770
+ import { dirname as dirname10, resolve as resolve18 } from "node:path";
22333
22771
  import { pathToFileURL as pathToFileURL2 } from "node:url";
22334
22772
 
22335
22773
  class OpenApiDocumentError extends Error {
@@ -22720,7 +23158,7 @@ function serializeOpenApiJson(document, space = 2) {
22720
23158
  }
22721
23159
  async function readOpenApiJson(path) {
22722
23160
  try {
22723
- const value = JSON.parse(await readFile10(resolve17(path), "utf8"));
23161
+ const value = JSON.parse(await readFile10(resolve18(path), "utf8"));
22724
23162
  return parseOpenApiDocument(value);
22725
23163
  } catch (error) {
22726
23164
  if (error instanceof OpenApiDocumentError)
@@ -22729,7 +23167,7 @@ async function readOpenApiJson(path) {
22729
23167
  }
22730
23168
  }
22731
23169
  async function writeOpenApiJson(document, outputPath, space = 2) {
22732
- const path = resolve17(outputPath);
23170
+ const path = resolve18(outputPath);
22733
23171
  const content = serializeOpenApiJson(document, space);
22734
23172
  await mkdir4(dirname10(path), { recursive: true });
22735
23173
  try {
@@ -22750,7 +23188,7 @@ async function writeOpenApiJson(document, outputPath, space = 2) {
22750
23188
  }
22751
23189
  async function loadGeneratedOpenApiDocument(modulePath) {
22752
23190
  try {
22753
- const moduleUrl = pathToFileURL2(resolve17(modulePath));
23191
+ const moduleUrl = pathToFileURL2(resolve18(modulePath));
22754
23192
  moduleUrl.searchParams.set("supacloud-openapi-export", "1");
22755
23193
  const loaded = await import(moduleUrl.href);
22756
23194
  if (!isRecord(loaded))
@@ -22847,17 +23285,17 @@ function arrayLength(value) {
22847
23285
  return Array.isArray(value) ? value.length : undefined;
22848
23286
  }
22849
23287
  async function sha256(path) {
22850
- return createHash9("sha256").update(await readFile11(path)).digest("hex");
23288
+ return createHash10("sha256").update(await readFile11(path)).digest("hex");
22851
23289
  }
22852
23290
  function overallStatus(findings) {
22853
23291
  return findings.reduce((current, finding) => STATUS_PRIORITY[finding.status] > STATUS_PRIORITY[current] ? finding.status : current, "compatible");
22854
23292
  }
22855
23293
  async function assessMigration(options) {
22856
- const projectDir = resolve18(options.projectDir);
23294
+ const projectDir = resolve19(options.projectDir);
22857
23295
  const compile = {
22858
23296
  ...options.compile,
22859
- rootDir: resolve18(options.compile.rootDir),
22860
- outDir: resolve18(options.compile.outDir)
23297
+ rootDir: resolve19(options.compile.rootDir),
23298
+ outDir: resolve19(options.compile.outDir)
22861
23299
  };
22862
23300
  const findings = [];
22863
23301
  const dependencyProblems = await checkMigrationDependencies(projectDir);
@@ -22937,8 +23375,8 @@ async function assessMigration(options) {
22937
23375
  }
22938
23376
  let openApi;
22939
23377
  if (options.baselineOpenApiPath && options.currentOpenApiPath) {
22940
- const baselinePath = resolve18(projectDir, options.baselineOpenApiPath);
22941
- const currentPath = resolve18(projectDir, options.currentOpenApiPath);
23378
+ const baselinePath = resolve19(projectDir, options.baselineOpenApiPath);
23379
+ const currentPath = resolve19(projectDir, options.currentOpenApiPath);
22942
23380
  try {
22943
23381
  const diff = diffOpenApiDocuments(await readOpenApiJson(baselinePath), await readOpenApiJson(currentPath));
22944
23382
  openApi = {
@@ -23032,6 +23470,7 @@ function printUsage() {
23032
23470
  Usage:
23033
23471
  supacloud-compiler compile [rootDir] [options]
23034
23472
  supacloud-compiler check [rootDir] [options]
23473
+ supacloud-compiler diagnostics [rootDir] [--json]
23035
23474
  supacloud-compiler dev [rootDir] [options]
23036
23475
  supacloud-compiler graph [rootDir] [options]
23037
23476
  supacloud-compiler explain <name> [rootDir] [options]
@@ -23053,6 +23492,7 @@ Usage:
23053
23492
  Commands:
23054
23493
  compile Compile application modules and generate artifacts
23055
23494
  check Check artifact drift and run governance gates
23495
+ diagnostics Read-only editor diagnostics and validated semantic code actions
23056
23496
  dev Watch source files and recompile on changes
23057
23497
  graph Print the discovered application graph
23058
23498
  explain Explain a module, provider, or external token
@@ -23131,7 +23571,7 @@ async function run() {
23131
23571
  process.exitCode = 1;
23132
23572
  return;
23133
23573
  }
23134
- if (!command || !["compile", "check", "dev", "graph", "explain", "context", "dev-context", "environment-bindings", "doctor", "migrate", "migration-assess", "fix", "graphql-schema", "plan", "build-delivery", "openapi-export", "openapi-diff"].includes(command)) {
23574
+ if (!command || !["compile", "check", "diagnostics", "dev", "graph", "explain", "context", "dev-context", "environment-bindings", "doctor", "migrate", "migration-assess", "fix", "graphql-schema", "plan", "build-delivery", "openapi-export", "openapi-diff"].includes(command)) {
23135
23575
  console.error(`Error: unknown command "${command}"`);
23136
23576
  printUsage();
23137
23577
  process.exit(1);
@@ -23300,7 +23740,7 @@ async function run() {
23300
23740
  } else if (arg === "--dry-run") {
23301
23741
  dryRun = true;
23302
23742
  } else if (arg === "--write") {
23303
- if (command === "context" || command === "dev-context" || command === "environment-bindings")
23743
+ if (command === "context" || command === "dev-context" || command === "diagnostics" || command === "environment-bindings")
23304
23744
  throw new Error(`${command} is read-only; --write is not supported`);
23305
23745
  if (command === "plan" || command === "migration-assess")
23306
23746
  throw new Error(`${command} is read-only; --write is not supported`);
@@ -23365,7 +23805,7 @@ async function run() {
23365
23805
  throw new Error("Build context requires a manifest, target, subject, events, request ID and --json");
23366
23806
  }
23367
23807
  try {
23368
- const pack = await createDeliveryExecutionContextPack(contextManifest, contextTarget, query, await readExecutionMetadata(resolve22(executionEventsPath)), executionRequestId);
23808
+ const pack = await createDeliveryExecutionContextPack(contextManifest, contextTarget, query, await readExecutionMetadata(resolve23(executionEventsPath)), executionRequestId);
23369
23809
  console.log(JSON.stringify(pack, null, 2));
23370
23810
  } catch (error) {
23371
23811
  console.log(JSON.stringify({
@@ -23384,7 +23824,7 @@ async function run() {
23384
23824
  const currentPath = openApiDiffPaths[1];
23385
23825
  if (!basePath || !currentPath)
23386
23826
  throw new Error("openapi-diff requires two JSON file paths");
23387
- const result = diffOpenApiDocuments(await readOpenApiJson(resolve22(process.cwd(), basePath)), await readOpenApiJson(resolve22(process.cwd(), currentPath)));
23827
+ const result = diffOpenApiDocuments(await readOpenApiJson(resolve23(process.cwd(), basePath)), await readOpenApiJson(resolve23(process.cwd(), currentPath)));
23388
23828
  console.log(json ? JSON.stringify(result, null, 2) : formatOpenApiDiff(result));
23389
23829
  if (!result.ok)
23390
23830
  process.exitCode = 1;
@@ -23399,8 +23839,8 @@ async function run() {
23399
23839
  if (!modulePath || !outputPath)
23400
23840
  throw new Error("openapi-export requires an OpenAPI module and output path");
23401
23841
  const result = await exportGeneratedOpenApiJson({
23402
- modulePath: resolve22(process.cwd(), modulePath),
23403
- outputPath: resolve22(process.cwd(), outputPath),
23842
+ modulePath: resolve23(process.cwd(), modulePath),
23843
+ outputPath: resolve23(process.cwd(), outputPath),
23404
23844
  ...openApiExportSpace === undefined ? {} : { space: openApiExportSpace }
23405
23845
  });
23406
23846
  console.log(json ? JSON.stringify({ ok: true, ...result }, null, 2) : result.written ? `OpenAPI JSON written: ${result.path}` : `OpenAPI JSON matches: ${result.path}`);
@@ -23408,7 +23848,7 @@ async function run() {
23408
23848
  }
23409
23849
  if (command === "migrate") {
23410
23850
  const result = await migrateProject({
23411
- rootDir: rootDir ? resolve22(process.cwd(), rootDir) : process.cwd(),
23851
+ rootDir: rootDir ? resolve23(process.cwd(), rootDir) : process.cwd(),
23412
23852
  write: !dryRun,
23413
23853
  ...fromVersion === undefined ? {} : { fromVersion },
23414
23854
  ...toVersion === undefined ? {} : { toVersion }
@@ -23446,8 +23886,8 @@ async function run() {
23446
23886
  if (checkSchema && command !== "graphql-schema")
23447
23887
  throw new Error("--check is only supported by graphql-schema");
23448
23888
  const defaults = resolveSupacloudConfig(loadedConfig, process.cwd());
23449
- const resolvedRoot = rootDir ? resolve22(process.cwd(), rootDir) : defaults.rootDir;
23450
- const resolvedOut = outDir ? resolve22(process.cwd(), outDir) : defaults.outDir;
23889
+ const resolvedRoot = rootDir ? resolve23(process.cwd(), rootDir) : defaults.rootDir;
23890
+ const resolvedOut = outDir ? resolve23(process.cwd(), outDir) : defaults.outDir;
23451
23891
  const configured = compileOptionsFromConfig({
23452
23892
  ...loadedConfig,
23453
23893
  root: resolvedRoot,
@@ -23466,7 +23906,7 @@ async function run() {
23466
23906
  let delivery = loadedConfig.delivery;
23467
23907
  if (deliveryPath !== undefined) {
23468
23908
  try {
23469
- delivery = JSON.parse(await readFile14(resolve22(process.cwd(), deliveryPath), "utf8"));
23909
+ delivery = JSON.parse(await readFile14(resolve23(process.cwd(), deliveryPath), "utf8"));
23470
23910
  } catch {
23471
23911
  throw new DeliveryConfigurationError;
23472
23912
  }
@@ -23524,9 +23964,24 @@ ${item.suggestion ?? ""}`).join(`
23524
23964
  } else if (command === "fix") {
23525
23965
  if (!query)
23526
23966
  throw new Error("fix requires a JSON file containing one DiagnosticFix");
23527
- const fix = JSON.parse(await readFile14(resolve22(process.cwd(), query), "utf8"));
23528
- const result = await applyDiagnosticFix(fix, { rootDir: resolvedRoot, dryRun });
23967
+ const input = JSON.parse(await readFile14(resolve23(process.cwd(), query), "utf8"));
23968
+ const envelope = input && typeof input === "object" && "fix" in input;
23969
+ if (envelope && (typeof input.expectedSourceHash !== "string" || !/^[a-f0-9]{64}$/.test(input.expectedSourceHash))) {
23970
+ throw new Error("Editor fix requires the source hash from its validated preview");
23971
+ }
23972
+ const result = await applyDiagnosticFix(envelope ? input.fix : input, {
23973
+ rootDir: resolvedRoot,
23974
+ dryRun,
23975
+ ...envelope ? { expectedSourceHash: input.expectedSourceHash } : {}
23976
+ });
23529
23977
  console.log(JSON.stringify({ ok: true, ...result }, null, 2));
23978
+ } else if (command === "diagnostics") {
23979
+ const result = await checkProject(compileDefaults);
23980
+ console.log(JSON.stringify({
23981
+ report: createDiagnosticReport(result.diagnostics),
23982
+ diagnostics: toEditorDiagnostics(result.diagnostics),
23983
+ actions: await createEditorCodeActions(result.diagnostics, { rootDir: resolvedRoot })
23984
+ }, null, 2));
23530
23985
  } else if (command === "compile") {
23531
23986
  const result = await compileProject(compileDefaults);
23532
23987
  const errors = result.diagnostics.filter((d) => d.severity === "error");
@@ -23650,7 +24105,7 @@ Source change detected; compiling...`);
23650
24105
  process.exitCode = 1;
23651
24106
  return;
23652
24107
  }
23653
- const file = resolve22(rootDir ? resolve22(process.cwd(), rootDir) : process.cwd(), bindingsFile ?? "supacloud.environments.json");
24108
+ const file = resolve23(rootDir ? resolve23(process.cwd(), rootDir) : process.cwd(), bindingsFile ?? "supacloud.environments.json");
23654
24109
  try {
23655
24110
  const document = await readEnvironmentBindingsFile(file);
23656
24111
  const graph = await analyzeProject(resolvedRoot);
@@ -23685,7 +24140,7 @@ Source change detected; compiling...`);
23685
24140
  try {
23686
24141
  const result = await checkProject(compileDefaults);
23687
24142
  if (executionEventsPath && executionRequestId) {
23688
- const pack = createExecutionContextPack({ ...result.graph, diagnostics: result.diagnostics }, query, await readExecutionMetadata(resolve22(process.cwd(), executionEventsPath)), executionRequestId);
24143
+ const pack = createExecutionContextPack({ ...result.graph, diagnostics: result.diagnostics }, query, await readExecutionMetadata(resolve23(process.cwd(), executionEventsPath)), executionRequestId);
23689
24144
  console.log(JSON.stringify(pack, null, 2));
23690
24145
  return;
23691
24146
  }