@supacloud/cli 0.60.1 → 0.62.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/LICENSE +202 -661
- package/NOTICE +8 -13
- package/README.md +1 -1
- package/dist/index.js +1278 -774
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -188364,7 +188364,7 @@ var require_parse_filepath = __commonJS(function(exports, module) {
|
|
|
188364
188364
|
});
|
|
188365
188365
|
|
|
188366
188366
|
// node_modules/@graphql-codegen/visitor-plugin-common/esm/imports.js
|
|
188367
|
-
import { dirname as dirname5, isAbsolute as
|
|
188367
|
+
import { dirname as dirname5, isAbsolute as isAbsolute4, join as join10, relative as relative5, resolve as resolve12 } from "path";
|
|
188368
188368
|
function generateFragmentImportStatement(statement, kind) {
|
|
188369
188369
|
const { importSource: fragmentImportSource, ...rest } = statement;
|
|
188370
188370
|
const { identifiers, path, namespace } = fragmentImportSource;
|
|
@@ -188398,20 +188398,20 @@ function generateImportStatement(statement) {
|
|
|
188398
188398
|
function resolveImportPath(baseDir, outputPath, sourcePath) {
|
|
188399
188399
|
const shouldAbsolute = !sourcePath.startsWith("~");
|
|
188400
188400
|
if (shouldAbsolute) {
|
|
188401
|
-
const absGeneratedFilePath =
|
|
188402
|
-
const absImportFilePath =
|
|
188401
|
+
const absGeneratedFilePath = resolve12(baseDir, outputPath);
|
|
188402
|
+
const absImportFilePath = resolve12(baseDir, sourcePath);
|
|
188403
188403
|
return resolveRelativeImport(absGeneratedFilePath, absImportFilePath);
|
|
188404
188404
|
}
|
|
188405
188405
|
return sourcePath.replace(`~`, "");
|
|
188406
188406
|
}
|
|
188407
188407
|
function resolveRelativeImport(from, to) {
|
|
188408
|
-
if (!
|
|
188408
|
+
if (!isAbsolute4(from)) {
|
|
188409
188409
|
throw new Error(`Argument 'from' must be an absolute path, '${from}' given.`);
|
|
188410
188410
|
}
|
|
188411
|
-
if (!
|
|
188411
|
+
if (!isAbsolute4(to)) {
|
|
188412
188412
|
throw new Error(`Argument 'to' must be an absolute path, '${to}' given.`);
|
|
188413
188413
|
}
|
|
188414
|
-
return fixLocalFilePath(clearExtension(
|
|
188414
|
+
return fixLocalFilePath(clearExtension(relative5(dirname5(from), to)));
|
|
188415
188415
|
}
|
|
188416
188416
|
function clearExtension(path) {
|
|
188417
188417
|
const parsedPath = import_parse_filepath.default(path);
|
|
@@ -221087,11 +221087,48 @@ function registerSupabaseCliTools(server2, options = {}) {
|
|
|
221087
221087
|
|
|
221088
221088
|
// src/shared/tools/lite-cli-tools.ts
|
|
221089
221089
|
import { spawn as spawn2 } from "node:child_process";
|
|
221090
|
-
import { existsSync as
|
|
221091
|
-
import {
|
|
221090
|
+
import { existsSync as existsSync8, statSync as statSync6 } from "node:fs";
|
|
221091
|
+
import { resolve as resolve10 } from "node:path";
|
|
221092
|
+
|
|
221093
|
+
// src/shared/tools/lite-cli-command.ts
|
|
221094
|
+
import { existsSync as existsSync7, readFileSync as readFileSync6, statSync as statSync5 } from "node:fs";
|
|
221095
|
+
import { isAbsolute as isAbsolute3, join as join6, relative as relative3, resolve as resolve9 } from "node:path";
|
|
221096
|
+
function isRecord3(value) {
|
|
221097
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
221098
|
+
}
|
|
221099
|
+
function resolveLiteCommand(workdir, environment = process.env) {
|
|
221100
|
+
const explicitBinary = environment.SUPACLOUD_LITE_CLI_BIN?.trim();
|
|
221101
|
+
if (explicitBinary) {
|
|
221102
|
+
if (explicitBinary.includes("\x00"))
|
|
221103
|
+
throw new Error("Invalid SUPACLOUD_LITE_CLI_BIN");
|
|
221104
|
+
return [explicitBinary];
|
|
221105
|
+
}
|
|
221106
|
+
const packageRoot = join6(resolve9(workdir), "node_modules", "@supacloud", "lite");
|
|
221107
|
+
const manifestPath = join6(packageRoot, "package.json");
|
|
221108
|
+
if (!existsSync7(manifestPath))
|
|
221109
|
+
return ["supacloud-lite"];
|
|
221110
|
+
const manifest = JSON.parse(readFileSync6(manifestPath, "utf8"));
|
|
221111
|
+
if (!isRecord3(manifest) || manifest.name !== "@supacloud/lite" || !isRecord3(manifest.bin)) {
|
|
221112
|
+
throw new Error("Invalid installed @supacloud/lite package manifest");
|
|
221113
|
+
}
|
|
221114
|
+
const entry = manifest.bin["supacloud-lite"];
|
|
221115
|
+
if (typeof entry !== "string" || !entry.trim() || entry.includes("\x00") || isAbsolute3(entry)) {
|
|
221116
|
+
throw new Error("Invalid installed @supacloud/lite bin");
|
|
221117
|
+
}
|
|
221118
|
+
const executable = resolve9(packageRoot, entry);
|
|
221119
|
+
const packageRelative = relative3(packageRoot, executable);
|
|
221120
|
+
if (!packageRelative || packageRelative === ".." || packageRelative.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) || isAbsolute3(packageRelative)) {
|
|
221121
|
+
throw new Error("Installed @supacloud/lite bin must stay inside its package");
|
|
221122
|
+
}
|
|
221123
|
+
if (!existsSync7(executable) || !statSync5(executable).isFile()) {
|
|
221124
|
+
throw new Error("Installed @supacloud/lite bin is missing; reinstall the package");
|
|
221125
|
+
}
|
|
221126
|
+
return [process.execPath, executable];
|
|
221127
|
+
}
|
|
221128
|
+
// src/shared/tools/lite-cli-tools.ts
|
|
221092
221129
|
function requireWorkdir(workdir, fallback) {
|
|
221093
|
-
const resolved =
|
|
221094
|
-
if (!
|
|
221130
|
+
const resolved = resolve10(workdir || fallback);
|
|
221131
|
+
if (!existsSync8(resolved) || !statSync6(resolved).isDirectory()) {
|
|
221095
221132
|
throw new Error(`Lite workdir not found: ${resolved}`);
|
|
221096
221133
|
}
|
|
221097
221134
|
return resolved;
|
|
@@ -221169,18 +221206,6 @@ function buildLiteArgs(request) {
|
|
|
221169
221206
|
booleanFlag(args, "--json", request.json);
|
|
221170
221207
|
return args;
|
|
221171
221208
|
}
|
|
221172
|
-
function resolveLiteCommand(workdir, environment = process.env) {
|
|
221173
|
-
const explicitBinary = environment.SUPACLOUD_LITE_CLI_BIN?.trim();
|
|
221174
|
-
if (explicitBinary) {
|
|
221175
|
-
if (explicitBinary.includes("\x00"))
|
|
221176
|
-
throw new Error("Invalid SUPACLOUD_LITE_CLI_BIN");
|
|
221177
|
-
return [explicitBinary];
|
|
221178
|
-
}
|
|
221179
|
-
const localPackageEntry = join6(resolve9(workdir), "node_modules", "@supacloud", "lite", "dist", "launcher.cjs");
|
|
221180
|
-
if (existsSync7(localPackageEntry))
|
|
221181
|
-
return [process.execPath, localPackageEntry];
|
|
221182
|
-
return ["supacloud-lite"];
|
|
221183
|
-
}
|
|
221184
221209
|
function spawnLiteCommand(command, workdir, environment, inheritOutput) {
|
|
221185
221210
|
const [executable, ...commandArguments] = command;
|
|
221186
221211
|
return new Promise((resolveExecution, rejectExecution) => {
|
|
@@ -221314,17 +221339,17 @@ function registerLiteCliTools(server2, options = {}) {
|
|
|
221314
221339
|
// src/shared/tools/ai-tools.ts
|
|
221315
221340
|
import {
|
|
221316
221341
|
cpSync,
|
|
221317
|
-
existsSync as
|
|
221342
|
+
existsSync as existsSync9,
|
|
221318
221343
|
lstatSync as lstatSync2,
|
|
221319
221344
|
mkdirSync as mkdirSync3,
|
|
221320
221345
|
mkdtempSync as mkdtempSync2,
|
|
221321
221346
|
readdirSync as readdirSync3,
|
|
221322
|
-
readFileSync as
|
|
221347
|
+
readFileSync as readFileSync7,
|
|
221323
221348
|
renameSync,
|
|
221324
221349
|
rmSync as rmSync2
|
|
221325
221350
|
} from "node:fs";
|
|
221326
221351
|
import { homedir as homedir2 } from "node:os";
|
|
221327
|
-
import { dirname as dirname4, join as join7, relative as
|
|
221352
|
+
import { dirname as dirname4, join as join7, relative as relative4, resolve as resolve11, sep as sep3 } from "node:path";
|
|
221328
221353
|
import { fileURLToPath } from "node:url";
|
|
221329
221354
|
var SKILL_NAME = "supacloud-cli";
|
|
221330
221355
|
function regularFiles(rootDirectory, currentDirectory = rootDirectory) {
|
|
@@ -221336,18 +221361,18 @@ function regularFiles(rootDirectory, currentDirectory = rootDirectory) {
|
|
|
221336
221361
|
if (directoryEntry.isDirectory())
|
|
221337
221362
|
files.push(...regularFiles(rootDirectory, entryPath));
|
|
221338
221363
|
if (directoryEntry.isFile())
|
|
221339
|
-
files.push(
|
|
221364
|
+
files.push(relative4(rootDirectory, entryPath).split(sep3).join("/"));
|
|
221340
221365
|
}
|
|
221341
221366
|
return files.sort();
|
|
221342
221367
|
}
|
|
221343
221368
|
function directoriesMatch(sourceDirectory, destinationDirectory) {
|
|
221344
|
-
if (!
|
|
221369
|
+
if (!existsSync9(destinationDirectory) || !lstatSync2(destinationDirectory).isDirectory())
|
|
221345
221370
|
return false;
|
|
221346
221371
|
const sourceFiles = regularFiles(sourceDirectory);
|
|
221347
221372
|
const destinationFiles = regularFiles(destinationDirectory);
|
|
221348
221373
|
if (sourceFiles.join("\x00") !== destinationFiles.join("\x00"))
|
|
221349
221374
|
return false;
|
|
221350
|
-
return sourceFiles.every((file) =>
|
|
221375
|
+
return sourceFiles.every((file) => readFileSync7(join7(sourceDirectory, file)).equals(readFileSync7(join7(destinationDirectory, file))));
|
|
221351
221376
|
}
|
|
221352
221377
|
function backupTimestamp(now) {
|
|
221353
221378
|
return now.toISOString().replace(/[-:.]/g, "");
|
|
@@ -221356,7 +221381,7 @@ function availableBackupDirectory(destinationDirectory, now) {
|
|
|
221356
221381
|
const baseDirectory = `${destinationDirectory}.backup-${backupTimestamp(now)}`;
|
|
221357
221382
|
let candidate = baseDirectory;
|
|
221358
221383
|
let suffix = 2;
|
|
221359
|
-
while (
|
|
221384
|
+
while (existsSync9(candidate)) {
|
|
221360
221385
|
candidate = `${baseDirectory}-${suffix}`;
|
|
221361
221386
|
suffix += 1;
|
|
221362
221387
|
}
|
|
@@ -221397,8 +221422,8 @@ function replaceSkill(sourceDirectory, targetRoot, destinationDirectory, backupD
|
|
|
221397
221422
|
}
|
|
221398
221423
|
}
|
|
221399
221424
|
function skillSummary(request, action, files, backupDirectory) {
|
|
221400
|
-
const sourceDirectory =
|
|
221401
|
-
const targetRoot =
|
|
221425
|
+
const sourceDirectory = resolve11(request.sourceDirectory);
|
|
221426
|
+
const targetRoot = resolve11(request.targetRoot);
|
|
221402
221427
|
return {
|
|
221403
221428
|
name: SKILL_NAME,
|
|
221404
221429
|
sourceDirectory,
|
|
@@ -221412,14 +221437,14 @@ function skillSummary(request, action, files, backupDirectory) {
|
|
|
221412
221437
|
};
|
|
221413
221438
|
}
|
|
221414
221439
|
function installSkill(request) {
|
|
221415
|
-
const sourceDirectory =
|
|
221416
|
-
const targetRoot =
|
|
221440
|
+
const sourceDirectory = resolve11(request.sourceDirectory);
|
|
221441
|
+
const targetRoot = resolve11(request.targetRoot);
|
|
221417
221442
|
const destinationDirectory = join7(targetRoot, SKILL_NAME);
|
|
221418
|
-
if (!
|
|
221443
|
+
if (!existsSync9(join7(sourceDirectory, "SKILL.md"))) {
|
|
221419
221444
|
throw new Error(`Bundled SupaCloud CLI skill not found: ${sourceDirectory}`);
|
|
221420
221445
|
}
|
|
221421
221446
|
const files = regularFiles(sourceDirectory);
|
|
221422
|
-
if (!
|
|
221447
|
+
if (!existsSync9(destinationDirectory))
|
|
221423
221448
|
return installNewSkill(request, files);
|
|
221424
221449
|
if (directoriesMatch(sourceDirectory, destinationDirectory)) {
|
|
221425
221450
|
return skillSummary(request, "none", files, null);
|
|
@@ -221430,16 +221455,16 @@ function installSkill(request) {
|
|
|
221430
221455
|
return installReplacementSkill(request, files);
|
|
221431
221456
|
}
|
|
221432
221457
|
function installNewSkill(request, files) {
|
|
221433
|
-
const sourceDirectory =
|
|
221434
|
-
const targetRoot =
|
|
221458
|
+
const sourceDirectory = resolve11(request.sourceDirectory);
|
|
221459
|
+
const targetRoot = resolve11(request.targetRoot);
|
|
221435
221460
|
if (request.mode === "write") {
|
|
221436
221461
|
createSkill(sourceDirectory, targetRoot, join7(targetRoot, SKILL_NAME));
|
|
221437
221462
|
}
|
|
221438
221463
|
return skillSummary(request, "create", files, null);
|
|
221439
221464
|
}
|
|
221440
221465
|
function installReplacementSkill(request, files) {
|
|
221441
|
-
const sourceDirectory =
|
|
221442
|
-
const targetRoot =
|
|
221466
|
+
const sourceDirectory = resolve11(request.sourceDirectory);
|
|
221467
|
+
const targetRoot = resolve11(request.targetRoot);
|
|
221443
221468
|
const destinationDirectory = join7(targetRoot, SKILL_NAME);
|
|
221444
221469
|
const backupDirectory = availableBackupDirectory(destinationDirectory, request.now);
|
|
221445
221470
|
if (request.mode === "write") {
|
|
@@ -221449,15 +221474,15 @@ function installReplacementSkill(request, files) {
|
|
|
221449
221474
|
}
|
|
221450
221475
|
function resolveDefaultCodexSkillRoot(environment = process.env, homeDirectory = homedir2()) {
|
|
221451
221476
|
const codexHome = environment.CODEX_HOME?.trim();
|
|
221452
|
-
return join7(
|
|
221477
|
+
return join7(resolve11(codexHome || join7(homeDirectory, ".codex")), "skills");
|
|
221453
221478
|
}
|
|
221454
221479
|
function resolveBundledSkillDirectory(moduleUrl = import.meta.url) {
|
|
221455
221480
|
const moduleDirectory = dirname4(fileURLToPath(moduleUrl));
|
|
221456
221481
|
const candidates = [
|
|
221457
|
-
|
|
221458
|
-
|
|
221482
|
+
resolve11(moduleDirectory, "../../../skills", SKILL_NAME),
|
|
221483
|
+
resolve11(moduleDirectory, "../skills", SKILL_NAME)
|
|
221459
221484
|
];
|
|
221460
|
-
const skillDirectory = candidates.find((candidate) =>
|
|
221485
|
+
const skillDirectory = candidates.find((candidate) => existsSync9(join7(candidate, "SKILL.md")));
|
|
221461
221486
|
if (!skillDirectory)
|
|
221462
221487
|
throw new Error("Bundled SupaCloud CLI skill is missing from this installation");
|
|
221463
221488
|
return skillDirectory;
|
|
@@ -221493,21 +221518,21 @@ function registerAiTools(server2) {
|
|
|
221493
221518
|
}
|
|
221494
221519
|
|
|
221495
221520
|
// src/shared/tools/app-tools.ts
|
|
221496
|
-
import { existsSync as
|
|
221521
|
+
import { existsSync as existsSync11, readFileSync as readFileSync9 } from "node:fs";
|
|
221497
221522
|
import { mkdir as mkdir6, readFile as readFile8, readdir as readdir5, writeFile as writeFile5 } from "node:fs/promises";
|
|
221498
|
-
import { basename as basename8, dirname as dirname12, join as join15, relative as relative12, resolve as
|
|
221523
|
+
import { basename as basename8, dirname as dirname12, join as join15, relative as relative12, resolve as resolve17 } from "node:path";
|
|
221499
221524
|
|
|
221500
221525
|
// node_modules/@supacloud/compiler/dist/index.js
|
|
221501
|
-
import { dirname as dirname22, relative as
|
|
221526
|
+
import { dirname as dirname22, relative as relative6, sep as sep4 } from "node:path";
|
|
221502
221527
|
import { createHash as createHash42 } from "node:crypto";
|
|
221503
221528
|
import { access, mkdir as mkdir2, rename as rename2, unlink, writeFile as writeFile2 } from "node:fs/promises";
|
|
221504
221529
|
import { join as join22 } from "node:path";
|
|
221505
|
-
var
|
|
221506
|
-
var
|
|
221530
|
+
var ts10 = __toESM(require_typescript(), 1);
|
|
221531
|
+
var ts11 = __toESM(require_typescript(), 1);
|
|
221507
221532
|
var import_graphql99 = __toESM(require_graphql2(), 1);
|
|
221508
221533
|
import { extname as extname3 } from "node:path";
|
|
221509
|
-
import { resolve as resolve32 } from "node:path";
|
|
221510
221534
|
import { resolve as resolve42 } from "node:path";
|
|
221535
|
+
import { resolve as resolve52 } from "node:path";
|
|
221511
221536
|
import { createHash as createHash52 } from "node:crypto";
|
|
221512
221537
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
221513
221538
|
import { relative as relative42, sep as sep42 } from "node:path";
|
|
@@ -226880,48 +226905,52 @@ var findTransformedDefinitions = (visitedResult) => {
|
|
|
226880
226905
|
import { createHash as createHash7 } from "node:crypto";
|
|
226881
226906
|
import { constants as constants2 } from "node:fs";
|
|
226882
226907
|
import { lstat as lstat2, mkdir as mkdir22, open as open3, readFile as readFile3, readdir as readdir3, realpath as realpath3, rename as rename22, rm as rm2, writeFile as writeFile22 } from "node:fs/promises";
|
|
226883
|
-
import { dirname as dirname42, isAbsolute as
|
|
226908
|
+
import { dirname as dirname42, isAbsolute as isAbsolute5, join as join52, relative as relative52, resolve as resolve72, sep as sep5 } from "node:path";
|
|
226884
226909
|
import { existsSync as existsSync32 } from "node:fs";
|
|
226885
|
-
import { dirname as dirname52, join as join62, relative as
|
|
226910
|
+
import { dirname as dirname52, join as join62, relative as relative62, sep as sep6 } from "node:path";
|
|
226886
226911
|
import { isAbsolute as isAbsolute22 } from "node:path";
|
|
226887
|
-
var
|
|
226888
|
-
|
|
226912
|
+
var ts15 = __toESM(require_typescript(), 1);
|
|
226913
|
+
import { createHash as createHash8, randomUUID } from "node:crypto";
|
|
226914
|
+
import { lstat as lstat22, readFile as readFile6, realpath as realpath4, rename as rename4, unlink as unlink2, writeFile as writeFile3 } from "node:fs/promises";
|
|
226915
|
+
import { dirname as dirname8, isAbsolute as isAbsolute32, relative as relative8, resolve as resolve122, sep as sep8 } from "node:path";
|
|
226916
|
+
var ts17 = __toESM(require_typescript(), 1);
|
|
226917
|
+
var ts7 = __toESM(require_typescript(), 1);
|
|
226889
226918
|
var ts2 = __toESM(require_typescript(), 1);
|
|
226890
226919
|
var ts = __toESM(require_typescript(), 1);
|
|
226891
|
-
var ts3 = __toESM(require_typescript(), 1);
|
|
226892
226920
|
var ts6 = __toESM(require_typescript(), 1);
|
|
226921
|
+
var ts4 = __toESM(require_typescript(), 1);
|
|
226922
|
+
var ts3 = __toESM(require_typescript(), 1);
|
|
226893
226923
|
var ts5 = __toESM(require_typescript(), 1);
|
|
226894
226924
|
import { createHash as createHash32 } from "node:crypto";
|
|
226895
226925
|
import { relative as relative22, resolve as resolvePath, sep as sep22 } from "node:path";
|
|
226896
226926
|
import { createHash as createHash22 } from "node:crypto";
|
|
226897
|
-
import { existsSync as
|
|
226898
|
-
import { dirname as dirname6, join as join12, resolve as
|
|
226899
|
-
import { createHash as
|
|
226927
|
+
import { existsSync as existsSync10, readFileSync as readFileSync8 } from "node:fs";
|
|
226928
|
+
import { dirname as dirname6, join as join12, resolve as resolve13 } from "node:path";
|
|
226929
|
+
import { createHash as createHash9 } from "node:crypto";
|
|
226930
|
+
import { resolve as resolve22 } from "node:path";
|
|
226931
|
+
var ts9 = __toESM(require_typescript(), 1);
|
|
226932
|
+
var ts8 = __toESM(require_typescript(), 1);
|
|
226933
|
+
var ts14 = __toESM(require_typescript(), 1);
|
|
226900
226934
|
import { createHash as createHash62 } from "node:crypto";
|
|
226901
226935
|
import { access as access2, readFile as readFile22 } from "node:fs/promises";
|
|
226902
226936
|
import { join as join42 } from "node:path";
|
|
226903
226937
|
import { existsSync as existsSync22, readFileSync as readFileSync22 } from "node:fs";
|
|
226904
|
-
import { dirname as dirname32, join as join32, relative as relative32, resolve as
|
|
226905
|
-
var ts11 = __toESM(require_typescript(), 1);
|
|
226938
|
+
import { dirname as dirname32, join as join32, relative as relative32, resolve as resolve32, sep as sep32 } from "node:path";
|
|
226906
226939
|
import { mkdir as mkdir3, mkdtemp, readFile as readFile5, realpath as realpath32, rename as rename3, rm as rm22 } from "node:fs/promises";
|
|
226907
226940
|
import { readFileSync as readFileSync32 } from "node:fs";
|
|
226908
|
-
import { dirname as dirname7, join as join92, relative as relative7, resolve as
|
|
226909
|
-
var
|
|
226910
|
-
var ts9 = __toESM(require_typescript(), 1);
|
|
226941
|
+
import { dirname as dirname7, join as join92, relative as relative7, resolve as resolve112, sep as sep7 } from "node:path";
|
|
226942
|
+
var ts13 = __toESM(require_typescript(), 1);
|
|
226911
226943
|
var ts12 = __toESM(require_typescript(), 1);
|
|
226912
|
-
import { join as join72, resolve as
|
|
226913
|
-
import { resolve as
|
|
226914
|
-
import { randomUUID } from "node:crypto";
|
|
226915
|
-
import { lstat as lstat22, readFile as readFile6, realpath as realpath4, rename as rename4, unlink as unlink2, writeFile as writeFile3 } from "node:fs/promises";
|
|
226916
|
-
import { dirname as dirname8, isAbsolute as isAbsolute32, relative as relative8, resolve as resolve112, sep as sep8 } from "node:path";
|
|
226944
|
+
import { join as join72, resolve as resolve82 } from "node:path";
|
|
226945
|
+
import { resolve as resolve102 } from "node:path";
|
|
226917
226946
|
import { existsSync as existsSync42, watch } from "node:fs";
|
|
226918
|
-
import { dirname as dirname9, relative as relative10, resolve as
|
|
226919
|
-
import { createHash as
|
|
226947
|
+
import { dirname as dirname9, relative as relative10, resolve as resolve14, sep as sep10 } from "node:path";
|
|
226948
|
+
import { createHash as createHash92 } from "node:crypto";
|
|
226920
226949
|
import { access as access3, readdir as readdir32, readFile as readFile7 } from "node:fs/promises";
|
|
226921
|
-
import { isAbsolute as isAbsolute42, relative as relative9, resolve as
|
|
226922
|
-
var
|
|
226950
|
+
import { isAbsolute as isAbsolute42, relative as relative9, resolve as resolve132, sep as sep9 } from "node:path";
|
|
226951
|
+
var ts16 = __toESM(require_typescript(), 1);
|
|
226923
226952
|
import { existsSync as existsSync52 } from "node:fs";
|
|
226924
|
-
import { join as join112, resolve as
|
|
226953
|
+
import { join as join112, resolve as resolve19 } from "node:path";
|
|
226925
226954
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
226926
226955
|
var __defProp2 = Object.defineProperty;
|
|
226927
226956
|
var __returnValue2 = (v) => v;
|
|
@@ -227627,7 +227656,7 @@ function validateGraph(graph, options = false) {
|
|
|
227627
227656
|
symbol: owner.module.className,
|
|
227628
227657
|
targetModule: module.name,
|
|
227629
227658
|
importPath: (() => {
|
|
227630
|
-
const value =
|
|
227659
|
+
const value = relative6(dirname22(module.file), owner.module.file).replace(/\.(tsx?|mts|cts)$/, "").split(sep4).join("/");
|
|
227631
227660
|
return value.startsWith(".") ? value : `./${value}`;
|
|
227632
227661
|
})()
|
|
227633
227662
|
});
|
|
@@ -228523,6 +228552,12 @@ class ModuleGenerator {
|
|
|
228523
228552
|
}
|
|
228524
228553
|
renderFactories() {
|
|
228525
228554
|
const sections = [this.renderServicesFactory()];
|
|
228555
|
+
if (this.hasApplicationLifecycle("init")) {
|
|
228556
|
+
sections.push(this.renderApplicationLifecycle("init"));
|
|
228557
|
+
}
|
|
228558
|
+
if (this.hasApplicationLifecycle("destroy")) {
|
|
228559
|
+
sections.push(this.renderApplicationLifecycle("destroy"));
|
|
228560
|
+
}
|
|
228526
228561
|
if (this.hasFactoryContent("request")) {
|
|
228527
228562
|
sections.push(this.renderScopeFactory("request"));
|
|
228528
228563
|
sections.push(this.renderScopeDestroyer("request"));
|
|
@@ -228539,6 +228574,12 @@ class ModuleGenerator {
|
|
|
228539
228574
|
` name: ${JSON.stringify(this.module.name)} as const,`,
|
|
228540
228575
|
` createServices: create${this.pascal}Services,`
|
|
228541
228576
|
];
|
|
228577
|
+
if (this.hasApplicationLifecycle("init")) {
|
|
228578
|
+
lines.push(` initializeServices: initialize${this.pascal}Services,`);
|
|
228579
|
+
}
|
|
228580
|
+
if (this.hasApplicationLifecycle("destroy")) {
|
|
228581
|
+
lines.push(` destroyServices: destroy${this.pascal}Services,`);
|
|
228582
|
+
}
|
|
228542
228583
|
if (this.hasFactoryContent("request")) {
|
|
228543
228584
|
lines.push(` createRequestScope: create${this.pascal}RequestScope,`);
|
|
228544
228585
|
lines.push(` destroyRequestScope: destroy${this.pascal}RequestScope,`);
|
|
@@ -228561,6 +228602,40 @@ class ModuleGenerator {
|
|
|
228561
228602
|
hasFactoryContent(kind) {
|
|
228562
228603
|
return this.module.providers.some((p) => factoryOfScope(p.scope) === kind) || this.module.controllers.some((c) => factoryOfScope(c.scope) === kind);
|
|
228563
228604
|
}
|
|
228605
|
+
hasApplicationLifecycle(kind) {
|
|
228606
|
+
return this.applicationLifecyclePlan(kind).length > 0;
|
|
228607
|
+
}
|
|
228608
|
+
applicationLifecyclePlan(kind) {
|
|
228609
|
+
const result = [];
|
|
228610
|
+
const multiIndices = new Map;
|
|
228611
|
+
for (const provider of orderProviders(this.module.providers.filter((p) => factoryOfScope(p.scope) === "services"))) {
|
|
228612
|
+
const index = provider.multi ? multiIndices.get(provider.token) ?? 0 : undefined;
|
|
228613
|
+
if (index !== undefined)
|
|
228614
|
+
multiIndices.set(provider.token, index + 1);
|
|
228615
|
+
const owned = provider.kind !== "existing";
|
|
228616
|
+
const selected = kind === "init" ? provider.hasOnInit : provider.hasOnDestroy;
|
|
228617
|
+
if (owned && selected)
|
|
228618
|
+
result.push({ key: camelName(provider.token), ...index === undefined ? {} : { index } });
|
|
228619
|
+
}
|
|
228620
|
+
for (const controller of this.module.controllers) {
|
|
228621
|
+
if (factoryOfScope(controller.scope) !== "services")
|
|
228622
|
+
continue;
|
|
228623
|
+
const selected = kind === "init" ? controller.hasOnInit : controller.hasOnDestroy;
|
|
228624
|
+
if (selected)
|
|
228625
|
+
result.push({ key: camelName(controller.className) });
|
|
228626
|
+
}
|
|
228627
|
+
return result;
|
|
228628
|
+
}
|
|
228629
|
+
renderApplicationLifecycle(kind) {
|
|
228630
|
+
const suffix = kind === "init" ? "initialize" : "destroy";
|
|
228631
|
+
const helper = kind === "init" ? "initializeServiceInstances" : "destroyServiceInstances";
|
|
228632
|
+
return [
|
|
228633
|
+
`async function ${suffix}${this.pascal}Services(services: Record<string, unknown>): Promise<void> {`,
|
|
228634
|
+
` await ${helper}(services, ${JSON.stringify(this.applicationLifecyclePlan(kind))});`,
|
|
228635
|
+
`}`
|
|
228636
|
+
].join(`
|
|
228637
|
+
`);
|
|
228638
|
+
}
|
|
228564
228639
|
renderControllers() {
|
|
228565
228640
|
if (this.module.controllers.length === 0)
|
|
228566
228641
|
return "[]";
|
|
@@ -230280,6 +230355,10 @@ export interface CompiledModule {
|
|
|
230280
230355
|
deps: Record<string, unknown>,
|
|
230281
230356
|
imported: Record<string, Record<string, unknown>>,
|
|
230282
230357
|
): Record<string, unknown>;
|
|
230358
|
+
/** Initializes application-scoped instances owned by this module. */
|
|
230359
|
+
initializeServices?(services: Record<string, unknown>): Promise<void>;
|
|
230360
|
+
/** Destroys application-scoped instances owned by this module. */
|
|
230361
|
+
destroyServices?(services: Record<string, unknown>): Promise<void>;
|
|
230283
230362
|
createRequestScope?(
|
|
230284
230363
|
services: Record<string, unknown>,
|
|
230285
230364
|
ctx: unknown,
|
|
@@ -230364,7 +230443,54 @@ function destroyScopeInstances(
|
|
|
230364
230443
|
});
|
|
230365
230444
|
scopeDestructions.set(scope, destruction);
|
|
230366
230445
|
return destruction;
|
|
230367
|
-
}
|
|
230446
|
+
}
|
|
230447
|
+
|
|
230448
|
+
type CompiledServiceLifecycleEntry = { key: string; index?: number };
|
|
230449
|
+
|
|
230450
|
+
async function initializeServiceInstances(
|
|
230451
|
+
services: Record<string, unknown>,
|
|
230452
|
+
plan: readonly CompiledServiceLifecycleEntry[],
|
|
230453
|
+
): Promise<void> {
|
|
230454
|
+
const seen = new Set<unknown>();
|
|
230455
|
+
for (const entry of plan) {
|
|
230456
|
+
const value = services[entry.key];
|
|
230457
|
+
const instance = entry.index === undefined
|
|
230458
|
+
? value
|
|
230459
|
+
: Array.isArray(value) ? value[entry.index] : undefined;
|
|
230460
|
+
if (seen.has(instance)) continue;
|
|
230461
|
+
seen.add(instance);
|
|
230462
|
+
if (!isRecord(instance) || !isFunction(instance.onInit)) continue;
|
|
230463
|
+
await instance.onInit();
|
|
230464
|
+
}
|
|
230465
|
+
}
|
|
230466
|
+
|
|
230467
|
+
async function destroyServiceInstances(
|
|
230468
|
+
services: Record<string, unknown>,
|
|
230469
|
+
plan: readonly CompiledServiceLifecycleEntry[],
|
|
230470
|
+
): Promise<void> {
|
|
230471
|
+
const errors: unknown[] = [];
|
|
230472
|
+
const seen = new Set<unknown>();
|
|
230473
|
+
for (const entry of [...plan].reverse()) {
|
|
230474
|
+
const value = services[entry.key];
|
|
230475
|
+
const instance = entry.index === undefined
|
|
230476
|
+
? value
|
|
230477
|
+
: Array.isArray(value) ? value[entry.index] : undefined;
|
|
230478
|
+
if (seen.has(instance)) continue;
|
|
230479
|
+
seen.add(instance);
|
|
230480
|
+
if (!isRecord(instance)) continue;
|
|
230481
|
+
const hook = isFunction(instance.onDestroy)
|
|
230482
|
+
? instance.onDestroy
|
|
230483
|
+
: isFunction(instance.ngOnDestroy) ? instance.ngOnDestroy : undefined;
|
|
230484
|
+
if (!hook) continue;
|
|
230485
|
+
try {
|
|
230486
|
+
await hook.call(instance);
|
|
230487
|
+
} catch (error) {
|
|
230488
|
+
errors.push(error);
|
|
230489
|
+
}
|
|
230490
|
+
}
|
|
230491
|
+
if (errors.length > 0) throw new AggregateError(errors, "Application service destruction failed");
|
|
230492
|
+
}
|
|
230493
|
+
`;
|
|
230368
230494
|
var init_generate = __esm2(() => {
|
|
230369
230495
|
init_contract_manifest();
|
|
230370
230496
|
});
|
|
@@ -230586,16 +230712,16 @@ function graphqlInputPaths(options) {
|
|
|
230586
230712
|
} catch {
|
|
230587
230713
|
return [];
|
|
230588
230714
|
}
|
|
230589
|
-
const root =
|
|
230590
|
-
const schema =
|
|
230591
|
-
const documents =
|
|
230715
|
+
const root = resolve42(options.rootDir);
|
|
230716
|
+
const schema = resolve42(root, options.graphql.schema);
|
|
230717
|
+
const documents = ts10.sys.readDirectory(root, [".graphql", ".gql"], ["**/node_modules/**", "**/.git/**", resolve42(options.outDir)], options.graphql.documents ?? ["**/*.graphql", "**/*.gql"]).map((path) => resolve42(path)).filter((path) => path !== schema);
|
|
230592
230718
|
return [schema, ...[...new Set(documents)].sort()];
|
|
230593
230719
|
}
|
|
230594
230720
|
var init_graphql_inputs = __esm2(() => {
|
|
230595
230721
|
init_graphql_options();
|
|
230596
230722
|
});
|
|
230597
230723
|
function renderGraphqlValidators(source, operationNames) {
|
|
230598
|
-
const fileName =
|
|
230724
|
+
const fileName = resolve52("/__supacloud_graphql__/contracts.ts");
|
|
230599
230725
|
const options = {
|
|
230600
230726
|
strict: true,
|
|
230601
230727
|
noUncheckedIndexedAccess: true,
|
|
@@ -230604,18 +230730,18 @@ function renderGraphqlValidators(source, operationNames) {
|
|
|
230604
230730
|
noPropertyAccessFromIndexSignature: true,
|
|
230605
230731
|
noFallthroughCasesInSwitch: true,
|
|
230606
230732
|
skipLibCheck: false,
|
|
230607
|
-
target:
|
|
230733
|
+
target: ts11.ScriptTarget.ES2022,
|
|
230608
230734
|
lib: ["lib.es2022.d.ts"],
|
|
230609
230735
|
types: [],
|
|
230610
230736
|
noEmit: true
|
|
230611
230737
|
};
|
|
230612
|
-
const host =
|
|
230738
|
+
const host = ts11.createCompilerHost(options);
|
|
230613
230739
|
const getSourceFile = host.getSourceFile.bind(host);
|
|
230614
|
-
host.getSourceFile = (path, languageVersion, onError, shouldCreateNewSourceFile) =>
|
|
230615
|
-
const program =
|
|
230616
|
-
const diagnostics =
|
|
230740
|
+
host.getSourceFile = (path, languageVersion, onError, shouldCreateNewSourceFile) => resolve52(path) === fileName ? ts11.createSourceFile(path, source, languageVersion, true) : getSourceFile(path, languageVersion, onError, shouldCreateNewSourceFile);
|
|
230741
|
+
const program = ts11.createProgram([fileName], options, host);
|
|
230742
|
+
const diagnostics = ts11.getPreEmitDiagnostics(program);
|
|
230617
230743
|
if (diagnostics.length) {
|
|
230618
|
-
throw new Error(`Generated GraphQL types cannot be validated: ${diagnostics.map((item) =>
|
|
230744
|
+
throw new Error(`Generated GraphQL types cannot be validated: ${diagnostics.map((item) => ts11.flattenDiagnosticMessageText(item.messageText, `
|
|
230619
230745
|
`)).join("; ")}`);
|
|
230620
230746
|
}
|
|
230621
230747
|
const checker = program.getTypeChecker();
|
|
@@ -230645,25 +230771,25 @@ function renderGraphqlValidators(source, operationNames) {
|
|
|
230645
230771
|
return name;
|
|
230646
230772
|
}
|
|
230647
230773
|
function expression(type) {
|
|
230648
|
-
if (type.flags &
|
|
230774
|
+
if (type.flags & ts11.TypeFlags.Any)
|
|
230649
230775
|
return unsupported(type);
|
|
230650
|
-
if (type.flags &
|
|
230776
|
+
if (type.flags & ts11.TypeFlags.Unknown)
|
|
230651
230777
|
return "true";
|
|
230652
|
-
if (type.flags &
|
|
230778
|
+
if (type.flags & ts11.TypeFlags.Never)
|
|
230653
230779
|
return "false";
|
|
230654
|
-
if (type.flags &
|
|
230780
|
+
if (type.flags & ts11.TypeFlags.Null)
|
|
230655
230781
|
return "value === null";
|
|
230656
|
-
if (type.flags &
|
|
230782
|
+
if (type.flags & ts11.TypeFlags.Undefined)
|
|
230657
230783
|
return "value === undefined";
|
|
230658
230784
|
if (type.isStringLiteral() || type.isNumberLiteral())
|
|
230659
230785
|
return `value === ${JSON.stringify(type.value)}`;
|
|
230660
|
-
if (type.flags &
|
|
230786
|
+
if (type.flags & ts11.TypeFlags.BooleanLiteral)
|
|
230661
230787
|
return `value === ${checker.typeToString(type)}`;
|
|
230662
|
-
if (type.flags &
|
|
230788
|
+
if (type.flags & ts11.TypeFlags.String)
|
|
230663
230789
|
return 'typeof value === "string"';
|
|
230664
|
-
if (type.flags &
|
|
230790
|
+
if (type.flags & ts11.TypeFlags.Number)
|
|
230665
230791
|
return 'typeof value === "number" && Number.isFinite(value)';
|
|
230666
|
-
if (type.flags &
|
|
230792
|
+
if (type.flags & ts11.TypeFlags.Boolean)
|
|
230667
230793
|
return 'typeof value === "boolean"';
|
|
230668
230794
|
if (type.isUnion())
|
|
230669
230795
|
return type.types.map((part) => `${reference(part)}(value)`).join(" || ");
|
|
@@ -230672,16 +230798,16 @@ function renderGraphqlValidators(source, operationNames) {
|
|
|
230672
230798
|
if (checker.isTupleType(type))
|
|
230673
230799
|
return unsupported(type);
|
|
230674
230800
|
if (checker.isArrayType(type)) {
|
|
230675
|
-
const item = checker.getIndexTypeOfType(type,
|
|
230801
|
+
const item = checker.getIndexTypeOfType(type, ts11.IndexKind.Number);
|
|
230676
230802
|
if (!item)
|
|
230677
230803
|
return unsupported(type);
|
|
230678
230804
|
return `isGraphqlArray(value) && Array.from(value).every(${reference(item)})`;
|
|
230679
230805
|
}
|
|
230680
|
-
if (type.flags &
|
|
230806
|
+
if (type.flags & ts11.TypeFlags.Object) {
|
|
230681
230807
|
if (type.getCallSignatures().length || type.getConstructSignatures().length)
|
|
230682
230808
|
return unsupported(type);
|
|
230683
230809
|
const indexes = checker.getIndexInfosOfType(type);
|
|
230684
|
-
if (indexes.some((index) => !(index.keyType.flags &
|
|
230810
|
+
if (indexes.some((index) => !(index.keyType.flags & ts11.TypeFlags.String)))
|
|
230685
230811
|
return unsupported(type);
|
|
230686
230812
|
const properties = checker.getPropertiesOfType(type).map((property) => {
|
|
230687
230813
|
const declaration = property.valueDeclaration ?? property.declarations?.[0];
|
|
@@ -230690,7 +230816,7 @@ function renderGraphqlValidators(source, operationNames) {
|
|
|
230690
230816
|
const check = reference(checker.getTypeOfSymbolAtLocation(property, declaration));
|
|
230691
230817
|
const key = JSON.stringify(property.name);
|
|
230692
230818
|
const present = `Object.prototype.hasOwnProperty.call(value, ${key})`;
|
|
230693
|
-
return property.flags &
|
|
230819
|
+
return property.flags & ts11.SymbolFlags.Optional ? `(!${present} || ${check}(value[${key}]))` : `(${present} && ${check}(value[${key}]))`;
|
|
230694
230820
|
});
|
|
230695
230821
|
const indexedValues = indexes.map((index) => `Object.values(value).every(${reference(index.type)})`);
|
|
230696
230822
|
return ["isGraphqlRecord(value)", ...properties, ...indexedValues].join(" && ");
|
|
@@ -239882,7 +240008,7 @@ function canonical2(value) {
|
|
|
239882
240008
|
}
|
|
239883
240009
|
function inside2(parent, path) {
|
|
239884
240010
|
const part = relative52(parent, path);
|
|
239885
|
-
return !
|
|
240011
|
+
return !isAbsolute5(part) && part !== ".." && !part.startsWith(`..${sep5}`);
|
|
239886
240012
|
}
|
|
239887
240013
|
async function exists2(path) {
|
|
239888
240014
|
try {
|
|
@@ -239939,7 +240065,7 @@ async function reserveOutput(project, requested) {
|
|
|
239939
240065
|
if (!inside2(project, requested))
|
|
239940
240066
|
throw new Error("Delivery output must be inside the application project.");
|
|
239941
240067
|
const base = await realpath3(project);
|
|
239942
|
-
const path =
|
|
240068
|
+
const path = resolve72(base, relative52(project, requested));
|
|
239943
240069
|
if (relative52(base, path).split(sep5).some((part) => part === ".git" || part === "node_modules")) {
|
|
239944
240070
|
throw new Error("Delivery output cannot use repository or dependency internals.");
|
|
239945
240071
|
}
|
|
@@ -240169,7 +240295,7 @@ function createContextPack(graph, subject) {
|
|
|
240169
240295
|
}
|
|
240170
240296
|
const modules = graph.modules.filter((module) => selected.has(module.name));
|
|
240171
240297
|
const queryDocuments = graph.graphql?.documents.filter((file) => modules.some((module) => {
|
|
240172
|
-
const path =
|
|
240298
|
+
const path = relative62(dirname52(module.file), file);
|
|
240173
240299
|
return path !== ".." && !path.startsWith(`..${sep6}`);
|
|
240174
240300
|
})) ?? [];
|
|
240175
240301
|
const graphql = graph.graphql ? {
|
|
@@ -240205,6 +240331,12 @@ function createContextPack(graph, subject) {
|
|
|
240205
240331
|
routeContracts: inspectRouteContracts({ ...graph, modules }),
|
|
240206
240332
|
...graphql ? { graphql } : {},
|
|
240207
240333
|
diagnostics: (graph.diagnostics ?? []).filter((diagnostic) => diagnostic.file === undefined || files.includes(diagnostic.file)),
|
|
240334
|
+
conventions: {
|
|
240335
|
+
singleResult: "async-await",
|
|
240336
|
+
eventComposition: "rxjs",
|
|
240337
|
+
angularHost: "@supacloud/app/angular",
|
|
240338
|
+
cancellation: "explicit-owner-signal"
|
|
240339
|
+
},
|
|
240208
240340
|
relatedModules: {
|
|
240209
240341
|
imports: subjectModule.imports.filter((name) => selected.has(name)),
|
|
240210
240342
|
importedBy: graph.modules.filter((module) => module.imports.includes(subjectModule.name)).map((module) => module.name).sort()
|
|
@@ -241097,6 +241229,207 @@ var init_src = __esm2(() => {
|
|
|
241097
241229
|
var init_delivery_migration_archive2 = __esm2(() => {
|
|
241098
241230
|
init_src();
|
|
241099
241231
|
});
|
|
241232
|
+
async function applyDiagnosticFix(fix, options = {}) {
|
|
241233
|
+
if (!fix || typeof fix.targetFile !== "string")
|
|
241234
|
+
throw new Error("Invalid DiagnosticFix");
|
|
241235
|
+
const root = await realpath4(options.rootDir ?? process.cwd());
|
|
241236
|
+
const file = resolve122(root, fix.targetFile);
|
|
241237
|
+
const stat = await lstat22(file);
|
|
241238
|
+
const resolved = await realpath4(file);
|
|
241239
|
+
const relativePath = relative8(root, resolved);
|
|
241240
|
+
if (stat.isSymbolicLink() || !stat.isFile() || isAbsolute32(relativePath) || relativePath === ".." || relativePath.startsWith(`..${sep8}`)) {
|
|
241241
|
+
throw new Error("Fix target must be a regular file inside rootDir");
|
|
241242
|
+
}
|
|
241243
|
+
const original = await readFile6(file, "utf8");
|
|
241244
|
+
const sourceHash = createHash8("sha256").update(original).digest("hex");
|
|
241245
|
+
if (options.expectedSourceHash !== undefined && options.expectedSourceHash !== sourceHash) {
|
|
241246
|
+
throw new Error("Fix source changed since preview; analyze the project again");
|
|
241247
|
+
}
|
|
241248
|
+
let source = parse52(file, original);
|
|
241249
|
+
let content;
|
|
241250
|
+
switch (fix.type) {
|
|
241251
|
+
case "set_command_mode": {
|
|
241252
|
+
if (fix.property !== "transaction" && fix.property !== "idempotency" || fix.value !== "required" && fix.value !== "none") {
|
|
241253
|
+
throw new Error("Command mode fix requires an explicit property and policy value");
|
|
241254
|
+
}
|
|
241255
|
+
const object = decoratorObject(findClass(source, fix.command), "Command");
|
|
241256
|
+
const current = property(object, fix.property);
|
|
241257
|
+
if (!current || current.initializer.getText(source) !== fix.expectedExpression) {
|
|
241258
|
+
throw new Error("Command mode changed since diagnosis; analyze the project again");
|
|
241259
|
+
}
|
|
241260
|
+
content = replaceProperty(source, object, fix.property, ts15.factory.createStringLiteral(fix.value));
|
|
241261
|
+
break;
|
|
241262
|
+
}
|
|
241263
|
+
case "add_module_import": {
|
|
241264
|
+
if (!fix.importPath || !fix.symbol)
|
|
241265
|
+
throw new Error("Module fix requires importPath and symbol");
|
|
241266
|
+
identifier2(fix.symbol);
|
|
241267
|
+
const withImport = importSymbol(source, fix.importPath, fix.symbol);
|
|
241268
|
+
source = parse52(file, withImport);
|
|
241269
|
+
const object = unique2(moduleObjects(source).filter((candidate) => !fix.targetModule || stringProperty(candidate, "name") === fix.targetModule), "target module");
|
|
241270
|
+
const imports = property(object, "imports");
|
|
241271
|
+
if (imports && !ts15.isArrayLiteralExpression(imports.initializer)) {
|
|
241272
|
+
throw new Error("Module imports must be a static array");
|
|
241273
|
+
}
|
|
241274
|
+
const values = imports && ts15.isArrayLiteralExpression(imports.initializer) ? imports.initializer.elements : [];
|
|
241275
|
+
if (values.some(ts15.isSpreadElement))
|
|
241276
|
+
throw new Error("Module imports cannot contain spread elements");
|
|
241277
|
+
content = values.some((value) => ts15.isIdentifier(value) && value.text === fix.symbol) ? withImport : replaceProperty(source, object, "imports", ts15.factory.createArrayLiteralExpression([
|
|
241278
|
+
...values,
|
|
241279
|
+
ts15.factory.createIdentifier(fix.symbol)
|
|
241280
|
+
]));
|
|
241281
|
+
break;
|
|
241282
|
+
}
|
|
241283
|
+
case "add_command_permission": {
|
|
241284
|
+
const permission = options.permission ?? fix.permission;
|
|
241285
|
+
if (!permission?.trim()) {
|
|
241286
|
+
throw new Error("Permission fix requires an explicit permission; privileges are never inferred");
|
|
241287
|
+
}
|
|
241288
|
+
const command = findClass(source, fix.command);
|
|
241289
|
+
const object = decoratorObject(command, "Command");
|
|
241290
|
+
const current = property(object, "permission");
|
|
241291
|
+
if (current && (!ts15.isStringLiteral(current.initializer) || current.initializer.text !== permission)) {
|
|
241292
|
+
throw new Error("Command permission already exists with a different value");
|
|
241293
|
+
}
|
|
241294
|
+
content = current ? original : replaceProperty(source, object, "permission", ts15.factory.createStringLiteral(permission));
|
|
241295
|
+
break;
|
|
241296
|
+
}
|
|
241297
|
+
case "add_route_parameter_binding": {
|
|
241298
|
+
const controller = findClass(source, fix.controller);
|
|
241299
|
+
const method = unique2(controller.members.filter((member) => ts15.isMethodDeclaration(member) && nameOf(member.name) === fix.route), "route handler");
|
|
241300
|
+
const parameter = unique2(method.parameters.filter((candidate) => ts15.isIdentifier(candidate.name) && candidate.name.text === fix.parameter), "same-named route parameter");
|
|
241301
|
+
const binding = fix.binding === "param" ? "Param" : fix.binding === "query" ? "Query" : undefined;
|
|
241302
|
+
if (!binding)
|
|
241303
|
+
throw new Error("Invalid route binding");
|
|
241304
|
+
const decorators = ts15.getDecorators(parameter) ?? [];
|
|
241305
|
+
if (decorators.length > 0)
|
|
241306
|
+
throw new Error("Parameter already has a decorator");
|
|
241307
|
+
const framework = unique2(source.statements.filter((statement) => ts15.isImportDeclaration(statement) && statement.importClause?.namedBindings && ts15.isNamedImports(statement.importClause.namedBindings) && statement.importClause.namedBindings.elements.some((element) => ["Controller", "Get", "Post", "Put", "Patch", "Delete", "Head", "Options"].includes(element.name.text))), "framework import");
|
|
241308
|
+
if (!ts15.isImportDeclaration(framework) || !ts15.isStringLiteral(framework.moduleSpecifier)) {
|
|
241309
|
+
throw new Error("Framework import must be static");
|
|
241310
|
+
}
|
|
241311
|
+
const edited = original.slice(0, parameter.getStart(source)) + `@${binding}(${JSON.stringify(fix.parameter)}) ` + original.slice(parameter.getStart(source));
|
|
241312
|
+
content = importSymbol(parse52(file, edited), framework.moduleSpecifier.text, binding);
|
|
241313
|
+
break;
|
|
241314
|
+
}
|
|
241315
|
+
default:
|
|
241316
|
+
throw new Error(`Diagnostic fix '${fix.type}' requires a manual semantic decision; no files changed`);
|
|
241317
|
+
}
|
|
241318
|
+
parse52(file, content);
|
|
241319
|
+
const result = { file, changed: content !== original, content, sourceHash };
|
|
241320
|
+
if (options.dryRun === false && result.changed) {
|
|
241321
|
+
const temporary = `${file}.supacloud-fix-${randomUUID()}`;
|
|
241322
|
+
try {
|
|
241323
|
+
await writeFile3(temporary, content, { encoding: "utf8", flag: "wx", mode: stat.mode });
|
|
241324
|
+
if (await readFile6(file, "utf8") !== original)
|
|
241325
|
+
throw new Error("Target changed while preparing the fix");
|
|
241326
|
+
await rename4(temporary, file);
|
|
241327
|
+
} finally {
|
|
241328
|
+
await unlink2(temporary).catch(() => {});
|
|
241329
|
+
}
|
|
241330
|
+
}
|
|
241331
|
+
return result;
|
|
241332
|
+
}
|
|
241333
|
+
function parse52(file, text) {
|
|
241334
|
+
const result = ts15.transpileModule(text, {
|
|
241335
|
+
fileName: file,
|
|
241336
|
+
reportDiagnostics: true,
|
|
241337
|
+
compilerOptions: { target: ts15.ScriptTarget.ESNext, experimentalDecorators: true }
|
|
241338
|
+
});
|
|
241339
|
+
if (result.diagnostics?.some((item) => item.category === ts15.DiagnosticCategory.Error)) {
|
|
241340
|
+
throw new Error("Cannot fix syntactically invalid TypeScript");
|
|
241341
|
+
}
|
|
241342
|
+
return ts15.createSourceFile(file, text, ts15.ScriptTarget.Latest, true, ts15.ScriptKind.TS);
|
|
241343
|
+
}
|
|
241344
|
+
function unique2(items, description) {
|
|
241345
|
+
if (items.length !== 1)
|
|
241346
|
+
throw new Error(`Expected exactly one ${description}; found ${items.length}`);
|
|
241347
|
+
return items[0];
|
|
241348
|
+
}
|
|
241349
|
+
function identifier2(value) {
|
|
241350
|
+
if (!/^[A-Za-z_$][\w$]*$/.test(value))
|
|
241351
|
+
throw new Error(`Invalid identifier '${value}'`);
|
|
241352
|
+
}
|
|
241353
|
+
function nameOf(name) {
|
|
241354
|
+
if (!name)
|
|
241355
|
+
return "";
|
|
241356
|
+
return ts15.isIdentifier(name) || ts15.isStringLiteral(name) || ts15.isNumericLiteral(name) ? name.text : "";
|
|
241357
|
+
}
|
|
241358
|
+
function property(object, key) {
|
|
241359
|
+
if (object.properties.some((item) => !ts15.isPropertyAssignment(item) || ts15.isComputedPropertyName(item.name))) {
|
|
241360
|
+
throw new Error("Fix requires explicit static object properties");
|
|
241361
|
+
}
|
|
241362
|
+
const values = object.properties.filter((item) => ts15.isPropertyAssignment(item) && nameOf(item.name) === key);
|
|
241363
|
+
if (values.length > 1)
|
|
241364
|
+
throw new Error(`Duplicate '${key}' property`);
|
|
241365
|
+
return values[0];
|
|
241366
|
+
}
|
|
241367
|
+
function stringProperty(object, key) {
|
|
241368
|
+
const value = property(object, key)?.initializer;
|
|
241369
|
+
return value && ts15.isStringLiteral(value) ? value.text : undefined;
|
|
241370
|
+
}
|
|
241371
|
+
function replaceProperty(source, object, key, value) {
|
|
241372
|
+
const previous = property(object, key);
|
|
241373
|
+
const replacement = ts15.factory.createPropertyAssignment(key, value);
|
|
241374
|
+
const properties = object.properties.map((item) => item === previous ? replacement : item);
|
|
241375
|
+
if (!previous)
|
|
241376
|
+
properties.push(replacement);
|
|
241377
|
+
const updated = ts15.factory.updateObjectLiteralExpression(object, properties);
|
|
241378
|
+
return source.text.slice(0, object.getStart(source)) + ts15.createPrinter().printNode(ts15.EmitHint.Expression, updated, source) + source.text.slice(object.end);
|
|
241379
|
+
}
|
|
241380
|
+
function findClass(source, name) {
|
|
241381
|
+
return unique2(source.statements.filter((statement) => ts15.isClassDeclaration(statement) && statement.name?.text === name), `class '${name}'`);
|
|
241382
|
+
}
|
|
241383
|
+
function decoratorObject(node, name) {
|
|
241384
|
+
const decorator = unique2((ts15.getDecorators(node) ?? []).filter((item) => ts15.isCallExpression(item.expression) && item.expression.expression.getText() === name), `@${name} decorator`);
|
|
241385
|
+
const argument = ts15.isCallExpression(decorator.expression) ? decorator.expression.arguments[0] : undefined;
|
|
241386
|
+
if (!argument || !ts15.isObjectLiteralExpression(argument))
|
|
241387
|
+
throw new Error(`@${name} requires a static object`);
|
|
241388
|
+
return argument;
|
|
241389
|
+
}
|
|
241390
|
+
function moduleObjects(source) {
|
|
241391
|
+
const result = [];
|
|
241392
|
+
for (const statement of source.statements) {
|
|
241393
|
+
if (ts15.isClassDeclaration(statement) && (ts15.getDecorators(statement) ?? []).some((item) => ts15.isCallExpression(item.expression) && item.expression.expression.getText() === "Module")) {
|
|
241394
|
+
result.push(decoratorObject(statement, "Module"));
|
|
241395
|
+
}
|
|
241396
|
+
if (ts15.isVariableStatement(statement)) {
|
|
241397
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
241398
|
+
const call = declaration.initializer;
|
|
241399
|
+
if (call && ts15.isCallExpression(call) && ["defineModule", "defineFeatureSlice"].includes(call.expression.getText()) && call.arguments[0] && ts15.isObjectLiteralExpression(call.arguments[0])) {
|
|
241400
|
+
result.push(call.arguments[0]);
|
|
241401
|
+
}
|
|
241402
|
+
}
|
|
241403
|
+
}
|
|
241404
|
+
}
|
|
241405
|
+
return result;
|
|
241406
|
+
}
|
|
241407
|
+
function importSymbol(source, path, symbol) {
|
|
241408
|
+
identifier2(symbol);
|
|
241409
|
+
const current = resolve122(source.fileName).replace(/\.(tsx?|mts|cts)$/, "");
|
|
241410
|
+
const target = resolve122(dirname8(source.fileName), path).replace(/\.(tsx?|mts|cts)$/, "");
|
|
241411
|
+
if (current === target)
|
|
241412
|
+
return source.text;
|
|
241413
|
+
const matches = source.statements.filter((item) => ts15.isImportDeclaration(item) && ts15.isStringLiteral(item.moduleSpecifier) && item.moduleSpecifier.text === path);
|
|
241414
|
+
if (matches.length > 1)
|
|
241415
|
+
throw new Error(`Ambiguous imports from '${path}'`);
|
|
241416
|
+
const match = matches[0];
|
|
241417
|
+
if (match && ts15.isImportDeclaration(match) && match.importClause?.namedBindings && ts15.isNamedImports(match.importClause.namedBindings) && !match.importClause.isTypeOnly) {
|
|
241418
|
+
if (match.importClause.namedBindings.elements.some((item) => item.name.text === symbol))
|
|
241419
|
+
return source.text;
|
|
241420
|
+
const bindings = match.importClause.namedBindings;
|
|
241421
|
+
const updated = ts15.factory.updateNamedImports(bindings, [
|
|
241422
|
+
...bindings.elements,
|
|
241423
|
+
ts15.factory.createImportSpecifier(false, undefined, ts15.factory.createIdentifier(symbol))
|
|
241424
|
+
]);
|
|
241425
|
+
return source.text.slice(0, bindings.getStart(source)) + ts15.createPrinter().printNode(ts15.EmitHint.Unspecified, updated, source) + source.text.slice(bindings.end);
|
|
241426
|
+
}
|
|
241427
|
+
if (match)
|
|
241428
|
+
throw new Error(`Import from '${path}' is not a named value import`);
|
|
241429
|
+
return `import { ${symbol} } from ${JSON.stringify(path)};
|
|
241430
|
+
${source.text}`;
|
|
241431
|
+
}
|
|
241432
|
+
var init_fixes = () => {};
|
|
241100
241433
|
var EXECUTION_CONTEXT_LIMITS;
|
|
241101
241434
|
var ExecutionContextError;
|
|
241102
241435
|
var init_execution_context = __esm2(() => {
|
|
@@ -241217,7 +241550,7 @@ function record3(kind, name, sourceFile, node) {
|
|
|
241217
241550
|
file: sourceFile.fileName,
|
|
241218
241551
|
start: node.getStart(sourceFile),
|
|
241219
241552
|
end: node.end,
|
|
241220
|
-
fingerprint:
|
|
241553
|
+
fingerprint: createHash9("sha1").update(`${kind}:${text}`).digest("hex")
|
|
241221
241554
|
};
|
|
241222
241555
|
}
|
|
241223
241556
|
function decoratorName(decorator) {
|
|
@@ -241289,7 +241622,7 @@ function decoratedDeclaration(decorator) {
|
|
|
241289
241622
|
};
|
|
241290
241623
|
}
|
|
241291
241624
|
function createIncrementalProgramSession(projectRoot) {
|
|
241292
|
-
const rootDir =
|
|
241625
|
+
const rootDir = resolve13(projectRoot);
|
|
241293
241626
|
let projectConfig = readProjectConfig(rootDir);
|
|
241294
241627
|
let projectConfigKey = configKey(projectConfig);
|
|
241295
241628
|
let builder;
|
|
@@ -241318,8 +241651,8 @@ function createIncrementalProgramSession(projectRoot) {
|
|
|
241318
241651
|
}
|
|
241319
241652
|
projectConfig = nextProjectConfig;
|
|
241320
241653
|
projectConfigKey = nextProjectConfigKey;
|
|
241321
|
-
const normalizedRoots = [...new Set(rootNames.map((file) =>
|
|
241322
|
-
const normalizedChanged = [...new Set(changedPaths.map((file) =>
|
|
241654
|
+
const normalizedRoots = [...new Set(rootNames.map((file) => resolve13(rootDir, file)))].sort();
|
|
241655
|
+
const normalizedChanged = [...new Set(changedPaths.map((file) => resolve13(rootDir, file)))];
|
|
241323
241656
|
const invalidatedPaths = new Set(normalizedChanged.map(canonical3));
|
|
241324
241657
|
for (const sourceFile of oldSourceFiles.values()) {
|
|
241325
241658
|
if (sourceVersion(sourceFile.fileName) !== sourceFileVersion(sourceFile)) {
|
|
@@ -241328,10 +241661,10 @@ function createIncrementalProgramSession(projectRoot) {
|
|
|
241328
241661
|
}
|
|
241329
241662
|
const invalidateAllResolutions = configChanged || [...invalidatedPaths].some((fileName) => {
|
|
241330
241663
|
const wasInProgram = oldSourceFiles.has(fileName);
|
|
241331
|
-
return wasInProgram !==
|
|
241664
|
+
return wasInProgram !== existsSync10(fileName);
|
|
241332
241665
|
});
|
|
241333
241666
|
for (const fileName of normalizedChanged) {
|
|
241334
|
-
if (!
|
|
241667
|
+
if (!existsSync10(fileName))
|
|
241335
241668
|
sourceFileCache.delete(canonical3(fileName));
|
|
241336
241669
|
}
|
|
241337
241670
|
const host = createHost(projectConfig.options, rootDir, sourceFileCache, invalidatedPaths, invalidateAllResolutions);
|
|
@@ -241420,7 +241753,7 @@ function createHost(options, rootDir, sourceFileCache, invalidatedPaths, invalid
|
|
|
241420
241753
|
return host;
|
|
241421
241754
|
}
|
|
241422
241755
|
function canonical3(fileName) {
|
|
241423
|
-
const normalized =
|
|
241756
|
+
const normalized = resolve13(fileName);
|
|
241424
241757
|
return ts2.sys.useCaseSensitiveFileNames ? normalized : normalized.toLowerCase();
|
|
241425
241758
|
}
|
|
241426
241759
|
function sourceFileParseKey(languageVersion) {
|
|
@@ -241442,7 +241775,7 @@ function hashText(text) {
|
|
|
241442
241775
|
}
|
|
241443
241776
|
function sourceVersion(fileName) {
|
|
241444
241777
|
try {
|
|
241445
|
-
return hashText(
|
|
241778
|
+
return hashText(readFileSync8(fileName, "utf8"));
|
|
241446
241779
|
} catch {
|
|
241447
241780
|
return "missing";
|
|
241448
241781
|
}
|
|
@@ -241453,7 +241786,7 @@ function sourceFileVersion(sourceFile) {
|
|
|
241453
241786
|
}
|
|
241454
241787
|
function readProjectConfig(rootDir) {
|
|
241455
241788
|
const configPath = join12(rootDir, "tsconfig.json");
|
|
241456
|
-
if (!
|
|
241789
|
+
if (!existsSync10(configPath)) {
|
|
241457
241790
|
return {
|
|
241458
241791
|
options: {
|
|
241459
241792
|
target: ts2.ScriptTarget.ES2022,
|
|
@@ -241491,11 +241824,168 @@ function readProjectConfig(rootDir) {
|
|
|
241491
241824
|
};
|
|
241492
241825
|
}
|
|
241493
241826
|
init_validate();
|
|
241827
|
+
function bindApiSource(source) {
|
|
241828
|
+
const file = resolve22(source.fileName);
|
|
241829
|
+
const bound = ts3.createSourceFile(file, source.text, ts3.ScriptTarget.Latest, true);
|
|
241830
|
+
const options = { noLib: true, noResolve: true, target: ts3.ScriptTarget.ES2022 };
|
|
241831
|
+
const host = {
|
|
241832
|
+
getSourceFile: (name) => resolve22(name) === file ? bound : undefined,
|
|
241833
|
+
getDefaultLibFileName: () => "",
|
|
241834
|
+
writeFile: () => {},
|
|
241835
|
+
getCurrentDirectory: () => process.cwd(),
|
|
241836
|
+
getDirectories: () => [],
|
|
241837
|
+
fileExists: (name) => resolve22(name) === file,
|
|
241838
|
+
readFile: (name) => resolve22(name) === file ? source.text : undefined,
|
|
241839
|
+
getCanonicalFileName: (name) => name,
|
|
241840
|
+
useCaseSensitiveFileNames: () => true,
|
|
241841
|
+
getNewLine: () => `
|
|
241842
|
+
`
|
|
241843
|
+
};
|
|
241844
|
+
const program = ts3.createProgram([file], options, host);
|
|
241845
|
+
return { source: bound, checker: program.getTypeChecker() };
|
|
241846
|
+
}
|
|
241847
|
+
function importedFrom(node) {
|
|
241848
|
+
let current = node;
|
|
241849
|
+
while (current && !ts3.isImportDeclaration(current))
|
|
241850
|
+
current = current.parent;
|
|
241851
|
+
return current && ts3.isImportDeclaration(current) && ts3.isStringLiteral(current.moduleSpecifier) ? current.moduleSpecifier.text : undefined;
|
|
241852
|
+
}
|
|
241853
|
+
function apiOrigin(expression, checker, seen = new Set) {
|
|
241854
|
+
if (seen.has(expression))
|
|
241855
|
+
return;
|
|
241856
|
+
seen.add(expression);
|
|
241857
|
+
if (ts3.isParenthesizedExpression(expression) || ts3.isAsExpression(expression) || ts3.isSatisfiesExpression(expression) || ts3.isTypeAssertionExpression(expression)) {
|
|
241858
|
+
return apiOrigin(expression.expression, checker, seen);
|
|
241859
|
+
}
|
|
241860
|
+
if (ts3.isPropertyAccessExpression(expression) || ts3.isElementAccessExpression(expression)) {
|
|
241861
|
+
const name = ts3.isPropertyAccessExpression(expression) ? expression.name.text : ts3.isStringLiteral(expression.argumentExpression) ? expression.argumentExpression.text : undefined;
|
|
241862
|
+
const namespace = apiOrigin(expression.expression, checker, seen);
|
|
241863
|
+
return namespace?.name === "*" && name ? { module: namespace.module, name } : undefined;
|
|
241864
|
+
}
|
|
241865
|
+
if (!ts3.isIdentifier(expression))
|
|
241866
|
+
return;
|
|
241867
|
+
const symbol = checker.getSymbolAtLocation(expression);
|
|
241868
|
+
for (const declaration of symbol?.declarations ?? []) {
|
|
241869
|
+
if (ts3.isImportSpecifier(declaration) && !declaration.isTypeOnly && !declaration.parent.parent.isTypeOnly) {
|
|
241870
|
+
const module = importedFrom(declaration);
|
|
241871
|
+
if (module)
|
|
241872
|
+
return { module, name: (declaration.propertyName ?? declaration.name).text };
|
|
241873
|
+
}
|
|
241874
|
+
if (ts3.isNamespaceImport(declaration) && !declaration.parent.isTypeOnly) {
|
|
241875
|
+
const module = importedFrom(declaration);
|
|
241876
|
+
if (module)
|
|
241877
|
+
return { module, name: "*" };
|
|
241878
|
+
}
|
|
241879
|
+
if (ts3.isVariableDeclaration(declaration) && declaration.initializer && ts3.isVariableDeclarationList(declaration.parent) && declaration.parent.flags & ts3.NodeFlags.Const) {
|
|
241880
|
+
return apiOrigin(declaration.initializer, checker, seen);
|
|
241881
|
+
}
|
|
241882
|
+
}
|
|
241883
|
+
return;
|
|
241884
|
+
}
|
|
241885
|
+
var angularState = new Set(["@angular/core", "@supacloud/app/angular"]);
|
|
241886
|
+
var signalBridges = new Set(["@angular/core/rxjs-interop", "@supacloud/app/angular", "@supacloud/app/rxjs"]);
|
|
241887
|
+
function scanReactiveSource(input, file) {
|
|
241888
|
+
if (!input.statements.some((node) => ts4.isImportDeclaration(node) && ts4.isStringLiteral(node.moduleSpecifier) && (angularState.has(node.moduleSpecifier.text) || signalBridges.has(node.moduleSpecifier.text))))
|
|
241889
|
+
return [];
|
|
241890
|
+
const { source, checker } = bindApiSource(input);
|
|
241891
|
+
const diagnostics = [];
|
|
241892
|
+
const reported = new Set;
|
|
241893
|
+
const visit = (node, reactive) => {
|
|
241894
|
+
if (ts4.isCallExpression(node)) {
|
|
241895
|
+
const origin = apiOrigin(node.expression, checker);
|
|
241896
|
+
if (reactive && origin && signalBridges.has(origin.module) && ["toSignal", "toScopedSignal", "rxResource"].includes(origin.name) && !reported.has(node.pos)) {
|
|
241897
|
+
reported.add(node.pos);
|
|
241898
|
+
const start = source.getLineAndCharacterOfPosition(node.getStart(source));
|
|
241899
|
+
const end = source.getLineAndCharacterOfPosition(node.end);
|
|
241900
|
+
diagnostics.push({
|
|
241901
|
+
severity: "error",
|
|
241902
|
+
code: "reactive-subscription-in-computation",
|
|
241903
|
+
file,
|
|
241904
|
+
line: start.line + 1,
|
|
241905
|
+
column: start.character,
|
|
241906
|
+
endLine: end.line + 1,
|
|
241907
|
+
endColumn: end.character,
|
|
241908
|
+
message: `${origin.name} creates a subscription inside a reactive computation.`,
|
|
241909
|
+
suggestion: "Create the subscription once in its explicit owner scope, then derive state with computed. Hoisting requires ownership review; no automatic edit is safe.",
|
|
241910
|
+
docsUrl: "https://supacloud.dev/errors/reactive-subscription-in-computation"
|
|
241911
|
+
});
|
|
241912
|
+
}
|
|
241913
|
+
if (origin && angularState.has(origin.module) && ["computed", "effect", "untracked"].includes(origin.name)) {
|
|
241914
|
+
const callback = node.arguments[0];
|
|
241915
|
+
if (callback && (ts4.isArrowFunction(callback) || ts4.isFunctionExpression(callback))) {
|
|
241916
|
+
visit(callback.body, origin.name === "untracked" ? false : true);
|
|
241917
|
+
for (const argument of node.arguments.slice(1))
|
|
241918
|
+
visit(argument, reactive);
|
|
241919
|
+
return;
|
|
241920
|
+
}
|
|
241921
|
+
}
|
|
241922
|
+
let expression = node.expression;
|
|
241923
|
+
while (ts4.isParenthesizedExpression(expression))
|
|
241924
|
+
expression = expression.expression;
|
|
241925
|
+
if (ts4.isArrowFunction(expression) || ts4.isFunctionExpression(expression))
|
|
241926
|
+
visit(expression.body, reactive);
|
|
241927
|
+
}
|
|
241928
|
+
if (ts4.isFunctionLike(node)) {
|
|
241929
|
+
if (!reactive)
|
|
241930
|
+
ts4.forEachChild(node, (child) => visit(child, false));
|
|
241931
|
+
return;
|
|
241932
|
+
}
|
|
241933
|
+
ts4.forEachChild(node, (child) => visit(child, reactive));
|
|
241934
|
+
};
|
|
241935
|
+
visit(source, false);
|
|
241936
|
+
return diagnostics;
|
|
241937
|
+
}
|
|
241938
|
+
function providerArgument(node, checker) {
|
|
241939
|
+
let current = node;
|
|
241940
|
+
while (ts5.isParenthesizedExpression(current.parent))
|
|
241941
|
+
current = current.parent;
|
|
241942
|
+
if (!ts5.isCallExpression(current.parent) || current.parent.expression !== current)
|
|
241943
|
+
return false;
|
|
241944
|
+
current = current.parent;
|
|
241945
|
+
while (ts5.isParenthesizedExpression(current.parent))
|
|
241946
|
+
current = current.parent;
|
|
241947
|
+
const parent = current.parent;
|
|
241948
|
+
if (!ts5.isCallExpression(parent) || !parent.arguments.some((argument) => argument === current))
|
|
241949
|
+
return false;
|
|
241950
|
+
const owner = apiOrigin(parent.expression, checker);
|
|
241951
|
+
return owner?.name === "provideHttpClient" && ["@supacloud/app", "@supacloud/app/http"].includes(owner.module);
|
|
241952
|
+
}
|
|
241953
|
+
function scanHttpProviderImports(source, file) {
|
|
241954
|
+
if (!source.text.includes("@supacloud/app"))
|
|
241955
|
+
return [];
|
|
241956
|
+
const { source: sf, checker } = bindApiSource(source);
|
|
241957
|
+
const diagnostics = [];
|
|
241958
|
+
const visit = (node) => {
|
|
241959
|
+
if (ts5.isCallExpression(node)) {
|
|
241960
|
+
const origin = apiOrigin(node.expression, checker);
|
|
241961
|
+
if (origin?.module === "@supacloud/app" && origin.name === "withInterceptors" && providerArgument(node.expression, checker)) {
|
|
241962
|
+
const start = sf.getLineAndCharacterOfPosition(node.getStart(sf));
|
|
241963
|
+
const end = sf.getLineAndCharacterOfPosition(node.end);
|
|
241964
|
+
diagnostics.push({
|
|
241965
|
+
severity: "error",
|
|
241966
|
+
code: "http-provider-import-mismatch",
|
|
241967
|
+
file,
|
|
241968
|
+
line: start.line + 1,
|
|
241969
|
+
column: start.character,
|
|
241970
|
+
endLine: end.line + 1,
|
|
241971
|
+
endColumn: end.character,
|
|
241972
|
+
message: "The root withInterceptors returns an interceptor array, not a provideHttpClient feature.",
|
|
241973
|
+
suggestion: "Import withInterceptors from @supacloud/app/http. Preview the http-provider-entrypoint source migration; mixed/namespace uses require manual review.",
|
|
241974
|
+
docsUrl: "https://supacloud.dev/errors/http-provider-import-mismatch"
|
|
241975
|
+
});
|
|
241976
|
+
}
|
|
241977
|
+
}
|
|
241978
|
+
ts5.forEachChild(node, visit);
|
|
241979
|
+
};
|
|
241980
|
+
visit(sf);
|
|
241981
|
+
return diagnostics;
|
|
241982
|
+
}
|
|
241494
241983
|
var runtimeApis = new Set([
|
|
241495
241984
|
"inject",
|
|
241496
241985
|
"createEnvironmentInjector",
|
|
241497
241986
|
"runInInjectionContext",
|
|
241498
241987
|
"EnvironmentInjector",
|
|
241988
|
+
"Injector",
|
|
241499
241989
|
"bootstrapBun",
|
|
241500
241990
|
"runInScope",
|
|
241501
241991
|
"runInRequestContext",
|
|
@@ -241505,25 +241995,33 @@ var runtimeApis = new Set([
|
|
|
241505
241995
|
function scanRuntimeDi(source, file) {
|
|
241506
241996
|
const diagnostics = [];
|
|
241507
241997
|
const namespaces = new Set;
|
|
241508
|
-
const report = (node) =>
|
|
241509
|
-
|
|
241510
|
-
|
|
241511
|
-
|
|
241512
|
-
|
|
241513
|
-
|
|
241514
|
-
|
|
241515
|
-
|
|
241516
|
-
|
|
241998
|
+
const report = (node) => {
|
|
241999
|
+
const start = source.getLineAndCharacterOfPosition(node.getStart());
|
|
242000
|
+
const end = source.getLineAndCharacterOfPosition(node.end);
|
|
242001
|
+
diagnostics.push({
|
|
242002
|
+
severity: "error",
|
|
242003
|
+
code: "runtime-injection-disallowed",
|
|
242004
|
+
errorCode: "SC2012",
|
|
242005
|
+
docsUrl: "https://supacloud.dev/errors/SC2012",
|
|
242006
|
+
file,
|
|
242007
|
+
line: start.line + 1,
|
|
242008
|
+
column: start.character,
|
|
242009
|
+
endLine: end.line + 1,
|
|
242010
|
+
endColumn: end.character,
|
|
242011
|
+
message: "Compiled applications cannot import runtime DI. Use explicit constructors and generated scope factories.",
|
|
242012
|
+
suggestion: "Use constructor dependencies and generated request/job factories. Keep Angular runtime services outside the compiled application source root."
|
|
242013
|
+
});
|
|
242014
|
+
};
|
|
241517
242015
|
for (const statement of source.statements) {
|
|
241518
|
-
if (!(
|
|
242016
|
+
if (!(ts6.isImportDeclaration(statement) || ts6.isExportDeclaration(statement)) || !statement.moduleSpecifier || !ts6.isStringLiteral(statement.moduleSpecifier) || !(/^@supacloud\/app(?:\/|$)/.test(statement.moduleSpecifier.text) || statement.moduleSpecifier.text === "@angular/core"))
|
|
241519
242017
|
continue;
|
|
241520
|
-
if (
|
|
242018
|
+
if (ts6.isImportDeclaration(statement)) {
|
|
241521
242019
|
if (statement.importClause?.isTypeOnly)
|
|
241522
242020
|
continue;
|
|
241523
242021
|
const binding = statement.importClause?.namedBindings;
|
|
241524
|
-
if (binding &&
|
|
242022
|
+
if (binding && ts6.isNamespaceImport(binding))
|
|
241525
242023
|
namespaces.add(binding.name.text);
|
|
241526
|
-
if (binding &&
|
|
242024
|
+
if (binding && ts6.isNamedImports(binding))
|
|
241527
242025
|
for (const item of binding.elements) {
|
|
241528
242026
|
if (!item.isTypeOnly && runtimeApis.has((item.propertyName ?? item.name).text))
|
|
241529
242027
|
report(item);
|
|
@@ -241531,24 +242029,29 @@ function scanRuntimeDi(source, file) {
|
|
|
241531
242029
|
} else if (!statement.isTypeOnly) {
|
|
241532
242030
|
if (!statement.exportClause)
|
|
241533
242031
|
report(statement);
|
|
241534
|
-
else if (
|
|
242032
|
+
else if (ts6.isNamedExports(statement.exportClause))
|
|
241535
242033
|
for (const item of statement.exportClause.elements) {
|
|
241536
242034
|
if (!item.isTypeOnly && runtimeApis.has((item.propertyName ?? item.name).text))
|
|
241537
242035
|
report(item);
|
|
241538
242036
|
}
|
|
241539
242037
|
}
|
|
241540
242038
|
}
|
|
241541
|
-
|
|
241542
|
-
|
|
241543
|
-
|
|
241544
|
-
|
|
241545
|
-
|
|
241546
|
-
|
|
241547
|
-
|
|
241548
|
-
|
|
241549
|
-
|
|
241550
|
-
|
|
241551
|
-
|
|
242039
|
+
if (namespaces.size > 0) {
|
|
242040
|
+
const bound = bindApiSource(source);
|
|
242041
|
+
const protectedNamespace = (expression) => {
|
|
242042
|
+
const origin = apiOrigin(expression, bound.checker);
|
|
242043
|
+
return origin?.name === "*" && (origin.module === "@angular/core" || /^@supacloud\/app(?:\/|$)/.test(origin.module));
|
|
242044
|
+
};
|
|
242045
|
+
const visit = (node) => {
|
|
242046
|
+
if (ts6.isPropertyAccessExpression(node) && protectedNamespace(node.expression) && runtimeApis.has(node.name.text))
|
|
242047
|
+
report(node);
|
|
242048
|
+
if (ts6.isElementAccessExpression(node) && protectedNamespace(node.expression) && (!ts6.isStringLiteral(node.argumentExpression) || runtimeApis.has(node.argumentExpression.text)))
|
|
242049
|
+
report(node);
|
|
242050
|
+
ts6.forEachChild(node, visit);
|
|
242051
|
+
};
|
|
242052
|
+
visit(bound.source);
|
|
242053
|
+
}
|
|
242054
|
+
return [...diagnostics, ...scanReactiveSource(source, file), ...scanHttpProviderImports(source, file)];
|
|
241552
242055
|
}
|
|
241553
242056
|
var DEFAULT_INCLUDE = ["**/*.module.ts", "**/*.ts"];
|
|
241554
242057
|
var ROUTE_DECORATORS = {
|
|
@@ -241597,36 +242100,39 @@ function lineOf(node) {
|
|
|
241597
242100
|
return sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;
|
|
241598
242101
|
}
|
|
241599
242102
|
function variableName3(decl) {
|
|
241600
|
-
return
|
|
242103
|
+
return ts7.isIdentifier(decl.name) ? decl.name.text : nodeText(decl.name);
|
|
241601
242104
|
}
|
|
241602
242105
|
function propertyName(name) {
|
|
241603
|
-
if (
|
|
242106
|
+
if (ts7.isIdentifier(name) || ts7.isPrivateIdentifier(name))
|
|
241604
242107
|
return name.text;
|
|
241605
|
-
if (
|
|
242108
|
+
if (ts7.isStringLiteral(name) || ts7.isNumericLiteral(name))
|
|
241606
242109
|
return name.text;
|
|
241607
242110
|
return nodeText(name);
|
|
241608
242111
|
}
|
|
241609
242112
|
function parameterName(param) {
|
|
241610
|
-
return
|
|
242113
|
+
return ts7.isIdentifier(param.name) ? param.name.text : nodeText(param.name);
|
|
241611
242114
|
}
|
|
241612
242115
|
function decoratorsOf(node) {
|
|
241613
|
-
return
|
|
242116
|
+
return ts7.canHaveDecorators(node) ? ts7.getDecorators(node) ?? [] : [];
|
|
241614
242117
|
}
|
|
241615
242118
|
function decoratorArguments(dec) {
|
|
241616
|
-
return
|
|
242119
|
+
return ts7.isCallExpression(dec.expression) ? dec.expression.arguments : [];
|
|
241617
242120
|
}
|
|
241618
242121
|
function hasMethod(cls, name) {
|
|
241619
|
-
return cls.members.some((member) => (
|
|
242122
|
+
return cls.members.some((member) => (ts7.isMethodDeclaration(member) || ts7.isGetAccessorDeclaration(member) || ts7.isSetAccessorDeclaration(member)) && member.name !== undefined && propertyName(member.name) === name);
|
|
241620
242123
|
}
|
|
241621
242124
|
function hasDestroyHook(cls) {
|
|
241622
242125
|
return hasMethod(cls, "onDestroy") || hasMethod(cls, "ngOnDestroy");
|
|
241623
242126
|
}
|
|
242127
|
+
function hasInitHook(cls) {
|
|
242128
|
+
return hasMethod(cls, "onInit");
|
|
242129
|
+
}
|
|
241624
242130
|
function descendantsOfKind(root, predicate) {
|
|
241625
242131
|
const result = [];
|
|
241626
242132
|
const visit = (node) => {
|
|
241627
242133
|
if (predicate(node))
|
|
241628
242134
|
result.push(node);
|
|
241629
|
-
|
|
242135
|
+
ts7.forEachChild(node, visit);
|
|
241630
242136
|
};
|
|
241631
242137
|
visit(root);
|
|
241632
242138
|
return result;
|
|
@@ -241635,7 +242141,7 @@ async function analyzeProject(rootDir, include, cache, changedPaths) {
|
|
|
241635
242141
|
const session = cache?.programSession ?? createIncrementalProgramSession(rootDir);
|
|
241636
242142
|
if (cache)
|
|
241637
242143
|
cache.programSession = session;
|
|
241638
|
-
const rootNames =
|
|
242144
|
+
const rootNames = ts7.sys.readDirectory(rootDir, [".ts", ".tsx"], ["node_modules", "dist"], include ?? DEFAULT_INCLUDE);
|
|
241639
242145
|
const update = session.update(rootNames, changedPaths);
|
|
241640
242146
|
const program = update.program;
|
|
241641
242147
|
const checker = program.getTypeChecker();
|
|
@@ -241671,7 +242177,7 @@ async function analyzeProject(rootDir, include, cache, changedPaths) {
|
|
|
241671
242177
|
for (const sf of sourceFiles) {
|
|
241672
242178
|
const traits = nativeTraitFiles.get(sf.fileName);
|
|
241673
242179
|
if (!cache || traits?.has("module")) {
|
|
241674
|
-
for (const cls of sf.statements.filter(
|
|
242180
|
+
for (const cls of sf.statements.filter(ts7.isClassDeclaration)) {
|
|
241675
242181
|
const moduleDec = findDecorator(cls, "Module");
|
|
241676
242182
|
if (!moduleDec)
|
|
241677
242183
|
continue;
|
|
@@ -241688,14 +242194,14 @@ async function analyzeProject(rootDir, include, cache, changedPaths) {
|
|
|
241688
242194
|
}
|
|
241689
242195
|
}
|
|
241690
242196
|
if (!cache || traits?.has("defineModule") || traits?.has("defineFeatureSlice")) {
|
|
241691
|
-
for (const call of descendantsOfKind(sf,
|
|
242197
|
+
for (const call of descendantsOfKind(sf, ts7.isCallExpression)) {
|
|
241692
242198
|
if (!["defineModule", "defineFeatureSlice"].includes(nodeText(call.expression)))
|
|
241693
242199
|
continue;
|
|
241694
242200
|
const parent = call.parent;
|
|
241695
|
-
if (!parent || !
|
|
242201
|
+
if (!parent || !ts7.isVariableDeclaration(parent))
|
|
241696
242202
|
continue;
|
|
241697
242203
|
const arg = call.arguments[0];
|
|
241698
|
-
if (!arg || !
|
|
242204
|
+
if (!arg || !ts7.isObjectLiteralExpression(arg))
|
|
241699
242205
|
continue;
|
|
241700
242206
|
candidates.push({
|
|
241701
242207
|
node: parent,
|
|
@@ -241831,6 +242337,7 @@ async function analyzeProject(rootDir, include, cache, changedPaths) {
|
|
|
241831
242337
|
...functionalInjects.length > 0 ? { functionalInjects } : {},
|
|
241832
242338
|
providedIn: "root",
|
|
241833
242339
|
...hasDestroyHook(classInfo.decl) ? { hasOnDestroy: true } : {},
|
|
242340
|
+
...hasInitHook(classInfo.decl) ? { hasOnInit: true } : {},
|
|
241834
242341
|
exported: true,
|
|
241835
242342
|
file,
|
|
241836
242343
|
line,
|
|
@@ -241842,7 +242349,7 @@ async function analyzeProject(rootDir, include, cache, changedPaths) {
|
|
|
241842
242349
|
const controllerDec = findDecorator(classInfo.decl, "Controller");
|
|
241843
242350
|
if (controllerDec) {
|
|
241844
242351
|
const arg = decoratorArguments(controllerDec)[0];
|
|
241845
|
-
const isStandalone = arg &&
|
|
242352
|
+
const isStandalone = arg && ts7.isObjectLiteralExpression(arg) && booleanProp(arg, "standalone");
|
|
241846
242353
|
if (isStandalone) {
|
|
241847
242354
|
const ctrl = parseController(classInfo.decl, ctx);
|
|
241848
242355
|
if (ctrl)
|
|
@@ -242002,16 +242509,16 @@ function collectModuleSourceClosure(module, ctx) {
|
|
|
242002
242509
|
ownedFiles.add(relativeFile);
|
|
242003
242510
|
for (const statement of sourceFile.statements) {
|
|
242004
242511
|
let moduleName;
|
|
242005
|
-
if (
|
|
242512
|
+
if (ts7.isImportDeclaration(statement) && ts7.isStringLiteral(statement.moduleSpecifier)) {
|
|
242006
242513
|
moduleName = statement.moduleSpecifier.text;
|
|
242007
|
-
} else if (
|
|
242514
|
+
} else if (ts7.isExportDeclaration(statement) && statement.moduleSpecifier && ts7.isStringLiteral(statement.moduleSpecifier)) {
|
|
242008
242515
|
moduleName = statement.moduleSpecifier.text;
|
|
242009
|
-
} else if (
|
|
242516
|
+
} else if (ts7.isImportEqualsDeclaration(statement) && ts7.isExternalModuleReference(statement.moduleReference) && ts7.isStringLiteral(statement.moduleReference.expression)) {
|
|
242010
242517
|
moduleName = statement.moduleReference.expression.text;
|
|
242011
242518
|
}
|
|
242012
242519
|
if (!moduleName || moduleName.startsWith("node:"))
|
|
242013
242520
|
continue;
|
|
242014
|
-
const resolved =
|
|
242521
|
+
const resolved = ts7.resolveModuleName(moduleName, sourceFile.fileName, ctx.program.getCompilerOptions(), ts7.sys).resolvedModule?.resolvedFileName;
|
|
242015
242522
|
if (resolved && isProjectSourcePath(resolved, ctx.rootDir) && !enqueued.has(resolved)) {
|
|
242016
242523
|
enqueued.add(resolved);
|
|
242017
242524
|
queue.push(resolved);
|
|
@@ -242033,7 +242540,7 @@ function isProjectSourceFile(sourceFile, rootDir) {
|
|
|
242033
242540
|
return isProjectSourcePath(sourceFile.fileName, rootDir) && /\.(tsx?|mts|cts)$/.test(sourceFile.fileName);
|
|
242034
242541
|
}
|
|
242035
242542
|
function indexFile(sf, ctx) {
|
|
242036
|
-
for (const cls of sf.statements.filter(
|
|
242543
|
+
for (const cls of sf.statements.filter(ts7.isClassDeclaration)) {
|
|
242037
242544
|
const name = cls.name?.text;
|
|
242038
242545
|
if (name && !ctx.classesByName.has(name)) {
|
|
242039
242546
|
ctx.classesByName.set(name, { name, decl: cls, file: sf.fileName });
|
|
@@ -242041,9 +242548,9 @@ function indexFile(sf, ctx) {
|
|
|
242041
242548
|
if (name)
|
|
242042
242549
|
indexInfraResource(cls, name, sf, ctx);
|
|
242043
242550
|
}
|
|
242044
|
-
for (const statement of sf.statements.filter(
|
|
242551
|
+
for (const statement of sf.statements.filter(ts7.isVariableStatement)) {
|
|
242045
242552
|
for (const decl of statement.declarationList.declarations) {
|
|
242046
|
-
if (
|
|
242553
|
+
if (ts7.isIdentifier(decl.name) && !ctx.variablesByName.has(decl.name.text)) {
|
|
242047
242554
|
ctx.variablesByName.set(decl.name.text, decl);
|
|
242048
242555
|
}
|
|
242049
242556
|
const info = parseTokenVariable(decl, sf.fileName);
|
|
@@ -242055,16 +242562,16 @@ function indexFile(sf, ctx) {
|
|
|
242055
242562
|
}
|
|
242056
242563
|
function parseTokenVariable(decl, file) {
|
|
242057
242564
|
const init = decl.initializer;
|
|
242058
|
-
if (!init || !
|
|
242565
|
+
if (!init || !ts7.isNewExpression(init))
|
|
242059
242566
|
return;
|
|
242060
242567
|
if (nodeText(init.expression) !== "InjectionToken")
|
|
242061
242568
|
return;
|
|
242062
242569
|
const [nameArg, optionsArg] = init.arguments ?? [];
|
|
242063
242570
|
const info = { name: variableName3(decl), file, line: lineOf(decl) };
|
|
242064
|
-
if (nameArg &&
|
|
242571
|
+
if (nameArg && ts7.isStringLiteral(nameArg)) {
|
|
242065
242572
|
info.stringName = nameArg.text;
|
|
242066
242573
|
}
|
|
242067
|
-
if (optionsArg &&
|
|
242574
|
+
if (optionsArg && ts7.isObjectLiteralExpression(optionsArg)) {
|
|
242068
242575
|
const scope = stringLiteralProp(optionsArg, "scope");
|
|
242069
242576
|
if (scope && isScope(scope)) {
|
|
242070
242577
|
info.scope = scope;
|
|
@@ -242084,23 +242591,23 @@ function parseModule(candidate, nameByNode, ctx) {
|
|
|
242084
242591
|
const { options, className, file, line } = candidate;
|
|
242085
242592
|
const name = nameByNode.get(candidate.node) ?? className;
|
|
242086
242593
|
const featureSpec = parseFeatureSpec(getProp(options, "spec"), ctx);
|
|
242087
|
-
const tags = arrayProp(options, "tags").map((el) =>
|
|
242594
|
+
const tags = arrayProp(options, "tags").map((el) => ts7.isStringLiteral(el) ? el.text : nodeText(el).replace(/['"]/g, "")).filter(Boolean);
|
|
242088
242595
|
const aspects = parseAspectRefs(getProp(options, "aspects"), ctx, `module ${name}`);
|
|
242089
242596
|
const moduleResourceNames = parseModuleInfraResources(infraResourceProp(options, "resources", ctx), ctx, `module ${name}`, sourcePath(ctx.rootDir, file), line);
|
|
242090
242597
|
const imports = arrayProp(options, "imports").map((el) => {
|
|
242091
242598
|
const unwrapped = unwrapForwardRef(el);
|
|
242092
|
-
const decl =
|
|
242599
|
+
const decl = ts7.isIdentifier(unwrapped) ? resolveDeclaration(unwrapped, ctx)[0] : undefined;
|
|
242093
242600
|
if (decl) {
|
|
242094
242601
|
const known = nameByNode.get(decl);
|
|
242095
242602
|
if (known)
|
|
242096
242603
|
return known;
|
|
242097
|
-
if (
|
|
242604
|
+
if (ts7.isClassDeclaration(decl)) {
|
|
242098
242605
|
const dec = findDecorator(decl, "Module");
|
|
242099
242606
|
const decOptions = dec && decoratorObjectArg(dec);
|
|
242100
242607
|
const decName = decOptions && stringLiteralProp(decOptions, "name");
|
|
242101
242608
|
return decName ?? decl.name?.text ?? nodeText(el);
|
|
242102
242609
|
}
|
|
242103
|
-
if (
|
|
242610
|
+
if (ts7.isVariableDeclaration(decl))
|
|
242104
242611
|
return variableName3(decl);
|
|
242105
242612
|
}
|
|
242106
242613
|
return nodeText(el);
|
|
@@ -242114,7 +242621,7 @@ function parseModule(candidate, nameByNode, ctx) {
|
|
|
242114
242621
|
providers.push(...parsedProviders);
|
|
242115
242622
|
continue;
|
|
242116
242623
|
}
|
|
242117
|
-
if (
|
|
242624
|
+
if (ts7.isCallExpression(el)) {
|
|
242118
242625
|
const helper = nodeText(el.expression).split(".").pop() ?? nodeText(el.expression);
|
|
242119
242626
|
warn(ctx, "unsupported-provider-helper", `无法静态展开 provider helper '${helper}';请改用显式 Provider 或实现编译器支持的 helper`, sourcePath(ctx.rootDir, el.getSourceFile().fileName), lineOf(el));
|
|
242120
242627
|
continue;
|
|
@@ -242124,10 +242631,10 @@ function parseModule(candidate, nameByNode, ctx) {
|
|
|
242124
242631
|
providers.push(provider);
|
|
242125
242632
|
}
|
|
242126
242633
|
for (const el of arrayProp(options, "jobs")) {
|
|
242127
|
-
if (!
|
|
242634
|
+
if (!ts7.isIdentifier(el))
|
|
242128
242635
|
continue;
|
|
242129
242636
|
const decl = resolveDeclaration(el, ctx)[0];
|
|
242130
|
-
if (!decl || !
|
|
242637
|
+
if (!decl || !ts7.isClassDeclaration(decl))
|
|
242131
242638
|
continue;
|
|
242132
242639
|
const className = decl.name?.text ?? el.text;
|
|
242133
242640
|
const registeredProvider = providers.find((provider) => provider.token === className || provider.useClass === className);
|
|
@@ -242149,6 +242656,7 @@ function parseModule(candidate, nameByNode, ctx) {
|
|
|
242149
242656
|
...deps.hostDeps.length > 0 ? { hostDeps: deps.hostDeps } : {},
|
|
242150
242657
|
...deps.functionalInjects.length > 0 ? { functionalInjects: deps.functionalInjects } : {},
|
|
242151
242658
|
...hasDestroyHook(decl) ? { hasOnDestroy: true } : {},
|
|
242659
|
+
...hasInitHook(decl) ? { hasOnInit: true } : {},
|
|
242152
242660
|
exported: exportsSet.has(className),
|
|
242153
242661
|
file: sourcePath(ctx.rootDir, decl.getSourceFile().fileName),
|
|
242154
242662
|
line: lineOf(decl),
|
|
@@ -242164,18 +242672,18 @@ function parseModule(candidate, nameByNode, ctx) {
|
|
|
242164
242672
|
const handlerClasses = [];
|
|
242165
242673
|
const seenHandlers = new Set;
|
|
242166
242674
|
const collectHandler = (expr) => {
|
|
242167
|
-
if (!
|
|
242675
|
+
if (!ts7.isIdentifier(expr))
|
|
242168
242676
|
return;
|
|
242169
242677
|
const decl = resolveDeclaration(expr, ctx)[0];
|
|
242170
|
-
if (decl &&
|
|
242678
|
+
if (decl && ts7.isClassDeclaration(decl) && !seenHandlers.has(decl.name?.text ?? "")) {
|
|
242171
242679
|
seenHandlers.add(decl.name?.text ?? "");
|
|
242172
242680
|
handlerClasses.push(decl);
|
|
242173
242681
|
}
|
|
242174
242682
|
};
|
|
242175
242683
|
for (const el of arrayProp(options, "providers")) {
|
|
242176
|
-
if (
|
|
242684
|
+
if (ts7.isIdentifier(el))
|
|
242177
242685
|
collectHandler(el);
|
|
242178
|
-
if (
|
|
242686
|
+
if (ts7.isObjectLiteralExpression(el)) {
|
|
242179
242687
|
const useClass = getProp(el, "useClass");
|
|
242180
242688
|
if (useClass)
|
|
242181
242689
|
collectHandler(useClass);
|
|
@@ -242284,17 +242792,17 @@ function parseFeatureSpec(input, ctx, seen = new Set) {
|
|
|
242284
242792
|
if (seen.has(input))
|
|
242285
242793
|
return;
|
|
242286
242794
|
seen.add(input);
|
|
242287
|
-
if (
|
|
242288
|
-
const local = input.getSourceFile().statements.flatMap((statement) =>
|
|
242795
|
+
if (ts7.isIdentifier(input)) {
|
|
242796
|
+
const local = input.getSourceFile().statements.flatMap((statement) => ts7.isVariableStatement(statement) ? [...statement.declarationList.declarations] : []);
|
|
242289
242797
|
const resolved = resolveDeclaration(input, ctx)[0];
|
|
242290
|
-
const decl = (resolved &&
|
|
242291
|
-
if (decl &&
|
|
242798
|
+
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);
|
|
242799
|
+
if (decl && ts7.isVariableDeclaration(decl))
|
|
242292
242800
|
return parseFeatureSpec(decl.initializer, ctx, seen);
|
|
242293
242801
|
}
|
|
242294
|
-
if (
|
|
242802
|
+
if (ts7.isCallExpression(input) && nodeText(input.expression) === "defineFeatureSpec") {
|
|
242295
242803
|
return parseFeatureSpec(input.arguments[0], ctx, seen);
|
|
242296
242804
|
}
|
|
242297
|
-
if (
|
|
242805
|
+
if (ts7.isAsExpression(input) || ts7.isSatisfiesExpression(input) || ts7.isParenthesizedExpression(input)) {
|
|
242298
242806
|
return parseFeatureSpec(input.expression, ctx, seen);
|
|
242299
242807
|
}
|
|
242300
242808
|
const invalid = () => {
|
|
@@ -242307,28 +242815,28 @@ function parseFeatureSpec(input, ctx, seen = new Set) {
|
|
|
242307
242815
|
});
|
|
242308
242816
|
return;
|
|
242309
242817
|
};
|
|
242310
|
-
if (!
|
|
242818
|
+
if (!ts7.isObjectLiteralExpression(input))
|
|
242311
242819
|
return invalid();
|
|
242312
242820
|
const name = stringLiteralProp(input, "name");
|
|
242313
242821
|
const statesExpr = getProp(input, "states");
|
|
242314
242822
|
const transitionObject = getProp(input, "transitions");
|
|
242315
|
-
if (!name || !statesExpr || !
|
|
242823
|
+
if (!name || !statesExpr || !ts7.isArrayLiteralExpression(statesExpr) || statesExpr.elements.some((state) => !ts7.isStringLiteral(state)) || !transitionObject || !ts7.isObjectLiteralExpression(transitionObject) || input.properties.some((property) => !ts7.isPropertyAssignment(property))) {
|
|
242316
242824
|
return invalid();
|
|
242317
242825
|
}
|
|
242318
242826
|
const states = [];
|
|
242319
242827
|
for (const state of statesExpr.elements) {
|
|
242320
|
-
if (!
|
|
242828
|
+
if (!ts7.isStringLiteral(state))
|
|
242321
242829
|
return invalid();
|
|
242322
242830
|
states.push(state.text);
|
|
242323
242831
|
}
|
|
242324
242832
|
const transitions = [];
|
|
242325
242833
|
for (const property of transitionObject.properties) {
|
|
242326
|
-
if (!
|
|
242834
|
+
if (!ts7.isPropertyAssignment(property) || ts7.isComputedPropertyName(property.name) || !ts7.isObjectLiteralExpression(property.initializer))
|
|
242327
242835
|
return invalid();
|
|
242328
242836
|
const options = property.initializer;
|
|
242329
242837
|
const from = stringLiteralProp(options, "from");
|
|
242330
242838
|
const to = stringLiteralProp(options, "to");
|
|
242331
|
-
if (!from || !to || options.properties.some((prop) => !
|
|
242839
|
+
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))) {
|
|
242332
242840
|
return invalid();
|
|
242333
242841
|
}
|
|
242334
242842
|
const permission = stringLiteralProp(options, "permission");
|
|
@@ -242355,21 +242863,21 @@ function resolveStaticObjectLiteral(input, ctx, seen = new Set) {
|
|
|
242355
242863
|
if (!input || seen.has(input))
|
|
242356
242864
|
return;
|
|
242357
242865
|
seen.add(input);
|
|
242358
|
-
if (
|
|
242866
|
+
if (ts7.isAsExpression(input) || ts7.isSatisfiesExpression(input) || ts7.isParenthesizedExpression(input)) {
|
|
242359
242867
|
return resolveStaticObjectLiteral(input.expression, ctx, seen);
|
|
242360
242868
|
}
|
|
242361
|
-
if (
|
|
242362
|
-
const declaration = resolveDeclaration(input, ctx).find(
|
|
242869
|
+
if (ts7.isIdentifier(input)) {
|
|
242870
|
+
const declaration = resolveDeclaration(input, ctx).find(ts7.isVariableDeclaration);
|
|
242363
242871
|
return declaration?.initializer ? resolveStaticObjectLiteral(declaration.initializer, ctx, seen) : undefined;
|
|
242364
242872
|
}
|
|
242365
|
-
if (
|
|
242873
|
+
if (ts7.isCallExpression(input)) {
|
|
242366
242874
|
const expressionName = nodeText(input.expression);
|
|
242367
242875
|
if (expressionName === "defineRouteContract" || expressionName.endsWith(".defineRouteContract")) {
|
|
242368
242876
|
return resolveStaticObjectLiteral(input.arguments[0], ctx, seen);
|
|
242369
242877
|
}
|
|
242370
242878
|
return;
|
|
242371
242879
|
}
|
|
242372
|
-
return
|
|
242880
|
+
return ts7.isObjectLiteralExpression(input) ? input : undefined;
|
|
242373
242881
|
}
|
|
242374
242882
|
function routePolicyProperty(object, name, ctx, seen = new Set) {
|
|
242375
242883
|
if (seen.has(object))
|
|
@@ -242377,15 +242885,15 @@ function routePolicyProperty(object, name, ctx, seen = new Set) {
|
|
|
242377
242885
|
const ancestry = new Set(seen).add(object);
|
|
242378
242886
|
let result = { unresolved: false };
|
|
242379
242887
|
for (const property of object.properties) {
|
|
242380
|
-
if (
|
|
242888
|
+
if (ts7.isSpreadAssignment(property)) {
|
|
242381
242889
|
const spread = resolveStaticObjectLiteral(property.expression, ctx);
|
|
242382
242890
|
const nested = spread ? routePolicyProperty(spread, name, ctx, ancestry) : { unresolved: true };
|
|
242383
242891
|
if (nested.unresolved || nested.value !== undefined)
|
|
242384
242892
|
result = nested;
|
|
242385
|
-
} else if (
|
|
242893
|
+
} else if (ts7.isComputedPropertyName(property.name)) {
|
|
242386
242894
|
result = { unresolved: true };
|
|
242387
242895
|
} else if (propertyName(property.name) === name) {
|
|
242388
|
-
result =
|
|
242896
|
+
result = ts7.isPropertyAssignment(property) ? { value: property.initializer, unresolved: false } : { unresolved: true };
|
|
242389
242897
|
}
|
|
242390
242898
|
}
|
|
242391
242899
|
return result;
|
|
@@ -242423,9 +242931,9 @@ function parseProvider(el, exportsSet, ctx) {
|
|
|
242423
242931
|
const file = sourcePath(ctx.rootDir, el.getSourceFile().fileName);
|
|
242424
242932
|
const line = lineOf(el);
|
|
242425
242933
|
const unwrappedEl = unwrapForwardRef(el);
|
|
242426
|
-
if (
|
|
242934
|
+
if (ts7.isIdentifier(unwrappedEl)) {
|
|
242427
242935
|
const decl = resolveDeclaration(unwrappedEl, ctx)[0];
|
|
242428
|
-
const cls = decl &&
|
|
242936
|
+
const cls = decl && ts7.isClassDeclaration(decl) ? decl : undefined;
|
|
242429
242937
|
const className = cls?.name?.text ?? unwrappedEl.text;
|
|
242430
242938
|
const { deps, optionalDeps, selfDeps, skipSelfDeps, hostDeps, functionalInjects, missing } = cls ? classDeps(cls, ctx) : { deps: [], optionalDeps: [], selfDeps: [], skipSelfDeps: [], hostDeps: [], functionalInjects: [], missing: false };
|
|
242431
242939
|
const injectable = cls ? parseInjectableOptions(cls, ctx) : undefined;
|
|
@@ -242446,13 +242954,14 @@ function parseProvider(el, exportsSet, ctx) {
|
|
|
242446
242954
|
...functionalInjects.length > 0 ? { functionalInjects } : {},
|
|
242447
242955
|
...injectable?.providedIn ? { providedIn: injectable.providedIn } : {},
|
|
242448
242956
|
...cls && hasDestroyHook(cls) ? { hasOnDestroy: true } : {},
|
|
242957
|
+
...cls && hasInitHook(cls) ? { hasOnInit: true } : {},
|
|
242449
242958
|
exported: exportsSet.has(className),
|
|
242450
242959
|
file,
|
|
242451
242960
|
line,
|
|
242452
242961
|
...cls ? { importPath: modulePath(ctx.rootDir, cls.getSourceFile().fileName) } : {}
|
|
242453
242962
|
};
|
|
242454
242963
|
}
|
|
242455
|
-
if (!
|
|
242964
|
+
if (!ts7.isObjectLiteralExpression(el))
|
|
242456
242965
|
return;
|
|
242457
242966
|
const provideExpr = getProp(el, "provide");
|
|
242458
242967
|
if (!provideExpr)
|
|
@@ -242467,8 +242976,8 @@ function parseProvider(el, exportsSet, ctx) {
|
|
|
242467
242976
|
const useExistingExpr = getProp(el, "useExisting");
|
|
242468
242977
|
if (useClassExpr) {
|
|
242469
242978
|
const unwrappedClass = unwrapForwardRef(useClassExpr);
|
|
242470
|
-
const decl =
|
|
242471
|
-
const cls = decl &&
|
|
242979
|
+
const decl = ts7.isIdentifier(unwrappedClass) ? resolveDeclaration(unwrappedClass, ctx)[0] : undefined;
|
|
242980
|
+
const cls = decl && ts7.isClassDeclaration(decl) ? decl : undefined;
|
|
242472
242981
|
const useClass = cls?.name?.text ?? nodeText(unwrappedClass);
|
|
242473
242982
|
let deps = explicitDeps;
|
|
242474
242983
|
let optionalDeps = [];
|
|
@@ -242516,6 +243025,7 @@ function parseProvider(el, exportsSet, ctx) {
|
|
|
242516
243025
|
...multi === undefined ? {} : { multi },
|
|
242517
243026
|
...injectable?.providedIn ? { providedIn: injectable.providedIn } : {},
|
|
242518
243027
|
...cls && hasMethod(cls, "onDestroy") ? { hasOnDestroy: true } : {},
|
|
243028
|
+
...cls && hasInitHook(cls) ? { hasOnInit: true } : {},
|
|
242519
243029
|
exported: exportsSet.has(token),
|
|
242520
243030
|
file,
|
|
242521
243031
|
line,
|
|
@@ -242524,7 +243034,7 @@ function parseProvider(el, exportsSet, ctx) {
|
|
|
242524
243034
|
}
|
|
242525
243035
|
if (useValueExpr) {
|
|
242526
243036
|
validateProviderCompatibility(provideExpr, useValueExpr, "value", token, ctx, file, line);
|
|
242527
|
-
const importPath =
|
|
243037
|
+
const importPath = ts7.isIdentifier(useValueExpr) ? importPathOf(useValueExpr, ctx) : undefined;
|
|
242528
243038
|
return {
|
|
242529
243039
|
token,
|
|
242530
243040
|
tokenKind,
|
|
@@ -242540,12 +243050,12 @@ function parseProvider(el, exportsSet, ctx) {
|
|
|
242540
243050
|
};
|
|
242541
243051
|
}
|
|
242542
243052
|
if (useFactoryExpr) {
|
|
242543
|
-
const factoryName =
|
|
243053
|
+
const factoryName = ts7.isIdentifier(useFactoryExpr) ? (() => {
|
|
242544
243054
|
const decl = resolveDeclaration(useFactoryExpr, ctx)[0];
|
|
242545
|
-
return decl && (
|
|
243055
|
+
return decl && (ts7.isFunctionDeclaration(decl) || ts7.isVariableDeclaration(decl)) ? (ts7.isFunctionDeclaration(decl) ? decl.name?.text : variableName3(decl)) ?? useFactoryExpr.text : useFactoryExpr.text;
|
|
242546
243056
|
})() : nodeText(useFactoryExpr);
|
|
242547
243057
|
validateProviderCompatibility(provideExpr, useFactoryExpr, "factory", token, ctx, file, line);
|
|
242548
|
-
const importPath =
|
|
243058
|
+
const importPath = ts7.isIdentifier(useFactoryExpr) ? importPathOf(useFactoryExpr, ctx) : undefined;
|
|
242549
243059
|
return {
|
|
242550
243060
|
token,
|
|
242551
243061
|
tokenKind,
|
|
@@ -242581,20 +243091,20 @@ function parseProvider(el, exportsSet, ctx) {
|
|
|
242581
243091
|
function expandProviderExpressions(expressions, ctx, seen = new Set) {
|
|
242582
243092
|
const result = [];
|
|
242583
243093
|
for (const expression of expressions) {
|
|
242584
|
-
if (
|
|
243094
|
+
if (ts7.isSpreadElement(expression)) {
|
|
242585
243095
|
result.push(...expandProviderExpressions([expression.expression], ctx, seen));
|
|
242586
243096
|
continue;
|
|
242587
243097
|
}
|
|
242588
|
-
if (
|
|
243098
|
+
if (ts7.isIdentifier(expression)) {
|
|
242589
243099
|
const declaration = resolveDeclaration(expression, ctx)[0];
|
|
242590
|
-
if (declaration &&
|
|
243100
|
+
if (declaration && ts7.isVariableDeclaration(declaration) && declaration.initializer) {
|
|
242591
243101
|
const key = `${declaration.getSourceFile().fileName}:${declaration.pos}`;
|
|
242592
243102
|
if (seen.has(key))
|
|
242593
243103
|
continue;
|
|
242594
243104
|
const initializer = declaration.initializer;
|
|
242595
|
-
if (
|
|
243105
|
+
if (ts7.isCallExpression(initializer) && isProviderHelper(initializer, "makeEnvironmentProviders")) {
|
|
242596
243106
|
const nested = initializer.arguments[0];
|
|
242597
|
-
if (nested &&
|
|
243107
|
+
if (nested && ts7.isArrayLiteralExpression(nested)) {
|
|
242598
243108
|
seen.add(key);
|
|
242599
243109
|
result.push(...expandProviderExpressions([...nested.elements], ctx, seen));
|
|
242600
243110
|
seen.delete(key);
|
|
@@ -242603,9 +243113,9 @@ function expandProviderExpressions(expressions, ctx, seen = new Set) {
|
|
|
242603
243113
|
}
|
|
242604
243114
|
}
|
|
242605
243115
|
}
|
|
242606
|
-
if (
|
|
243116
|
+
if (ts7.isCallExpression(expression) && isProviderHelper(expression, "makeEnvironmentProviders")) {
|
|
242607
243117
|
const nested = expression.arguments[0];
|
|
242608
|
-
if (nested &&
|
|
243118
|
+
if (nested && ts7.isArrayLiteralExpression(nested)) {
|
|
242609
243119
|
result.push(...expandProviderExpressions([...nested.elements], ctx, seen));
|
|
242610
243120
|
continue;
|
|
242611
243121
|
}
|
|
@@ -242618,7 +243128,7 @@ function isProviderHelper(expression, name) {
|
|
|
242618
243128
|
return nodeText(expression.expression).split(".").pop() === name;
|
|
242619
243129
|
}
|
|
242620
243130
|
function parseFunctionalProvider(expression, exportsSet, ctx) {
|
|
242621
|
-
if (!
|
|
243131
|
+
if (!ts7.isCallExpression(expression))
|
|
242622
243132
|
return;
|
|
242623
243133
|
const helper = nodeText(expression.expression).split(".").pop();
|
|
242624
243134
|
const args = expression.arguments;
|
|
@@ -242631,7 +243141,7 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
|
|
|
242631
243141
|
return [];
|
|
242632
243142
|
const { name: token, kind: tokenKind } = tokenNameOf(tokenExpr, ctx);
|
|
242633
243143
|
validateProviderCompatibility(tokenExpr, valueExpr, "value", token, ctx, file, line);
|
|
242634
|
-
const importPath =
|
|
243144
|
+
const importPath = ts7.isIdentifier(valueExpr) ? importPathOf(valueExpr, ctx) : undefined;
|
|
242635
243145
|
return [{
|
|
242636
243146
|
token,
|
|
242637
243147
|
tokenKind,
|
|
@@ -242650,7 +243160,7 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
|
|
|
242650
243160
|
if (!initializer)
|
|
242651
243161
|
return [];
|
|
242652
243162
|
const token = helper === "provideAppInitializer" ? "APP_INITIALIZER" : "ENVIRONMENT_INITIALIZER";
|
|
242653
|
-
const importPath =
|
|
243163
|
+
const importPath = ts7.isIdentifier(initializer) ? importPathOf(initializer, ctx) : undefined;
|
|
242654
243164
|
return [{
|
|
242655
243165
|
token,
|
|
242656
243166
|
tokenKind: "injection-token",
|
|
@@ -242669,7 +243179,7 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
|
|
|
242669
243179
|
const providers = [];
|
|
242670
243180
|
const routes = args[0];
|
|
242671
243181
|
if (routes) {
|
|
242672
|
-
const importPath =
|
|
243182
|
+
const importPath = ts7.isIdentifier(routes) ? importPathOf(routes, ctx) : undefined;
|
|
242673
243183
|
providers.push({
|
|
242674
243184
|
token: "ROUTE_CONFIG",
|
|
242675
243185
|
tokenKind: "injection-token",
|
|
@@ -242684,7 +243194,7 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
|
|
|
242684
243194
|
});
|
|
242685
243195
|
}
|
|
242686
243196
|
for (const feature of args.slice(1)) {
|
|
242687
|
-
if (!
|
|
243197
|
+
if (!ts7.isCallExpression(feature))
|
|
242688
243198
|
continue;
|
|
242689
243199
|
const featureName = nodeText(feature.expression).split(".").pop();
|
|
242690
243200
|
if (featureName === "withRouterConfig" && feature.arguments[0]) {
|
|
@@ -242701,8 +243211,8 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
|
|
|
242701
243211
|
});
|
|
242702
243212
|
} else if (featureName === "withTitleStrategy" && feature.arguments[0]) {
|
|
242703
243213
|
const strategy = feature.arguments[0];
|
|
242704
|
-
const isClass =
|
|
242705
|
-
const importPath =
|
|
243214
|
+
const isClass = ts7.isIdentifier(strategy) && Boolean(resolveDeclaration(strategy, ctx).find((declaration) => ts7.isClassDeclaration(declaration)));
|
|
243215
|
+
const importPath = ts7.isIdentifier(strategy) ? importPathOf(strategy, ctx) : undefined;
|
|
242706
243216
|
providers.push({
|
|
242707
243217
|
token: "TITLE_STRATEGY",
|
|
242708
243218
|
tokenKind: "injection-token",
|
|
@@ -242734,14 +243244,14 @@ function parseFunctionalProvider(expression, exportsSet, ctx) {
|
|
|
242734
243244
|
importModule: "@supacloud/app"
|
|
242735
243245
|
}];
|
|
242736
243246
|
for (const feature of args) {
|
|
242737
|
-
if (!
|
|
243247
|
+
if (!ts7.isCallExpression(feature))
|
|
242738
243248
|
continue;
|
|
242739
243249
|
const featureName = nodeText(feature.expression).split(".").pop();
|
|
242740
243250
|
if (featureName === "withInterceptors") {
|
|
242741
243251
|
for (const interceptorArg of feature.arguments) {
|
|
242742
|
-
const values =
|
|
243252
|
+
const values = ts7.isArrayLiteralExpression(interceptorArg) ? [...interceptorArg.elements] : [interceptorArg];
|
|
242743
243253
|
for (const value of values) {
|
|
242744
|
-
const importPath =
|
|
243254
|
+
const importPath = ts7.isIdentifier(value) ? importPathOf(value, ctx) : undefined;
|
|
242745
243255
|
providers.push({
|
|
242746
243256
|
token: "HTTP_INTERCEPTORS",
|
|
242747
243257
|
tokenKind: "injection-token",
|
|
@@ -242788,9 +243298,9 @@ function providerTokenValueType(expr, ctx) {
|
|
|
242788
243298
|
const typeArguments = typeArgumentsOf(type, ctx);
|
|
242789
243299
|
if (typeArguments.length > 0)
|
|
242790
243300
|
return typeArguments[0];
|
|
242791
|
-
if (
|
|
243301
|
+
if (ts7.isIdentifier(expr)) {
|
|
242792
243302
|
const declaration = resolveDeclaration(expr, ctx)[0];
|
|
242793
|
-
if (declaration &&
|
|
243303
|
+
if (declaration && ts7.isClassDeclaration(declaration)) {
|
|
242794
243304
|
return declaredClassType(declaration, ctx);
|
|
242795
243305
|
}
|
|
242796
243306
|
}
|
|
@@ -242798,9 +243308,9 @@ function providerTokenValueType(expr, ctx) {
|
|
|
242798
243308
|
}
|
|
242799
243309
|
function providerImplementationType(expr, kind, ctx) {
|
|
242800
243310
|
if (kind === "class" || kind === "existing") {
|
|
242801
|
-
if (
|
|
243311
|
+
if (ts7.isIdentifier(expr)) {
|
|
242802
243312
|
const declaration = resolveDeclaration(expr, ctx)[0];
|
|
242803
|
-
if (declaration &&
|
|
243313
|
+
if (declaration && ts7.isClassDeclaration(declaration)) {
|
|
242804
243314
|
return declaredClassType(declaration, ctx);
|
|
242805
243315
|
}
|
|
242806
243316
|
}
|
|
@@ -242810,7 +243320,7 @@ function providerImplementationType(expr, kind, ctx) {
|
|
|
242810
243320
|
}
|
|
242811
243321
|
if (kind === "factory") {
|
|
242812
243322
|
const type = ctx.checker.getTypeAtLocation(expr);
|
|
242813
|
-
const signature = ctx.checker.getSignaturesOfType(type,
|
|
243323
|
+
const signature = ctx.checker.getSignaturesOfType(type, ts7.SignatureKind.Call)[0];
|
|
242814
243324
|
return signature?.getReturnType();
|
|
242815
243325
|
}
|
|
242816
243326
|
return ctx.checker.getTypeAtLocation(expr);
|
|
@@ -242829,16 +243339,16 @@ function isTypeReference(type) {
|
|
|
242829
243339
|
return "target" in type;
|
|
242830
243340
|
}
|
|
242831
243341
|
function isUnknownOrAny(type) {
|
|
242832
|
-
return (type.flags & (
|
|
243342
|
+
return (type.flags & (ts7.TypeFlags.Any | ts7.TypeFlags.Unknown)) !== 0;
|
|
242833
243343
|
}
|
|
242834
243344
|
function parseController(input, ctx) {
|
|
242835
243345
|
let decl;
|
|
242836
|
-
if (
|
|
243346
|
+
if (ts7.isClassDeclaration(input)) {
|
|
242837
243347
|
decl = input;
|
|
242838
243348
|
} else {
|
|
242839
243349
|
const unwrapped = unwrapForwardRef(input);
|
|
242840
|
-
const resolved =
|
|
242841
|
-
if (resolved &&
|
|
243350
|
+
const resolved = ts7.isIdentifier(unwrapped) ? resolveDeclaration(unwrapped, ctx)[0] : undefined;
|
|
243351
|
+
if (resolved && ts7.isClassDeclaration(resolved)) {
|
|
242842
243352
|
decl = resolved;
|
|
242843
243353
|
}
|
|
242844
243354
|
}
|
|
@@ -242851,9 +243361,9 @@ function parseController(input, ctx) {
|
|
|
242851
243361
|
let standalone;
|
|
242852
243362
|
const pathArg = decoratorArguments(controllerDec)[0];
|
|
242853
243363
|
if (pathArg) {
|
|
242854
|
-
if (
|
|
243364
|
+
if (ts7.isStringLiteral(pathArg)) {
|
|
242855
243365
|
path = pathArg.text;
|
|
242856
|
-
} else if (
|
|
243366
|
+
} else if (ts7.isObjectLiteralExpression(pathArg)) {
|
|
242857
243367
|
const p = stringLiteralProp(pathArg, "path");
|
|
242858
243368
|
if (p)
|
|
242859
243369
|
path = p;
|
|
@@ -242876,7 +243386,7 @@ function parseController(input, ctx) {
|
|
|
242876
243386
|
}
|
|
242877
243387
|
}
|
|
242878
243388
|
}
|
|
242879
|
-
for (const method of decl.members.filter(
|
|
243389
|
+
for (const method of decl.members.filter(ts7.isMethodDeclaration)) {
|
|
242880
243390
|
for (const dec of decoratorsOf(method)) {
|
|
242881
243391
|
const name = decoratorName2(dec);
|
|
242882
243392
|
const httpMethod = name ? ROUTE_DECORATORS[name] : undefined;
|
|
@@ -242884,7 +243394,7 @@ function parseController(input, ctx) {
|
|
|
242884
243394
|
continue;
|
|
242885
243395
|
const args = decoratorArguments(dec);
|
|
242886
243396
|
const pathArg = args[0];
|
|
242887
|
-
const routePath = pathArg &&
|
|
243397
|
+
const routePath = pathArg && ts7.isStringLiteral(pathArg) ? pathArg.text : "/";
|
|
242888
243398
|
const route = {
|
|
242889
243399
|
method: httpMethod,
|
|
242890
243400
|
path: routePath,
|
|
@@ -242958,12 +243468,12 @@ function parseController(input, ctx) {
|
|
|
242958
243468
|
} else if (dName === "Headers") {
|
|
242959
243469
|
hasBindingDecorator = true;
|
|
242960
243470
|
const argument = dArgs[0];
|
|
242961
|
-
const bindingName = argument !== undefined &&
|
|
243471
|
+
const bindingName = argument !== undefined && ts7.isStringLiteral(argument) ? argument.text : undefined;
|
|
242962
243472
|
paramNode = { name: pName, kind: "headers", ...bindingName === undefined ? {} : { bindingName } };
|
|
242963
243473
|
} else if (dName === "Cookie") {
|
|
242964
243474
|
hasBindingDecorator = true;
|
|
242965
243475
|
const argument = dArgs[0];
|
|
242966
|
-
const bindingName = argument !== undefined &&
|
|
243476
|
+
const bindingName = argument !== undefined && ts7.isStringLiteral(argument) ? argument.text : undefined;
|
|
242967
243477
|
paramNode = { name: pName, kind: "cookie", ...bindingName === undefined ? {} : { bindingName } };
|
|
242968
243478
|
}
|
|
242969
243479
|
}
|
|
@@ -243025,20 +243535,20 @@ function parseController(input, ctx) {
|
|
|
243025
243535
|
}
|
|
243026
243536
|
} else if (dName === "Title") {
|
|
243027
243537
|
const tArg = mArgs[0];
|
|
243028
|
-
if (tArg &&
|
|
243538
|
+
if (tArg && ts7.isStringLiteral(tArg)) {
|
|
243029
243539
|
route.title = tArg.text;
|
|
243030
243540
|
}
|
|
243031
243541
|
} else if (dName === "Data") {
|
|
243032
243542
|
const dArg = mArgs[0];
|
|
243033
|
-
if (dArg &&
|
|
243543
|
+
if (dArg && ts7.isObjectLiteralExpression(dArg)) {
|
|
243034
243544
|
route.data = { ...route.data, ...parseObjectLiteralValues(dArg) };
|
|
243035
243545
|
}
|
|
243036
243546
|
} else if (dName === "Resolve") {
|
|
243037
243547
|
const rArg = mArgs[0];
|
|
243038
|
-
if (rArg &&
|
|
243548
|
+
if (rArg && ts7.isObjectLiteralExpression(rArg)) {
|
|
243039
243549
|
const resolvers = route.resolvers ?? {};
|
|
243040
243550
|
for (const prop of rArg.properties) {
|
|
243041
|
-
if (
|
|
243551
|
+
if (ts7.isPropertyAssignment(prop)) {
|
|
243042
243552
|
const rName = propertyName(prop.name);
|
|
243043
243553
|
const init = prop.initializer;
|
|
243044
243554
|
if (init)
|
|
@@ -243066,7 +243576,7 @@ function parseController(input, ctx) {
|
|
|
243066
243576
|
}
|
|
243067
243577
|
const parse = parsePolicy.value;
|
|
243068
243578
|
if (parse) {
|
|
243069
|
-
if (
|
|
243579
|
+
if (ts7.isStringLiteral(parse) && parse.text === "none")
|
|
243070
243580
|
route.parse = "none";
|
|
243071
243581
|
else
|
|
243072
243582
|
ctx.diagnostics.push({
|
|
@@ -243078,7 +243588,7 @@ function parseController(input, ctx) {
|
|
|
243078
243588
|
}
|
|
243079
243589
|
const allowDeleteBody = deletePolicy.value;
|
|
243080
243590
|
if (allowDeleteBody) {
|
|
243081
|
-
if (allowDeleteBody.kind ===
|
|
243591
|
+
if (allowDeleteBody.kind === ts7.SyntaxKind.TrueKeyword)
|
|
243082
243592
|
route.allowDeleteBody = true;
|
|
243083
243593
|
else
|
|
243084
243594
|
ctx.diagnostics.push({
|
|
@@ -243103,7 +243613,7 @@ function parseController(input, ctx) {
|
|
|
243103
243613
|
});
|
|
243104
243614
|
}
|
|
243105
243615
|
const contract = getProp(optionsObject, "contract");
|
|
243106
|
-
if (contract &&
|
|
243616
|
+
if (contract && ts7.isObjectLiteralExpression(contract)) {
|
|
243107
243617
|
route.contract = {};
|
|
243108
243618
|
for (const field of ["body", "response", "evidence"]) {
|
|
243109
243619
|
const value = stringLiteralProp(contract, field);
|
|
@@ -243121,7 +243631,7 @@ function parseController(input, ctx) {
|
|
|
243121
243631
|
}
|
|
243122
243632
|
for (const field of ["body", "params", "query", "headers", "cookie", "response"]) {
|
|
243123
243633
|
const schemaExpr = getProp(optionsObject, field);
|
|
243124
|
-
if (schemaExpr &&
|
|
243634
|
+
if (schemaExpr && ts7.isIdentifier(schemaExpr)) {
|
|
243125
243635
|
route[field] = nodeText(schemaExpr);
|
|
243126
243636
|
const importPath = importPathOf(schemaExpr, ctx);
|
|
243127
243637
|
if (importPath)
|
|
@@ -243136,7 +243646,7 @@ function parseController(input, ctx) {
|
|
|
243136
243646
|
const responses = {};
|
|
243137
243647
|
const selectors = new Map;
|
|
243138
243648
|
for (const property of responsesObject.properties) {
|
|
243139
|
-
if (!
|
|
243649
|
+
if (!ts7.isPropertyAssignment(property) || ts7.isComputedPropertyName(property.name))
|
|
243140
243650
|
continue;
|
|
243141
243651
|
const status = propertyName(property.name);
|
|
243142
243652
|
if (!isRouteResponseSelector(status)) {
|
|
@@ -243168,7 +243678,7 @@ function parseController(input, ctx) {
|
|
|
243168
243678
|
}
|
|
243169
243679
|
selectors.set(canonical, status);
|
|
243170
243680
|
const schemaExpr = property.initializer;
|
|
243171
|
-
if (!
|
|
243681
|
+
if (!ts7.isIdentifier(schemaExpr)) {
|
|
243172
243682
|
ctx.diagnostics.push({
|
|
243173
243683
|
severity: "error",
|
|
243174
243684
|
code: "invalid-route-response-map",
|
|
@@ -243190,18 +243700,18 @@ function parseController(input, ctx) {
|
|
|
243190
243700
|
route.responses = responses;
|
|
243191
243701
|
}
|
|
243192
243702
|
const commandExpr = getProp(optionsObject, "command");
|
|
243193
|
-
if (commandExpr &&
|
|
243703
|
+
if (commandExpr && ts7.isIdentifier(commandExpr)) {
|
|
243194
243704
|
const commandDecl = resolveDeclaration(commandExpr, ctx)[0];
|
|
243195
|
-
route.command = commandDecl &&
|
|
243705
|
+
route.command = commandDecl && ts7.isClassDeclaration(commandDecl) ? commandDecl.name?.text ?? commandExpr.text : commandExpr.text;
|
|
243196
243706
|
}
|
|
243197
243707
|
const guardsExpr = getProp(optionsObject, "guards");
|
|
243198
|
-
if (guardsExpr &&
|
|
243708
|
+
if (guardsExpr && ts7.isArrayLiteralExpression(guardsExpr)) {
|
|
243199
243709
|
for (const el of guardsExpr.elements) {
|
|
243200
243710
|
routeGuards.push(tokenText(el, ctx));
|
|
243201
243711
|
}
|
|
243202
243712
|
}
|
|
243203
243713
|
const canMatchExpr = getProp(optionsObject, "canMatch");
|
|
243204
|
-
if (canMatchExpr &&
|
|
243714
|
+
if (canMatchExpr && ts7.isArrayLiteralExpression(canMatchExpr)) {
|
|
243205
243715
|
const canMatchList = [];
|
|
243206
243716
|
for (const el of canMatchExpr.elements) {
|
|
243207
243717
|
canMatchList.push(tokenText(el, ctx));
|
|
@@ -243211,16 +243721,16 @@ function parseController(input, ctx) {
|
|
|
243211
243721
|
}
|
|
243212
243722
|
}
|
|
243213
243723
|
const canDeactivateExpr = getProp(optionsObject, "canDeactivate");
|
|
243214
|
-
if (canDeactivateExpr &&
|
|
243724
|
+
if (canDeactivateExpr && ts7.isArrayLiteralExpression(canDeactivateExpr)) {
|
|
243215
243725
|
for (const el of canDeactivateExpr.elements) {
|
|
243216
243726
|
routeCanDeactivate.push(tokenText(el, ctx));
|
|
243217
243727
|
}
|
|
243218
243728
|
}
|
|
243219
243729
|
const resolversExpr = getProp(optionsObject, "resolvers");
|
|
243220
|
-
if (resolversExpr &&
|
|
243730
|
+
if (resolversExpr && ts7.isObjectLiteralExpression(resolversExpr)) {
|
|
243221
243731
|
const resolvers = {};
|
|
243222
243732
|
for (const prop of resolversExpr.properties) {
|
|
243223
|
-
if (
|
|
243733
|
+
if (ts7.isPropertyAssignment(prop)) {
|
|
243224
243734
|
const rName = propertyName(prop.name);
|
|
243225
243735
|
const init = prop.initializer;
|
|
243226
243736
|
if (init)
|
|
@@ -243232,22 +243742,22 @@ function parseController(input, ctx) {
|
|
|
243232
243742
|
}
|
|
243233
243743
|
}
|
|
243234
243744
|
const redirectToExpr = getProp(optionsObject, "redirectTo");
|
|
243235
|
-
if (redirectToExpr &&
|
|
243745
|
+
if (redirectToExpr && ts7.isStringLiteral(redirectToExpr)) {
|
|
243236
243746
|
route.redirectTo = redirectToExpr.text;
|
|
243237
243747
|
}
|
|
243238
243748
|
const pathMatchExpr = getProp(optionsObject, "pathMatch");
|
|
243239
|
-
if (pathMatchExpr &&
|
|
243749
|
+
if (pathMatchExpr && ts7.isStringLiteral(pathMatchExpr)) {
|
|
243240
243750
|
const val = pathMatchExpr.text;
|
|
243241
243751
|
if (val === "full" || val === "prefix") {
|
|
243242
243752
|
route.pathMatch = val;
|
|
243243
243753
|
}
|
|
243244
243754
|
}
|
|
243245
243755
|
const titleExpr = getProp(optionsObject, "title");
|
|
243246
|
-
if (titleExpr &&
|
|
243756
|
+
if (titleExpr && ts7.isStringLiteral(titleExpr)) {
|
|
243247
243757
|
route.title = titleExpr.text;
|
|
243248
243758
|
}
|
|
243249
243759
|
const dataExpr = getProp(optionsObject, "data");
|
|
243250
|
-
if (dataExpr &&
|
|
243760
|
+
if (dataExpr && ts7.isObjectLiteralExpression(dataExpr)) {
|
|
243251
243761
|
route.data = { ...route.data, ...parseObjectLiteralValues(dataExpr) };
|
|
243252
243762
|
}
|
|
243253
243763
|
const aspects = parseAspectRefs(getProp(optionsObject, "aspects"), ctx, `route ${httpMethod} ${routePath}`);
|
|
@@ -243269,6 +243779,7 @@ function parseController(input, ctx) {
|
|
|
243269
243779
|
scope: injectable?.scope ?? "request",
|
|
243270
243780
|
deps,
|
|
243271
243781
|
...hasDestroyHook(decl) ? { hasOnDestroy: true } : {},
|
|
243782
|
+
...hasInitHook(decl) ? { hasOnInit: true } : {},
|
|
243272
243783
|
...optionalDeps.length > 0 ? { optionalDeps } : {},
|
|
243273
243784
|
...selfDeps.length > 0 ? { selfDeps } : {},
|
|
243274
243785
|
...skipSelfDeps.length > 0 ? { skipSelfDeps } : {},
|
|
@@ -243302,7 +243813,7 @@ function parseJobOptions(meta, owner, ctx) {
|
|
|
243302
243813
|
const expression = getProp(meta, field);
|
|
243303
243814
|
if (!expression)
|
|
243304
243815
|
continue;
|
|
243305
|
-
if (!
|
|
243816
|
+
if (!ts7.isIdentifier(expression)) {
|
|
243306
243817
|
jobOptionError(ctx, "invalid-job-schema", `${owner} 的 ${field} schema 必须是可静态解析的标识符引用,不能使用内联调用或动态表达式`, expression, "SC4019", `将 schema 提取为命名导出,例如 ${field}: ${field === "input" ? "JobInput" : "JobOutput"}。`);
|
|
243307
243818
|
continue;
|
|
243308
243819
|
}
|
|
@@ -243326,7 +243837,7 @@ function parseJobEnum(meta, field, allowed, owner, ctx, code, errorCode) {
|
|
|
243326
243837
|
const expression = getProp(meta, field);
|
|
243327
243838
|
if (!expression)
|
|
243328
243839
|
return;
|
|
243329
|
-
if (!
|
|
243840
|
+
if (!ts7.isStringLiteral(expression) || !allowed.includes(expression.text)) {
|
|
243330
243841
|
jobOptionError(ctx, code, `${owner} 的 ${field} 必须是 ${allowed.map((value) => JSON.stringify(value)).join(" 或 ")} 字符串字面量`, expression, errorCode);
|
|
243331
243842
|
return;
|
|
243332
243843
|
}
|
|
@@ -243336,7 +243847,7 @@ function parseJobInteger(meta, field, min, max, owner, ctx, code, errorCode) {
|
|
|
243336
243847
|
const expression = getProp(meta, field);
|
|
243337
243848
|
if (!expression)
|
|
243338
243849
|
return;
|
|
243339
|
-
const value =
|
|
243850
|
+
const value = ts7.isNumericLiteral(expression) ? Number(expression.text) : Number.NaN;
|
|
243340
243851
|
if (!Number.isSafeInteger(value) || value < min || value > max) {
|
|
243341
243852
|
jobOptionError(ctx, code, `${owner} 的 ${field} 必须是 ${min} 到 ${max} 之间的安全整数`, expression, errorCode);
|
|
243342
243853
|
return;
|
|
@@ -243372,7 +243883,7 @@ function isOpaqueSchema(identifier, declaration, ctx) {
|
|
|
243372
243883
|
const property = type.getProperty(kind.value === "Union" ? "anyOf" : "allOf");
|
|
243373
243884
|
if (!property)
|
|
243374
243885
|
return true;
|
|
243375
|
-
const members = ctx.checker.getIndexTypeOfType(ctx.checker.getTypeOfSymbolAtLocation(property, identifier),
|
|
243886
|
+
const members = ctx.checker.getIndexTypeOfType(ctx.checker.getTypeOfSymbolAtLocation(property, identifier), ts7.IndexKind.Number);
|
|
243376
243887
|
if (!members)
|
|
243377
243888
|
return true;
|
|
243378
243889
|
const branches = members.isUnion() ? members.types : [members];
|
|
@@ -243384,8 +243895,8 @@ function isOpaqueSchema(identifier, declaration, ctx) {
|
|
|
243384
243895
|
}
|
|
243385
243896
|
if (opaque(ctx.checker.getTypeAtLocation(identifier), new Set))
|
|
243386
243897
|
return true;
|
|
243387
|
-
const initializer = declaration &&
|
|
243388
|
-
return Boolean(initializer &&
|
|
243898
|
+
const initializer = declaration && ts7.isVariableDeclaration(declaration) ? declaration.initializer : undefined;
|
|
243899
|
+
return Boolean(initializer && ts7.isCallExpression(initializer) && ts7.isPropertyAccessExpression(initializer.expression) && ["Unknown", "Any"].includes(initializer.expression.name.text));
|
|
243389
243900
|
}
|
|
243390
243901
|
function checkedRpc(meta, ctx) {
|
|
243391
243902
|
const expression = getProp(meta, "rpc");
|
|
@@ -243406,7 +243917,7 @@ function checkedRpc(meta, ctx) {
|
|
|
243406
243917
|
}
|
|
243407
243918
|
function classDeps(cls, ctx) {
|
|
243408
243919
|
const injectable = parseInjectableOptions(cls, ctx);
|
|
243409
|
-
const ctor = cls.members.find(
|
|
243920
|
+
const ctor = cls.members.find(ts7.isConstructorDeclaration);
|
|
243410
243921
|
const deps = injectable?.deps ? [...injectable.deps] : [];
|
|
243411
243922
|
const optionalDeps = [];
|
|
243412
243923
|
const selfDeps = [];
|
|
@@ -243440,23 +243951,23 @@ function classDeps(cls, ctx) {
|
|
|
243440
243951
|
}
|
|
243441
243952
|
});
|
|
243442
243953
|
}
|
|
243443
|
-
for (const prop of cls.members.filter(
|
|
243954
|
+
for (const prop of cls.members.filter(ts7.isPropertyDeclaration)) {
|
|
243444
243955
|
const init = prop.initializer;
|
|
243445
|
-
if (init &&
|
|
243956
|
+
if (init && ts7.isCallExpression(init)) {
|
|
243446
243957
|
const callName = nodeText(init.expression).split(".").pop();
|
|
243447
243958
|
if (callName === "inject") {
|
|
243448
243959
|
const [tokenArg, optionsArg] = init.arguments;
|
|
243449
243960
|
if (tokenArg) {
|
|
243450
243961
|
const tokenName = tokenText(tokenArg, ctx);
|
|
243451
243962
|
const unwrappedToken = unwrapForwardRef(tokenArg);
|
|
243452
|
-
const known =
|
|
243963
|
+
const known = ts7.isStringLiteral(unwrappedToken) || ts7.isIdentifier(unwrappedToken) && (ctx.tokensByName.has(tokenName) || ctx.classesByName.has(tokenName));
|
|
243453
243964
|
if (!known) {
|
|
243454
243965
|
missing = true;
|
|
243455
243966
|
continue;
|
|
243456
243967
|
}
|
|
243457
243968
|
if (!deps.includes(tokenName))
|
|
243458
243969
|
deps.push(tokenName);
|
|
243459
|
-
const options = optionsArg &&
|
|
243970
|
+
const options = optionsArg && ts7.isObjectLiteralExpression(optionsArg) ? {
|
|
243460
243971
|
optional: booleanProp(optionsArg, "optional") ?? false,
|
|
243461
243972
|
self: booleanProp(optionsArg, "self") ?? false,
|
|
243462
243973
|
skipSelf: booleanProp(optionsArg, "skipSelf") ?? false,
|
|
@@ -243471,9 +243982,9 @@ function classDeps(cls, ctx) {
|
|
|
243471
243982
|
if (options.host && !hostDeps.includes(tokenName))
|
|
243472
243983
|
hostDeps.push(tokenName);
|
|
243473
243984
|
if (!functionalInjects.some((entry) => entry.token === tokenName)) {
|
|
243474
|
-
const declaration =
|
|
243985
|
+
const declaration = ts7.isIdentifier(unwrappedToken) ? resolveDeclaration(unwrappedToken, ctx)[0] : undefined;
|
|
243475
243986
|
const localFile = declaration && isProjectSourcePath(declaration.getSourceFile().fileName, ctx.rootDir) ? declaration.getSourceFile().fileName : undefined;
|
|
243476
|
-
const importModule = declaration && !localFile &&
|
|
243987
|
+
const importModule = declaration && !localFile && ts7.isIdentifier(unwrappedToken) ? importModuleOf(unwrappedToken, ctx) : undefined;
|
|
243477
243988
|
functionalInjects.push({
|
|
243478
243989
|
token: tokenName,
|
|
243479
243990
|
expression: nodeText(unwrappedToken),
|
|
@@ -243517,7 +244028,7 @@ function parseInjectableOptions(cls, ctx) {
|
|
|
243517
244028
|
}
|
|
243518
244029
|
function parseInjectParams(cls, ctx) {
|
|
243519
244030
|
const result = new Map;
|
|
243520
|
-
const ctor = cls.members.find(
|
|
244031
|
+
const ctor = cls.members.find(ts7.isConstructorDeclaration);
|
|
243521
244032
|
if (!ctor)
|
|
243522
244033
|
return result;
|
|
243523
244034
|
ctor.parameters.forEach((param, index) => {
|
|
@@ -243533,7 +244044,7 @@ function parseInjectParams(cls, ctx) {
|
|
|
243533
244044
|
}
|
|
243534
244045
|
function parseOptionalParams(cls) {
|
|
243535
244046
|
const result = new Set;
|
|
243536
|
-
const ctor = cls.members.find(
|
|
244047
|
+
const ctor = cls.members.find(ts7.isConstructorDeclaration);
|
|
243537
244048
|
if (!ctor)
|
|
243538
244049
|
return result;
|
|
243539
244050
|
ctor.parameters.forEach((param, index) => {
|
|
@@ -243548,7 +244059,7 @@ function parseOptionalParams(cls) {
|
|
|
243548
244059
|
}
|
|
243549
244060
|
function parseModifierParams(cls, modifierName) {
|
|
243550
244061
|
const result = new Set;
|
|
243551
|
-
const ctor = cls.members.find(
|
|
244062
|
+
const ctor = cls.members.find(ts7.isConstructorDeclaration);
|
|
243552
244063
|
if (!ctor)
|
|
243553
244064
|
return result;
|
|
243554
244065
|
ctor.parameters.forEach((param, index) => {
|
|
@@ -243560,13 +244071,13 @@ function parseModifierParams(cls, modifierName) {
|
|
|
243560
244071
|
return result;
|
|
243561
244072
|
}
|
|
243562
244073
|
function unwrapForwardRef(expr) {
|
|
243563
|
-
if (
|
|
244074
|
+
if (ts7.isCallExpression(expr)) {
|
|
243564
244075
|
const exprText = nodeText(expr.expression);
|
|
243565
244076
|
if (exprText === "forwardRef" || exprText.endsWith(".forwardRef")) {
|
|
243566
244077
|
const arg = expr.arguments[0];
|
|
243567
|
-
if (arg && (
|
|
244078
|
+
if (arg && (ts7.isArrowFunction(arg) || ts7.isFunctionExpression(arg))) {
|
|
243568
244079
|
const body = arg.body;
|
|
243569
|
-
if (body &&
|
|
244080
|
+
if (body && ts7.isExpression(body)) {
|
|
243570
244081
|
return unwrapForwardRef(body);
|
|
243571
244082
|
}
|
|
243572
244083
|
}
|
|
@@ -243576,13 +244087,13 @@ function unwrapForwardRef(expr) {
|
|
|
243576
244087
|
}
|
|
243577
244088
|
function tokenText(expr, ctx) {
|
|
243578
244089
|
const unwrapped = unwrapForwardRef(expr);
|
|
243579
|
-
if (
|
|
244090
|
+
if (ts7.isStringLiteral(unwrapped))
|
|
243580
244091
|
return unwrapped.text;
|
|
243581
|
-
if (
|
|
244092
|
+
if (ts7.isIdentifier(unwrapped)) {
|
|
243582
244093
|
const decl = resolveDeclaration(unwrapped, ctx)[0];
|
|
243583
|
-
if (decl &&
|
|
244094
|
+
if (decl && ts7.isClassDeclaration(decl))
|
|
243584
244095
|
return decl.name?.text ?? unwrapped.text;
|
|
243585
|
-
if (decl &&
|
|
244096
|
+
if (decl && ts7.isVariableDeclaration(decl))
|
|
243586
244097
|
return variableName3(decl);
|
|
243587
244098
|
}
|
|
243588
244099
|
return nodeText(unwrapped);
|
|
@@ -243602,12 +244113,12 @@ function resolveScope(input, ctx) {
|
|
|
243602
244113
|
}
|
|
243603
244114
|
function tokenNameOf(expr, ctx) {
|
|
243604
244115
|
const unwrapped = unwrapForwardRef(expr);
|
|
243605
|
-
if (
|
|
244116
|
+
if (ts7.isIdentifier(unwrapped)) {
|
|
243606
244117
|
const decl = resolveDeclaration(unwrapped, ctx)[0];
|
|
243607
|
-
if (decl &&
|
|
244118
|
+
if (decl && ts7.isClassDeclaration(decl)) {
|
|
243608
244119
|
return { name: decl.name?.text ?? nodeText(expr), kind: "class" };
|
|
243609
244120
|
}
|
|
243610
|
-
if (decl &&
|
|
244121
|
+
if (decl && ts7.isVariableDeclaration(decl)) {
|
|
243611
244122
|
const name = variableName3(decl);
|
|
243612
244123
|
return { name, kind: ctx.tokensByName.has(name) ? "injection-token" : "class" };
|
|
243613
244124
|
}
|
|
@@ -243623,10 +244134,10 @@ function resolveDeclaration(id, ctx) {
|
|
|
243623
244134
|
return [];
|
|
243624
244135
|
let declarations = symbol.declarations ?? [];
|
|
243625
244136
|
for (let guard = 0;guard < 4; guard += 1) {
|
|
243626
|
-
const isAlias = declarations.some((d) =>
|
|
244137
|
+
const isAlias = declarations.some((d) => ts7.isImportSpecifier(d) || ts7.isImportClause(d) || ts7.isNamespaceImport(d));
|
|
243627
244138
|
if (!isAlias)
|
|
243628
244139
|
break;
|
|
243629
|
-
if (!(symbol.flags &
|
|
244140
|
+
if (!(symbol.flags & ts7.SymbolFlags.Alias))
|
|
243630
244141
|
break;
|
|
243631
244142
|
const aliased = ctx.checker.getAliasedSymbol(symbol);
|
|
243632
244143
|
symbol = aliased;
|
|
@@ -243646,9 +244157,9 @@ function importModuleOf(id, ctx) {
|
|
|
243646
244157
|
for (const declaration of declarations) {
|
|
243647
244158
|
let current = declaration;
|
|
243648
244159
|
while (current) {
|
|
243649
|
-
if (
|
|
244160
|
+
if (ts7.isImportDeclaration(current)) {
|
|
243650
244161
|
const moduleSpecifier = current.moduleSpecifier;
|
|
243651
|
-
return
|
|
244162
|
+
return ts7.isStringLiteral(moduleSpecifier) ? moduleSpecifier.text : undefined;
|
|
243652
244163
|
}
|
|
243653
244164
|
current = current.parent;
|
|
243654
244165
|
}
|
|
@@ -243660,27 +244171,27 @@ function findDecorator(cls, name) {
|
|
|
243660
244171
|
}
|
|
243661
244172
|
function decoratorName2(dec) {
|
|
243662
244173
|
const expr = dec.expression;
|
|
243663
|
-
if (
|
|
244174
|
+
if (ts7.isCallExpression(expr)) {
|
|
243664
244175
|
return nodeText(expr.expression).split(".").pop();
|
|
243665
244176
|
}
|
|
243666
|
-
if (
|
|
244177
|
+
if (ts7.isIdentifier(expr))
|
|
243667
244178
|
return expr.text;
|
|
243668
244179
|
return;
|
|
243669
244180
|
}
|
|
243670
244181
|
function decoratorObjectArg(dec) {
|
|
243671
244182
|
const expr = dec.expression;
|
|
243672
|
-
if (!
|
|
244183
|
+
if (!ts7.isCallExpression(expr))
|
|
243673
244184
|
return;
|
|
243674
244185
|
const arg = expr.arguments[0];
|
|
243675
|
-
return arg &&
|
|
244186
|
+
return arg && ts7.isObjectLiteralExpression(arg) ? arg : undefined;
|
|
243676
244187
|
}
|
|
243677
244188
|
function getProp(obj, name) {
|
|
243678
|
-
const prop = obj.properties.find((item) => (
|
|
244189
|
+
const prop = obj.properties.find((item) => (ts7.isPropertyAssignment(item) || ts7.isShorthandPropertyAssignment(item)) && propertyName(item.name) === name);
|
|
243679
244190
|
if (!prop)
|
|
243680
244191
|
return;
|
|
243681
|
-
if (
|
|
244192
|
+
if (ts7.isPropertyAssignment(prop))
|
|
243682
244193
|
return prop.initializer;
|
|
243683
|
-
if (
|
|
244194
|
+
if (ts7.isShorthandPropertyAssignment(prop))
|
|
243684
244195
|
return prop.name;
|
|
243685
244196
|
return;
|
|
243686
244197
|
}
|
|
@@ -243688,10 +244199,10 @@ function toCompilerDiagnostic(diagnostic, rootDir) {
|
|
|
243688
244199
|
const file = diagnostic.file;
|
|
243689
244200
|
const position = file && diagnostic.start !== undefined ? file.getLineAndCharacterOfPosition(diagnostic.start) : undefined;
|
|
243690
244201
|
return {
|
|
243691
|
-
severity: diagnostic.category ===
|
|
244202
|
+
severity: diagnostic.category === ts7.DiagnosticCategory.Error ? "error" : "warn",
|
|
243692
244203
|
code: `typescript-${diagnostic.code}`,
|
|
243693
244204
|
errorCode: `TS${diagnostic.code}`,
|
|
243694
|
-
message:
|
|
244205
|
+
message: ts7.flattenDiagnosticMessageText(diagnostic.messageText, `
|
|
243695
244206
|
`),
|
|
243696
244207
|
...file ? { file: sourcePath(rootDir, file.fileName) } : {},
|
|
243697
244208
|
...position ? { line: position.line + 1 } : {}
|
|
@@ -243699,16 +244210,16 @@ function toCompilerDiagnostic(diagnostic, rootDir) {
|
|
|
243699
244210
|
}
|
|
243700
244211
|
function stringLiteralProp(obj, name) {
|
|
243701
244212
|
const expr = getProp(obj, name);
|
|
243702
|
-
return expr &&
|
|
244213
|
+
return expr && ts7.isStringLiteral(expr) ? expr.text : undefined;
|
|
243703
244214
|
}
|
|
243704
244215
|
function arrayProp(obj, name) {
|
|
243705
244216
|
const expr = getProp(obj, name);
|
|
243706
|
-
return expr &&
|
|
244217
|
+
return expr && ts7.isArrayLiteralExpression(expr) ? [...expr.elements] : [];
|
|
243707
244218
|
}
|
|
243708
244219
|
function parseAspectRefs(expression, ctx, owner) {
|
|
243709
244220
|
if (!expression)
|
|
243710
244221
|
return [];
|
|
243711
|
-
if (!
|
|
244222
|
+
if (!ts7.isArrayLiteralExpression(expression)) {
|
|
243712
244223
|
ctx.diagnostics.push({
|
|
243713
244224
|
severity: "error",
|
|
243714
244225
|
code: "dynamic-aspect-reference",
|
|
@@ -243723,7 +244234,7 @@ function parseAspectRefs(expression, ctx, owner) {
|
|
|
243723
244234
|
}
|
|
243724
244235
|
const refs = [];
|
|
243725
244236
|
for (const element of expression.elements) {
|
|
243726
|
-
if (
|
|
244237
|
+
if (ts7.isSpreadElement(element) || !ts7.isIdentifier(element)) {
|
|
243727
244238
|
ctx.diagnostics.push({
|
|
243728
244239
|
severity: "error",
|
|
243729
244240
|
code: "dynamic-aspect-reference",
|
|
@@ -243736,7 +244247,7 @@ function parseAspectRefs(expression, ctx, owner) {
|
|
|
243736
244247
|
});
|
|
243737
244248
|
continue;
|
|
243738
244249
|
}
|
|
243739
|
-
const declaration = resolveDeclaration(element, ctx).find((candidate) =>
|
|
244250
|
+
const declaration = resolveDeclaration(element, ctx).find((candidate) => ts7.isFunctionDeclaration(candidate) || ts7.isVariableDeclaration(candidate) && candidate.initializer !== undefined && (ts7.isArrowFunction(candidate.initializer) || ts7.isFunctionExpression(candidate.initializer)));
|
|
243740
244251
|
if (!declaration) {
|
|
243741
244252
|
ctx.diagnostics.push({
|
|
243742
244253
|
severity: "error",
|
|
@@ -243750,7 +244261,7 @@ function parseAspectRefs(expression, ctx, owner) {
|
|
|
243750
244261
|
});
|
|
243751
244262
|
continue;
|
|
243752
244263
|
}
|
|
243753
|
-
const name =
|
|
244264
|
+
const name = ts7.isFunctionDeclaration(declaration) ? declaration.name?.text : ts7.isVariableDeclaration(declaration) ? variableName3(declaration) : undefined;
|
|
243754
244265
|
if (!name)
|
|
243755
244266
|
continue;
|
|
243756
244267
|
const declaredFile = declaration.getSourceFile().fileName;
|
|
@@ -243770,9 +244281,9 @@ function booleanProp(obj, name) {
|
|
|
243770
244281
|
const expr = getProp(obj, name);
|
|
243771
244282
|
if (!expr)
|
|
243772
244283
|
return;
|
|
243773
|
-
if (expr.kind ===
|
|
244284
|
+
if (expr.kind === ts7.SyntaxKind.TrueKeyword)
|
|
243774
244285
|
return true;
|
|
243775
|
-
if (expr.kind ===
|
|
244286
|
+
if (expr.kind === ts7.SyntaxKind.FalseKeyword)
|
|
243776
244287
|
return false;
|
|
243777
244288
|
return;
|
|
243778
244289
|
}
|
|
@@ -243786,15 +244297,15 @@ function parseBindingOptions(args, defaultName) {
|
|
|
243786
244297
|
let defaultValue;
|
|
243787
244298
|
const first = args[0];
|
|
243788
244299
|
const second = args[1];
|
|
243789
|
-
if (first &&
|
|
244300
|
+
if (first && ts7.isStringLiteral(first)) {
|
|
243790
244301
|
name = first.text;
|
|
243791
|
-
} else if (first &&
|
|
244302
|
+
} else if (first && ts7.isObjectLiteralExpression(first)) {
|
|
243792
244303
|
const nameProp = getProp(first, "name");
|
|
243793
|
-
if (nameProp &&
|
|
244304
|
+
if (nameProp && ts7.isStringLiteral(nameProp)) {
|
|
243794
244305
|
name = nameProp.text;
|
|
243795
244306
|
}
|
|
243796
244307
|
const trProp = getProp(first, "transform");
|
|
243797
|
-
if (trProp &&
|
|
244308
|
+
if (trProp && ts7.isStringLiteral(trProp)) {
|
|
243798
244309
|
const val = trProp.text;
|
|
243799
244310
|
if (val === "number" || val === "boolean" || val === "string") {
|
|
243800
244311
|
transform = val;
|
|
@@ -243805,9 +244316,9 @@ function parseBindingOptions(args, defaultName) {
|
|
|
243805
244316
|
defaultValue = parseLiteralValue(defProp);
|
|
243806
244317
|
}
|
|
243807
244318
|
}
|
|
243808
|
-
if (second &&
|
|
244319
|
+
if (second && ts7.isObjectLiteralExpression(second)) {
|
|
243809
244320
|
const trProp = getProp(second, "transform");
|
|
243810
|
-
if (trProp &&
|
|
244321
|
+
if (trProp && ts7.isStringLiteral(trProp)) {
|
|
243811
244322
|
const val = trProp.text;
|
|
243812
244323
|
if (val === "number" || val === "boolean" || val === "string") {
|
|
243813
244324
|
transform = val;
|
|
@@ -243821,18 +244332,18 @@ function parseBindingOptions(args, defaultName) {
|
|
|
243821
244332
|
return { name, ...transform ? { transform } : {}, default: defaultValue };
|
|
243822
244333
|
}
|
|
243823
244334
|
function parseLiteralValue(node) {
|
|
243824
|
-
if (
|
|
244335
|
+
if (ts7.isStringLiteral(node))
|
|
243825
244336
|
return node.text;
|
|
243826
|
-
if (
|
|
244337
|
+
if (ts7.isNumericLiteral(node))
|
|
243827
244338
|
return Number(node.text);
|
|
243828
|
-
if (node.kind ===
|
|
244339
|
+
if (node.kind === ts7.SyntaxKind.TrueKeyword)
|
|
243829
244340
|
return true;
|
|
243830
|
-
if (node.kind ===
|
|
244341
|
+
if (node.kind === ts7.SyntaxKind.FalseKeyword)
|
|
243831
244342
|
return false;
|
|
243832
|
-
if (
|
|
244343
|
+
if (ts7.isArrayLiteralExpression(node)) {
|
|
243833
244344
|
return node.elements.map(parseLiteralValue);
|
|
243834
244345
|
}
|
|
243835
|
-
if (
|
|
244346
|
+
if (ts7.isObjectLiteralExpression(node)) {
|
|
243836
244347
|
return parseObjectLiteralValues(node);
|
|
243837
244348
|
}
|
|
243838
244349
|
return;
|
|
@@ -243840,7 +244351,7 @@ function parseLiteralValue(node) {
|
|
|
243840
244351
|
function parseObjectLiteralValues(obj) {
|
|
243841
244352
|
const result = {};
|
|
243842
244353
|
for (const prop of obj.properties) {
|
|
243843
|
-
if (
|
|
244354
|
+
if (ts7.isPropertyAssignment(prop)) {
|
|
243844
244355
|
const name = propertyName(prop.name);
|
|
243845
244356
|
const init = prop.initializer;
|
|
243846
244357
|
if (init) {
|
|
@@ -243857,7 +244368,7 @@ function sourcePath(rootDir, absFile) {
|
|
|
243857
244368
|
return relative22(rootDir, absFile).split(sep22).join("/");
|
|
243858
244369
|
}
|
|
243859
244370
|
function unwrapInfraResourceExpression(value) {
|
|
243860
|
-
while (
|
|
244371
|
+
while (ts7.isParenthesizedExpression(value) || ts7.isAsExpression(value) || ts7.isTypeAssertionExpression(value) || ts7.isSatisfiesExpression(value) || ts7.isNonNullExpression(value)) {
|
|
243861
244372
|
value = value.expression;
|
|
243862
244373
|
}
|
|
243863
244374
|
return value;
|
|
@@ -243867,7 +244378,7 @@ function infraResourceProp(obj, name, ctx) {
|
|
|
243867
244378
|
if (members.length === 0)
|
|
243868
244379
|
return;
|
|
243869
244380
|
const member = members[0];
|
|
243870
|
-
if (members.length !== 1 || !
|
|
244381
|
+
if (members.length !== 1 || !ts7.isPropertyAssignment(member) || ts7.isComputedPropertyName(member.name) || obj.properties.some(ts7.isSpreadAssignment)) {
|
|
243871
244382
|
pushResourceError(ctx, "unknown-resource", `${name} 必须是唯一、显式的静态属性,且不能被对象展开覆盖`, sourcePath(ctx.rootDir, obj.getSourceFile().fileName), lineOf(member), `使用 ${name}: [...],不要使用简写属性、计算属性或对象展开。`);
|
|
243872
244383
|
return;
|
|
243873
244384
|
}
|
|
@@ -243880,7 +244391,7 @@ function indexInfraResource(cls, className, sf, ctx) {
|
|
|
243880
244391
|
const file = sourcePath(ctx.rootDir, sf.fileName);
|
|
243881
244392
|
const line = lineOf(cls);
|
|
243882
244393
|
const options = decoratorObjectArg(decorator);
|
|
243883
|
-
if (!options || options.properties.some((property) => !
|
|
244394
|
+
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) {
|
|
243884
244395
|
pushResourceError(ctx, "invalid-resource-kind", "@InfraResource 需要静态的 { name, kind } 对象参数", file, line, '使用 @InfraResource({ name: "orders-db", kind: "database" }),不要使用对象展开或重复属性。');
|
|
243885
244396
|
return;
|
|
243886
244397
|
}
|
|
@@ -243911,14 +244422,14 @@ function indexInfraResource(cls, className, sf, ctx) {
|
|
|
243911
244422
|
}
|
|
243912
244423
|
function resolveInfraResourceRef(el, ctx, owner, file, line) {
|
|
243913
244424
|
const unwrapped = unwrapInfraResourceExpression(unwrapForwardRef(unwrapInfraResourceExpression(el)));
|
|
243914
|
-
const identifier =
|
|
244425
|
+
const identifier = ts7.isIdentifier(unwrapped) ? unwrapped : ts7.isPropertyAccessExpression(unwrapped) && ts7.isIdentifier(unwrapped.name) ? unwrapped.name : undefined;
|
|
243915
244426
|
let symbol = identifier ? ctx.checker.getSymbolAtLocation(identifier) : undefined;
|
|
243916
244427
|
const visited = new Set;
|
|
243917
|
-
while (symbol && symbol.flags &
|
|
244428
|
+
while (symbol && symbol.flags & ts7.SymbolFlags.Alias && !visited.has(symbol)) {
|
|
243918
244429
|
visited.add(symbol);
|
|
243919
244430
|
symbol = ctx.checker.getAliasedSymbol(symbol);
|
|
243920
244431
|
}
|
|
243921
|
-
const declaration = symbol?.declarations?.find(
|
|
244432
|
+
const declaration = symbol?.declarations?.find(ts7.isClassDeclaration);
|
|
243922
244433
|
const resource = declaration ? ctx.infraResources.get(declaration) : undefined;
|
|
243923
244434
|
if (!resource) {
|
|
243924
244435
|
pushResourceError(ctx, "unknown-resource", `${owner} 引用的资源 '${nodeText(el)}' 未声明为 @InfraResource`, file, line, "引用实际声明了 @InfraResource({ name, kind }) 的类,不能依赖其他文件的同名类。");
|
|
@@ -243931,7 +244442,7 @@ function parseModuleInfraResources(value, ctx, owner, file, line) {
|
|
|
243931
244442
|
if (!value)
|
|
243932
244443
|
return names;
|
|
243933
244444
|
const array = unwrapInfraResourceExpression(value);
|
|
243934
|
-
if (!
|
|
244445
|
+
if (!ts7.isArrayLiteralExpression(array)) {
|
|
243935
244446
|
pushResourceError(ctx, "unknown-resource", `${owner} 的 resources 必须是静态数组`, file, line, "使用 resources: [ResourceClass];省略该属性表示不声明资源。");
|
|
243936
244447
|
return names;
|
|
243937
244448
|
}
|
|
@@ -243946,14 +244457,14 @@ function parseInfraResourceUseRefs(value, ctx, owner, file, line) {
|
|
|
243946
244457
|
if (!value)
|
|
243947
244458
|
return [];
|
|
243948
244459
|
const array = unwrapInfraResourceExpression(value);
|
|
243949
|
-
if (!
|
|
244460
|
+
if (!ts7.isArrayLiteralExpression(array)) {
|
|
243950
244461
|
pushResourceError(ctx, "unknown-resource", `${owner} 的 uses 必须是静态数组`, file, line, '使用 uses: [{ resource: ResourceClass, operations: ["read"] }]。');
|
|
243951
244462
|
return [];
|
|
243952
244463
|
}
|
|
243953
244464
|
const uses = new Map;
|
|
243954
244465
|
for (const element of array.elements) {
|
|
243955
244466
|
const entry = unwrapInfraResourceExpression(element);
|
|
243956
|
-
if (!
|
|
244467
|
+
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) {
|
|
243957
244468
|
pushResourceError(ctx, "unknown-resource", `${owner} 的 uses 项必须是显式的 { resource, operations } 对象`, file, lineOf(element), "使用显式属性,不要使用对象/数组展开、简写、计算属性或重复属性。");
|
|
243958
244469
|
continue;
|
|
243959
244470
|
}
|
|
@@ -243971,14 +244482,14 @@ function parseInfraResourceUseRefs(value, ctx, owner, file, line) {
|
|
|
243971
244482
|
operations.add("read");
|
|
243972
244483
|
} else {
|
|
243973
244484
|
const operationArray = unwrapInfraResourceExpression(operationsEl);
|
|
243974
|
-
if (!
|
|
244485
|
+
if (!ts7.isArrayLiteralExpression(operationArray) || operationArray.elements.length === 0) {
|
|
243975
244486
|
pushResourceError(ctx, "invalid-resource-operation", `${owner} 对资源 '${resource}' 的 operations 必须是非空静态数组`, file, lineOf(operationsEl), "仅省略 operations 时默认 read;显式填写时必须包含有效操作。");
|
|
243976
244487
|
continue;
|
|
243977
244488
|
}
|
|
243978
244489
|
let invalid = false;
|
|
243979
244490
|
for (const operationEl of operationArray.elements) {
|
|
243980
244491
|
const operation = unwrapInfraResourceExpression(operationEl);
|
|
243981
|
-
if (!
|
|
244492
|
+
if (!ts7.isStringLiteral(operation) || !isInfraResourceOperation(operation.text)) {
|
|
243982
244493
|
pushResourceError(ctx, "invalid-resource-operation", `${owner} 对资源 '${resource}' 声明了无效操作 '${nodeText(operationEl)}'`, file, lineOf(operationEl), `operations 只能包含字符串字面量 ${INFRA_RESOURCE_OPERATIONS.join(" | ")}。`);
|
|
243983
244494
|
invalid = true;
|
|
243984
244495
|
continue;
|
|
@@ -244023,10 +244534,10 @@ var SQL_SAFETY_DIAGNOSTIC_CODES = {
|
|
|
244023
244534
|
function scanDrizzleSql(sourceFile, checker, file, strict) {
|
|
244024
244535
|
const diagnostics = [];
|
|
244025
244536
|
const importedSql = (expression) => {
|
|
244026
|
-
const symbol = checker.getSymbolAtLocation(
|
|
244537
|
+
const symbol = checker.getSymbolAtLocation(ts8.isPropertyAccessExpression(expression) ? expression.name : expression);
|
|
244027
244538
|
if (!symbol)
|
|
244028
244539
|
return false;
|
|
244029
|
-
const target = symbol.flags &
|
|
244540
|
+
const target = symbol.flags & ts8.SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol;
|
|
244030
244541
|
return target.name === "sql" && (target.declarations ?? []).some((declaration) => /(?:^|\/)node_modules\/drizzle-orm\//.test(declaration.getSourceFile().fileName.replaceAll("\\", "/")));
|
|
244031
244542
|
};
|
|
244032
244543
|
const report = (code, node, message) => {
|
|
@@ -244040,16 +244551,16 @@ function scanDrizzleSql(sourceFile, checker, file, strict) {
|
|
|
244040
244551
|
});
|
|
244041
244552
|
};
|
|
244042
244553
|
const visit = (node) => {
|
|
244043
|
-
if (
|
|
244554
|
+
if (ts8.isTaggedTemplateExpression(node) && importedSql(node.tag) && node.typeArguments?.some((type) => type.kind !== ts8.SyntaxKind.UnknownKeyword)) {
|
|
244044
244555
|
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.");
|
|
244045
244556
|
}
|
|
244046
|
-
if (
|
|
244557
|
+
if (ts8.isCallExpression(node) && ts8.isPropertyAccessExpression(node.expression) && node.expression.name.text === "raw" && importedSql(node.expression.expression)) {
|
|
244047
244558
|
const argument = node.arguments[0];
|
|
244048
|
-
if (!argument || !
|
|
244559
|
+
if (!argument || !ts8.isStringLiteral(argument) && !ts8.isNoSubstitutionTemplateLiteral(argument)) {
|
|
244049
244560
|
report("sql-raw-dynamic", node, "Dynamic sql.raw bypasses parameter binding. Interpolate values with sql templates; keep reviewed static DDL in migrations.");
|
|
244050
244561
|
}
|
|
244051
244562
|
}
|
|
244052
|
-
|
|
244563
|
+
ts8.forEachChild(node, visit);
|
|
244053
244564
|
};
|
|
244054
244565
|
visit(sourceFile);
|
|
244055
244566
|
return diagnostics;
|
|
@@ -244079,7 +244590,7 @@ function scanGeneratedArtifacts(artifacts, strict = true) {
|
|
|
244079
244590
|
for (const [file, content] of Object.entries(artifacts)) {
|
|
244080
244591
|
if (content === undefined)
|
|
244081
244592
|
continue;
|
|
244082
|
-
const sourceFile =
|
|
244593
|
+
const sourceFile = ts9.createSourceFile(file, content, ts9.ScriptTarget.Latest, true, ts9.ScriptKind.TS);
|
|
244083
244594
|
for (const node of descendantsOfKind2(sourceFile, isAnyKeyword)) {
|
|
244084
244595
|
diagnostics.push(makeDiagnostic("generated-any", `生成产物 ${file} 包含 any;严格生成模式要求使用 unknown、具体接口或泛型约束。`, sourceFile, node, strict));
|
|
244085
244596
|
}
|
|
@@ -244087,31 +244598,31 @@ function scanGeneratedArtifacts(artifacts, strict = true) {
|
|
|
244087
244598
|
return diagnostics;
|
|
244088
244599
|
}
|
|
244089
244600
|
function scanProductionSource(options) {
|
|
244090
|
-
const rootDir =
|
|
244091
|
-
const configPath =
|
|
244601
|
+
const rootDir = resolve32(options.rootDir);
|
|
244602
|
+
const configPath = ts9.findConfigFile(rootDir, ts9.sys.fileExists) ?? join32(rootDir, "tsconfig.json");
|
|
244092
244603
|
const projectConfig = existsSync22(configPath) ? readProjectConfig2(configPath) : {
|
|
244093
244604
|
options: {
|
|
244094
244605
|
strict: true,
|
|
244095
244606
|
skipLibCheck: true,
|
|
244096
|
-
target:
|
|
244097
|
-
module:
|
|
244098
|
-
moduleResolution:
|
|
244607
|
+
target: ts9.ScriptTarget.ES2022,
|
|
244608
|
+
module: ts9.ModuleKind.ESNext,
|
|
244609
|
+
moduleResolution: ts9.ModuleResolutionKind.Bundler
|
|
244099
244610
|
},
|
|
244100
244611
|
errors: []
|
|
244101
244612
|
};
|
|
244102
244613
|
const include = options.include ?? ["**/*.ts", "**/*.tsx", "**/*.mts", "**/*.cts"];
|
|
244103
|
-
const rootNames =
|
|
244614
|
+
const rootNames = ts9.sys.readDirectory(rootDir, [".ts", ".tsx", ".mts", ".cts"], ["node_modules", "dist"], include).filter((file) => isProductionSourcePath(rootDir, file, [...DEFAULT_EXCLUDES, ...options.exclude ?? []]));
|
|
244104
244615
|
const compilerOptions = { ...projectConfig.options, noEmit: true };
|
|
244105
|
-
const host =
|
|
244616
|
+
const host = ts9.createCompilerHost(compilerOptions);
|
|
244106
244617
|
host.getCurrentDirectory = () => dirname32(configPath);
|
|
244107
|
-
const program =
|
|
244618
|
+
const program = ts9.createProgram(rootNames, compilerOptions, host);
|
|
244108
244619
|
const outDir = options.outDir ? normalizeRelative(rootDir, options.outDir) : undefined;
|
|
244109
244620
|
const excludes = [...DEFAULT_EXCLUDES, ...options.exclude ?? []];
|
|
244110
244621
|
const sourceFiles = program.getSourceFiles().filter((sourceFile) => isProductionSource(rootDir, sourceFile, excludes, outDir));
|
|
244111
244622
|
const diagnostics = [...projectConfig.errors, ...program.getOptionsDiagnostics()].map((diagnostic) => ({
|
|
244112
244623
|
severity: "error",
|
|
244113
244624
|
code: "source-config",
|
|
244114
|
-
message:
|
|
244625
|
+
message: ts9.flattenDiagnosticMessageText(diagnostic.messageText, `
|
|
244115
244626
|
`),
|
|
244116
244627
|
file: diagnostic.file ? normalizeRelative(rootDir, diagnostic.file.fileName) : normalizeRelative(rootDir, configPath),
|
|
244117
244628
|
...diagnostic.file && diagnostic.start !== undefined ? { line: diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start).line + 1 } : {},
|
|
@@ -244128,7 +244639,7 @@ function scanProductionSource(options) {
|
|
|
244128
244639
|
diagnostics.push({
|
|
244129
244640
|
severity: "error",
|
|
244130
244641
|
code: "source-typescript",
|
|
244131
|
-
message:
|
|
244642
|
+
message: ts9.flattenDiagnosticMessageText(diagnostic.messageText, `
|
|
244132
244643
|
`),
|
|
244133
244644
|
...diagnostic.file ? { file: normalizeRelative(rootDir, diagnostic.file.fileName) } : {},
|
|
244134
244645
|
...diagnostic.file && diagnostic.start !== undefined ? { line: diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start).line + 1 } : {},
|
|
@@ -244138,9 +244649,9 @@ function scanProductionSource(options) {
|
|
|
244138
244649
|
for (const sourceFile of sourceFiles) {
|
|
244139
244650
|
scanSourceFile(sourceFile, checker, rootDir, diagnostics, options.strict ?? false);
|
|
244140
244651
|
diagnostics.push(...scanDrizzleSql(sourceFile, checker, normalizeRelative(rootDir, sourceFile.fileName), options.strict ?? false));
|
|
244141
|
-
const scanner =
|
|
244142
|
-
for (let kind = scanner.scan();kind !==
|
|
244143
|
-
if ((kind ===
|
|
244652
|
+
const scanner = ts9.createScanner(ts9.ScriptTarget.Latest, false, sourceFile.languageVariant, sourceFile.text);
|
|
244653
|
+
for (let kind = scanner.scan();kind !== ts9.SyntaxKind.EndOfFileToken; kind = scanner.scan()) {
|
|
244654
|
+
if ((kind === ts9.SyntaxKind.SingleLineCommentTrivia || kind === ts9.SyntaxKind.MultiLineCommentTrivia) && /@ts-(?:ignore|nocheck|expect-error)\b/.test(scanner.getTokenText())) {
|
|
244144
244655
|
diagnostics.push({
|
|
244145
244656
|
severity: "error",
|
|
244146
244657
|
code: "source-type-suppression",
|
|
@@ -244160,22 +244671,22 @@ function scanSourceFile(sourceFile, checker, rootDir, diagnostics, strict) {
|
|
|
244160
244671
|
diagnostics.push(makeDiagnostic("source-any", "生产源码使用了显式 any;请改用 unknown、具体接口或泛型约束。", sourceFile, node, strict, rootDir));
|
|
244161
244672
|
}
|
|
244162
244673
|
for (const node of descendants(sourceFile)) {
|
|
244163
|
-
if (
|
|
244164
|
-
if (
|
|
244674
|
+
if (ts9.isAsExpression(node)) {
|
|
244675
|
+
if (ts9.isAsExpression(node.parent) || ts9.isTypeAssertionExpression(node.parent))
|
|
244165
244676
|
continue;
|
|
244166
244677
|
const assertedType = node.type.getText(sourceFile);
|
|
244167
244678
|
if (assertedType === "const")
|
|
244168
244679
|
continue;
|
|
244169
244680
|
diagnostics.push(makeDiagnostic("source-type-assertion", `生产源码包含类型断言 ${node.getText(sourceFile)};请优先使用类型守卫、satisfies 或显式边界解析。`, sourceFile, node, strict, rootDir));
|
|
244170
|
-
} else if (
|
|
244171
|
-
if (
|
|
244681
|
+
} else if (ts9.isTypeAssertionExpression(node)) {
|
|
244682
|
+
if (ts9.isAsExpression(node.parent) || ts9.isTypeAssertionExpression(node.parent))
|
|
244172
244683
|
continue;
|
|
244173
244684
|
diagnostics.push(makeDiagnostic("source-type-assertion", `生产源码包含类型断言 ${node.getText(sourceFile)};请优先使用类型守卫、satisfies 或显式边界解析。`, sourceFile, node, strict, rootDir));
|
|
244174
|
-
} else if (
|
|
244685
|
+
} else if (ts9.isNonNullExpression(node)) {
|
|
244175
244686
|
diagnostics.push(makeDiagnostic("source-non-null-assertion", `生产源码包含非空断言 ${node.getText(sourceFile)};请显式处理 null/undefined。`, sourceFile, node, strict, rootDir));
|
|
244176
244687
|
}
|
|
244177
244688
|
}
|
|
244178
|
-
for (const declaration of descendantsOfKind2(sourceFile,
|
|
244689
|
+
for (const declaration of descendantsOfKind2(sourceFile, ts9.isVariableDeclaration)) {
|
|
244179
244690
|
const initializer = declaration.initializer;
|
|
244180
244691
|
if (!initializer || declaration.type)
|
|
244181
244692
|
continue;
|
|
@@ -244191,11 +244702,11 @@ function scanSourceFile(sourceFile, checker, rootDir, diagnostics, strict) {
|
|
|
244191
244702
|
if (isLetDeclaration(declaration) && isLiteralSyntax(initializer) && !isLiteralType(declarationType)) {
|
|
244192
244703
|
diagnostics.push(makeDiagnostic("source-implicit-widening", `变量 ${declaration.name.getText(sourceFile)} 的字面量类型从 ${checker.typeToString(initializerType, initializer)} 隐式宽化为 ${checker.typeToString(declarationType, declaration)};请补充类型或使用 const。`, sourceFile, declaration, strict, rootDir));
|
|
244193
244704
|
}
|
|
244194
|
-
if (
|
|
244705
|
+
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))) {
|
|
244195
244706
|
diagnostics.push(makeDiagnostic("source-implicit-widening", `常量对象 ${declaration.name.getText(sourceFile)} 的字面量属性会隐式宽化;请补充对象类型或使用 as const。`, sourceFile, declaration, strict, rootDir));
|
|
244196
244707
|
}
|
|
244197
244708
|
}
|
|
244198
|
-
for (const parameter of descendantsOfKind2(sourceFile,
|
|
244709
|
+
for (const parameter of descendantsOfKind2(sourceFile, ts9.isParameter)) {
|
|
244199
244710
|
if (parameter.type)
|
|
244200
244711
|
continue;
|
|
244201
244712
|
for (const name of bindingNames(parameter.name)) {
|
|
@@ -244206,10 +244717,10 @@ function scanSourceFile(sourceFile, checker, rootDir, diagnostics, strict) {
|
|
|
244206
244717
|
}
|
|
244207
244718
|
}
|
|
244208
244719
|
function readProjectConfig2(configPath) {
|
|
244209
|
-
const config =
|
|
244720
|
+
const config = ts9.readConfigFile(configPath, (file) => readFileSync22(file, "utf8"));
|
|
244210
244721
|
if (config.error)
|
|
244211
244722
|
return { options: {}, errors: [config.error] };
|
|
244212
|
-
const parsed =
|
|
244723
|
+
const parsed = ts9.parseJsonConfigFileContent(config.config, ts9.sys, dirname32(configPath));
|
|
244213
244724
|
return { options: parsed.options, errors: parsed.errors };
|
|
244214
244725
|
}
|
|
244215
244726
|
function isProductionSource(rootDir, sourceFile, excludes, outDir) {
|
|
@@ -244229,42 +244740,42 @@ function globMatches(value, pattern) {
|
|
|
244229
244740
|
return new RegExp(`^${escaped}$`).test(value);
|
|
244230
244741
|
}
|
|
244231
244742
|
function bindingNames(name) {
|
|
244232
|
-
if (
|
|
244743
|
+
if (ts9.isIdentifier(name))
|
|
244233
244744
|
return [name];
|
|
244234
|
-
return name.elements.flatMap((element) =>
|
|
244745
|
+
return name.elements.flatMap((element) => ts9.isBindingElement(element) ? bindingNames(element.name) : []);
|
|
244235
244746
|
}
|
|
244236
244747
|
function isLiteralExpression(node) {
|
|
244237
244748
|
if (!node)
|
|
244238
244749
|
return false;
|
|
244239
244750
|
return [
|
|
244240
|
-
|
|
244241
|
-
|
|
244242
|
-
|
|
244243
|
-
|
|
244751
|
+
ts9.SyntaxKind.StringLiteral,
|
|
244752
|
+
ts9.SyntaxKind.NumericLiteral,
|
|
244753
|
+
ts9.SyntaxKind.TrueKeyword,
|
|
244754
|
+
ts9.SyntaxKind.FalseKeyword
|
|
244244
244755
|
].includes(node.kind);
|
|
244245
244756
|
}
|
|
244246
244757
|
function isLiteralSyntax(node) {
|
|
244247
|
-
return
|
|
244758
|
+
return ts9.isStringLiteral(node) || ts9.isNumericLiteral(node) || node.kind === ts9.SyntaxKind.TrueKeyword || node.kind === ts9.SyntaxKind.FalseKeyword;
|
|
244248
244759
|
}
|
|
244249
244760
|
function isLiteralType(type) {
|
|
244250
|
-
return (type.flags & (
|
|
244761
|
+
return (type.flags & (ts9.TypeFlags.StringLiteral | ts9.TypeFlags.NumberLiteral | ts9.TypeFlags.BooleanLiteral | ts9.TypeFlags.BigIntLiteral)) !== 0;
|
|
244251
244762
|
}
|
|
244252
244763
|
function isAnyType(type) {
|
|
244253
|
-
return (type.flags &
|
|
244764
|
+
return (type.flags & ts9.TypeFlags.Any) !== 0;
|
|
244254
244765
|
}
|
|
244255
244766
|
function isLetDeclaration(declaration) {
|
|
244256
|
-
return
|
|
244767
|
+
return ts9.isVariableDeclarationList(declaration.parent) && (declaration.parent.flags & ts9.NodeFlags.Let) !== 0;
|
|
244257
244768
|
}
|
|
244258
244769
|
function isConstDeclaration(declaration) {
|
|
244259
|
-
return
|
|
244770
|
+
return ts9.isVariableDeclarationList(declaration.parent) && (declaration.parent.flags & ts9.NodeFlags.Const) !== 0;
|
|
244260
244771
|
}
|
|
244261
244772
|
function descendants(root) {
|
|
244262
244773
|
const result = [];
|
|
244263
244774
|
const visit = (node) => {
|
|
244264
244775
|
result.push(node);
|
|
244265
|
-
|
|
244776
|
+
ts9.forEachChild(node, visit);
|
|
244266
244777
|
};
|
|
244267
|
-
|
|
244778
|
+
ts9.forEachChild(root, visit);
|
|
244268
244779
|
return result;
|
|
244269
244780
|
}
|
|
244270
244781
|
function descendantsOfKind2(root, predicate) {
|
|
@@ -244272,9 +244783,9 @@ function descendantsOfKind2(root, predicate) {
|
|
|
244272
244783
|
const visit = (node) => {
|
|
244273
244784
|
if (predicate(node))
|
|
244274
244785
|
result.push(node);
|
|
244275
|
-
|
|
244786
|
+
ts9.forEachChild(node, visit);
|
|
244276
244787
|
};
|
|
244277
|
-
|
|
244788
|
+
ts9.forEachChild(root, visit);
|
|
244278
244789
|
return result;
|
|
244279
244790
|
}
|
|
244280
244791
|
function makeDiagnostic(code, message, fileOrSourceFile, node, strict, rootDir) {
|
|
@@ -244295,7 +244806,7 @@ function normalizeRelative(rootDir, filePath) {
|
|
|
244295
244806
|
return relative32(rootDir, filePath).split(sep32).join("/").replace(/^\.\//, "");
|
|
244296
244807
|
}
|
|
244297
244808
|
function isAnyKeyword(node) {
|
|
244298
|
-
return node.kind ===
|
|
244809
|
+
return node.kind === ts9.SyntaxKind.AnyKeyword;
|
|
244299
244810
|
}
|
|
244300
244811
|
init_route_contracts();
|
|
244301
244812
|
function withDefaultGovernance(options) {
|
|
@@ -245076,7 +245587,7 @@ async function prepareDeliveryMigrations(project, generatedRoot, declarations =
|
|
|
245076
245587
|
const inputs = new Map;
|
|
245077
245588
|
let totalBytes = 0;
|
|
245078
245589
|
for (const declaration of [...declarations].sort((a, b) => BigInt(a.version) < BigInt(b.version) ? -1 : BigInt(a.version) > BigInt(b.version) ? 1 : 0)) {
|
|
245079
|
-
const source =
|
|
245590
|
+
const source = resolve102(project, declaration.source);
|
|
245080
245591
|
if (!inside2(project, source) || inside2(generatedRoot, source))
|
|
245081
245592
|
throw new Error("Invalid migration source.");
|
|
245082
245593
|
const bytes = await readBoundedOwned2(project, source, 1048576);
|
|
@@ -245125,7 +245636,7 @@ async function buildDeliveryProject(options, delivery) {
|
|
|
245125
245636
|
const settings = parseDeliveryOptions(delivery);
|
|
245126
245637
|
if (typeof Bun === "undefined")
|
|
245127
245638
|
throw new Error("Independent delivery builds require Bun.");
|
|
245128
|
-
const configPath =
|
|
245639
|
+
const configPath = ts14.findConfigFile(resolve112(options.rootDir), ts14.sys.fileExists);
|
|
245129
245640
|
if (!configPath)
|
|
245130
245641
|
throw new Error("Independent delivery builds require a project tsconfig.json.");
|
|
245131
245642
|
const lexicalProject = dirname7(configPath);
|
|
@@ -245133,19 +245644,19 @@ async function buildDeliveryProject(options, delivery) {
|
|
|
245133
245644
|
const sourceRoot = await realpath32(options.rootDir);
|
|
245134
245645
|
if (!inside2(project, sourceRoot))
|
|
245135
245646
|
throw new Error("Application sources must be inside the project.");
|
|
245136
|
-
const requested =
|
|
245647
|
+
const requested = resolve112(options.outDir, "delivery");
|
|
245137
245648
|
if (!inside2(lexicalProject, requested))
|
|
245138
245649
|
throw new Error("Output must be inside the application project.");
|
|
245139
|
-
const buildRoot =
|
|
245140
|
-
const generatedRoot =
|
|
245650
|
+
const buildRoot = resolve112(project, relative7(lexicalProject, requested));
|
|
245651
|
+
const generatedRoot = resolve112(project, relative7(lexicalProject, options.outDir));
|
|
245141
245652
|
if (inside2(generatedRoot, sourceRoot))
|
|
245142
245653
|
throw new Error("Output must not contain the application source root.");
|
|
245143
245654
|
const configInputs = new Map;
|
|
245144
|
-
const parsedConfig =
|
|
245145
|
-
...
|
|
245655
|
+
const parsedConfig = ts14.getParsedCommandLineOfConfigFile(await realpath32(configPath), {}, {
|
|
245656
|
+
...ts14.sys,
|
|
245146
245657
|
readFile(path) {
|
|
245147
245658
|
const contents = readFileSync32(path, "utf8");
|
|
245148
|
-
configInputs.set(
|
|
245659
|
+
configInputs.set(resolve112(path), digest3(contents));
|
|
245149
245660
|
return contents;
|
|
245150
245661
|
},
|
|
245151
245662
|
onUnRecoverableConfigFileDiagnostic() {
|
|
@@ -245183,7 +245694,7 @@ async function buildDeliveryProject(options, delivery) {
|
|
|
245183
245694
|
if (!target || (kind === "worker" ? target.kind !== "jobs" : target.kind === "jobs")) {
|
|
245184
245695
|
throw new Error("Delivery host kind does not match its target.");
|
|
245185
245696
|
}
|
|
245186
|
-
const path =
|
|
245697
|
+
const path = resolve112(sourceRoot, app.source);
|
|
245187
245698
|
if (inside2(generatedRoot, path) || !/\.[cm]?ts$/.test(path))
|
|
245188
245699
|
throw new Error("Hosts require application TypeScript source.");
|
|
245189
245700
|
hosts.set(app.target, { path, kind, hash: digest3(await readOwned(sourceRoot, path)) });
|
|
@@ -245262,7 +245773,7 @@ async function buildDeliveryProject(options, delivery) {
|
|
|
245262
245773
|
for (const [name, contents] of Object.entries(generated))
|
|
245263
245774
|
await writeArtifact(stage, `generated/${name}`, contents);
|
|
245264
245775
|
{
|
|
245265
|
-
const program =
|
|
245776
|
+
const program = ts14.createProgram({
|
|
245266
245777
|
rootNames: [
|
|
245267
245778
|
...parsedConfig.fileNames.filter((path) => !inside2(generatedRoot, path)),
|
|
245268
245779
|
...Object.keys(generated).map((name) => join92(stage, "generated", name))
|
|
@@ -245270,12 +245781,12 @@ async function buildDeliveryProject(options, delivery) {
|
|
|
245270
245781
|
options: { ...parsedConfig.options, rootDir: project },
|
|
245271
245782
|
...parsedConfig.projectReferences ? { projectReferences: parsedConfig.projectReferences } : {}
|
|
245272
245783
|
});
|
|
245273
|
-
const diagnostics =
|
|
245274
|
-
if (diagnostics.some((item) => item.category ===
|
|
245275
|
-
return failed(diagnostics.filter((item) => item.category ===
|
|
245784
|
+
const diagnostics = ts14.getPreEmitDiagnostics(program);
|
|
245785
|
+
if (diagnostics.some((item) => item.category === ts14.DiagnosticCategory.Error)) {
|
|
245786
|
+
return failed(diagnostics.filter((item) => item.category === ts14.DiagnosticCategory.Error).map((item) => ({
|
|
245276
245787
|
severity: "error",
|
|
245277
245788
|
code: "delivery-generated-type-error",
|
|
245278
|
-
message:
|
|
245789
|
+
message: ts14.flattenDiagnosticMessageText(item.messageText, `
|
|
245279
245790
|
`),
|
|
245280
245791
|
...item.file ? { file: item.file.fileName } : {}
|
|
245281
245792
|
})));
|
|
@@ -245310,7 +245821,7 @@ async function buildDeliveryProject(options, delivery) {
|
|
|
245310
245821
|
}));
|
|
245311
245822
|
const assetInputs = {};
|
|
245312
245823
|
for (const asset of assets.filter((asset) => asset.target === target.name)) {
|
|
245313
|
-
const path =
|
|
245824
|
+
const path = resolve112(sourceRoot, asset.source);
|
|
245314
245825
|
const bytes = await readOwned(sourceRoot, path);
|
|
245315
245826
|
const hash = digest3(bytes);
|
|
245316
245827
|
const previousHash = snapshots.get(path);
|
|
@@ -245419,202 +245930,7 @@ async function buildDeliveryProject(options, delivery) {
|
|
|
245419
245930
|
}
|
|
245420
245931
|
init_delivery_migration_archive2();
|
|
245421
245932
|
init_feature();
|
|
245422
|
-
|
|
245423
|
-
if (!fix || typeof fix.targetFile !== "string")
|
|
245424
|
-
throw new Error("Invalid DiagnosticFix");
|
|
245425
|
-
const root = await realpath4(options.rootDir ?? process.cwd());
|
|
245426
|
-
const file = resolve112(root, fix.targetFile);
|
|
245427
|
-
const stat = await lstat22(file);
|
|
245428
|
-
const resolved = await realpath4(file);
|
|
245429
|
-
const relativePath = relative8(root, resolved);
|
|
245430
|
-
if (stat.isSymbolicLink() || !stat.isFile() || isAbsolute32(relativePath) || relativePath === ".." || relativePath.startsWith(`..${sep8}`)) {
|
|
245431
|
-
throw new Error("Fix target must be a regular file inside rootDir");
|
|
245432
|
-
}
|
|
245433
|
-
const original = await readFile6(file, "utf8");
|
|
245434
|
-
let source = parse52(file, original);
|
|
245435
|
-
let content;
|
|
245436
|
-
switch (fix.type) {
|
|
245437
|
-
case "set_command_mode": {
|
|
245438
|
-
if (fix.property !== "transaction" && fix.property !== "idempotency" || fix.value !== "required" && fix.value !== "none") {
|
|
245439
|
-
throw new Error("Command mode fix requires an explicit property and policy value");
|
|
245440
|
-
}
|
|
245441
|
-
const object = decoratorObject(findClass(source, fix.command), "Command");
|
|
245442
|
-
const current = property(object, fix.property);
|
|
245443
|
-
if (!current || current.initializer.getText(source) !== fix.expectedExpression) {
|
|
245444
|
-
throw new Error("Command mode changed since diagnosis; analyze the project again");
|
|
245445
|
-
}
|
|
245446
|
-
content = replaceProperty(source, object, fix.property, ts12.factory.createStringLiteral(fix.value));
|
|
245447
|
-
break;
|
|
245448
|
-
}
|
|
245449
|
-
case "add_module_import": {
|
|
245450
|
-
if (!fix.importPath || !fix.symbol)
|
|
245451
|
-
throw new Error("Module fix requires importPath and symbol");
|
|
245452
|
-
identifier2(fix.symbol);
|
|
245453
|
-
const withImport = importSymbol(source, fix.importPath, fix.symbol);
|
|
245454
|
-
source = parse52(file, withImport);
|
|
245455
|
-
const object = unique2(moduleObjects(source).filter((candidate) => !fix.targetModule || stringProperty(candidate, "name") === fix.targetModule), "target module");
|
|
245456
|
-
const imports = property(object, "imports");
|
|
245457
|
-
if (imports && !ts12.isArrayLiteralExpression(imports.initializer)) {
|
|
245458
|
-
throw new Error("Module imports must be a static array");
|
|
245459
|
-
}
|
|
245460
|
-
const values = imports && ts12.isArrayLiteralExpression(imports.initializer) ? imports.initializer.elements : [];
|
|
245461
|
-
if (values.some(ts12.isSpreadElement))
|
|
245462
|
-
throw new Error("Module imports cannot contain spread elements");
|
|
245463
|
-
content = values.some((value) => ts12.isIdentifier(value) && value.text === fix.symbol) ? withImport : replaceProperty(source, object, "imports", ts12.factory.createArrayLiteralExpression([
|
|
245464
|
-
...values,
|
|
245465
|
-
ts12.factory.createIdentifier(fix.symbol)
|
|
245466
|
-
]));
|
|
245467
|
-
break;
|
|
245468
|
-
}
|
|
245469
|
-
case "add_command_permission": {
|
|
245470
|
-
const permission = options.permission ?? fix.permission;
|
|
245471
|
-
if (!permission?.trim()) {
|
|
245472
|
-
throw new Error("Permission fix requires an explicit permission; privileges are never inferred");
|
|
245473
|
-
}
|
|
245474
|
-
const command = findClass(source, fix.command);
|
|
245475
|
-
const object = decoratorObject(command, "Command");
|
|
245476
|
-
const current = property(object, "permission");
|
|
245477
|
-
if (current && (!ts12.isStringLiteral(current.initializer) || current.initializer.text !== permission)) {
|
|
245478
|
-
throw new Error("Command permission already exists with a different value");
|
|
245479
|
-
}
|
|
245480
|
-
content = current ? original : replaceProperty(source, object, "permission", ts12.factory.createStringLiteral(permission));
|
|
245481
|
-
break;
|
|
245482
|
-
}
|
|
245483
|
-
case "add_route_parameter_binding": {
|
|
245484
|
-
const controller = findClass(source, fix.controller);
|
|
245485
|
-
const method = unique2(controller.members.filter((member) => ts12.isMethodDeclaration(member) && nameOf(member.name) === fix.route), "route handler");
|
|
245486
|
-
const parameter = unique2(method.parameters.filter((candidate) => ts12.isIdentifier(candidate.name) && candidate.name.text === fix.parameter), "same-named route parameter");
|
|
245487
|
-
const binding = fix.binding === "param" ? "Param" : fix.binding === "query" ? "Query" : undefined;
|
|
245488
|
-
if (!binding)
|
|
245489
|
-
throw new Error("Invalid route binding");
|
|
245490
|
-
const decorators = ts12.getDecorators(parameter) ?? [];
|
|
245491
|
-
if (decorators.length > 0)
|
|
245492
|
-
throw new Error("Parameter already has a decorator");
|
|
245493
|
-
const framework = unique2(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");
|
|
245494
|
-
if (!ts12.isImportDeclaration(framework) || !ts12.isStringLiteral(framework.moduleSpecifier)) {
|
|
245495
|
-
throw new Error("Framework import must be static");
|
|
245496
|
-
}
|
|
245497
|
-
const edited = original.slice(0, parameter.getStart(source)) + `@${binding}(${JSON.stringify(fix.parameter)}) ` + original.slice(parameter.getStart(source));
|
|
245498
|
-
content = importSymbol(parse52(file, edited), framework.moduleSpecifier.text, binding);
|
|
245499
|
-
break;
|
|
245500
|
-
}
|
|
245501
|
-
default:
|
|
245502
|
-
throw new Error(`Diagnostic fix '${fix.type}' requires a manual semantic decision; no files changed`);
|
|
245503
|
-
}
|
|
245504
|
-
parse52(file, content);
|
|
245505
|
-
const result = { file, changed: content !== original, content };
|
|
245506
|
-
if (options.dryRun === false && result.changed) {
|
|
245507
|
-
const temporary = `${file}.supacloud-fix-${randomUUID()}`;
|
|
245508
|
-
try {
|
|
245509
|
-
await writeFile3(temporary, content, { encoding: "utf8", flag: "wx", mode: stat.mode });
|
|
245510
|
-
if (await readFile6(file, "utf8") !== original)
|
|
245511
|
-
throw new Error("Target changed while preparing the fix");
|
|
245512
|
-
await rename4(temporary, file);
|
|
245513
|
-
} finally {
|
|
245514
|
-
await unlink2(temporary).catch(() => {});
|
|
245515
|
-
}
|
|
245516
|
-
}
|
|
245517
|
-
return result;
|
|
245518
|
-
}
|
|
245519
|
-
function parse52(file, text) {
|
|
245520
|
-
const result = ts12.transpileModule(text, {
|
|
245521
|
-
fileName: file,
|
|
245522
|
-
reportDiagnostics: true,
|
|
245523
|
-
compilerOptions: { target: ts12.ScriptTarget.ESNext, experimentalDecorators: true }
|
|
245524
|
-
});
|
|
245525
|
-
if (result.diagnostics?.some((item) => item.category === ts12.DiagnosticCategory.Error)) {
|
|
245526
|
-
throw new Error("Cannot fix syntactically invalid TypeScript");
|
|
245527
|
-
}
|
|
245528
|
-
return ts12.createSourceFile(file, text, ts12.ScriptTarget.Latest, true, ts12.ScriptKind.TS);
|
|
245529
|
-
}
|
|
245530
|
-
function unique2(items, description) {
|
|
245531
|
-
if (items.length !== 1)
|
|
245532
|
-
throw new Error(`Expected exactly one ${description}; found ${items.length}`);
|
|
245533
|
-
return items[0];
|
|
245534
|
-
}
|
|
245535
|
-
function identifier2(value) {
|
|
245536
|
-
if (!/^[A-Za-z_$][\w$]*$/.test(value))
|
|
245537
|
-
throw new Error(`Invalid identifier '${value}'`);
|
|
245538
|
-
}
|
|
245539
|
-
function nameOf(name) {
|
|
245540
|
-
if (!name)
|
|
245541
|
-
return "";
|
|
245542
|
-
return ts12.isIdentifier(name) || ts12.isStringLiteral(name) || ts12.isNumericLiteral(name) ? name.text : "";
|
|
245543
|
-
}
|
|
245544
|
-
function property(object, key) {
|
|
245545
|
-
if (object.properties.some((item) => !ts12.isPropertyAssignment(item) || ts12.isComputedPropertyName(item.name))) {
|
|
245546
|
-
throw new Error("Fix requires explicit static object properties");
|
|
245547
|
-
}
|
|
245548
|
-
const values = object.properties.filter((item) => ts12.isPropertyAssignment(item) && nameOf(item.name) === key);
|
|
245549
|
-
if (values.length > 1)
|
|
245550
|
-
throw new Error(`Duplicate '${key}' property`);
|
|
245551
|
-
return values[0];
|
|
245552
|
-
}
|
|
245553
|
-
function stringProperty(object, key) {
|
|
245554
|
-
const value = property(object, key)?.initializer;
|
|
245555
|
-
return value && ts12.isStringLiteral(value) ? value.text : undefined;
|
|
245556
|
-
}
|
|
245557
|
-
function replaceProperty(source, object, key, value) {
|
|
245558
|
-
const previous = property(object, key);
|
|
245559
|
-
const replacement = ts12.factory.createPropertyAssignment(key, value);
|
|
245560
|
-
const properties = object.properties.map((item) => item === previous ? replacement : item);
|
|
245561
|
-
if (!previous)
|
|
245562
|
-
properties.push(replacement);
|
|
245563
|
-
const updated = ts12.factory.updateObjectLiteralExpression(object, properties);
|
|
245564
|
-
return source.text.slice(0, object.getStart(source)) + ts12.createPrinter().printNode(ts12.EmitHint.Expression, updated, source) + source.text.slice(object.end);
|
|
245565
|
-
}
|
|
245566
|
-
function findClass(source, name) {
|
|
245567
|
-
return unique2(source.statements.filter((statement) => ts12.isClassDeclaration(statement) && statement.name?.text === name), `class '${name}'`);
|
|
245568
|
-
}
|
|
245569
|
-
function decoratorObject(node, name) {
|
|
245570
|
-
const decorator = unique2((ts12.getDecorators(node) ?? []).filter((item) => ts12.isCallExpression(item.expression) && item.expression.expression.getText() === name), `@${name} decorator`);
|
|
245571
|
-
const argument = ts12.isCallExpression(decorator.expression) ? decorator.expression.arguments[0] : undefined;
|
|
245572
|
-
if (!argument || !ts12.isObjectLiteralExpression(argument))
|
|
245573
|
-
throw new Error(`@${name} requires a static object`);
|
|
245574
|
-
return argument;
|
|
245575
|
-
}
|
|
245576
|
-
function moduleObjects(source) {
|
|
245577
|
-
const result = [];
|
|
245578
|
-
for (const statement of source.statements) {
|
|
245579
|
-
if (ts12.isClassDeclaration(statement) && (ts12.getDecorators(statement) ?? []).some((item) => ts12.isCallExpression(item.expression) && item.expression.expression.getText() === "Module")) {
|
|
245580
|
-
result.push(decoratorObject(statement, "Module"));
|
|
245581
|
-
}
|
|
245582
|
-
if (ts12.isVariableStatement(statement)) {
|
|
245583
|
-
for (const declaration of statement.declarationList.declarations) {
|
|
245584
|
-
const call = declaration.initializer;
|
|
245585
|
-
if (call && ts12.isCallExpression(call) && ["defineModule", "defineFeatureSlice"].includes(call.expression.getText()) && call.arguments[0] && ts12.isObjectLiteralExpression(call.arguments[0])) {
|
|
245586
|
-
result.push(call.arguments[0]);
|
|
245587
|
-
}
|
|
245588
|
-
}
|
|
245589
|
-
}
|
|
245590
|
-
}
|
|
245591
|
-
return result;
|
|
245592
|
-
}
|
|
245593
|
-
function importSymbol(source, path, symbol) {
|
|
245594
|
-
identifier2(symbol);
|
|
245595
|
-
const current = resolve112(source.fileName).replace(/\.(tsx?|mts|cts)$/, "");
|
|
245596
|
-
const target = resolve112(dirname8(source.fileName), path).replace(/\.(tsx?|mts|cts)$/, "");
|
|
245597
|
-
if (current === target)
|
|
245598
|
-
return source.text;
|
|
245599
|
-
const matches = source.statements.filter((item) => ts12.isImportDeclaration(item) && ts12.isStringLiteral(item.moduleSpecifier) && item.moduleSpecifier.text === path);
|
|
245600
|
-
if (matches.length > 1)
|
|
245601
|
-
throw new Error(`Ambiguous imports from '${path}'`);
|
|
245602
|
-
const match = matches[0];
|
|
245603
|
-
if (match && ts12.isImportDeclaration(match) && match.importClause?.namedBindings && ts12.isNamedImports(match.importClause.namedBindings) && !match.importClause.isTypeOnly) {
|
|
245604
|
-
if (match.importClause.namedBindings.elements.some((item) => item.name.text === symbol))
|
|
245605
|
-
return source.text;
|
|
245606
|
-
const bindings = match.importClause.namedBindings;
|
|
245607
|
-
const updated = ts12.factory.updateNamedImports(bindings, [
|
|
245608
|
-
...bindings.elements,
|
|
245609
|
-
ts12.factory.createImportSpecifier(false, undefined, ts12.factory.createIdentifier(symbol))
|
|
245610
|
-
]);
|
|
245611
|
-
return source.text.slice(0, bindings.getStart(source)) + ts12.createPrinter().printNode(ts12.EmitHint.Unspecified, updated, source) + source.text.slice(bindings.end);
|
|
245612
|
-
}
|
|
245613
|
-
if (match)
|
|
245614
|
-
throw new Error(`Import from '${path}' is not a named value import`);
|
|
245615
|
-
return `import { ${symbol} } from ${JSON.stringify(path)};
|
|
245616
|
-
${source.text}`;
|
|
245617
|
-
}
|
|
245933
|
+
init_fixes();
|
|
245618
245934
|
init_execution_context();
|
|
245619
245935
|
init_delivery_context();
|
|
245620
245936
|
init_application_development2();
|
|
@@ -245712,11 +246028,11 @@ async function readSourceBytes(path) {
|
|
|
245712
246028
|
return readFile7(path);
|
|
245713
246029
|
}
|
|
245714
246030
|
async function updateSnapshot(previous, options, changedPaths) {
|
|
245715
|
-
const rootDir =
|
|
245716
|
-
const outDir =
|
|
246031
|
+
const rootDir = resolve132(options.rootDir);
|
|
246032
|
+
const outDir = resolve132(options.outDir);
|
|
245717
246033
|
const files = { ...previous.files };
|
|
245718
246034
|
await Promise.all(changedPaths.map(async (changedPath) => {
|
|
245719
|
-
const absolutePath = isAbsolute42(changedPath) ?
|
|
246035
|
+
const absolutePath = isAbsolute42(changedPath) ? resolve132(changedPath) : resolve132(rootDir, changedPath);
|
|
245720
246036
|
const relativeChangedPath = relative9(rootDir, absolutePath);
|
|
245721
246037
|
if (relativeChangedPath === ".." || relativeChangedPath.startsWith(`..${sep9}`))
|
|
245722
246038
|
return;
|
|
@@ -245726,7 +246042,7 @@ async function updateSnapshot(previous, options, changedPaths) {
|
|
|
245726
246042
|
try {
|
|
245727
246043
|
await access3(absolutePath);
|
|
245728
246044
|
const content = await readSourceBytes(absolutePath);
|
|
245729
|
-
files[relativePath] =
|
|
246045
|
+
files[relativePath] = createHash92("sha256").update(content).digest("hex");
|
|
245730
246046
|
} catch {
|
|
245731
246047
|
delete files[relativePath];
|
|
245732
246048
|
}
|
|
@@ -245734,14 +246050,14 @@ async function updateSnapshot(previous, options, changedPaths) {
|
|
|
245734
246050
|
return { files, optionsKey: optionsKeyOf(options) };
|
|
245735
246051
|
}
|
|
245736
246052
|
async function createSnapshot(options) {
|
|
245737
|
-
const rootDir =
|
|
245738
|
-
const outDir =
|
|
246053
|
+
const rootDir = resolve132(options.rootDir);
|
|
246054
|
+
const outDir = resolve132(options.outDir);
|
|
245739
246055
|
const paths = await listSourceFiles(rootDir, outDir);
|
|
245740
246056
|
const files = {};
|
|
245741
246057
|
const entries = await Promise.all(paths.map(async (path) => {
|
|
245742
246058
|
const content = await readSourceBytes(path);
|
|
245743
246059
|
const key = relative9(rootDir, path).split(sep9).join("/");
|
|
245744
|
-
return [key,
|
|
246060
|
+
return [key, createHash92("sha256").update(content).digest("hex")];
|
|
245745
246061
|
}));
|
|
245746
246062
|
for (const [key, hash] of entries)
|
|
245747
246063
|
files[key] = hash;
|
|
@@ -245749,7 +246065,7 @@ async function createSnapshot(options) {
|
|
|
245749
246065
|
const key = relative9(rootDir, path).split(sep9).join("/");
|
|
245750
246066
|
try {
|
|
245751
246067
|
const content = await readSourceBytes(path);
|
|
245752
|
-
files[key] =
|
|
246068
|
+
files[key] = createHash92("sha256").update(content).digest("hex");
|
|
245753
246069
|
} catch {
|
|
245754
246070
|
files[key] = "missing";
|
|
245755
246071
|
}
|
|
@@ -245758,8 +246074,8 @@ async function createSnapshot(options) {
|
|
|
245758
246074
|
}
|
|
245759
246075
|
function optionsKeyOf(options) {
|
|
245760
246076
|
return JSON.stringify({
|
|
245761
|
-
rootDir:
|
|
245762
|
-
outDir:
|
|
246077
|
+
rootDir: resolve132(options.rootDir),
|
|
246078
|
+
outDir: resolve132(options.outDir),
|
|
245763
246079
|
include: options.include,
|
|
245764
246080
|
strict: options.strict,
|
|
245765
246081
|
writeOnError: options.writeOnError,
|
|
@@ -245783,7 +246099,7 @@ async function listSourceFiles(rootDir, outDir) {
|
|
|
245783
246099
|
const result = [];
|
|
245784
246100
|
const visit = async (directory) => {
|
|
245785
246101
|
for (const entry of await readdir32(directory, { withFileTypes: true })) {
|
|
245786
|
-
const path =
|
|
246102
|
+
const path = resolve132(directory, entry.name);
|
|
245787
246103
|
if (entry.isDirectory()) {
|
|
245788
246104
|
if (entry.name === "node_modules" || entry.name === ".git" || path === outDir)
|
|
245789
246105
|
continue;
|
|
@@ -245916,8 +246232,8 @@ function isCompilerConfigurationPath(rootDir, changedPath) {
|
|
|
245916
246232
|
].includes(relativePath) || /^tsconfig\.[^/]+\.json$/.test(relativePath);
|
|
245917
246233
|
}
|
|
245918
246234
|
function watchProject(options) {
|
|
245919
|
-
const rootDir =
|
|
245920
|
-
const outDir =
|
|
246235
|
+
const rootDir = resolve14(options.rootDir);
|
|
246236
|
+
const outDir = resolve14(options.outDir);
|
|
245921
246237
|
const debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;
|
|
245922
246238
|
let timer;
|
|
245923
246239
|
let closed = false;
|
|
@@ -245927,7 +246243,7 @@ function watchProject(options) {
|
|
|
245927
246243
|
const pendingPaths = new Set;
|
|
245928
246244
|
let watcher;
|
|
245929
246245
|
let schemaWatcher;
|
|
245930
|
-
const schemaPath = options.graphql ?
|
|
246246
|
+
const schemaPath = options.graphql ? resolve14(rootDir, options.graphql.schema) : undefined;
|
|
245931
246247
|
const incremental = createIncrementalCompiler();
|
|
245932
246248
|
let initialEvent;
|
|
245933
246249
|
let resolveReady = () => {
|
|
@@ -246037,7 +246353,7 @@ function watchProject(options) {
|
|
|
246037
246353
|
watcher = watch(rootDir, { recursive: true }, (_eventType, filename) => {
|
|
246038
246354
|
if (!filename)
|
|
246039
246355
|
return schedule();
|
|
246040
|
-
const changedPath =
|
|
246356
|
+
const changedPath = resolve14(rootDir, filename.toString());
|
|
246041
246357
|
const relativePath = relative10(outDir, changedPath);
|
|
246042
246358
|
if (!relativePath.startsWith("..") && relativePath !== "")
|
|
246043
246359
|
return;
|
|
@@ -246050,7 +246366,7 @@ function watchProject(options) {
|
|
|
246050
246366
|
while (!existsSync42(directory) && dirname9(directory) !== directory)
|
|
246051
246367
|
directory = dirname9(directory);
|
|
246052
246368
|
schemaWatcher = watch(directory, { recursive: true }, (_eventType, filename) => {
|
|
246053
|
-
if (!filename ||
|
|
246369
|
+
if (!filename || resolve14(directory, filename.toString()) === schemaPath)
|
|
246054
246370
|
schedule(schemaPath);
|
|
246055
246371
|
});
|
|
246056
246372
|
}
|
|
@@ -246073,9 +246389,9 @@ function watchProject(options) {
|
|
|
246073
246389
|
}
|
|
246074
246390
|
var ROUTE_DECORATORS2 = new Set(["Get", "Post", "Put", "Patch", "Delete", "Head", "Options"]);
|
|
246075
246391
|
var MIGRATION_COMPILER_OPTIONS = {
|
|
246076
|
-
target:
|
|
246077
|
-
module:
|
|
246078
|
-
moduleResolution:
|
|
246392
|
+
target: ts16.ScriptTarget.ES2022,
|
|
246393
|
+
module: ts16.ModuleKind.ESNext,
|
|
246394
|
+
moduleResolution: ts16.ModuleResolutionKind.Bundler,
|
|
246079
246395
|
noEmit: true,
|
|
246080
246396
|
skipLibCheck: true
|
|
246081
246397
|
};
|
|
@@ -246175,8 +246491,8 @@ function validateGovernanceConfig(config) {
|
|
|
246175
246491
|
function resolveSupacloudConfig(config = {}, cwd = process.cwd()) {
|
|
246176
246492
|
const resolved = defineSupacloudConfig(config);
|
|
246177
246493
|
return {
|
|
246178
|
-
rootDir:
|
|
246179
|
-
outDir:
|
|
246494
|
+
rootDir: resolve19(cwd, resolved.root ?? DEFAULT_SUPACLOUD_CONFIG.root),
|
|
246495
|
+
outDir: resolve19(cwd, resolved.outDir ?? DEFAULT_SUPACLOUD_CONFIG.outDir),
|
|
246180
246496
|
include: resolved.include ?? [...DEFAULT_SUPACLOUD_CONFIG.include],
|
|
246181
246497
|
strict: resolved.strict ?? DEFAULT_SUPACLOUD_CONFIG.strict,
|
|
246182
246498
|
requireRouteContracts: resolved.requireRouteContracts ?? DEFAULT_SUPACLOUD_CONFIG.requireRouteContracts,
|
|
@@ -246194,7 +246510,7 @@ function resolveSupacloudConfig(config = {}, cwd = process.cwd()) {
|
|
|
246194
246510
|
treeShakeUnusedProviders: resolved.treeShakeUnusedProviders ?? DEFAULT_SUPACLOUD_CONFIG.treeShakeUnusedProviders,
|
|
246195
246511
|
graphql: resolved.graphql ? {
|
|
246196
246512
|
...resolved.graphql,
|
|
246197
|
-
schema:
|
|
246513
|
+
schema: resolve19(cwd, resolved.graphql.schema)
|
|
246198
246514
|
} : undefined
|
|
246199
246515
|
};
|
|
246200
246516
|
}
|
|
@@ -246333,9 +246649,99 @@ function buildToolDefinitions(manifest) {
|
|
|
246333
246649
|
return { openai, mcp };
|
|
246334
246650
|
}
|
|
246335
246651
|
|
|
246652
|
+
// src/shared/tools/app-starter-reactive.ts
|
|
246653
|
+
var STARTER_REACTIVE_GUIDE = `# Reactive development / 响应式开发
|
|
246654
|
+
|
|
246655
|
+
RxJS is installed by default. Ordinary queries and business commands still use
|
|
246656
|
+
async/await. Use RxJS for ongoing events and timing/composition, not as a new
|
|
246657
|
+
transaction, retry or durable-delivery system.
|
|
246658
|
+
|
|
246659
|
+
Host defaults:
|
|
246660
|
+
- In a native Angular host, use signal/resource APIs from @supacloud/app/angular
|
|
246661
|
+
and Angular's scheduler. Do not mix them with the legacy root signal graph.
|
|
246662
|
+
- In framework-neutral code, use async/await for one result and RxJS for event
|
|
246663
|
+
composition. The host owns cancellation through an explicit signal.
|
|
246664
|
+
|
|
246665
|
+
- Import native operators from rxjs; do not invent another event/operator library.
|
|
246666
|
+
- Import takeUntilAborted / toReadableStream from @supacloud/app/reactive.
|
|
246667
|
+
- Every subscription belongs to a request, connection, task or application owner.
|
|
246668
|
+
Bind the owner's AbortSignal before starting work; release it on exit.
|
|
246669
|
+
- toReadableStream has a bounded item buffer and fails on overflow. It is not
|
|
246670
|
+
an event journal. Do not silently drop durable business events or audit records.
|
|
246671
|
+
- Never wrap command submission in defer/retry/repeat or submit from subscribe.
|
|
246672
|
+
Await the existing governed command and then observe its existing receipt.
|
|
246673
|
+
- Do not shareReplay authenticated values globally across projects or sessions.
|
|
246674
|
+
- subscribe(async ...) does not await processing. Keep acknowledged task-output
|
|
246675
|
+
consumers on the SDK's for-await watch path; do not advance onCursor via next().
|
|
246676
|
+
|
|
246677
|
+
## SupaCloud JS
|
|
246678
|
+
|
|
246679
|
+
The platform SDK is @supacloud/js, not a replacement Supabase client. Keep the
|
|
246680
|
+
client from createSupaCloudClient. Database/Auth/Storage calls use client.supabase;
|
|
246681
|
+
platform commands/tasks use the existing client.commands / client.tasks APIs.
|
|
246682
|
+
For applications using this SDK, import observeQuery and observeTask from
|
|
246683
|
+
@supacloud/js/reactive. Pass the request signal to the native query builder:
|
|
246684
|
+
|
|
246685
|
+
observeQuery(signal => client.supabase.from("widgets").select("id").abortSignal(signal), { signal: owner.signal })
|
|
246686
|
+
|
|
246687
|
+
The query result keeps data/error/count/status; non-null errors enter error().
|
|
246688
|
+
The query factory runs once per subscriber. This is intended for reads, not
|
|
246689
|
+
replaying writes. A PromiseLike is supported; an already-started Promise is not
|
|
246690
|
+
an appropriate factory. Unsubscribe aborts cooperative I/O, not committed work.
|
|
246691
|
+
|
|
246692
|
+
Submit a background task ONCE with the existing SDK, then observe the receipt:
|
|
246693
|
+
|
|
246694
|
+
const task = await client.functions.invokeBackground("render", { body: input });
|
|
246695
|
+
const progress = observeTask(task, { signal: owner.signal });
|
|
246696
|
+
|
|
246697
|
+
Unsubscribing progress does not cancel the server task. Task read/decoder errors
|
|
246698
|
+
terminate observation; there is no automatic business retry. Realtime-to-polling
|
|
246699
|
+
fallback and project validation remain the SDK's responsibilities. Do not invent
|
|
246700
|
+
a public.tasks table or copy service credentials into browser code.
|
|
246701
|
+
|
|
246702
|
+
Run bun run check. Add cancellation, error, overflow and cross-owner isolation
|
|
246703
|
+
coverage whenever adding streaming behavior. These APIs require the matching
|
|
246704
|
+
framework/SDK release or the packed candidate packages used by repository CI.
|
|
246705
|
+
`;
|
|
246706
|
+
var STARTER_REACTIVE_AGENTS = `# Application development rules
|
|
246707
|
+
|
|
246708
|
+
Read README.md and REACTIVE.md before adding asynchronous features. If the
|
|
246709
|
+
application is hosted by Angular, read the @supacloud/app/angular guidance
|
|
246710
|
+
before choosing a signal API.
|
|
246711
|
+
Prefer the generated contracts and existing project-bound @supacloud/js client.
|
|
246712
|
+
Use async/await for a single result; RxJS is the default event-composition library.
|
|
246713
|
+
Bind subscriptions to an explicit owner and propagate cancellation to native I/O.
|
|
246714
|
+
Never automatically retry a write or turn observable delivery into durable ack.
|
|
246715
|
+
Do not bypass authorization, transactions, idempotency or audit to simplify code.
|
|
246716
|
+
Run bun run check; include negative and cleanup tests. Never store live credentials.
|
|
246717
|
+
`;
|
|
246718
|
+
var STARTER_REACTIVE_TEST = `import { expect, test } from "bun:test";
|
|
246719
|
+
import { Observable } from "rxjs";
|
|
246720
|
+
import { takeUntilAborted, toReadableStream } from "@supacloud/app/reactive";
|
|
246721
|
+
|
|
246722
|
+
test("the owner's signal releases reactive work exactly once", () => {
|
|
246723
|
+
const owner = new AbortController();
|
|
246724
|
+
let starts = 0, stops = 0;
|
|
246725
|
+
const source = new Observable<number>(() => { starts++; return () => { stops++; }; });
|
|
246726
|
+
source.pipe(takeUntilAborted(owner.signal)).subscribe();
|
|
246727
|
+
owner.abort();
|
|
246728
|
+
source.pipe(takeUntilAborted(owner.signal)).subscribe();
|
|
246729
|
+
expect(starts).toBe(1);
|
|
246730
|
+
expect(stops).toBe(1);
|
|
246731
|
+
});
|
|
246732
|
+
|
|
246733
|
+
test("cancelled stream consumers release their subscription", async () => {
|
|
246734
|
+
let stops = 0;
|
|
246735
|
+
const source = new Observable<number>(() => () => { stops++; });
|
|
246736
|
+
const stream = toReadableStream(source);
|
|
246737
|
+
await stream.cancel();
|
|
246738
|
+
expect(stops).toBe(1);
|
|
246739
|
+
});
|
|
246740
|
+
`;
|
|
246741
|
+
|
|
246336
246742
|
// src/shared/tools/app-starter.ts
|
|
246337
246743
|
import { lstat as lstat3, mkdir as mkdir4, readdir as readdir4, writeFile as writeFile4 } from "node:fs/promises";
|
|
246338
|
-
import { basename as basename7, dirname as dirname10, join as join13, resolve as
|
|
246744
|
+
import { basename as basename7, dirname as dirname10, join as join13, resolve as resolve15 } from "node:path";
|
|
246339
246745
|
|
|
246340
246746
|
// src/shared/tools/app-starter-environment.ts
|
|
246341
246747
|
var STARTER_ENVIRONMENT = String.raw`import { existsSync, readFileSync } from "node:fs";
|
|
@@ -246470,7 +246876,7 @@ test("partial and untagged inherited remote profiles cannot mix with selected fi
|
|
|
246470
246876
|
// ../compiler/package.json
|
|
246471
246877
|
var package_default = {
|
|
246472
246878
|
name: "@supacloud/compiler",
|
|
246473
|
-
version: "0.
|
|
246879
|
+
version: "0.30.0",
|
|
246474
246880
|
description: "Static compiler for @supacloud/app metadata: builds the application graph from AST, validates it, and generates reflection-free factory code",
|
|
246475
246881
|
type: "module",
|
|
246476
246882
|
main: "./dist/index.js",
|
|
@@ -246484,6 +246890,11 @@ var package_default = {
|
|
|
246484
246890
|
types: "./dist/index.d.ts",
|
|
246485
246891
|
import: "./dist/index.js",
|
|
246486
246892
|
default: "./dist/index.js"
|
|
246893
|
+
},
|
|
246894
|
+
"./diagnostics": {
|
|
246895
|
+
types: "./dist/diagnostics.d.ts",
|
|
246896
|
+
import: "./dist/diagnostics.js",
|
|
246897
|
+
default: "./dist/diagnostics.js"
|
|
246487
246898
|
}
|
|
246488
246899
|
},
|
|
246489
246900
|
files: [
|
|
@@ -246495,7 +246906,7 @@ var package_default = {
|
|
|
246495
246906
|
],
|
|
246496
246907
|
scripts: {
|
|
246497
246908
|
build: "bun run clean && bun run build:js && bun run build:types",
|
|
246498
|
-
"build:js": "bun build src/index.ts src/cli.ts src/delivery-bundle-worker.ts --outdir dist --target node --conditions=supacloud-source --external @typescript/typescript6 --external graphql --external '@graphql-codegen/*'",
|
|
246909
|
+
"build:js": "bun build src/index.ts src/diagnostics.ts src/cli.ts src/delivery-bundle-worker.ts --outdir dist --target node --conditions=supacloud-source --external @typescript/typescript6 --external graphql --external '@graphql-codegen/*'",
|
|
246499
246910
|
"build:types": "tsc -p tsconfig.json --emitDeclarationOnly",
|
|
246500
246911
|
clean: "rm -rf dist",
|
|
246501
246912
|
prepublishOnly: "bun run build && bun run test:package",
|
|
@@ -246512,14 +246923,14 @@ var package_default = {
|
|
|
246512
246923
|
"codegen",
|
|
246513
246924
|
"elysia"
|
|
246514
246925
|
],
|
|
246515
|
-
license: "
|
|
246926
|
+
license: "Apache-2.0",
|
|
246516
246927
|
repository: {
|
|
246517
246928
|
type: "git",
|
|
246518
246929
|
url: "https://github.com/vibeunion/supacloud.git",
|
|
246519
246930
|
directory: "packages/compiler"
|
|
246520
246931
|
},
|
|
246521
246932
|
dependencies: {
|
|
246522
|
-
"@supacloud/delivery": "
|
|
246933
|
+
"@supacloud/delivery": "0.4.0",
|
|
246523
246934
|
typebox: "1.3.34",
|
|
246524
246935
|
"@graphql-codegen/core": "^6.2.0",
|
|
246525
246936
|
"@graphql-codegen/typed-document-node": "^7.1.0",
|
|
@@ -246538,7 +246949,7 @@ var package_default = {
|
|
|
246538
246949
|
// ../app/package.json
|
|
246539
246950
|
var package_default2 = {
|
|
246540
246951
|
name: "@supacloud/app",
|
|
246541
|
-
version: "0.
|
|
246952
|
+
version: "0.21.0",
|
|
246542
246953
|
description: "Angular-style application metadata for SupaCloud: modules, DI tokens, providers, scopes, controllers and commands",
|
|
246543
246954
|
type: "module",
|
|
246544
246955
|
main: "./dist/index.js",
|
|
@@ -246564,6 +246975,31 @@ var package_default2 = {
|
|
|
246564
246975
|
types: "./dist/execution.d.ts",
|
|
246565
246976
|
import: "./dist/execution.js",
|
|
246566
246977
|
default: "./dist/execution.js"
|
|
246978
|
+
},
|
|
246979
|
+
"./reactive": {
|
|
246980
|
+
types: "./dist/reactive.d.ts",
|
|
246981
|
+
import: "./dist/reactive.js",
|
|
246982
|
+
default: "./dist/reactive.js"
|
|
246983
|
+
},
|
|
246984
|
+
"./rxjs": {
|
|
246985
|
+
types: "./dist/rxjs.d.ts",
|
|
246986
|
+
import: "./dist/rxjs.js",
|
|
246987
|
+
default: "./dist/rxjs.js"
|
|
246988
|
+
},
|
|
246989
|
+
"./angular": {
|
|
246990
|
+
types: "./dist/angular.d.ts",
|
|
246991
|
+
import: "./dist/angular.js",
|
|
246992
|
+
default: "./dist/angular.js"
|
|
246993
|
+
},
|
|
246994
|
+
"./http": {
|
|
246995
|
+
types: "./dist/http.d.ts",
|
|
246996
|
+
import: "./dist/http.js",
|
|
246997
|
+
default: "./dist/http.js"
|
|
246998
|
+
},
|
|
246999
|
+
"./runtime": {
|
|
247000
|
+
types: "./dist/runtime.d.ts",
|
|
247001
|
+
import: "./dist/runtime.js",
|
|
247002
|
+
default: "./dist/runtime.js"
|
|
246567
247003
|
}
|
|
246568
247004
|
},
|
|
246569
247005
|
files: [
|
|
@@ -246571,14 +247007,17 @@ var package_default2 = {
|
|
|
246571
247007
|
"LICENSE-APACHE-2.0.txt",
|
|
246572
247008
|
"dist",
|
|
246573
247009
|
"README.md",
|
|
246574
|
-
"EXECUTION.md"
|
|
247010
|
+
"EXECUTION.md",
|
|
247011
|
+
"REACTIVE.md",
|
|
247012
|
+
"ANGULAR.md"
|
|
246575
247013
|
],
|
|
246576
247014
|
scripts: {
|
|
246577
247015
|
build: "bun run clean && bun run build:js && bun run build:types",
|
|
246578
|
-
"build:js": "bun build src/index.ts src/execution.ts --outdir dist --target node --external @supacloud/contracts && bun build src/contract_client.ts src/browser.ts --outdir dist --target browser --external @supacloud/contracts",
|
|
247016
|
+
"build:js": "bun build src/index.ts src/execution.ts --outdir dist --target node --external @supacloud/contracts --external '@angular/*' --external rxjs --format esm && bun build src/contract_client.ts src/browser.ts --outdir dist --target browser --external @supacloud/contracts --format esm && bun build src/reactive.ts --outdir dist --target browser --external rxjs --format esm && bun build src/angular.ts src/rxjs.ts --outdir dist --target browser --external '@angular/*' --external rxjs --format esm && bun build src/http.ts --outdir dist --target node --external @supacloud/app --format esm && bun build src/runtime.ts --outdir dist --target browser --format esm",
|
|
246579
247017
|
"build:types": "tsc -p tsconfig.json --emitDeclarationOnly",
|
|
246580
247018
|
clean: "rm -rf dist",
|
|
246581
|
-
|
|
247019
|
+
"check:package": "node ../../.github/scripts/esm-package-policy.mjs --pack .",
|
|
247020
|
+
prepublishOnly: "bun run build && bun run check:package",
|
|
246582
247021
|
test: "bun test",
|
|
246583
247022
|
typecheck: "tsc -p tsconfig.json --noEmit",
|
|
246584
247023
|
"typecheck:test": "tsc -p tsconfig.test.json --noEmit"
|
|
@@ -246590,27 +247029,29 @@ var package_default2 = {
|
|
|
246590
247029
|
"module",
|
|
246591
247030
|
"elysia"
|
|
246592
247031
|
],
|
|
246593
|
-
license: "
|
|
247032
|
+
license: "Apache-2.0",
|
|
246594
247033
|
repository: {
|
|
246595
247034
|
type: "git",
|
|
246596
247035
|
url: "https://github.com/vibeunion/supacloud.git",
|
|
246597
247036
|
directory: "packages/app"
|
|
246598
247037
|
},
|
|
246599
247038
|
dependencies: {
|
|
246600
|
-
"@supacloud/contracts": "file:../contracts",
|
|
246601
247039
|
"@angular/core": "^22.1.5",
|
|
247040
|
+
"@supacloud/contracts": "0.8.0",
|
|
247041
|
+
rxjs: "7.8.2",
|
|
246602
247042
|
typebox: "1.3.34"
|
|
246603
247043
|
},
|
|
246604
247044
|
devDependencies: {
|
|
246605
247045
|
"@types/bun": "^1.4.2",
|
|
246606
247046
|
"@types/node": "^26.5.0",
|
|
246607
|
-
typescript: "^7.0.2"
|
|
247047
|
+
typescript: "^7.0.2",
|
|
247048
|
+
"@angular/compiler": "22.1.5"
|
|
246608
247049
|
}
|
|
246609
247050
|
};
|
|
246610
247051
|
// ../elysia/package.json
|
|
246611
247052
|
var package_default3 = {
|
|
246612
247053
|
name: "@supacloud/elysia",
|
|
246613
|
-
version: "0.
|
|
247054
|
+
version: "0.23.0",
|
|
246614
247055
|
description: "Elysia runtime adapter for SupaCloud compiled modules: application/request scopes, route registration and validation",
|
|
246615
247056
|
type: "module",
|
|
246616
247057
|
main: "./dist/index.js",
|
|
@@ -246652,7 +247093,7 @@ var package_default3 = {
|
|
|
246652
247093
|
"dependency-injection",
|
|
246653
247094
|
"module"
|
|
246654
247095
|
],
|
|
246655
|
-
license: "
|
|
247096
|
+
license: "Apache-2.0",
|
|
246656
247097
|
repository: {
|
|
246657
247098
|
type: "git",
|
|
246658
247099
|
url: "https://github.com/vibeunion/supacloud.git",
|
|
@@ -246785,7 +247226,8 @@ function baseFiles(name) {
|
|
|
246785
247226
|
dependencies: {
|
|
246786
247227
|
"@supacloud/app": `^${package_default2.version}`,
|
|
246787
247228
|
"@supacloud/elysia": `^${package_default3.version}`,
|
|
246788
|
-
elysia: "2.0.0-beta.19"
|
|
247229
|
+
elysia: "2.0.0-beta.19",
|
|
247230
|
+
rxjs: package_default2.dependencies.rxjs
|
|
246789
247231
|
},
|
|
246790
247232
|
devDependencies: {
|
|
246791
247233
|
"@supacloud/compiler": `^${package_default.version}`,
|
|
@@ -246836,6 +247278,9 @@ export default defineSupacloudConfig({
|
|
|
246836
247278
|
`,
|
|
246837
247279
|
"src/application.ts": APPLICATION_SOURCE(name),
|
|
246838
247280
|
"generated/application.ts": GENERATED_BOOTSTRAP,
|
|
247281
|
+
"REACTIVE.md": STARTER_REACTIVE_GUIDE,
|
|
247282
|
+
"AGENTS.md": STARTER_REACTIVE_AGENTS,
|
|
247283
|
+
"tests/reactive.test.ts": STARTER_REACTIVE_TEST,
|
|
246839
247284
|
"scripts/environment.ts": STARTER_ENVIRONMENT,
|
|
246840
247285
|
"tests/environment.test.ts": STARTER_ENVIRONMENT_TEST,
|
|
246841
247286
|
"scripts/dev.ts": DEV_SCRIPT,
|
|
@@ -248068,7 +248513,7 @@ export async function createDeliveryApplication(modules: CompiledModule[], lifec
|
|
|
248068
248513
|
// ../commands/package.json
|
|
248069
248514
|
var package_default4 = {
|
|
248070
248515
|
name: "@supacloud/commands",
|
|
248071
|
-
version: "0.
|
|
248516
|
+
version: "0.9.0",
|
|
248072
248517
|
description: "Storage-independent durable command execution and recovery",
|
|
248073
248518
|
type: "module",
|
|
248074
248519
|
main: "./dist/index.js",
|
|
@@ -248114,7 +248559,7 @@ var package_default4 = {
|
|
|
248114
248559
|
optional: true
|
|
248115
248560
|
}
|
|
248116
248561
|
},
|
|
248117
|
-
license: "
|
|
248562
|
+
license: "Apache-2.0",
|
|
248118
248563
|
repository: {
|
|
248119
248564
|
type: "git",
|
|
248120
248565
|
url: "https://github.com/vibeunion/supacloud.git",
|
|
@@ -248124,24 +248569,41 @@ var package_default4 = {
|
|
|
248124
248569
|
// ../contracts/package.json
|
|
248125
248570
|
var package_default5 = {
|
|
248126
248571
|
name: "@supacloud/contracts",
|
|
248127
|
-
version: "0.
|
|
248572
|
+
version: "0.8.0",
|
|
248128
248573
|
description: "SupaCloud command protocol with optional client and browser entrypoints",
|
|
248129
248574
|
type: "module",
|
|
248130
|
-
main: "./dist/index.
|
|
248131
|
-
types: "./dist/index.d.
|
|
248575
|
+
main: "./dist/index.cjs",
|
|
248576
|
+
types: "./dist/index.d.mts",
|
|
248132
248577
|
exports: {
|
|
248133
248578
|
".": {
|
|
248134
|
-
|
|
248135
|
-
|
|
248136
|
-
|
|
248579
|
+
import: {
|
|
248580
|
+
types: "./dist/index.d.mts",
|
|
248581
|
+
default: "./dist/index.mjs"
|
|
248582
|
+
},
|
|
248583
|
+
require: {
|
|
248584
|
+
types: "./dist/index.d.cts",
|
|
248585
|
+
default: "./dist/index.cjs"
|
|
248586
|
+
}
|
|
248137
248587
|
},
|
|
248138
248588
|
"./client": {
|
|
248139
|
-
|
|
248140
|
-
|
|
248589
|
+
import: {
|
|
248590
|
+
types: "./dist/client.d.mts",
|
|
248591
|
+
default: "./dist/client.mjs"
|
|
248592
|
+
},
|
|
248593
|
+
require: {
|
|
248594
|
+
types: "./dist/client.d.cts",
|
|
248595
|
+
default: "./dist/client.cjs"
|
|
248596
|
+
}
|
|
248141
248597
|
},
|
|
248142
248598
|
"./browser": {
|
|
248143
|
-
|
|
248144
|
-
|
|
248599
|
+
import: {
|
|
248600
|
+
types: "./dist/browser.d.mts",
|
|
248601
|
+
default: "./dist/browser.mjs"
|
|
248602
|
+
},
|
|
248603
|
+
require: {
|
|
248604
|
+
types: "./dist/browser.d.cts",
|
|
248605
|
+
default: "./dist/browser.cjs"
|
|
248606
|
+
}
|
|
248145
248607
|
}
|
|
248146
248608
|
},
|
|
248147
248609
|
files: [
|
|
@@ -248151,29 +248613,33 @@ var package_default5 = {
|
|
|
248151
248613
|
"README.md"
|
|
248152
248614
|
],
|
|
248153
248615
|
scripts: {
|
|
248154
|
-
build: "bun run build:js && bun run build:types",
|
|
248155
|
-
"build:js": "bun build
|
|
248156
|
-
"build:types": "tsc -p tsconfig.json --emitDeclarationOnly",
|
|
248616
|
+
build: "bun run clean && bun run build:js && bun run build:types",
|
|
248617
|
+
"build:js": "bun run build:js:esm && bun run build:js:cjs",
|
|
248618
|
+
"build:types": "tsc -p tsconfig.json --emitDeclarationOnly && node ../../scripts/copy-dual-declarations.mjs dist",
|
|
248157
248619
|
typecheck: "tsc -p tsconfig.json --noEmit",
|
|
248158
248620
|
"typecheck:test": "tsc -p tsconfig.test.json --noEmit",
|
|
248159
248621
|
test: "bun test",
|
|
248160
|
-
prepublishOnly: "bun run build"
|
|
248622
|
+
prepublishOnly: "bun run build",
|
|
248623
|
+
"build:js:esm": 'bun build src/index.ts src/client.ts src/browser.ts --outdir dist --format esm --entry-naming "[name].mjs" --chunk-naming "[name]-[hash].mjs" --target browser --splitting',
|
|
248624
|
+
"build:js:cjs": 'bun build src/index.ts src/client.ts src/browser.ts --outdir dist --format cjs --entry-naming "[name].cjs" --chunk-naming "[name]-[hash].cjs" --target browser',
|
|
248625
|
+
clean: "rm -rf dist"
|
|
248161
248626
|
},
|
|
248162
248627
|
devDependencies: {
|
|
248163
248628
|
"@types/bun": "1.4.2",
|
|
248164
248629
|
typescript: "7.0.2"
|
|
248165
248630
|
},
|
|
248166
|
-
license: "
|
|
248631
|
+
license: "Apache-2.0",
|
|
248167
248632
|
repository: {
|
|
248168
248633
|
type: "git",
|
|
248169
248634
|
url: "https://github.com/vibeunion/supacloud.git",
|
|
248170
248635
|
directory: "packages/contracts"
|
|
248171
|
-
}
|
|
248636
|
+
},
|
|
248637
|
+
module: "./dist/index.mjs"
|
|
248172
248638
|
};
|
|
248173
248639
|
// ../db/package.json
|
|
248174
248640
|
var package_default6 = {
|
|
248175
248641
|
name: "@supacloud/db",
|
|
248176
|
-
version: "0.
|
|
248642
|
+
version: "0.11.0",
|
|
248177
248643
|
description: "Database governance layer for SupaCloud: RLS policies, RPC functions and grants as first-class resources, with manifest/catalog reconciliation",
|
|
248178
248644
|
type: "module",
|
|
248179
248645
|
main: "./dist/index.js",
|
|
@@ -248230,7 +248696,7 @@ var package_default6 = {
|
|
|
248230
248696
|
"rls",
|
|
248231
248697
|
"postgresql"
|
|
248232
248698
|
],
|
|
248233
|
-
license: "
|
|
248699
|
+
license: "Apache-2.0",
|
|
248234
248700
|
repository: {
|
|
248235
248701
|
type: "git",
|
|
248236
248702
|
url: "https://github.com/vibeunion/supacloud.git",
|
|
@@ -248262,45 +248728,75 @@ var package_default6 = {
|
|
|
248262
248728
|
// ../supacloud-js/package.json
|
|
248263
248729
|
var package_default7 = {
|
|
248264
248730
|
name: "@supacloud/js",
|
|
248265
|
-
version: "0.
|
|
248731
|
+
version: "0.36.0",
|
|
248266
248732
|
description: "Platform SDK for SupaCloud, built on top of supabase-js",
|
|
248267
248733
|
type: "module",
|
|
248268
|
-
main: "./dist/index.
|
|
248269
|
-
module: "./dist/index.
|
|
248270
|
-
types: "./dist/index.d.
|
|
248734
|
+
main: "./dist/index.cjs",
|
|
248735
|
+
module: "./dist/index.mjs",
|
|
248736
|
+
types: "./dist/index.d.mts",
|
|
248271
248737
|
exports: {
|
|
248272
248738
|
".": {
|
|
248273
|
-
|
|
248274
|
-
|
|
248275
|
-
|
|
248739
|
+
import: {
|
|
248740
|
+
types: "./dist/index.d.mts",
|
|
248741
|
+
default: "./dist/index.mjs"
|
|
248742
|
+
},
|
|
248743
|
+
require: {
|
|
248744
|
+
types: "./dist/index.d.cts",
|
|
248745
|
+
default: "./dist/index.cjs"
|
|
248746
|
+
}
|
|
248276
248747
|
},
|
|
248277
248748
|
"./task-events": {
|
|
248278
|
-
|
|
248279
|
-
|
|
248280
|
-
|
|
248749
|
+
import: {
|
|
248750
|
+
types: "./dist/task-events.d.mts",
|
|
248751
|
+
default: "./dist/task-events.mjs"
|
|
248752
|
+
},
|
|
248753
|
+
require: {
|
|
248754
|
+
types: "./dist/task-events.d.cts",
|
|
248755
|
+
default: "./dist/task-events.cjs"
|
|
248756
|
+
}
|
|
248281
248757
|
},
|
|
248282
248758
|
"./contracts": {
|
|
248283
|
-
|
|
248284
|
-
|
|
248285
|
-
|
|
248759
|
+
import: {
|
|
248760
|
+
types: "./dist/contracts.d.mts",
|
|
248761
|
+
default: "./dist/contracts.mjs"
|
|
248762
|
+
},
|
|
248763
|
+
require: {
|
|
248764
|
+
types: "./dist/contracts.d.cts",
|
|
248765
|
+
default: "./dist/contracts.cjs"
|
|
248766
|
+
}
|
|
248767
|
+
},
|
|
248768
|
+
"./reactive": {
|
|
248769
|
+
import: {
|
|
248770
|
+
types: "./dist/reactive.d.mts",
|
|
248771
|
+
default: "./dist/reactive.mjs"
|
|
248772
|
+
},
|
|
248773
|
+
require: {
|
|
248774
|
+
types: "./dist/reactive.d.cts",
|
|
248775
|
+
default: "./dist/reactive.cjs"
|
|
248776
|
+
}
|
|
248286
248777
|
}
|
|
248287
248778
|
},
|
|
248288
248779
|
files: [
|
|
248289
248780
|
"NOTICE",
|
|
248290
248781
|
"LICENSE-APACHE-2.0.txt",
|
|
248291
248782
|
"dist",
|
|
248292
|
-
"README.md"
|
|
248783
|
+
"README.md",
|
|
248784
|
+
"COMPATIBILITY.md",
|
|
248785
|
+
"REACTIVE.md"
|
|
248293
248786
|
],
|
|
248294
248787
|
scripts: {
|
|
248295
248788
|
test: "bun test",
|
|
248296
248789
|
build: "bun run clean && bun run build:js && bun run build:types",
|
|
248297
|
-
"build:js": "bun build
|
|
248298
|
-
"build:types": "tsc -p tsconfig.json --emitDeclarationOnly",
|
|
248790
|
+
"build:js": "bun run build:js:esm && bun run build:js:cjs",
|
|
248791
|
+
"build:types": "tsc -p tsconfig.json --emitDeclarationOnly && node ../../scripts/copy-dual-declarations.mjs dist",
|
|
248299
248792
|
clean: "rm -rf dist",
|
|
248300
|
-
prepublishOnly: "bun run build",
|
|
248793
|
+
prepublishOnly: "bun run build && bun run check:package",
|
|
248301
248794
|
"typecheck:consumer": "tsc -p tsconfig.consumer.json --noEmit",
|
|
248302
248795
|
typecheck: "tsc -p tsconfig.json --noEmit",
|
|
248303
|
-
"typecheck:test": "tsc -p tsconfig.test.json --noEmit"
|
|
248796
|
+
"typecheck:test": "tsc -p tsconfig.test.json --noEmit",
|
|
248797
|
+
"check:package": "node ../../.github/scripts/esm-package-policy.mjs --pack .",
|
|
248798
|
+
"build:js:esm": 'bun build src/index.ts src/task-events.ts --outdir dist --format esm --entry-naming "[name].mjs" --chunk-naming "[name]-[hash].mjs" --target node --external @supabase/supabase-js --external @supacloud/contracts && bun build src/contracts.ts --outdir dist --format esm --entry-naming "[name].mjs" --chunk-naming "[name]-[hash].mjs" --target browser --external @supacloud/contracts && bun build src/reactive.ts --outdir dist --format esm --entry-naming "[name].mjs" --chunk-naming "[name]-[hash].mjs" --target browser --external rxjs',
|
|
248799
|
+
"build:js:cjs": 'bun build src/index.ts src/task-events.ts --outdir dist --format cjs --entry-naming "[name].cjs" --chunk-naming "[name]-[hash].cjs" --target node --external @supabase/supabase-js --external @supacloud/contracts && bun build src/contracts.ts --outdir dist --format cjs --entry-naming "[name].cjs" --chunk-naming "[name]-[hash].cjs" --target browser --external @supacloud/contracts && bun build src/reactive.ts --outdir dist --format cjs --entry-naming "[name].cjs" --chunk-naming "[name]-[hash].cjs" --target browser --external rxjs'
|
|
248304
248800
|
},
|
|
248305
248801
|
keywords: [
|
|
248306
248802
|
"supacloud",
|
|
@@ -248309,7 +248805,7 @@ var package_default7 = {
|
|
|
248309
248805
|
"background-tasks",
|
|
248310
248806
|
"realtime"
|
|
248311
248807
|
],
|
|
248312
|
-
license: "
|
|
248808
|
+
license: "Apache-2.0",
|
|
248313
248809
|
repository: {
|
|
248314
248810
|
type: "git",
|
|
248315
248811
|
url: "https://github.com/vibeunion/supacloud.git",
|
|
@@ -248319,12 +248815,16 @@ var package_default7 = {
|
|
|
248319
248815
|
"@supabase/supabase-js": "^2.115.0"
|
|
248320
248816
|
},
|
|
248321
248817
|
dependencies: {
|
|
248322
|
-
"@supacloud/contracts": "
|
|
248818
|
+
"@supacloud/contracts": "0.8.0",
|
|
248819
|
+
rxjs: "7.8.2"
|
|
248323
248820
|
},
|
|
248324
248821
|
devDependencies: {
|
|
248325
248822
|
"@types/bun": "^1.4.2",
|
|
248326
248823
|
"@supabase/supabase-js": "^2.115.0",
|
|
248327
248824
|
typescript: "^7.0.2"
|
|
248825
|
+
},
|
|
248826
|
+
engines: {
|
|
248827
|
+
node: ">=22.12.0"
|
|
248328
248828
|
}
|
|
248329
248829
|
};
|
|
248330
248830
|
|
|
@@ -248360,7 +248860,8 @@ function appStarterFiles(name) {
|
|
|
248360
248860
|
"@supacloud/db": `^${package_default6.version}`,
|
|
248361
248861
|
"@supacloud/js": `^${package_default7.version}`,
|
|
248362
248862
|
"@supabase/supabase-js": package_default7.peerDependencies["@supabase/supabase-js"],
|
|
248363
|
-
elysia: "2.0.0-beta.19"
|
|
248863
|
+
elysia: "2.0.0-beta.19",
|
|
248864
|
+
rxjs: package_default2.dependencies.rxjs
|
|
248364
248865
|
},
|
|
248365
248866
|
devDependencies: {
|
|
248366
248867
|
"@supacloud/compiler": `^${package_default.version}`,
|
|
@@ -248473,6 +248974,9 @@ test("generated query client preserves its read contract without a live database
|
|
|
248473
248974
|
expect(await queries.ReviewList({ first: 10 })).toEqual(data);
|
|
248474
248975
|
});
|
|
248475
248976
|
`,
|
|
248977
|
+
"REACTIVE.md": STARTER_REACTIVE_GUIDE,
|
|
248978
|
+
"AGENTS.md": STARTER_REACTIVE_AGENTS,
|
|
248979
|
+
"tests/reactive.test.ts": STARTER_REACTIVE_TEST,
|
|
248476
248980
|
"scripts/environment.ts": STARTER_ENVIRONMENT,
|
|
248477
248981
|
"tests/environment.test.ts": STARTER_ENVIRONMENT_TEST,
|
|
248478
248982
|
"scripts/dev.ts": `import { watchProject, compileOptionsFromConfig, loadSupacloudConfig } from "@supacloud/compiler";
|
|
@@ -249037,7 +249541,7 @@ and governance; TypeScript checks both application and generated source.
|
|
|
249037
249541
|
};
|
|
249038
249542
|
}
|
|
249039
249543
|
async function initializeAppProject(options) {
|
|
249040
|
-
const root =
|
|
249544
|
+
const root = resolve15(options.root ?? process.cwd());
|
|
249041
249545
|
const name = options.name ?? basename7(root);
|
|
249042
249546
|
if (!/^[a-z][a-z0-9-]*$/.test(name) || name.length > 100) {
|
|
249043
249547
|
throw new Error("Project name must be lowercase kebab-case (1-100 characters)");
|
|
@@ -249137,7 +249641,7 @@ test("${name} controller preserves an asynchronous read failure", async () => {
|
|
|
249137
249641
|
// src/shared/tools/app-scaffold-writes.ts
|
|
249138
249642
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
249139
249643
|
import { link, lstat as lstat4, mkdir as mkdir5, open as open4, readFile as readFile4, realpath as realpath5, rename as rename5, rmdir, unlink as unlink3 } from "node:fs/promises";
|
|
249140
|
-
import { dirname as dirname11, isAbsolute as
|
|
249644
|
+
import { dirname as dirname11, isAbsolute as isAbsolute6, join as join14, relative as relative11, resolve as resolve16, sep as sep11, win32 } from "node:path";
|
|
249141
249645
|
|
|
249142
249646
|
class ScaffoldError extends Error {
|
|
249143
249647
|
code;
|
|
@@ -249151,16 +249655,16 @@ function fsCode(error) {
|
|
|
249151
249655
|
return error instanceof Error && "code" in error && typeof error.code === "string" ? error.code : undefined;
|
|
249152
249656
|
}
|
|
249153
249657
|
function scaffoldPath(root, path) {
|
|
249154
|
-
if (!path || path.includes("\x00") || path.includes("\\") ||
|
|
249658
|
+
if (!path || path.includes("\x00") || path.includes("\\") || isAbsolute6(path) || win32.isAbsolute(path)) {
|
|
249155
249659
|
throw new ScaffoldError("SCAFFOLD_PATH_INVALID", "Scaffold paths must be relative to the project root");
|
|
249156
249660
|
}
|
|
249157
249661
|
const parts = path.split("/");
|
|
249158
249662
|
if (parts.some((part) => /[<>:"|?*\u0000-\u001f]/.test(part) || /[ .]$/.test(part) && part !== "." && part !== ".." || /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\.|$)/i.test(part) || part.toLowerCase() === ".git" || part.toLowerCase() === ".supacloud-generate.lock")) {
|
|
249159
249663
|
throw new ScaffoldError("SCAFFOLD_PATH_INVALID", "Scaffold path is reserved or not portable");
|
|
249160
249664
|
}
|
|
249161
|
-
const target =
|
|
249665
|
+
const target = resolve16(root, path);
|
|
249162
249666
|
const local = relative11(root, target);
|
|
249163
|
-
if (!local || local === ".." || local.startsWith(`..${sep11}`) ||
|
|
249667
|
+
if (!local || local === ".." || local.startsWith(`..${sep11}`) || isAbsolute6(local)) {
|
|
249164
249668
|
throw new ScaffoldError("SCAFFOLD_PATH_INVALID", "Scaffold path is outside the project root");
|
|
249165
249669
|
}
|
|
249166
249670
|
return target;
|
|
@@ -249197,7 +249701,7 @@ function sameFile(a, b) {
|
|
|
249197
249701
|
return a === null ? b === null : b !== null && a.content === b.content && a.dev === b.dev && a.ino === b.ino && a.mode === b.mode;
|
|
249198
249702
|
}
|
|
249199
249703
|
async function planScaffoldWrites(root, writes) {
|
|
249200
|
-
const canonical = await realpath5(
|
|
249704
|
+
const canonical = await realpath5(resolve16(root));
|
|
249201
249705
|
const targets = new Set;
|
|
249202
249706
|
const planned = [];
|
|
249203
249707
|
for (const write of writes) {
|
|
@@ -249456,7 +249960,7 @@ async function generateScaffold(args) {
|
|
|
249456
249960
|
throw new ScaffoldError("SCAFFOLD_OPTION_INVALID", `--${flag.replaceAll("_", "-")} must be boolean`);
|
|
249457
249961
|
}
|
|
249458
249962
|
}
|
|
249459
|
-
const root =
|
|
249963
|
+
const root = resolve17(args.root || process.cwd());
|
|
249460
249964
|
const dir = args.dir ?? "src/features";
|
|
249461
249965
|
if (dir !== ".")
|
|
249462
249966
|
scaffoldPath(root, dir);
|
|
@@ -249485,7 +249989,7 @@ async function generateScaffold(args) {
|
|
|
249485
249989
|
const name = kind === "controller" ? moduleName : requireIdentifier(args.name, "name");
|
|
249486
249990
|
const subdir = kind === "command" ? "commands" : kind === "query" ? "queries" : kind === "job" ? "jobs" : kind === "contract" ? "contracts" : "";
|
|
249487
249991
|
const path = join15(dir, moduleName, subdir, `${name}.${kind}.ts`).replaceAll("\\", "/");
|
|
249488
|
-
if (kind === "controller" &&
|
|
249992
|
+
if (kind === "controller" && existsSync11(scaffoldPath(root, path))) {
|
|
249489
249993
|
throw new ScaffoldError("SCAFFOLD_EXISTS", `Controller already exists: ${path}(请手工合并路由到现有 controller)`);
|
|
249490
249994
|
}
|
|
249491
249995
|
const content = kind === "command" ? commandScaffold(moduleName, name) : kind === "query" ? queryScaffold(moduleName, name) : kind === "job" ? jobScaffold(moduleName, name) : kind === "contract" ? contractScaffold(moduleName, name) : controllerScaffold(moduleName);
|
|
@@ -249503,7 +250007,7 @@ async function generateScaffold(args) {
|
|
|
249503
250007
|
if (new RegExp(`\\b${moduleSymbol}\\b`).test(original)) {
|
|
249504
250008
|
throw new ScaffoldError("SCAFFOLD_REGISTRATION_CONFLICT", `Registration target already references ${moduleSymbol}; review the import manually`);
|
|
249505
250009
|
}
|
|
249506
|
-
let importPath = relative12(dirname12(target),
|
|
250010
|
+
let importPath = relative12(dirname12(target), resolve17(root, modulePath)).replaceAll("\\", "/").replace(/\.ts$/, "");
|
|
249507
250011
|
if (!importPath.startsWith("."))
|
|
249508
250012
|
importPath = `./${importPath}`;
|
|
249509
250013
|
const edit = await applyDiagnosticFix({
|
|
@@ -249570,17 +250074,17 @@ function parseInclude(include) {
|
|
|
249570
250074
|
return patterns && patterns.length > 0 ? patterns : undefined;
|
|
249571
250075
|
}
|
|
249572
250076
|
function sourceRoot(args, root, configured) {
|
|
249573
|
-
const hasConfig = ["ts", "mts", "js", "mjs"].some((extension) =>
|
|
250077
|
+
const hasConfig = ["ts", "mts", "js", "mjs"].some((extension) => existsSync11(join15(root, `supacloud.config.${extension}`)));
|
|
249574
250078
|
return args.root && !hasConfig ? "." : configured;
|
|
249575
250079
|
}
|
|
249576
250080
|
async function projectCompileConfig(args) {
|
|
249577
|
-
const root =
|
|
249578
|
-
const configFile = ["ts", "mts", "js", "mjs"].map((extension) => join15(root, `supacloud.config.${extension}`)).find((candidate) =>
|
|
250081
|
+
const root = resolve17(args.root || process.cwd());
|
|
250082
|
+
const configFile = ["ts", "mts", "js", "mjs"].map((extension) => join15(root, `supacloud.config.${extension}`)).find((candidate) => existsSync11(candidate)) ?? null;
|
|
249579
250083
|
const loadedConfig = await loadSupacloudConfig(root);
|
|
249580
250084
|
const defaults = resolveSupacloudConfig(loadedConfig, root);
|
|
249581
250085
|
const configuredRoot = sourceRoot(args, root, loadedConfig.root);
|
|
249582
250086
|
const include = parseInclude(args.include) ?? loadedConfig.include;
|
|
249583
|
-
const outDir = args.out_dir ?
|
|
250087
|
+
const outDir = args.out_dir ? resolve17(root, args.out_dir) : defaults.outDir;
|
|
249584
250088
|
const result = await checkProject(compileOptionsFromConfig({
|
|
249585
250089
|
...loadedConfig,
|
|
249586
250090
|
...configuredRoot === undefined ? {} : { root: configuredRoot },
|
|
@@ -249592,7 +250096,7 @@ async function projectCompileConfig(args) {
|
|
|
249592
250096
|
}
|
|
249593
250097
|
async function readAllowedDependencies(root) {
|
|
249594
250098
|
const path = join15(root, "package.json");
|
|
249595
|
-
if (!
|
|
250099
|
+
if (!existsSync11(path))
|
|
249596
250100
|
return { dependencies: [], devDependencies: [] };
|
|
249597
250101
|
try {
|
|
249598
250102
|
const parsed = JSON.parse(await readFile8(path, "utf8"));
|
|
@@ -249737,11 +250241,11 @@ async function runDoctor(args) {
|
|
|
249737
250241
|
`), doctor.errors > 0);
|
|
249738
250242
|
}
|
|
249739
250243
|
async function runFix(args) {
|
|
249740
|
-
const root =
|
|
250244
|
+
const root = resolve17(args.root || process.cwd());
|
|
249741
250245
|
const fixPath = args.fix?.trim();
|
|
249742
250246
|
if (!fixPath)
|
|
249743
250247
|
throw new Error("app fix requires --fix <path-to-diagnostic-fix.json>");
|
|
249744
|
-
const parsed = JSON.parse(await readFile8(
|
|
250248
|
+
const parsed = JSON.parse(await readFile8(resolve17(root, fixPath), "utf8"));
|
|
249745
250249
|
const write = args.write === true;
|
|
249746
250250
|
const applied = await applyDiagnosticFix(parsed, { rootDir: root, dryRun: !write });
|
|
249747
250251
|
return textResult(JSON.stringify({
|
|
@@ -249784,7 +250288,7 @@ function devDatabase(profile, explicit) {
|
|
|
249784
250288
|
}
|
|
249785
250289
|
function readManifestModules(outDir) {
|
|
249786
250290
|
try {
|
|
249787
|
-
const parsed = JSON.parse(
|
|
250291
|
+
const parsed = JSON.parse(readFileSync9(join15(outDir, "app.manifest.json"), "utf8"));
|
|
249788
250292
|
return Array.isArray(parsed.modules) ? parsed.modules.map((module) => module.name) : [];
|
|
249789
250293
|
} catch {
|
|
249790
250294
|
return [];
|
|
@@ -249817,12 +250321,12 @@ async function runAppDev(args, options) {
|
|
|
249817
250321
|
throw new ScaffoldError("SCAFFOLD_OPTION_INVALID", "app dev --profile must be fast or integration");
|
|
249818
250322
|
}
|
|
249819
250323
|
const database = devDatabase(profile, args.database_url);
|
|
249820
|
-
const root =
|
|
250324
|
+
const root = resolve17(args.root || process.cwd());
|
|
249821
250325
|
const loadedConfig = await loadSupacloudConfig(root);
|
|
249822
250326
|
const defaults = resolveSupacloudConfig(loadedConfig, root);
|
|
249823
250327
|
const configuredRoot = sourceRoot(args, root, loadedConfig.root);
|
|
249824
250328
|
const include = parseInclude(args.include) ?? loadedConfig.include;
|
|
249825
|
-
const outDir = args.out_dir ?
|
|
250329
|
+
const outDir = args.out_dir ? resolve17(root, args.out_dir) : defaults.outDir;
|
|
249826
250330
|
const watch = args.once !== true && args.watch !== false;
|
|
249827
250331
|
const compileOptions = compileOptionsFromConfig({
|
|
249828
250332
|
...loadedConfig,
|
|
@@ -249908,7 +250412,7 @@ async function runAppDev(args, options) {
|
|
|
249908
250412
|
return report(lastEvent, "stopped");
|
|
249909
250413
|
}
|
|
249910
250414
|
async function runCompile(args) {
|
|
249911
|
-
const root =
|
|
250415
|
+
const root = resolve17(args.root || process.cwd());
|
|
249912
250416
|
const loadedConfig = await loadSupacloudConfig(root);
|
|
249913
250417
|
const defaults = resolveSupacloudConfig(loadedConfig, root);
|
|
249914
250418
|
const configuredRoot = sourceRoot(args, root, loadedConfig.root);
|
|
@@ -249917,7 +250421,7 @@ async function runCompile(args) {
|
|
|
249917
250421
|
...compileOptionsFromConfig({
|
|
249918
250422
|
...loadedConfig,
|
|
249919
250423
|
...configuredRoot === undefined ? {} : { root: configuredRoot },
|
|
249920
|
-
outDir: args.out_dir ?
|
|
250424
|
+
outDir: args.out_dir ? resolve17(root, args.out_dir) : defaults.outDir,
|
|
249921
250425
|
...include === undefined ? {} : { include },
|
|
249922
250426
|
strict: args.strict ?? loadedConfig.strict ?? false
|
|
249923
250427
|
}, root),
|
|
@@ -249941,7 +250445,7 @@ async function runCompile(args) {
|
|
|
249941
250445
|
return textResult(text, hasError);
|
|
249942
250446
|
}
|
|
249943
250447
|
async function runCheck(args) {
|
|
249944
|
-
const root =
|
|
250448
|
+
const root = resolve17(args.root || process.cwd());
|
|
249945
250449
|
const loadedConfig = await loadSupacloudConfig(root);
|
|
249946
250450
|
const defaults = resolveSupacloudConfig(loadedConfig, root);
|
|
249947
250451
|
const configuredRoot = sourceRoot(args, root, loadedConfig.root);
|
|
@@ -249949,7 +250453,7 @@ async function runCheck(args) {
|
|
|
249949
250453
|
const config = compileOptionsFromConfig({
|
|
249950
250454
|
...loadedConfig,
|
|
249951
250455
|
...configuredRoot === undefined ? {} : { root: configuredRoot },
|
|
249952
|
-
outDir: args.out_dir ?
|
|
250456
|
+
outDir: args.out_dir ? resolve17(root, args.out_dir) : defaults.outDir,
|
|
249953
250457
|
...include === undefined ? {} : { include },
|
|
249954
250458
|
strict: args.strict ?? loadedConfig.strict ?? false
|
|
249955
250459
|
}, root);
|
|
@@ -249977,9 +250481,9 @@ async function runCheck(args) {
|
|
|
249977
250481
|
}
|
|
249978
250482
|
async function readManifest(root, args) {
|
|
249979
250483
|
const config = await loadSupacloudConfig(root);
|
|
249980
|
-
const outDir = args.out_dir ?
|
|
250484
|
+
const outDir = args.out_dir ? resolve17(root, args.out_dir) : resolveSupacloudConfig(config, root).outDir;
|
|
249981
250485
|
const manifestPath = join15(outDir, "app.manifest.json");
|
|
249982
|
-
if (!
|
|
250486
|
+
if (!existsSync11(manifestPath)) {
|
|
249983
250487
|
throw new Error(`Manifest not found: ${manifestPath}(先运行 app compile 生成)`);
|
|
249984
250488
|
}
|
|
249985
250489
|
const parsed = JSON.parse(await readFile8(manifestPath, "utf8"));
|
|
@@ -250022,7 +250526,7 @@ function formatGraphText(manifest) {
|
|
|
250022
250526
|
`);
|
|
250023
250527
|
}
|
|
250024
250528
|
async function runGraph(args) {
|
|
250025
|
-
const root =
|
|
250529
|
+
const root = resolve17(args.root || process.cwd());
|
|
250026
250530
|
const manifest = await readManifest(root, args);
|
|
250027
250531
|
if (args.format === "json")
|
|
250028
250532
|
return textResult(JSON.stringify(manifest, null, 2));
|
|
@@ -250090,7 +250594,7 @@ async function runExplain(args) {
|
|
|
250090
250594
|
const target = args.target?.trim();
|
|
250091
250595
|
if (!target)
|
|
250092
250596
|
throw new Error("app explain requires --target(provider 类名 / token 名 / command 名 / job 名)");
|
|
250093
|
-
const root =
|
|
250597
|
+
const root = resolve17(args.root || process.cwd());
|
|
250094
250598
|
const manifest = await readManifest(root, args);
|
|
250095
250599
|
for (const module of manifest.modules) {
|
|
250096
250600
|
const job = module.jobs?.find((entry) => entry.name === target || entry.className === target);
|
|
@@ -250165,10 +250669,10 @@ async function runExplain(args) {
|
|
|
250165
250669
|
return textResult(`未找到对象: ${target}`, true);
|
|
250166
250670
|
}
|
|
250167
250671
|
async function runExportTools(args) {
|
|
250168
|
-
const root =
|
|
250672
|
+
const root = resolve17(args.root || process.cwd());
|
|
250169
250673
|
const manifest = await readManifest(root, { ...args, out_dir: undefined });
|
|
250170
250674
|
const definitions = buildToolDefinitions(manifest);
|
|
250171
|
-
const outDir =
|
|
250675
|
+
const outDir = resolve17(args.out_dir || join15(root, "generated"));
|
|
250172
250676
|
if (args.format === "json") {
|
|
250173
250677
|
return textResult(JSON.stringify(definitions, null, 2));
|
|
250174
250678
|
}
|
|
@@ -250189,11 +250693,11 @@ async function runExportTools(args) {
|
|
|
250189
250693
|
return textResult(summary);
|
|
250190
250694
|
}
|
|
250191
250695
|
async function runDelivery(args) {
|
|
250192
|
-
const root =
|
|
250696
|
+
const root = resolve17(args.root || process.cwd());
|
|
250193
250697
|
const loaded = await loadSupacloudConfig(root);
|
|
250194
250698
|
const options = compileOptionsFromConfig({
|
|
250195
250699
|
...loaded,
|
|
250196
|
-
...args.out_dir === undefined ? {} : { outDir:
|
|
250700
|
+
...args.out_dir === undefined ? {} : { outDir: resolve17(root, args.out_dir) },
|
|
250197
250701
|
...args.include === undefined ? {} : { include: parseInclude(args.include) },
|
|
250198
250702
|
...args.strict === undefined ? {} : { strict: args.strict }
|
|
250199
250703
|
}, root);
|
|
@@ -250351,8 +250855,8 @@ function registerAppAliases(server2) {
|
|
|
250351
250855
|
}
|
|
250352
250856
|
|
|
250353
250857
|
// src/shared/tools/db-governance-tools.ts
|
|
250354
|
-
import { existsSync as
|
|
250355
|
-
import { join as join16, resolve as
|
|
250858
|
+
import { existsSync as existsSync12 } from "node:fs";
|
|
250859
|
+
import { join as join16, resolve as resolve18 } from "node:path";
|
|
250356
250860
|
|
|
250357
250861
|
// node_modules/@supacloud/db/dist/index.js
|
|
250358
250862
|
var TABLES_SQL = `
|
|
@@ -250804,8 +251308,8 @@ function normalizeModule(candidate, sourcePath) {
|
|
|
250804
251308
|
};
|
|
250805
251309
|
}
|
|
250806
251310
|
async function loadDatabaseModules(root, moduleFile) {
|
|
250807
|
-
const filePath = moduleFile ?
|
|
250808
|
-
if (!
|
|
251311
|
+
const filePath = moduleFile ? resolve18(root, moduleFile) : join16(root, "db", "modules.ts");
|
|
251312
|
+
if (!existsSync12(filePath)) {
|
|
250809
251313
|
throw new Error(moduleFile ? `Module file not found: ${filePath}` : `Module file not found: ${filePath}(用 --module_file 指定一个导出 defineDatabaseModule(...) 的文件)`);
|
|
250810
251314
|
}
|
|
250811
251315
|
let imported;
|
|
@@ -250853,7 +251357,7 @@ async function runLint(args, root) {
|
|
|
250853
251357
|
const issues = [];
|
|
250854
251358
|
for (const module of selected) {
|
|
250855
251359
|
const readSqlFile = async (path) => {
|
|
250856
|
-
const absolute =
|
|
251360
|
+
const absolute = resolve18(root, path);
|
|
250857
251361
|
try {
|
|
250858
251362
|
return await Bun.file(absolute).text();
|
|
250859
251363
|
} catch (error) {
|
|
@@ -250889,14 +251393,14 @@ var defaultLiteSpawn = async (command, cwd) => {
|
|
|
250889
251393
|
return { exitCode, stdout, stderr };
|
|
250890
251394
|
};
|
|
250891
251395
|
async function runModuleCheckLite(args, root, spawn, liteBinary) {
|
|
250892
|
-
const projectDir =
|
|
251396
|
+
const projectDir = resolve18(args.project_dir?.trim() || root);
|
|
250893
251397
|
const binary = liteBinary === undefined ? Bun.which("supacloud-lite") : liteBinary;
|
|
250894
251398
|
if (!binary) {
|
|
250895
251399
|
throw new Error("db module_check --lite 需要本机可用的 supacloud-lite(npm i -g @supacloud/lite,或加入 PATH)");
|
|
250896
251400
|
}
|
|
250897
251401
|
const command = [binary, "db", "check", "--project-dir", projectDir];
|
|
250898
251402
|
if (args.module_file?.trim())
|
|
250899
|
-
command.push("--module-file",
|
|
251403
|
+
command.push("--module-file", resolve18(root, args.module_file.trim()));
|
|
250900
251404
|
const result = await spawn(command, projectDir);
|
|
250901
251405
|
const output = [result.stdout.trim(), result.stderr.trim()].filter(Boolean).join(`
|
|
250902
251406
|
`);
|
|
@@ -250947,7 +251451,7 @@ function registerDbGovernanceTools(server2, options = {}) {
|
|
|
250947
251451
|
lite: optional(Type.Boolean(), "[module_check] Reconcile against a local SupaCloud Lite project (runs supacloud-lite db check)"),
|
|
250948
251452
|
project_dir: optional(Type.String(), "[module_check] Lite project directory (with --lite; default: --root)")
|
|
250949
251453
|
}, async (request) => {
|
|
250950
|
-
const root =
|
|
251454
|
+
const root = resolve18(request.root || fallbackRoot);
|
|
250951
251455
|
switch (request.action) {
|
|
250952
251456
|
case "lint":
|
|
250953
251457
|
return runLint(request, root);
|
|
@@ -250963,8 +251467,8 @@ function registerDbGovernanceTools(server2, options = {}) {
|
|
|
250963
251467
|
|
|
250964
251468
|
// src/shared/tools/scheduled-function-tools.ts
|
|
250965
251469
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
250966
|
-
import { readFileSync as
|
|
250967
|
-
import { resolve as
|
|
251470
|
+
import { readFileSync as readFileSync10, statSync as statSync7 } from "node:fs";
|
|
251471
|
+
import { resolve as resolve20 } from "node:path";
|
|
250968
251472
|
import { isDeepStrictEqual } from "node:util";
|
|
250969
251473
|
var HEADER_NAME_PATTERN = /^[!#$%&'*+.^_`|~0-9A-Za-z-]{1,128}$/;
|
|
250970
251474
|
var ENVIRONMENT_NAME_PATTERN2 = /^[A-Za-z_][A-Za-z0-9_]{0,255}$/;
|
|
@@ -251048,14 +251552,14 @@ function validScheduledFunctionCron(expression) {
|
|
|
251048
251552
|
function readScheduleBodyFile(bodyPathInput) {
|
|
251049
251553
|
if (!bodyPathInput.trim())
|
|
251050
251554
|
throw new Error("'body_file' must be a path");
|
|
251051
|
-
const bodyPath =
|
|
251052
|
-
const bodyStat =
|
|
251555
|
+
const bodyPath = resolve20(bodyPathInput);
|
|
251556
|
+
const bodyStat = statSync7(bodyPath);
|
|
251053
251557
|
if (!bodyStat.isFile() || bodyStat.size > MAX_BODY_FILE_BYTES) {
|
|
251054
251558
|
throw new Error("Scheduled Function body file must be a regular file no larger than 1 MiB");
|
|
251055
251559
|
}
|
|
251056
251560
|
let payload;
|
|
251057
251561
|
try {
|
|
251058
|
-
payload = JSON.parse(
|
|
251562
|
+
payload = JSON.parse(readFileSync10(bodyPath, "utf8"));
|
|
251059
251563
|
} catch (error) {
|
|
251060
251564
|
if (!(error instanceof SyntaxError))
|
|
251061
251565
|
throw error;
|
|
@@ -251630,9 +252134,9 @@ var MUTATION_TOOL_SCHEMA = {
|
|
|
251630
252134
|
|
|
251631
252135
|
// src/shared/tools/release-tools.ts
|
|
251632
252136
|
import { execFileSync } from "node:child_process";
|
|
251633
|
-
import { createHash as
|
|
251634
|
-
import { existsSync as
|
|
251635
|
-
import { dirname as dirname13, join as join17, relative as relative13, resolve as
|
|
252137
|
+
import { createHash as createHash10 } from "node:crypto";
|
|
252138
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync4, readdirSync as readdirSync4, readFileSync as readFileSync11, writeFileSync as writeFileSync3 } from "node:fs";
|
|
252139
|
+
import { dirname as dirname13, join as join17, relative as relative13, resolve as resolve21 } from "node:path";
|
|
251636
252140
|
var SAFE_PROJECT_REF = /^[A-Za-z0-9_-]{1,64}$/;
|
|
251637
252141
|
var BACKUP_ID = /^logical-full_[A-Za-z0-9_-]{1,64}_[a-f0-9]{32}$/;
|
|
251638
252142
|
var SHA256 = /^[a-f0-9]{64}$/;
|
|
@@ -251648,7 +252152,7 @@ var RELEASE_CANARY_DISABLE_RECEIPT_KEYS = new Set(["fixtureId", "state", "idempo
|
|
|
251648
252152
|
var RELEASE_CANARY_DISABLE_RPC_PATH = "/rest/v1/rpc/fa_release_canary_fixture_disable";
|
|
251649
252153
|
var RELEASE_CANARY_PENDING_RPC_PATH = "/rest/v1/rpc/fa_release_canary_fixture_pending";
|
|
251650
252154
|
var RELEASE_CANARY_CLAIM_MAX_LENGTH = 2048;
|
|
251651
|
-
function
|
|
252155
|
+
function isRecord4(value) {
|
|
251652
252156
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
251653
252157
|
}
|
|
251654
252158
|
function canonicalTimestamp4(value) {
|
|
@@ -251664,7 +252168,7 @@ function backupBelongsToProject(backupId, projectRef) {
|
|
|
251664
252168
|
return BACKUP_ID.test(backupId) && backupId.startsWith(`logical-full_${projectRef}_`);
|
|
251665
252169
|
}
|
|
251666
252170
|
function verifiedBackup(value, projectRef) {
|
|
251667
|
-
if (!
|
|
252171
|
+
if (!isRecord4(value) || typeof value.backup_id !== "string" || !backupBelongsToProject(value.backup_id, projectRef) || value.project_ref !== projectRef || typeof value.database !== "string" || !SAFE_DATABASE.test(value.database) || value.kind !== "logical-full" || !canonicalTimestamp4(value.created_at) || !canonicalTimestamp4(value.completed_at) || new Date(value.completed_at).valueOf() < new Date(value.created_at).valueOf() || typeof value.bytes !== "number" || !Number.isSafeInteger(value.bytes) || value.bytes <= 0 || typeof value.sha256 !== "string" || !SHA256.test(value.sha256))
|
|
251668
252172
|
return null;
|
|
251669
252173
|
return {
|
|
251670
252174
|
backup_id: value.backup_id,
|
|
@@ -251678,7 +252182,7 @@ function verifiedBackup(value, projectRef) {
|
|
|
251678
252182
|
};
|
|
251679
252183
|
}
|
|
251680
252184
|
function backupInventory(value, projectRef) {
|
|
251681
|
-
if (!
|
|
252185
|
+
if (!isRecord4(value) || !Array.isArray(value.backups))
|
|
251682
252186
|
return null;
|
|
251683
252187
|
const backups = value.backups.map((backup) => verifiedBackup(backup, projectRef));
|
|
251684
252188
|
if (backups.some((backup) => backup === null))
|
|
@@ -251757,7 +252261,7 @@ function readInventoryFailure(operation, read) {
|
|
|
251757
252261
|
return null;
|
|
251758
252262
|
}
|
|
251759
252263
|
function postgrestStatus(value) {
|
|
251760
|
-
if (!
|
|
252264
|
+
if (!isRecord4(value) || value.component !== "postgrest" || !["running", "stopped"].includes(String(value.desired)) || !["running", "stopped", "starting", "error"].includes(String(value.actual)) || !["healthy", "unhealthy", "unknown"].includes(String(value.health)))
|
|
251761
252265
|
return null;
|
|
251762
252266
|
return {
|
|
251763
252267
|
desired: value.desired,
|
|
@@ -251778,7 +252282,7 @@ function readPostgrestFailure(operation, read) {
|
|
|
251778
252282
|
return read.response.status === 200 && read.status ? null : releaseControlFailure(operation, "INVALID_RESPONSE", read.response.status);
|
|
251779
252283
|
}
|
|
251780
252284
|
function isRestartReceipt(value) {
|
|
251781
|
-
return
|
|
252285
|
+
return isRecord4(value) && value.service === "postgrest" && value.action === "restart" && value.success === true;
|
|
251782
252286
|
}
|
|
251783
252287
|
function releaseCanaryStageInput(subject, requestId) {
|
|
251784
252288
|
if (typeof subject !== "string" || !UUID.test(subject))
|
|
@@ -251788,7 +252292,7 @@ function releaseCanaryStageInput(subject, requestId) {
|
|
|
251788
252292
|
return { p_subject: subject, p_request_id: requestId };
|
|
251789
252293
|
}
|
|
251790
252294
|
function releaseCanaryStageReceipt(value) {
|
|
251791
|
-
if (!
|
|
252295
|
+
if (!isRecord4(value) || Object.keys(value).some((key) => !RELEASE_CANARY_STAGE_RECEIPT_KEYS.has(key)) || Object.keys(value).length !== RELEASE_CANARY_STAGE_RECEIPT_KEYS.size || typeof value.fixtureId !== "string" || !UUID.test(value.fixtureId) || typeof value.tenantKey !== "string" || !RELEASE_CANARY_TENANT_KEY.test(value.tenantKey) || value.state !== "staged" || value.idempotent !== true)
|
|
251792
252296
|
return null;
|
|
251793
252297
|
return {
|
|
251794
252298
|
fixtureId: value.fixtureId,
|
|
@@ -251831,7 +252335,7 @@ function releaseCanaryDisableInput(fixtureId, disableRequestId, issuer, subject)
|
|
|
251831
252335
|
};
|
|
251832
252336
|
}
|
|
251833
252337
|
function releaseCanaryDisableReceipt(receiptCandidate, fixtureId) {
|
|
251834
|
-
if (!
|
|
252338
|
+
if (!isRecord4(receiptCandidate) || Object.keys(receiptCandidate).some((key) => !RELEASE_CANARY_DISABLE_RECEIPT_KEYS.has(key)) || Object.keys(receiptCandidate).length !== RELEASE_CANARY_DISABLE_RECEIPT_KEYS.size || receiptCandidate.fixtureId !== fixtureId || receiptCandidate.state !== "disabled" || typeof receiptCandidate.idempotent !== "boolean")
|
|
251835
252339
|
return null;
|
|
251836
252340
|
return { fixtureId, state: "disabled", idempotent: receiptCandidate.idempotent };
|
|
251837
252341
|
}
|
|
@@ -251860,7 +252364,7 @@ function genericScopedReleaseScopeJson(scope) {
|
|
|
251860
252364
|
return JSON.stringify(canonicalValue(scope));
|
|
251861
252365
|
}
|
|
251862
252366
|
function genericScopedReleaseScopeSha256(scope) {
|
|
251863
|
-
return
|
|
252367
|
+
return createHash10("sha256").update(genericScopedReleaseScopeJson(scope)).digest("hex");
|
|
251864
252368
|
}
|
|
251865
252369
|
function resolveGitBaseCommit(cwd, explicitRef) {
|
|
251866
252370
|
if (typeof explicitRef === "string" && explicitRef.trim()) {
|
|
@@ -251926,15 +252430,15 @@ function collectScopeFiles(cwd, file, files, dir, task) {
|
|
|
251926
252430
|
const results = [];
|
|
251927
252431
|
const resolvePathWithFallbacks = (filePath) => {
|
|
251928
252432
|
const trimmed = filePath.trim();
|
|
251929
|
-
const resolved =
|
|
251930
|
-
if (
|
|
252433
|
+
const resolved = resolve21(cwd, trimmed);
|
|
252434
|
+
if (existsSync13(resolved))
|
|
251931
252435
|
return resolved;
|
|
251932
252436
|
const candidates = [
|
|
251933
|
-
|
|
251934
|
-
|
|
251935
|
-
|
|
252437
|
+
resolve21(cwd, "supacloud/fa/release-scopes", trimmed),
|
|
252438
|
+
resolve21(cwd, "release-scopes", trimmed),
|
|
252439
|
+
resolve21(cwd, "scopes", trimmed)
|
|
251936
252440
|
];
|
|
251937
|
-
const found = candidates.find(
|
|
252441
|
+
const found = candidates.find(existsSync13);
|
|
251938
252442
|
if (found)
|
|
251939
252443
|
return found;
|
|
251940
252444
|
throw new Error(`Scope file not found: ${filePath}`);
|
|
@@ -251955,13 +252459,13 @@ function collectScopeFiles(cwd, file, files, dir, task) {
|
|
|
251955
252459
|
if (!taskFilter && (!dir || typeof dir !== "string" || !dir.trim())) {
|
|
251956
252460
|
throw new Error("At least one of --file, --files, or --task is required for scope_rebind");
|
|
251957
252461
|
}
|
|
251958
|
-
const candidates = typeof dir === "string" && dir.trim() ? [
|
|
251959
|
-
|
|
251960
|
-
|
|
251961
|
-
|
|
252462
|
+
const candidates = typeof dir === "string" && dir.trim() ? [resolve21(cwd, dir.trim())] : [
|
|
252463
|
+
resolve21(cwd, "supacloud/fa/release-scopes"),
|
|
252464
|
+
resolve21(cwd, "release-scopes"),
|
|
252465
|
+
resolve21(cwd, "scopes")
|
|
251962
252466
|
];
|
|
251963
252467
|
for (const directory of candidates) {
|
|
251964
|
-
if (
|
|
252468
|
+
if (existsSync13(directory)) {
|
|
251965
252469
|
try {
|
|
251966
252470
|
const entries = readdirSync4(directory, { withFileTypes: true });
|
|
251967
252471
|
for (const entry of entries) {
|
|
@@ -251973,7 +252477,7 @@ function collectScopeFiles(cwd, file, files, dir, task) {
|
|
|
251973
252477
|
results.push(fullPath);
|
|
251974
252478
|
} else {
|
|
251975
252479
|
try {
|
|
251976
|
-
const parsed = JSON.parse(
|
|
252480
|
+
const parsed = JSON.parse(readFileSync11(fullPath, "utf8"));
|
|
251977
252481
|
if (typeof parsed?.taskId === "string" && parsed.taskId.toLowerCase() === taskFilter) {
|
|
251978
252482
|
results.push(fullPath);
|
|
251979
252483
|
}
|
|
@@ -251992,7 +252496,7 @@ function collectScopeFiles(cwd, file, files, dir, task) {
|
|
|
251992
252496
|
return [...new Set(results)];
|
|
251993
252497
|
}
|
|
251994
252498
|
function handleScopeRebind(args) {
|
|
251995
|
-
const cwd = typeof args.cwd === "string" && args.cwd.trim() ?
|
|
252499
|
+
const cwd = typeof args.cwd === "string" && args.cwd.trim() ? resolve21(args.cwd.trim()) : process.cwd();
|
|
251996
252500
|
const targetBaseCommit = resolveGitBaseCommit(cwd, args.base_commit);
|
|
251997
252501
|
const scopeFiles = collectScopeFiles(cwd, args.file, args.files, args.dir, args.task);
|
|
251998
252502
|
const dryRun = args.dry_run === true;
|
|
@@ -252000,7 +252504,7 @@ function handleScopeRebind(args) {
|
|
|
252000
252504
|
for (const filePath of scopeFiles) {
|
|
252001
252505
|
let content;
|
|
252002
252506
|
try {
|
|
252003
|
-
content =
|
|
252507
|
+
content = readFileSync11(filePath, "utf8");
|
|
252004
252508
|
} catch (cause) {
|
|
252005
252509
|
throw new Error(`Failed to read scope file '${filePath}': ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
252006
252510
|
}
|
|
@@ -252010,7 +252514,7 @@ function handleScopeRebind(args) {
|
|
|
252010
252514
|
} catch {
|
|
252011
252515
|
throw new Error(`Scope file '${filePath}' is not valid JSON`);
|
|
252012
252516
|
}
|
|
252013
|
-
if (!
|
|
252517
|
+
if (!isRecord4(parsed) || typeof parsed.baseCommit !== "string" || !/^[0-9a-f]{40}$/.test(parsed.baseCommit)) {
|
|
252014
252518
|
throw new Error(`Scope file '${filePath}' has missing or invalid baseCommit`);
|
|
252015
252519
|
}
|
|
252016
252520
|
const previousBaseCommit = parsed.baseCommit;
|
|
@@ -252044,19 +252548,19 @@ function handleScopeRebind(args) {
|
|
|
252044
252548
|
});
|
|
252045
252549
|
}
|
|
252046
252550
|
function handleScopeInspect(args) {
|
|
252047
|
-
const cwd = typeof args.cwd === "string" && args.cwd.trim() ?
|
|
252551
|
+
const cwd = typeof args.cwd === "string" && args.cwd.trim() ? resolve21(args.cwd.trim()) : process.cwd();
|
|
252048
252552
|
if (typeof args.file !== "string" || !args.file.trim()) {
|
|
252049
252553
|
throw new Error("'file' is required for scope_inspect");
|
|
252050
252554
|
}
|
|
252051
252555
|
const trimmed = args.file.trim();
|
|
252052
|
-
let filePath =
|
|
252053
|
-
if (!
|
|
252556
|
+
let filePath = resolve21(cwd, trimmed);
|
|
252557
|
+
if (!existsSync13(filePath)) {
|
|
252054
252558
|
const candidates = [
|
|
252055
|
-
|
|
252056
|
-
|
|
252057
|
-
|
|
252559
|
+
resolve21(cwd, "supacloud/fa/release-scopes", trimmed),
|
|
252560
|
+
resolve21(cwd, "release-scopes", trimmed),
|
|
252561
|
+
resolve21(cwd, "scopes", trimmed)
|
|
252058
252562
|
];
|
|
252059
|
-
const found = candidates.find(
|
|
252563
|
+
const found = candidates.find(existsSync13);
|
|
252060
252564
|
if (found)
|
|
252061
252565
|
filePath = found;
|
|
252062
252566
|
else
|
|
@@ -252064,7 +252568,7 @@ function handleScopeInspect(args) {
|
|
|
252064
252568
|
}
|
|
252065
252569
|
let content;
|
|
252066
252570
|
try {
|
|
252067
|
-
content =
|
|
252571
|
+
content = readFileSync11(filePath, "utf8");
|
|
252068
252572
|
} catch (cause) {
|
|
252069
252573
|
throw new Error(`Failed to read scope file '${args.file}': ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
252070
252574
|
}
|
|
@@ -252074,7 +252578,7 @@ function handleScopeInspect(args) {
|
|
|
252074
252578
|
} catch {
|
|
252075
252579
|
throw new Error(`Scope file '${args.file}' is not valid JSON`);
|
|
252076
252580
|
}
|
|
252077
|
-
if (!
|
|
252581
|
+
if (!isRecord4(parsed) || typeof parsed.baseCommit !== "string" || !/^[0-9a-f]{40}$/.test(parsed.baseCommit)) {
|
|
252078
252582
|
throw new Error(`Scope file '${args.file}' has missing or invalid baseCommit`);
|
|
252079
252583
|
}
|
|
252080
252584
|
const scopeSha256 = genericScopedReleaseScopeSha256(parsed);
|
|
@@ -252114,7 +252618,7 @@ function parseCommaList(value) {
|
|
|
252114
252618
|
return [];
|
|
252115
252619
|
}
|
|
252116
252620
|
function handleScopeCreate(args, fallbackRef) {
|
|
252117
|
-
const cwd = typeof args.cwd === "string" && args.cwd.trim() ?
|
|
252621
|
+
const cwd = typeof args.cwd === "string" && args.cwd.trim() ? resolve21(args.cwd.trim()) : process.cwd();
|
|
252118
252622
|
if (typeof args.file !== "string" || !args.file.trim()) {
|
|
252119
252623
|
throw new Error("'file' is required for scope_create");
|
|
252120
252624
|
}
|
|
@@ -252129,7 +252633,7 @@ function handleScopeCreate(args, fallbackRef) {
|
|
|
252129
252633
|
throw new Error("'ref' is invalid for release controls");
|
|
252130
252634
|
}
|
|
252131
252635
|
const targetBaseCommit = resolveGitBaseCommit(cwd, args.base_commit);
|
|
252132
|
-
const filePath =
|
|
252636
|
+
const filePath = resolve21(cwd, args.file.trim());
|
|
252133
252637
|
mkdirSync4(dirname13(filePath), { recursive: true });
|
|
252134
252638
|
const scope = {
|
|
252135
252639
|
baseCommit: targetBaseCommit,
|
|
@@ -252236,7 +252740,7 @@ function registerReleaseTools(server2, http, options = {}) {
|
|
|
252236
252740
|
if (!mutation.ok || mutation.status !== 200) {
|
|
252237
252741
|
return mutationFailure("release.logical_backup.create", mutation);
|
|
252238
252742
|
}
|
|
252239
|
-
const responseBackup =
|
|
252743
|
+
const responseBackup = isRecord4(mutation.data) ? verifiedBackup(mutation.data.backup, projectRef) : null;
|
|
252240
252744
|
const afterFailure = readInventoryFailure("release.logical_backup.create", after);
|
|
252241
252745
|
const addedBackup = after.inventory && newlyCreatedBackup(before.inventory, after.inventory);
|
|
252242
252746
|
if (!responseBackup || afterFailure || !addedBackup || !equalBackup(responseBackup, addedBackup)) {
|
|
@@ -252261,7 +252765,7 @@ function registerReleaseTools(server2, http, options = {}) {
|
|
|
252261
252765
|
if (!mutation.ok || mutation.status !== 200) {
|
|
252262
252766
|
return mutationFailure("release.logical_backup.restore", mutation);
|
|
252263
252767
|
}
|
|
252264
|
-
const responseBackup =
|
|
252768
|
+
const responseBackup = isRecord4(mutation.data) ? verifiedBackup(mutation.data.restored_backup, projectRef) : null;
|
|
252265
252769
|
const after = await readInventory(http, projectRef);
|
|
252266
252770
|
const afterFailure = readInventoryFailure("release.logical_backup.restore", after);
|
|
252267
252771
|
const restoredInventoryBackup = after.inventory?.find((backup) => backup.backup_id === request.backup_id);
|
|
@@ -252352,9 +252856,9 @@ function registerReleaseTools(server2, http, options = {}) {
|
|
|
252352
252856
|
|
|
252353
252857
|
// src/shared/tools/deploy-tools.ts
|
|
252354
252858
|
import { access as access4, lstat as lstat5, mkdtemp as mkdtemp2, opendir, readFile as readFile9, rm as rm3, writeFile as writeFile6 } from "node:fs/promises";
|
|
252355
|
-
import { createHash as
|
|
252859
|
+
import { createHash as createHash11 } from "node:crypto";
|
|
252356
252860
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
252357
|
-
import { basename as basename9, dirname as dirname14, join as join18, relative as relative14, resolve as
|
|
252861
|
+
import { basename as basename9, dirname as dirname14, join as join18, relative as relative14, resolve as resolve23, sep as sep12 } from "node:path";
|
|
252358
252862
|
import { spawn as spawn3 } from "node:child_process";
|
|
252359
252863
|
|
|
252360
252864
|
// node_modules/fflate/esm/index.mjs
|
|
@@ -253046,13 +253550,13 @@ async function readJson(path) {
|
|
|
253046
253550
|
}
|
|
253047
253551
|
}
|
|
253048
253552
|
async function findDeployConfigRoot(startDirectory) {
|
|
253049
|
-
let directory =
|
|
253553
|
+
let directory = resolve23(startDirectory);
|
|
253050
253554
|
while (true) {
|
|
253051
253555
|
if (await pathExists(join18(directory, "supacloud.json")))
|
|
253052
253556
|
return directory;
|
|
253053
253557
|
const parent = dirname14(directory);
|
|
253054
253558
|
if (parent === directory)
|
|
253055
|
-
return
|
|
253559
|
+
return resolve23(startDirectory);
|
|
253056
253560
|
directory = parent;
|
|
253057
253561
|
}
|
|
253058
253562
|
}
|
|
@@ -253170,9 +253674,9 @@ function selectDeployment(deployments, requestedId, projectName) {
|
|
|
253170
253674
|
throw new Error(deployments.length === 0 ? "No frontend deployments exist for this project" : `Multiple frontend deployments found (${ids}). Set frontend.id in supacloud.json or pass --id`);
|
|
253171
253675
|
}
|
|
253172
253676
|
function targetRoot(configRoot, target, name) {
|
|
253173
|
-
const root =
|
|
253174
|
-
const prefix = `${
|
|
253175
|
-
if (root !==
|
|
253677
|
+
const root = resolve23(configRoot, target.root || (name === "frontend" ? "." : name));
|
|
253678
|
+
const prefix = `${resolve23(configRoot)}${sep12}`;
|
|
253679
|
+
if (root !== resolve23(configRoot) && !root.startsWith(prefix)) {
|
|
253176
253680
|
throw new Error(`Deploy target '${name}' root must stay inside the repository root`);
|
|
253177
253681
|
}
|
|
253178
253682
|
return root;
|
|
@@ -253223,8 +253727,8 @@ function defaultOutputDirectory(framework) {
|
|
|
253223
253727
|
}
|
|
253224
253728
|
}
|
|
253225
253729
|
function resolveInsideProject(projectDirectory, candidate, allowRoot = false) {
|
|
253226
|
-
const resolved =
|
|
253227
|
-
const projectRoot =
|
|
253730
|
+
const resolved = resolve23(projectDirectory, candidate);
|
|
253731
|
+
const projectRoot = resolve23(projectDirectory);
|
|
253228
253732
|
const projectPrefix = `${projectRoot}${sep12}`;
|
|
253229
253733
|
if (!allowRoot && resolved === projectRoot || resolved !== projectRoot && !resolved.startsWith(projectPrefix)) {
|
|
253230
253734
|
throw new Error("Frontend output directory must stay inside the project directory");
|
|
@@ -253289,7 +253793,7 @@ async function createFrontendArchive(outputDirectory) {
|
|
|
253289
253793
|
try {
|
|
253290
253794
|
const archiveBytes = zipSync(collected.files, { level: 6, mtime: FIXED_ZIP_MTIME });
|
|
253291
253795
|
await writeFile6(archivePath, archiveBytes);
|
|
253292
|
-
const sha256 =
|
|
253796
|
+
const sha256 = createHash11("sha256").update(archiveBytes).digest("hex");
|
|
253293
253797
|
return {
|
|
253294
253798
|
archivePath,
|
|
253295
253799
|
sha256,
|
|
@@ -253335,7 +253839,7 @@ function deployResponse(result, json) {
|
|
|
253335
253839
|
}
|
|
253336
253840
|
function registerDeployTools(server2, http, options = {}) {
|
|
253337
253841
|
server2.tool("deploy", "Build and publish the linked frontend with one command", deployToolSchema, async (args) => {
|
|
253338
|
-
const invocationDirectory =
|
|
253842
|
+
const invocationDirectory = resolve23(String(args.cwd || options.cwd || process.cwd()));
|
|
253339
253843
|
const projectRef = String(args.ref || options.projectRef || "").trim();
|
|
253340
253844
|
if (!projectRef)
|
|
253341
253845
|
throw new Error("A linked project ref is required. Set SUPACLOUD_PROJECT_REF or pass --ref");
|
|
@@ -253508,11 +254012,11 @@ function registerDeployTools(server2, http, options = {}) {
|
|
|
253508
254012
|
|
|
253509
254013
|
// src/shared/tools/remote-dev-tools.ts
|
|
253510
254014
|
import { spawn as spawn4 } from "node:child_process";
|
|
253511
|
-
import { existsSync as
|
|
254015
|
+
import { existsSync as existsSync14 } from "node:fs";
|
|
253512
254016
|
import { readFile as readFile10 } from "node:fs/promises";
|
|
253513
254017
|
import { readdir as readdir6 } from "node:fs/promises";
|
|
253514
|
-
import { createHash as
|
|
253515
|
-
import { join as join19, resolve as
|
|
254018
|
+
import { createHash as createHash12 } from "node:crypto";
|
|
254019
|
+
import { join as join19, resolve as resolve24 } from "node:path";
|
|
253516
254020
|
var SAFE_TOKEN = /^[A-Za-z0-9._:@/+,-]+$/;
|
|
253517
254021
|
var SAFE_REMOTE_ROOT = /^\/(?:[A-Za-z0-9._-]+\/)*[A-Za-z0-9._-]+\/?$/;
|
|
253518
254022
|
var remoteDevToolSchema = {
|
|
@@ -253555,20 +254059,20 @@ function resolveDrizzleCommand(root, configured) {
|
|
|
253555
254059
|
if (configured?.trim())
|
|
253556
254060
|
return configured.trim();
|
|
253557
254061
|
const local = join19(root, "node_modules", ".bin", "drizzle-kit");
|
|
253558
|
-
return
|
|
254062
|
+
return existsSync14(local) ? local : "drizzle-kit";
|
|
253559
254063
|
}
|
|
253560
254064
|
function toolFailed(value) {
|
|
253561
254065
|
return value?.isError === true || value?.content?.some((chunk) => typeof chunk?.text === "string" && chunk.text.trimStart().startsWith("❌"));
|
|
253562
254066
|
}
|
|
253563
254067
|
async function migrateDatabase(args, options) {
|
|
253564
|
-
const root =
|
|
254068
|
+
const root = resolve24(String(args.project_dir || options.cwd || process.cwd()));
|
|
253565
254069
|
const projectConfig = await readProjectConfig3(root);
|
|
253566
254070
|
const config = projectConfig.dev || {};
|
|
253567
254071
|
const database = config.database || {};
|
|
253568
254072
|
const execute = options.execute || ((command, commandArgs, cwd) => runProcess(command, commandArgs, cwd));
|
|
253569
|
-
const drizzleConfig =
|
|
254073
|
+
const drizzleConfig = resolve24(root, String(args.drizzle_config || database.drizzleConfig || "drizzle.config.ts"));
|
|
253570
254074
|
const migrationsDir = String(args.migrations_dir || database.migrationsDir || "supabase/migrations");
|
|
253571
|
-
if (!
|
|
254075
|
+
if (!existsSync14(drizzleConfig))
|
|
253572
254076
|
throw new Error(`Drizzle config not found: ${drizzleConfig}`);
|
|
253573
254077
|
const generated = await execute(resolveDrizzleCommand(root, typeof args.drizzle_bin === "string" ? args.drizzle_bin : database.drizzleBin), ["generate", "--config", drizzleConfig], root);
|
|
253574
254078
|
if (generated.exitCode !== 0)
|
|
@@ -253587,7 +254091,7 @@ async function migrateDatabase(args, options) {
|
|
|
253587
254091
|
}
|
|
253588
254092
|
async function readProjectConfig3(root) {
|
|
253589
254093
|
const file = join19(root, "supacloud.json");
|
|
253590
|
-
if (!
|
|
254094
|
+
if (!existsSync14(file))
|
|
253591
254095
|
return {};
|
|
253592
254096
|
try {
|
|
253593
254097
|
const parsed = JSON.parse(await readFile10(file, "utf8"));
|
|
@@ -253613,7 +254117,7 @@ async function sourceFingerprint(root) {
|
|
|
253613
254117
|
}
|
|
253614
254118
|
};
|
|
253615
254119
|
await visit(root);
|
|
253616
|
-
const hash =
|
|
254120
|
+
const hash = createHash12("sha256");
|
|
253617
254121
|
for (const file of files) {
|
|
253618
254122
|
hash.update(file.slice(root.length).replace(/\\/g, "/"));
|
|
253619
254123
|
hash.update(await readFile10(file));
|
|
@@ -253637,13 +254141,13 @@ function targetDirectory(root, target, functionSlug, config = {}) {
|
|
|
253637
254141
|
if (target === "functions") {
|
|
253638
254142
|
const targets = config.targets && typeof config.targets === "object" ? config.targets : {};
|
|
253639
254143
|
const match = Object.values(targets).find((entry) => entry?.type === "edge_function" && (!functionSlug || String(entry.slug || "") === functionSlug));
|
|
253640
|
-
const base = match?.root ?
|
|
254144
|
+
const base = match?.root ? resolve24(root, String(match.root)) : join19(root, "supabase", "functions");
|
|
253641
254145
|
return match?.root ? base : functionSlug ? join19(base, safeToken(functionSlug, "function")) : base;
|
|
253642
254146
|
}
|
|
253643
254147
|
if (target === "frontend") {
|
|
253644
254148
|
const targets = config.targets && typeof config.targets === "object" ? config.targets : {};
|
|
253645
254149
|
const match = Object.values(targets).find((entry) => entry?.type === "frontend");
|
|
253646
|
-
return match?.root ?
|
|
254150
|
+
return match?.root ? resolve24(root, String(match.root)) : join19(root, "apps", "web");
|
|
253647
254151
|
}
|
|
253648
254152
|
return root;
|
|
253649
254153
|
}
|
|
@@ -253682,10 +254186,10 @@ function reloadCommand(config, target, projectRef, functionSlug) {
|
|
|
253682
254186
|
return [...command.split(" "), "--project-ref", safeToken(projectRef || "test", "project_ref"), "--target", targetConfigPath(target), ...functionSlug ? ["--function", safeToken(functionSlug, "function")] : []];
|
|
253683
254187
|
}
|
|
253684
254188
|
function sshArgs(connection, remoteCommand) {
|
|
253685
|
-
return ["-p", String(connection.port), "-i",
|
|
254189
|
+
return ["-p", String(connection.port), "-i", resolve24(connection.key), "-o", "BatchMode=yes", "-o", "StrictHostKeyChecking=yes", `${connection.user}@${connection.host}`, ...remoteCommand];
|
|
253686
254190
|
}
|
|
253687
254191
|
function rsyncArgs(connection, source, destination, excludes, deleteRemote) {
|
|
253688
|
-
const args = ["-az", "--checksum", "--partial", "--protect-args", "-e", `ssh -p ${connection.port} -i ${
|
|
254192
|
+
const args = ["-az", "--checksum", "--partial", "--protect-args", "-e", `ssh -p ${connection.port} -i ${resolve24(connection.key)} -o BatchMode=yes -o StrictHostKeyChecking=yes`];
|
|
253689
254193
|
if (deleteRemote)
|
|
253690
254194
|
args.push("--delete-delay");
|
|
253691
254195
|
for (const exclude of excludes) {
|
|
@@ -253697,17 +254201,17 @@ function rsyncArgs(connection, source, destination, excludes, deleteRemote) {
|
|
|
253697
254201
|
return args;
|
|
253698
254202
|
}
|
|
253699
254203
|
async function syncOnce(args, options) {
|
|
253700
|
-
const root =
|
|
254204
|
+
const root = resolve24(String(args.project_dir || options.cwd || process.cwd()));
|
|
253701
254205
|
const projectConfig = await readProjectConfig3(root);
|
|
253702
254206
|
const config = projectConfig.dev || {};
|
|
253703
254207
|
const target = String(args.target || "project");
|
|
253704
254208
|
const source = targetDirectory(root, target, typeof args.function === "string" ? args.function : undefined, projectConfig);
|
|
253705
|
-
if (!
|
|
254209
|
+
if (!existsSync14(source))
|
|
253706
254210
|
throw new Error(`Dev source directory not found: ${source}`);
|
|
253707
254211
|
let compiled = false;
|
|
253708
254212
|
if (config.compile === true && target !== "db") {
|
|
253709
|
-
const compileRoot =
|
|
253710
|
-
const compileOutDir =
|
|
254213
|
+
const compileRoot = resolve24(root, config.compileRoot || ".");
|
|
254214
|
+
const compileOutDir = resolve24(root, config.compileOutDir || "generated");
|
|
253711
254215
|
const compilation = await compileProject({
|
|
253712
254216
|
rootDir: compileRoot,
|
|
253713
254217
|
outDir: compileOutDir,
|
|
@@ -253745,7 +254249,7 @@ function registerRemoteDevTools(server2, options = {}) {
|
|
|
253745
254249
|
if (["production", "prod"].includes((options.environment || "").toLowerCase()))
|
|
253746
254250
|
throw new Error("Remote dev mode is forbidden for production environments");
|
|
253747
254251
|
if (args.action === "status") {
|
|
253748
|
-
const root =
|
|
254252
|
+
const root = resolve24(String(args.project_dir || options.cwd || process.cwd()));
|
|
253749
254253
|
const config = await readDevConfig(root);
|
|
253750
254254
|
const connection = connectionArgs(options, config, args);
|
|
253751
254255
|
const execute = options.execute || ((command, commandArgs, cwd) => runProcess(command, commandArgs, cwd));
|
|
@@ -253759,7 +254263,7 @@ function registerRemoteDevTools(server2, options = {}) {
|
|
|
253759
254263
|
return { content: [{ type: "text", text: JSON.stringify(await migrateDatabase(args, options), null, 2) }] };
|
|
253760
254264
|
}
|
|
253761
254265
|
if (args.action === "watch") {
|
|
253762
|
-
const root =
|
|
254266
|
+
const root = resolve24(String(args.project_dir || options.cwd || process.cwd()));
|
|
253763
254267
|
const interval = Math.max(100, Math.min(1e4, Number(args.interval_ms || 300)));
|
|
253764
254268
|
let fingerprint = "";
|
|
253765
254269
|
let lastSync = null;
|
|
@@ -253780,7 +254284,7 @@ function registerRemoteDevTools(server2, options = {}) {
|
|
|
253780
254284
|
// package.json
|
|
253781
254285
|
var package_default8 = {
|
|
253782
254286
|
name: "@supacloud/cli",
|
|
253783
|
-
version: "0.
|
|
254287
|
+
version: "0.62.0",
|
|
253784
254288
|
description: "Project-scoped CLI for SupaCloud users",
|
|
253785
254289
|
type: "module",
|
|
253786
254290
|
main: "./dist/index.js",
|
|
@@ -253807,7 +254311,7 @@ var package_default8 = {
|
|
|
253807
254311
|
"deploy",
|
|
253808
254312
|
"supabase"
|
|
253809
254313
|
],
|
|
253810
|
-
license: "
|
|
254314
|
+
license: "Apache-2.0",
|
|
253811
254315
|
repository: {
|
|
253812
254316
|
type: "git",
|
|
253813
254317
|
url: "https://github.com/vibeunion/supacloud.git",
|
|
@@ -253815,14 +254319,14 @@ var package_default8 = {
|
|
|
253815
254319
|
},
|
|
253816
254320
|
dependencies: {
|
|
253817
254321
|
"@sinclair/typebox": "^0.34.52",
|
|
253818
|
-
"@supacloud/compiler": "^0.
|
|
253819
|
-
"@supacloud/delivery": "0.
|
|
254322
|
+
"@supacloud/compiler": "^0.30.0",
|
|
254323
|
+
"@supacloud/delivery": "0.4.0",
|
|
253820
254324
|
"@supacloud/db": "^0.2.0",
|
|
253821
254325
|
fflate: "^0.8.3",
|
|
253822
254326
|
typebox: "1.3.34"
|
|
253823
254327
|
},
|
|
253824
254328
|
overrides: {
|
|
253825
|
-
"@supacloud/delivery": "0.
|
|
254329
|
+
"@supacloud/delivery": "0.4.0"
|
|
253826
254330
|
},
|
|
253827
254331
|
devDependencies: {
|
|
253828
254332
|
"@types/bun": "^1.4.2",
|