ts-ag 1.1.26 → 1.2.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.
@@ -0,0 +1,642 @@
1
+ #!/usr/bin/env node
2
+ import { t as isDirectExecution } from "../utils-DLairfc9.mjs";
3
+ import { builtinModules } from "node:module";
4
+ import { existsSync } from "node:fs";
5
+ import { readFile } from "node:fs/promises";
6
+ import path from "node:path";
7
+ import { parseArgs, styleText } from "node:util";
8
+ import { parse } from "acorn";
9
+ import { ancestor } from "acorn-walk";
10
+ import { glob } from "glob";
11
+ import { unique } from "radash";
12
+ const JS_EXTENSIONS = [
13
+ ".mjs",
14
+ ".js",
15
+ ".cjs"
16
+ ];
17
+ const EXPORT_CONDITION_KEYS = new Set([
18
+ "browser",
19
+ "default",
20
+ "deno",
21
+ "development",
22
+ "import",
23
+ "node",
24
+ "production",
25
+ "require",
26
+ "worker"
27
+ ]);
28
+ const LABEL = styleText("cyan", "[check-llrt-worker]");
29
+ //#endregion
30
+ //#region src/scripts/check-llrt/options.ts
31
+ function toArray(value) {
32
+ if (value === void 0) return [];
33
+ return Array.isArray(value) ? value : [value];
34
+ }
35
+ async function parseCliOptions() {
36
+ const { values } = parseArgs({
37
+ args: process.argv.slice(2),
38
+ options: {
39
+ "api-url": { type: "string" },
40
+ filter: {
41
+ type: "string",
42
+ short: "f",
43
+ multiple: true
44
+ },
45
+ package: {
46
+ type: "string",
47
+ short: "p",
48
+ multiple: true
49
+ },
50
+ verbose: {
51
+ type: "boolean",
52
+ short: "v"
53
+ },
54
+ workspace: {
55
+ type: "string",
56
+ short: "w",
57
+ multiple: true
58
+ }
59
+ }
60
+ });
61
+ const apiUrl = values["api-url"] ?? process.env.LLRT_API_URL ?? "https://raw.githubusercontent.com/awslabs/llrt/main/API.md";
62
+ const { packages, availablePackages } = await selectPackages(toArray(values.package).map((packagePath) => path.resolve(packagePath)), toArray(values.workspace).map((workspacePath) => path.resolve(workspacePath)), toArray(values.filter));
63
+ return {
64
+ apiUrl,
65
+ packages,
66
+ availablePackages,
67
+ verbose: values.verbose === true,
68
+ llrtApiMarkdown: parseLlrtApi(await fetchLlrtApiMarkdown(apiUrl))
69
+ };
70
+ }
71
+ async function fetchLlrtApiMarkdown(apiUrl) {
72
+ const apiResponse = await fetch(apiUrl);
73
+ if (!apiResponse.ok) throw new Error(`Failed to fetch LLRT API docs from ${apiUrl}: ${apiResponse.status}`);
74
+ return apiResponse.text();
75
+ }
76
+ function parseLlrtApi(markdown) {
77
+ const support = /* @__PURE__ */ new Map();
78
+ let currentModule;
79
+ for (const line of markdown.split("\n")) {
80
+ const trimmed = line.trim();
81
+ const moduleMatch = /^##\s+([a-z_]+(?:\/[a-z_-]+)*)$/.exec(trimmed);
82
+ if (moduleMatch) {
83
+ currentModule = moduleMatch[1];
84
+ support.set(currentModule, /* @__PURE__ */ new Set());
85
+ continue;
86
+ }
87
+ if (trimmed.startsWith("## ")) currentModule = void 0;
88
+ if (!currentModule) continue;
89
+ const memberMatch = /^\[([^\]]+)\]\(/.exec(trimmed);
90
+ if (memberMatch) support.get(currentModule)?.add(memberMatch[1]);
91
+ }
92
+ return support;
93
+ }
94
+ async function selectPackages(packagePaths, workspacePaths, filters) {
95
+ const explicitPaths = packagePaths.length > 0 ? packagePaths : workspacePaths.length === 0 ? [process.cwd()] : [];
96
+ const packageMap = /* @__PURE__ */ new Map();
97
+ for (const packagePath of explicitPaths) {
98
+ const pkg = await readPackage(packagePath);
99
+ packageMap.set(pkg.dir, pkg);
100
+ }
101
+ for (const workspacePath of workspacePaths) for (const pkg of await discoverWorkspacePackages(workspacePath)) packageMap.set(pkg.dir, pkg);
102
+ const availablePackages = [...packageMap.values()].sort((a, b) => a.dir.localeCompare(b.dir));
103
+ if (filters.length === 0) return {
104
+ packages: availablePackages,
105
+ availablePackages
106
+ };
107
+ return {
108
+ packages: availablePackages.filter((pkg) => filters.some((filter) => matchesPackageFilter(pkg, filter))),
109
+ availablePackages
110
+ };
111
+ }
112
+ async function readPackage(packagePath) {
113
+ const resolvedPath = path.resolve(packagePath);
114
+ const packageJsonPath = resolvedPath.endsWith("package.json") ? resolvedPath : path.join(resolvedPath, "package.json");
115
+ const packageJson = JSON.parse(await readFile(packageJsonPath, "utf8"));
116
+ const dir = path.dirname(packageJsonPath);
117
+ return {
118
+ name: packageJson.name ?? path.basename(dir),
119
+ dir,
120
+ packageJsonPath,
121
+ packageJson
122
+ };
123
+ }
124
+ async function discoverWorkspacePackages(workspacePath) {
125
+ const root = path.resolve(workspacePath);
126
+ const patterns = await readWorkspacePackagePatterns(root);
127
+ if (patterns.length === 0) {
128
+ const rootPackageJson = path.join(root, "package.json");
129
+ return existsSync(rootPackageJson) ? [await readPackage(rootPackageJson)] : [];
130
+ }
131
+ const includePatterns = patterns.filter((pattern) => !pattern.startsWith("!"));
132
+ const excludePatterns = patterns.filter((pattern) => pattern.startsWith("!")).map((pattern) => path.posix.join(pattern.slice(1).replace(/\\/g, "/"), "package.json"));
133
+ const packageJsonPaths = await glob(includePatterns.map((pattern) => path.posix.join(pattern.replace(/\\/g, "/"), "package.json")), {
134
+ absolute: true,
135
+ cwd: root,
136
+ ignore: ["**/node_modules/**", ...excludePatterns],
137
+ nodir: true
138
+ });
139
+ return (await Promise.all(packageJsonPaths.map((packageJsonPath) => readPackage(packageJsonPath)))).sort((a, b) => a.dir.localeCompare(b.dir));
140
+ }
141
+ async function readWorkspacePackagePatterns(root) {
142
+ const rootPackageJsonPath = path.join(root, "package.json");
143
+ const pnpmWorkspacePath = path.join(root, "pnpm-workspace.yaml");
144
+ const patterns = [];
145
+ if (existsSync(rootPackageJsonPath)) {
146
+ const rootPackage = JSON.parse(await readFile(rootPackageJsonPath, "utf8"));
147
+ if (Array.isArray(rootPackage.workspaces)) patterns.push(...rootPackage.workspaces);
148
+ else if (Array.isArray(rootPackage.workspaces?.packages)) patterns.push(...rootPackage.workspaces.packages);
149
+ }
150
+ if (existsSync(pnpmWorkspacePath)) patterns.push(...parsePnpmWorkspacePackages(await readFile(pnpmWorkspacePath, "utf8")));
151
+ return unique(patterns);
152
+ }
153
+ function parsePnpmWorkspacePackages(yaml) {
154
+ const patterns = [];
155
+ let inPackages = false;
156
+ let packageIndent = -1;
157
+ for (const line of yaml.split(/\r?\n/)) {
158
+ const trimmed = line.trim();
159
+ if (trimmed.length === 0 || trimmed.startsWith("#")) continue;
160
+ if (trimmed === "packages:") {
161
+ inPackages = true;
162
+ packageIndent = line.search(/\S/);
163
+ continue;
164
+ }
165
+ if (!inPackages) continue;
166
+ if (line.search(/\S/) <= packageIndent) break;
167
+ const match = /^-\s+(.+)$/.exec(trimmed);
168
+ if (match) patterns.push(stripYamlString(match[1]));
169
+ }
170
+ return patterns;
171
+ }
172
+ function stripYamlString(value) {
173
+ const trimmed = value.trim();
174
+ if (trimmed.startsWith("'") && trimmed.endsWith("'") || trimmed.startsWith("\"") && trimmed.endsWith("\"")) return trimmed.slice(1, -1);
175
+ return trimmed;
176
+ }
177
+ function matchesPackageFilter(pkg, filter, root = process.cwd()) {
178
+ const normalizedFilter = filter.replace(/\\/g, "/");
179
+ const relativeDir = path.relative(root, pkg.dir).replace(/\\/g, "/");
180
+ if (/[*?[\]{}]/.test(normalizedFilter)) {
181
+ const regex = globPatternToRegex(normalizedFilter);
182
+ return regex.test(pkg.name) || regex.test(relativeDir);
183
+ }
184
+ return pkg.name === normalizedFilter || relativeDir === normalizedFilter || relativeDir.startsWith(`${normalizedFilter}/`);
185
+ }
186
+ function globPatternToRegex(pattern) {
187
+ let source = "";
188
+ for (let index = 0; index < pattern.length; index++) {
189
+ const char = pattern[index];
190
+ const nextChar = pattern[index + 1];
191
+ if (char === "*" && nextChar === "*") {
192
+ source += ".*";
193
+ index++;
194
+ continue;
195
+ }
196
+ if (char === "*") {
197
+ source += "[^/]*";
198
+ continue;
199
+ }
200
+ if (char === "?") {
201
+ source += "[^/]";
202
+ continue;
203
+ }
204
+ source += char.replace(/[.+^${}()|[\]\\]/g, "\\$&");
205
+ }
206
+ return new RegExp(`^${source}$`);
207
+ }
208
+ //#endregion
209
+ //#region src/scripts/check-llrt/index.ts
210
+ const nodeBuiltinModules = new Set(builtinModules.filter((moduleName) => !moduleName.startsWith("_")).map((moduleName) => moduleName.replace(/^node:/, "")));
211
+ const formatPath = (filePath) => styleText("dim", path.relative(process.cwd(), filePath));
212
+ const logInfo = (message) => console.log(`${LABEL} ${message}`);
213
+ const logWarn = (message) => console.warn(`${LABEL} ${styleText("yellow", message)}`);
214
+ const logError = (message) => console.error(`${LABEL} ${styleText("red", message)}`);
215
+ async function checkLlrtWorker(options) {
216
+ const llrtSupport = options.llrtApiMarkdown;
217
+ const { packages, availablePackages } = options;
218
+ const packageByName = new Map(availablePackages.map((pkg) => [pkg.name, pkg]));
219
+ const diagnostics = [];
220
+ const usageByModule = /* @__PURE__ */ new Map();
221
+ const visitedFiles = /* @__PURE__ */ new Set();
222
+ const targets = packages.flatMap((pkg) => {
223
+ const packageTargets = extractWorkerExportTargets(pkg);
224
+ for (const target of packageTargets) if (!existsSync(target.filePath)) diagnostics.push({
225
+ packageName: pkg.name,
226
+ filePath: target.filePath,
227
+ message: `worker export \`${target.exportKey}\` points to missing built file`
228
+ });
229
+ return packageTargets;
230
+ });
231
+ const visitFile = async (pkg, filePath) => {
232
+ const normalizedPath = path.resolve(filePath);
233
+ const visitKey = `${pkg.name}:${normalizedPath}`;
234
+ if (visitedFiles.has(visitKey)) return;
235
+ visitedFiles.add(visitKey);
236
+ const sourceFile = parseJs(await readFile(normalizedPath, "utf8"));
237
+ const bindings = /* @__PURE__ */ new Map();
238
+ const pendingImports = [];
239
+ collectImports(sourceFile, bindings, pendingImports, diagnostics, pkg.name, normalizedPath, llrtSupport);
240
+ walkValueReferences(sourceFile, bindings, diagnostics, usageByModule, pkg.name, normalizedPath, llrtSupport);
241
+ for (const specifier of pendingImports) {
242
+ const resolved = resolveImportSpecifier(specifier, normalizedPath, packageByName, diagnostics, pkg.name);
243
+ if (resolved) await visitFile(resolved.pkg, resolved.filePath);
244
+ }
245
+ };
246
+ for (const target of targets) {
247
+ const pkg = packageByName.get(target.packageName);
248
+ if (pkg && existsSync(target.filePath)) await visitFile(pkg, target.filePath);
249
+ }
250
+ if (options.verbose && packages.length === 0) logWarn("No packages were selected");
251
+ return {
252
+ checkedApiUrl: options.apiUrl,
253
+ diagnostics,
254
+ packages,
255
+ targets,
256
+ usageByModule,
257
+ visitedFiles: [...visitedFiles].map((key) => key.slice(key.indexOf(":") + 1)).sort()
258
+ };
259
+ }
260
+ function extractWorkerExportTargets(pkg) {
261
+ const exportsValue = pkg.packageJson.exports;
262
+ if (exportsValue === void 0) return [];
263
+ const entries = isExportMap(exportsValue) ? Object.entries(exportsValue) : [[".", exportsValue]];
264
+ const targets = [];
265
+ for (const [exportKey, exportValue] of entries) for (const target of collectWorkerTargets(exportValue, false)) if (isJsFile(target)) targets.push({
266
+ packageName: pkg.name,
267
+ exportKey,
268
+ filePath: path.resolve(pkg.dir, target)
269
+ });
270
+ return uniqueTargets(targets);
271
+ }
272
+ function collectWorkerTargets(value, inWorkerBranch) {
273
+ if (typeof value === "string") return inWorkerBranch ? [value] : [];
274
+ if (Array.isArray(value)) return value.flatMap((item) => collectWorkerTargets(item, inWorkerBranch));
275
+ if (!isPlainObject(value)) return [];
276
+ const targets = [];
277
+ for (const [key, child] of Object.entries(value)) {
278
+ if (key === "types") continue;
279
+ if (key === "worker") targets.push(...collectWorkerTargets(child, true));
280
+ else if (inWorkerBranch) targets.push(...collectWorkerTargets(child, true));
281
+ }
282
+ return targets;
283
+ }
284
+ function resolveImportSpecifier(specifier, containingFile, packageByName, diagnostics, packageName) {
285
+ if (isRelativeSpecifier(specifier)) {
286
+ const filePath = resolveJsPath(path.resolve(path.dirname(containingFile), specifier));
287
+ return filePath ? {
288
+ pkg: findPackageForFile(filePath, packageByName) ?? packageByName.get(packageName),
289
+ filePath
290
+ } : void 0;
291
+ }
292
+ const parsedPackageSpecifier = parsePackageSpecifier(specifier);
293
+ const pkg = packageByName.get(parsedPackageSpecifier.name);
294
+ if (!pkg) return void 0;
295
+ const exportKey = parsedPackageSpecifier.subpath ? `.${parsedPackageSpecifier.subpath}` : ".";
296
+ const target = resolvePackageExportTarget(pkg.packageJson.exports, exportKey, [
297
+ "worker",
298
+ "import",
299
+ "default"
300
+ ]);
301
+ if (!target) return void 0;
302
+ const filePath = path.resolve(pkg.dir, target);
303
+ if (!existsSync(filePath)) {
304
+ diagnostics.push({
305
+ packageName,
306
+ filePath,
307
+ message: `workspace import \`${specifier}\` resolves to missing built file`
308
+ });
309
+ return;
310
+ }
311
+ return {
312
+ pkg,
313
+ filePath
314
+ };
315
+ }
316
+ function resolvePackageExportTarget(exportsValue, exportKey, conditions) {
317
+ if (exportsValue === void 0) return void 0;
318
+ if (!isExportMap(exportsValue)) return exportKey === "." ? selectConditionalTarget(exportsValue, conditions) : void 0;
319
+ return selectConditionalTarget(exportsValue[exportKey], conditions);
320
+ }
321
+ function selectConditionalTarget(value, conditions) {
322
+ if (typeof value === "string") return isJsFile(value) ? value : void 0;
323
+ if (Array.isArray(value)) {
324
+ for (const item of value) {
325
+ const target = selectConditionalTarget(item, conditions);
326
+ if (target) return target;
327
+ }
328
+ return;
329
+ }
330
+ if (!isPlainObject(value)) return void 0;
331
+ for (const condition of conditions) {
332
+ const target = selectConditionalTarget(value[condition], conditions);
333
+ if (target) return target;
334
+ }
335
+ }
336
+ function collectImports(sourceFile, bindings, pendingImports, diagnostics, packageName, filePath, support) {
337
+ ancestor(sourceFile, {
338
+ ImportDeclaration(node) {
339
+ const specifier = getLiteralString(node.source);
340
+ if (!specifier) return;
341
+ if (isBuiltinModule(specifier)) collectBuiltinImportSpecifiers(node.specifiers ?? [], specifier, bindings, diagnostics, packageName, filePath, support);
342
+ else pendingImports.push(specifier);
343
+ },
344
+ ExportNamedDeclaration(node) {
345
+ const specifier = getLiteralString(node.source);
346
+ if (!specifier) return;
347
+ if (isBuiltinModule(specifier)) {
348
+ validateBuiltinModule(specifier, diagnostics, packageName, filePath, support);
349
+ for (const spec of node.specifiers ?? []) {
350
+ const importedName = getExportedImportName(spec);
351
+ if (importedName) validatePath(packageName, filePath, normalizeBuiltinName(specifier), importedName, support, diagnostics, "imports");
352
+ }
353
+ } else pendingImports.push(specifier);
354
+ },
355
+ ExportAllDeclaration(node) {
356
+ const specifier = getLiteralString(node.source);
357
+ if (!specifier) return;
358
+ if (isBuiltinModule(specifier)) {
359
+ const moduleName = normalizeBuiltinName(specifier);
360
+ validateBuiltinModule(specifier, diagnostics, packageName, filePath, support);
361
+ diagnostics.push({
362
+ packageName,
363
+ filePath,
364
+ message: `re-exports entire builtin module \`${moduleName}\`, which cannot be validated against LLRT's partial API surface`
365
+ });
366
+ } else pendingImports.push(specifier);
367
+ },
368
+ ImportExpression(node) {
369
+ const specifier = getLiteralString(node.source);
370
+ if (!specifier) return;
371
+ if (isBuiltinModule(specifier)) validateBuiltinModule(specifier, diagnostics, packageName, filePath, support);
372
+ else pendingImports.push(specifier);
373
+ },
374
+ CallExpression(node, ancestors) {
375
+ if (!isRequireCall(node)) return;
376
+ const parent = ancestors.at(-2);
377
+ if (parent?.type === "VariableDeclarator" && parent.init === node) return;
378
+ const specifier = getLiteralString(node.arguments?.[0]);
379
+ if (!specifier) return;
380
+ if (isBuiltinModule(specifier)) validateBuiltinModule(specifier, diagnostics, packageName, filePath, support);
381
+ else pendingImports.push(specifier);
382
+ },
383
+ VariableDeclarator(node) {
384
+ if (!isRequireCall(node.init)) return;
385
+ const specifier = getLiteralString(node.init.arguments?.[0]);
386
+ if (!specifier) return;
387
+ if (isBuiltinModule(specifier)) collectRequireBinding(node.id, specifier, bindings, diagnostics, packageName, filePath, support);
388
+ }
389
+ });
390
+ }
391
+ function collectRequireBinding(pattern, specifier, bindings, diagnostics, packageName, filePath, support) {
392
+ const moduleName = normalizeBuiltinName(specifier);
393
+ if (!validateBuiltinModule(specifier, diagnostics, packageName, filePath, support)) return;
394
+ if (pattern.type === "Identifier") {
395
+ bindings.set(pattern.name, {
396
+ moduleName,
397
+ importedPath: "",
398
+ kind: "default"
399
+ });
400
+ return;
401
+ }
402
+ if (pattern.type !== "ObjectPattern") return;
403
+ for (const property of pattern.properties ?? []) {
404
+ if (property.type !== "Property") continue;
405
+ const importedName = getPropertyName(property.key);
406
+ const localName = property.value?.type === "Identifier" ? property.value.name : void 0;
407
+ if (!importedName || !localName) continue;
408
+ validatePath(packageName, filePath, moduleName, importedName, support, diagnostics, "imports");
409
+ bindings.set(localName, {
410
+ moduleName,
411
+ importedPath: importedName,
412
+ kind: "named"
413
+ });
414
+ }
415
+ }
416
+ function collectBuiltinImportSpecifiers(specifiers, specifier, bindings, diagnostics, packageName, filePath, support) {
417
+ const moduleName = normalizeBuiltinName(specifier);
418
+ const supportedMembers = support.get(moduleName);
419
+ if (!validateBuiltinModule(specifier, diagnostics, packageName, filePath, support)) return;
420
+ for (const spec of specifiers) {
421
+ if (spec.type === "ImportDefaultSpecifier" || spec.type === "ImportNamespaceSpecifier") {
422
+ bindings.set(spec.local.name, {
423
+ moduleName,
424
+ importedPath: "",
425
+ kind: spec.type === "ImportDefaultSpecifier" ? "default" : "namespace"
426
+ });
427
+ continue;
428
+ }
429
+ if (spec.type !== "ImportSpecifier") continue;
430
+ const importedName = getModuleExportName(spec.imported);
431
+ const localName = spec.local?.name;
432
+ if (!importedName || !localName) continue;
433
+ validatePath(packageName, filePath, moduleName, importedName, support, diagnostics, "imports");
434
+ bindings.set(localName, {
435
+ moduleName,
436
+ importedPath: importedName,
437
+ kind: "named"
438
+ });
439
+ }
440
+ if (specifiers.length === 0 && supportedMembers) return;
441
+ }
442
+ function walkValueReferences(sourceFile, bindings, diagnostics, usageByModule, packageName, filePath, support) {
443
+ const visitedIdentifiers = /* @__PURE__ */ new Set();
444
+ ancestor(sourceFile, { Identifier(node, ancestors) {
445
+ const binding = bindings.get(node.name);
446
+ if (!binding || !isValueReference(node, ancestors) || visitedIdentifiers.has(node.start)) return;
447
+ visitedIdentifiers.add(node.start);
448
+ const usedPath = getUsedPath(node, ancestors, binding);
449
+ if (!usedPath) {
450
+ diagnostics.push({
451
+ packageName,
452
+ filePath,
453
+ message: `uses \`${node.name}\` from \`${binding.moduleName}\` in a way this check cannot validate statically`
454
+ });
455
+ return;
456
+ }
457
+ const usedPaths = usageByModule.get(binding.moduleName) ?? /* @__PURE__ */ new Set();
458
+ usedPaths.add(usedPath);
459
+ usageByModule.set(binding.moduleName, usedPaths);
460
+ validatePath(packageName, filePath, binding.moduleName, usedPath, support, diagnostics, "uses");
461
+ } });
462
+ }
463
+ function getUsedPath(identifier, ancestors, binding) {
464
+ let current = identifier;
465
+ const segments = [];
466
+ for (let index = ancestors.length - 2; index >= 0; index--) {
467
+ const parent = ancestors[index];
468
+ if (parent.type !== "MemberExpression" || parent.object !== current || parent.computed) break;
469
+ const propertyName = getPropertyName(parent.property);
470
+ if (!propertyName) break;
471
+ segments.push(propertyName);
472
+ current = parent;
473
+ }
474
+ return (binding.importedPath ? [binding.importedPath, ...segments] : segments).join(".") || void 0;
475
+ }
476
+ function validateBuiltinModule(specifier, diagnostics, packageName, filePath, support) {
477
+ const moduleName = normalizeBuiltinName(specifier);
478
+ if (support.has(moduleName)) return true;
479
+ diagnostics.push({
480
+ packageName,
481
+ filePath,
482
+ message: `imports unsupported builtin module \`${moduleName}\``
483
+ });
484
+ return false;
485
+ }
486
+ function validatePath(packageName, filePath, moduleName, usedPath, support, diagnostics, verb) {
487
+ const supportedMembers = support.get(moduleName) ?? /* @__PURE__ */ new Set();
488
+ let prefix = usedPath;
489
+ while (prefix) {
490
+ if (supportedMembers.has(prefix)) return;
491
+ const dotIndex = prefix.lastIndexOf(".");
492
+ if (dotIndex === -1) break;
493
+ prefix = prefix.slice(0, dotIndex);
494
+ }
495
+ diagnostics.push({
496
+ packageName,
497
+ filePath,
498
+ message: `${verb} \`${usedPath}\` from \`${moduleName}\`, but LLRT API.md does not list it`
499
+ });
500
+ }
501
+ function parseJs(sourceText) {
502
+ try {
503
+ return parse(sourceText, {
504
+ allowHashBang: true,
505
+ ecmaVersion: "latest",
506
+ sourceType: "module"
507
+ });
508
+ } catch {
509
+ return parse(sourceText, {
510
+ allowHashBang: true,
511
+ ecmaVersion: "latest",
512
+ sourceType: "script"
513
+ });
514
+ }
515
+ }
516
+ function isValueReference(identifier, ancestors) {
517
+ const parent = ancestors.at(-2);
518
+ if (!parent) return false;
519
+ if (parent.type === "ImportSpecifier" || parent.type === "ImportDefaultSpecifier" || parent.type === "ImportNamespaceSpecifier") return false;
520
+ if (parent.type === "ExportSpecifier") return false;
521
+ if (parent.type === "MemberExpression" && parent.property === identifier && !parent.computed) return false;
522
+ if (parent.type === "Property" && parent.key === identifier && !parent.computed) return false;
523
+ if (parent.type === "VariableDeclarator" && parent.id === identifier) return false;
524
+ if (parent.type === "FunctionDeclaration" && parent.id === identifier) return false;
525
+ if (parent.type === "FunctionExpression" && parent.id === identifier) return false;
526
+ if (parent.type === "ClassDeclaration" && parent.id === identifier) return false;
527
+ if (parent.type === "ClassExpression" && parent.id === identifier) return false;
528
+ if (parent.type === "LabeledStatement") return false;
529
+ return true;
530
+ }
531
+ function resolveJsPath(basePath) {
532
+ if (existsSync(basePath) && isJsFile(basePath)) return basePath;
533
+ for (const extension of JS_EXTENSIONS) {
534
+ const filePath = `${basePath}${extension}`;
535
+ if (existsSync(filePath)) return filePath;
536
+ }
537
+ for (const extension of JS_EXTENSIONS) {
538
+ const filePath = path.join(basePath, `index${extension}`);
539
+ if (existsSync(filePath)) return filePath;
540
+ }
541
+ }
542
+ function findPackageForFile(filePath, packageByName) {
543
+ return [...packageByName.values()].sort((a, b) => b.dir.length - a.dir.length).find((pkg) => isWithinDir(filePath, pkg.dir));
544
+ }
545
+ function parsePackageSpecifier(specifier) {
546
+ if (specifier.startsWith("@")) {
547
+ const [scope, name, ...subpath] = specifier.split("/");
548
+ return {
549
+ name: `${scope}/${name}`,
550
+ subpath: subpath.length > 0 ? `/${subpath.join("/")}` : ""
551
+ };
552
+ }
553
+ const [name, ...subpath] = specifier.split("/");
554
+ return {
555
+ name,
556
+ subpath: subpath.length > 0 ? `/${subpath.join("/")}` : ""
557
+ };
558
+ }
559
+ function getExportedImportName(specifier) {
560
+ return getModuleExportName(specifier.local ?? specifier.exported);
561
+ }
562
+ function getModuleExportName(node) {
563
+ if (!node) return void 0;
564
+ if (node.type === "Identifier") return node.name;
565
+ if (node.type === "Literal" && typeof node.value === "string") return node.value;
566
+ }
567
+ function getPropertyName(node) {
568
+ if (!node) return void 0;
569
+ if (node.type === "Identifier") return node.name;
570
+ if (node.type === "PrivateIdentifier") return void 0;
571
+ if (node.type === "Literal" && typeof node.value === "string") return node.value;
572
+ }
573
+ function getLiteralString(node) {
574
+ if (!node) return void 0;
575
+ if (node.type === "Literal" && typeof node.value === "string") return node.value;
576
+ }
577
+ function isRequireCall(node) {
578
+ return node?.callee?.type === "Identifier" && node.callee.name === "require";
579
+ }
580
+ function isBuiltinModule(specifier) {
581
+ return nodeBuiltinModules.has(normalizeBuiltinName(specifier));
582
+ }
583
+ function normalizeBuiltinName(specifier) {
584
+ return specifier.replace(/^node:/, "");
585
+ }
586
+ function isRelativeSpecifier(specifier) {
587
+ return specifier.startsWith("./") || specifier.startsWith("../") || specifier === "." || specifier === "..";
588
+ }
589
+ function isJsFile(filePath) {
590
+ return JS_EXTENSIONS.some((extension) => filePath.endsWith(extension));
591
+ }
592
+ function isExportMap(value) {
593
+ if (!isPlainObject(value)) return false;
594
+ const keys = Object.keys(value);
595
+ return keys.some((key) => key.startsWith(".")) || !keys.some((key) => EXPORT_CONDITION_KEYS.has(key));
596
+ }
597
+ function isPlainObject(value) {
598
+ return typeof value === "object" && value !== null && !Array.isArray(value);
599
+ }
600
+ function isWithinDir(filePath, dirPath) {
601
+ const relPath = path.relative(dirPath, filePath);
602
+ return relPath === "" || !relPath.startsWith("..") && !path.isAbsolute(relPath);
603
+ }
604
+ function uniqueTargets(targets) {
605
+ const seen = /* @__PURE__ */ new Set();
606
+ return targets.filter((target) => {
607
+ const key = `${target.packageName}:${target.exportKey}:${target.filePath}`;
608
+ if (seen.has(key)) return false;
609
+ seen.add(key);
610
+ return true;
611
+ });
612
+ }
613
+ function compareDiagnostics(left, right) {
614
+ const packageCompare = left.packageName.localeCompare(right.packageName);
615
+ if (packageCompare !== 0) return packageCompare;
616
+ const pathCompare = left.filePath.localeCompare(right.filePath);
617
+ if (pathCompare !== 0) return pathCompare;
618
+ return left.message.localeCompare(right.message);
619
+ }
620
+ async function main() {
621
+ const options = await parseCliOptions();
622
+ const result = await checkLlrtWorker(options);
623
+ if (result.diagnostics.length > 0) {
624
+ logError("LLRT worker compatibility check failed.");
625
+ console.error(`${LABEL} Checked: ${result.checkedApiUrl}`);
626
+ for (const diagnostic of result.diagnostics.sort(compareDiagnostics)) console.error(`${LABEL} - ${diagnostic.packageName} ${formatPath(diagnostic.filePath)}: ${diagnostic.message}`);
627
+ process.exit(1);
628
+ }
629
+ logInfo(`${styleText("green", "passed")} LLRT worker compatibility check`);
630
+ logInfo(`Checked: ${result.checkedApiUrl}`);
631
+ logInfo(`Checked ${result.targets.length} worker export(s) in ${result.packages.length} package(s)`);
632
+ logInfo(`${result.packages.map((p) => p.name).join(", ")}`);
633
+ if (options.verbose) logInfo(`Visited ${result.visitedFiles.length} file(s)`);
634
+ for (const [moduleName, usedPaths] of [...result.usageByModule.entries()].sort((a, b) => a[0].localeCompare(b[0]))) logInfo(`${moduleName}: ${[...usedPaths].sort().join(", ")}`);
635
+ }
636
+ if (isDirectExecution(import.meta.url)) main().catch((error) => {
637
+ logError("Unhandled error in check-llrt-worker script");
638
+ console.error(error);
639
+ process.exit(1);
640
+ });
641
+ //#endregion
642
+ export { checkLlrtWorker, extractWorkerExportTargets, main };
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bun
2
- import { t as colorText } from "../cli-CoTTeqrl.mjs";
3
- import { dirname, isAbsolute, relative, resolve } from "path";
4
- import { parseArgs } from "util";
2
+ import { t as colorText } from "../cli-DAs6KeZ2.mjs";
3
+ import { dirname, isAbsolute, relative, resolve } from "node:path";
4
+ import { parseArgs } from "node:util";
5
5
  import console from "console";
6
6
  import { existsSync } from "fs";
7
7
  import { fileURLToPath } from "url";
@@ -267,5 +267,3 @@ if (isDirectExecution()) main().catch((error) => {
267
267
  });
268
268
  //#endregion
269
269
  export { createRegenerator, discoverAliasTargets, isAliasOutputFile, isWithinDir, main, processAliasTarget, resolveOutDir, resolveTsConfigPath, syncWatcherPaths, unique };
270
-
271
- //# sourceMappingURL=ts-alias.mjs.map