@tailor-platform/sdk-codemod 0.3.0-next.2 → 0.3.0-next.4

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,792 @@
1
+ import { a as importSource, c as localDeclarationNames, i as importBindings, n as collectBindingNames, o as importSpecNames, r as findImportStatements, s as isTypeOnlyImport } from "../../../ast-grep-helpers-D3FXAKNz.js";
2
+ import { Lang, parse } from "@ast-grep/napi";
3
+ //#region codemods/v2/runtime-subpath-namespace/scripts/transform.ts
4
+ const MODULES_BY_SOURCE = new Map([
5
+ {
6
+ namespace: "iconv",
7
+ source: "@tailor-platform/sdk/runtime/iconv",
8
+ members: {
9
+ convert: "convert",
10
+ convertBuffer: "convertBuffer",
11
+ decode: "decode",
12
+ encode: "encode",
13
+ encodings: "encodings",
14
+ Iconv: "Iconv"
15
+ }
16
+ },
17
+ {
18
+ namespace: "secretmanager",
19
+ source: "@tailor-platform/sdk/runtime/secretmanager",
20
+ members: {
21
+ getSecrets: "getSecrets",
22
+ getSecret: "getSecret"
23
+ }
24
+ },
25
+ {
26
+ namespace: "authconnection",
27
+ source: "@tailor-platform/sdk/runtime/authconnection",
28
+ members: { getConnectionToken: "getConnectionToken" }
29
+ },
30
+ {
31
+ namespace: "idp",
32
+ source: "@tailor-platform/sdk/runtime/idp",
33
+ members: { Client: "Client" }
34
+ },
35
+ {
36
+ namespace: "workflow",
37
+ source: "@tailor-platform/sdk/runtime/workflow",
38
+ members: {
39
+ triggerWorkflow: "triggerWorkflow",
40
+ resumeWorkflow: "resumeWorkflow",
41
+ triggerJobFunction: "triggerJobFunction",
42
+ wait: "wait",
43
+ resolve: "resolve"
44
+ }
45
+ },
46
+ {
47
+ namespace: "context",
48
+ source: "@tailor-platform/sdk/runtime/context",
49
+ members: { getInvoker: "getInvoker" }
50
+ },
51
+ {
52
+ namespace: "file",
53
+ source: "@tailor-platform/sdk/runtime/file",
54
+ members: {
55
+ upload: "upload",
56
+ download: "download",
57
+ downloadAsBase64: "downloadAsBase64",
58
+ delete: "delete",
59
+ deleteFile: "delete",
60
+ getMetadata: "getMetadata",
61
+ downloadStream: "downloadStream",
62
+ uploadStream: "uploadStream"
63
+ }
64
+ },
65
+ {
66
+ namespace: "aigateway",
67
+ source: "@tailor-platform/sdk/runtime/aigateway",
68
+ members: { get: "get" }
69
+ }
70
+ ].map((mod) => [mod.source, mod]));
71
+ const AGGREGATE_RUNTIME_SOURCE = "@tailor-platform/sdk/runtime";
72
+ const JSX_FILE_EXTENSIONS = /* @__PURE__ */ new Set([".tsx", ".jsx"]);
73
+ const JS_FILE_EXTENSIONS = /* @__PURE__ */ new Set([
74
+ ".js",
75
+ ".mjs",
76
+ ".cjs"
77
+ ]);
78
+ function quickFilter(source) {
79
+ return source.includes(AGGREGATE_RUNTIME_SOURCE);
80
+ }
81
+ function sourceLang(filePath, source) {
82
+ const lower = filePath.toLowerCase();
83
+ const extension = lower.slice(lower.lastIndexOf("."));
84
+ if (JSX_FILE_EXTENSIONS.has(extension)) return Lang.Tsx;
85
+ if (JS_FILE_EXTENSIONS.has(extension) && /<>|<\/>|<[A-Za-z][\w.$:-]/.test(source)) return Lang.Tsx;
86
+ return Lang.TypeScript;
87
+ }
88
+ function importClause(importStmt) {
89
+ return importStmt.children().find((child) => child.kind() === "import_clause") ?? null;
90
+ }
91
+ function hasDefaultImport(importStmt) {
92
+ return importClause(importStmt)?.children().some((child) => child.kind() === "identifier") ?? false;
93
+ }
94
+ function namespaceImportName(importStmt) {
95
+ return importClause(importStmt)?.children().find((child) => child.kind() === "namespace_import")?.children().find((child) => child.kind() === "identifier")?.text() ?? null;
96
+ }
97
+ function formatImport(source, namedSpecs, typeOnly = false, attributeText = "") {
98
+ const importKeyword = typeOnly ? "import type" : "import";
99
+ const named = namedSpecs.length > 0 ? `{ ${namedSpecs.join(", ")} }` : null;
100
+ const attributes = attributeText === "" ? "" : ` ${attributeText}`;
101
+ if (named) return `${importKeyword} ${named} from "${source}"${attributes};`;
102
+ return "";
103
+ }
104
+ function importAttributeText(importStmt) {
105
+ return importStmt.children().find((child) => child.kind() === "import_attribute")?.text() ?? "";
106
+ }
107
+ function replaceImportStatement(importStmt, nextText, sourceText) {
108
+ if (nextText !== "") return importStmt.replace(nextText);
109
+ const range = importStmt.range();
110
+ let endPos = range.end.index;
111
+ if (sourceText[endPos] === "\r" && sourceText[endPos + 1] === "\n") endPos += 2;
112
+ else if (sourceText[endPos] === "\n") endPos += 1;
113
+ return {
114
+ startPos: range.start.index,
115
+ endPos,
116
+ insertedText: ""
117
+ };
118
+ }
119
+ function isInsideImportStatement(node) {
120
+ let current = node.parent();
121
+ while (current) {
122
+ if (current.kind() === "import_statement") return true;
123
+ current = current.parent();
124
+ }
125
+ return false;
126
+ }
127
+ function isInsideExportSpecifier(node) {
128
+ let current = node.parent();
129
+ while (current) {
130
+ if (current.kind() === "export_specifier") return true;
131
+ if (current.kind() === "export_statement") return false;
132
+ current = current.parent();
133
+ }
134
+ return false;
135
+ }
136
+ function isInsideTypeQuery(node) {
137
+ let current = node.parent();
138
+ while (current) {
139
+ if (current.kind() === "type_query") return true;
140
+ if (current.kind() === "statement_block" || current.kind() === "program") return false;
141
+ current = current.parent();
142
+ }
143
+ return false;
144
+ }
145
+ function isJsxTagName(node) {
146
+ const parentKind = node.parent()?.kind();
147
+ return parentKind === "jsx_opening_element" || parentKind === "jsx_self_closing_element" || parentKind === "jsx_closing_element";
148
+ }
149
+ function sameNode(left, right) {
150
+ if (!left) return false;
151
+ const leftRange = left.range();
152
+ const rightRange = right.range();
153
+ return leftRange.start.index === rightRange.start.index && leftRange.end.index === rightRange.end.index;
154
+ }
155
+ function typeParameterName(typeParameter) {
156
+ return typeParameter.children().find((child) => child.kind() === "type_identifier") ?? null;
157
+ }
158
+ function typeParametersDeclare(typeParameters, name) {
159
+ return typeParameters.children().some((child) => child.kind() === "type_parameter" && typeParameterName(child)?.text() === name);
160
+ }
161
+ function isTypeParameterScoped(node) {
162
+ let current = node.parent();
163
+ while (current) {
164
+ if (current.kind() === "type_parameter" && sameNode(typeParameterName(current), node)) return true;
165
+ const typeParameters = current.children().find((child) => child.kind() === "type_parameters");
166
+ if (typeParameters && typeParametersDeclare(typeParameters, node.text())) return true;
167
+ current = current.parent();
168
+ }
169
+ return false;
170
+ }
171
+ function isNestedTypeMember(node) {
172
+ const parent = node.parent();
173
+ if (parent?.kind() !== "nested_type_identifier") return false;
174
+ return !sameNode(parent.children().find((child) => child.kind() === "identifier" || child.kind() === "type_identifier"), node);
175
+ }
176
+ function localTypeScopeDeclarationNames(root) {
177
+ const names = /* @__PURE__ */ new Set();
178
+ for (const node of root.findAll({ rule: { any: [
179
+ { kind: "type_parameter" },
180
+ { kind: "infer_type" },
181
+ { kind: "mapped_type_clause" }
182
+ ] } })) {
183
+ const name = node.children().find((child) => child.kind() === "type_identifier");
184
+ if (name) names.add(name.text());
185
+ }
186
+ return names;
187
+ }
188
+ function hasExportSpecifierReference(root, names) {
189
+ return root.findAll({ rule: { kind: "export_specifier" } }).some((specifier) => specifier.children().some((child) => child.kind() === "identifier" && names.has(child.text())));
190
+ }
191
+ function hasNonTypeQueryTypeReference(root, names) {
192
+ return root.findAll({ rule: { kind: "type_identifier" } }).some((node) => {
193
+ if (!names.has(node.text())) return false;
194
+ if (isInsideImportStatement(node)) return false;
195
+ if (isInsideExportSpecifier(node)) return false;
196
+ if (isTypeParameterScoped(node)) return false;
197
+ if (isNestedTypeMember(node)) return false;
198
+ return !isInsideTypeQuery(node);
199
+ });
200
+ }
201
+ function hasNamespaceTypeMemberReference(root, namespaceLocal) {
202
+ return root.findAll({ rule: { kind: "nested_type_identifier" } }).some((node) => {
203
+ return node.children().find((child) => child.kind() === "identifier" || child.kind() === "type_identifier")?.text() === namespaceLocal;
204
+ });
205
+ }
206
+ function findExportStatements(root) {
207
+ return root.findAll({ rule: { kind: "export_statement" } }).filter((stmt) => stmt.parent()?.kind() === "program").toSorted((a, b) => a.range().start.index - b.range().start.index);
208
+ }
209
+ function aggregateFileImportLocals(imports) {
210
+ const locals = /* @__PURE__ */ new Set();
211
+ for (const importStmt of imports) {
212
+ if (importSource(importStmt) !== AGGREGATE_RUNTIME_SOURCE) continue;
213
+ for (const binding of importBindings(importStmt)) if (!binding.typeOnly && binding.importedName === "file") locals.add(binding.localName);
214
+ }
215
+ return locals;
216
+ }
217
+ function isValueBindingLeafKind(kind) {
218
+ return kind === "identifier" || kind === "shorthand_property_identifier_pattern";
219
+ }
220
+ function isValueBindingPatternKind(kind) {
221
+ return isValueBindingLeafKind(kind) || kind === "object_pattern" || kind === "array_pattern" || kind === "rest_pattern";
222
+ }
223
+ function collectValueBindingNames(node, names, result) {
224
+ if (isValueBindingLeafKind(node.kind())) {
225
+ if (names.has(node.text())) result.add(node.text());
226
+ return;
227
+ }
228
+ for (const child of node.children()) {
229
+ if (child.kind() === "property_identifier") continue;
230
+ if (child.kind() === "=") break;
231
+ collectValueBindingNames(child, names, result);
232
+ }
233
+ }
234
+ function valueBindingNames(node, names) {
235
+ const result = /* @__PURE__ */ new Set();
236
+ collectValueBindingNames(node, names, result);
237
+ return result;
238
+ }
239
+ function directValueBindingNames(node, names) {
240
+ const result = /* @__PURE__ */ new Set();
241
+ for (const child of node.children()) {
242
+ if (child.kind() === "=") break;
243
+ if (isValueBindingPatternKind(child.kind())) collectValueBindingNames(child, names, result);
244
+ }
245
+ return result;
246
+ }
247
+ function firstDeclaratorChild(node) {
248
+ return node.children().find((child) => child.kind() !== "=") ?? null;
249
+ }
250
+ function addShadowedRange(ranges, name, scope) {
251
+ const range = scope.range();
252
+ const existing = ranges.get(name) ?? [];
253
+ existing.push({
254
+ start: range.start.index,
255
+ end: range.end.index
256
+ });
257
+ ranges.set(name, existing);
258
+ }
259
+ function nearestValueScope(node) {
260
+ let current = node.parent();
261
+ while (current) {
262
+ const kind = current.kind();
263
+ if (kind === "statement_block" || kind === "program" || kind === "switch_body" || kind === "for_statement" || kind === "for_in_statement") return current;
264
+ current = current.parent();
265
+ }
266
+ return node;
267
+ }
268
+ function functionValueScope(node) {
269
+ let current = node.parent();
270
+ while (current) {
271
+ const kind = current.kind();
272
+ if (kind === "function_declaration" || kind === "function_expression" || kind === "arrow_function" || kind === "method_definition" || kind === "program") return current;
273
+ current = current.parent();
274
+ }
275
+ return node;
276
+ }
277
+ function variableValueScope(node) {
278
+ const declaration = node.parent();
279
+ return /^var\b/.test(declaration?.text().trimStart() ?? "") ? functionValueScope(node) : nearestValueScope(node);
280
+ }
281
+ function parameterValueScope(node) {
282
+ let current = node.parent();
283
+ while (current) {
284
+ const kind = current.kind();
285
+ if (kind === "formal_parameters") {
286
+ current = current.parent();
287
+ continue;
288
+ }
289
+ if (kind === "function_declaration" || kind === "function_expression" || kind === "arrow_function" || kind === "method_definition") return current;
290
+ break;
291
+ }
292
+ return nearestValueScope(node);
293
+ }
294
+ function buildShadowedRanges(root, names) {
295
+ const ranges = /* @__PURE__ */ new Map();
296
+ for (const decl of root.findAll({ rule: { kind: "variable_declarator" } })) {
297
+ if (isInsideImportStatement(decl)) continue;
298
+ const binding = firstDeclaratorChild(decl);
299
+ if (!binding) continue;
300
+ for (const name of valueBindingNames(binding, names)) addShadowedRange(ranges, name, variableValueScope(decl));
301
+ }
302
+ for (const decl of root.findAll({ rule: { any: [
303
+ { kind: "function_declaration" },
304
+ { kind: "class_declaration" },
305
+ { kind: "enum_declaration" }
306
+ ] } })) {
307
+ const name = decl.children().find((child) => child.kind() === "identifier" && names.has(child.text()));
308
+ if (name) addShadowedRange(ranges, name.text(), nearestValueScope(decl));
309
+ }
310
+ for (const expression of root.findAll({ rule: { any: [{ kind: "function_expression" }, { kind: "class" }] } })) {
311
+ const name = expression.children().find((child) => (child.kind() === "identifier" || child.kind() === "type_identifier") && names.has(child.text()));
312
+ if (name) addShadowedRange(ranges, name.text(), expression);
313
+ }
314
+ for (const param of root.findAll({ rule: { any: [{ kind: "required_parameter" }, { kind: "optional_parameter" }] } })) for (const name of directValueBindingNames(param, names)) addShadowedRange(ranges, name, parameterValueScope(param));
315
+ for (const arrow of root.findAll({ rule: { kind: "arrow_function" } })) {
316
+ const children = arrow.children();
317
+ const arrowIndex = children.findIndex((child) => child.kind() === "=>");
318
+ if (arrowIndex === -1) continue;
319
+ for (const child of children.slice(0, arrowIndex)) {
320
+ if (child.kind() === "=") break;
321
+ if (!isValueBindingPatternKind(child.kind())) continue;
322
+ for (const name of valueBindingNames(child, names)) addShadowedRange(ranges, name, arrow);
323
+ }
324
+ }
325
+ for (const catchClause of root.findAll({ rule: { kind: "catch_clause" } })) for (const name of directValueBindingNames(catchClause, names)) addShadowedRange(ranges, name, catchClause);
326
+ for (const loop of root.findAll({ rule: { kind: "for_in_statement" } })) {
327
+ const children = loop.children();
328
+ const keywordIndex = children.findIndex((child) => child.kind() === "in" || child.kind() === "of");
329
+ if (keywordIndex === -1) continue;
330
+ for (const child of children.slice(0, keywordIndex)) for (const name of valueBindingNames(child, names)) addShadowedRange(ranges, name, loop);
331
+ }
332
+ return ranges;
333
+ }
334
+ function isShadowed(node, ranges) {
335
+ const candidates = ranges.get(node.text());
336
+ if (!candidates) return false;
337
+ const position = node.range().start.index;
338
+ return candidates.some((range) => position >= range.start && position < range.end);
339
+ }
340
+ function isAggregateFileReceiver(node, fileLocals, shadowedRanges) {
341
+ return node?.kind() === "identifier" && fileLocals.has(node.text()) && !isShadowed(node, shadowedRanges);
342
+ }
343
+ function aggregateFileDeleteAccesses(root, imports) {
344
+ const fileLocals = aggregateFileImportLocals(imports);
345
+ if (fileLocals.size === 0) return [];
346
+ const shadowedRanges = buildShadowedRanges(root, fileLocals);
347
+ const accesses = [];
348
+ for (const member of root.findAll({ rule: { kind: "member_expression" } })) {
349
+ const receiver = member.field("object");
350
+ const property = member.children().find((child) => child.kind() === "property_identifier");
351
+ if (isAggregateFileReceiver(receiver, fileLocals, shadowedRanges) && property?.text() === "deleteFile") accesses.push({
352
+ node: member,
353
+ property,
354
+ computed: false
355
+ });
356
+ }
357
+ for (const subscript of root.findAll({ rule: { kind: "subscript_expression" } })) {
358
+ const receiver = subscript.field("object");
359
+ const property = subscript.field("index");
360
+ if (isAggregateFileReceiver(receiver, fileLocals, shadowedRanges) && property?.kind() === "string" && property.text().slice(1, -1) === "deleteFile") accesses.push({
361
+ node: subscript,
362
+ property,
363
+ computed: true
364
+ });
365
+ }
366
+ return accesses;
367
+ }
368
+ function aggregateFileDeleteEdits(root, imports) {
369
+ return aggregateFileDeleteAccesses(root, imports).map(({ property, computed }) => {
370
+ if (!computed) return property.replace("delete");
371
+ const quote = property.text()[0] ?? "\"";
372
+ return property.replace(`${quote}delete${quote}`);
373
+ });
374
+ }
375
+ function declaratorSides(node) {
376
+ const children = node.children();
377
+ const equalsIndex = children.findIndex((child) => child.kind() === "=");
378
+ if (equalsIndex === -1) return null;
379
+ const binding = children.slice(0, equalsIndex).find((child) => child.kind() !== "comment");
380
+ const value = children.slice(equalsIndex + 1).find((child) => child.kind() !== "comment");
381
+ return binding && value ? {
382
+ binding,
383
+ value
384
+ } : null;
385
+ }
386
+ function aggregateFileDeleteDestructures(root, imports) {
387
+ const fileLocals = aggregateFileImportLocals(imports);
388
+ if (fileLocals.size === 0) return [];
389
+ const shadowedRanges = buildShadowedRanges(root, fileLocals);
390
+ return root.findAll({ rule: { kind: "variable_declarator" } }).filter((declarator) => {
391
+ const sides = declaratorSides(declarator);
392
+ if (!sides || sides.binding.kind() !== "object_pattern" || !isAggregateFileReceiver(sides.value, fileLocals, shadowedRanges)) return false;
393
+ return sides.binding.findAll({ rule: { any: [{ kind: "property_identifier" }, { kind: "shorthand_property_identifier_pattern" }] } }).some((property) => property.text() === "deleteFile");
394
+ });
395
+ }
396
+ function aggregateFileDeleteFindingNodes(root, imports) {
397
+ return [...aggregateFileDeleteAccesses(root, imports).map((access) => access.node), ...aggregateFileDeleteDestructures(root, imports)];
398
+ }
399
+ function usedNames(root, imports, removedNames) {
400
+ const names = localDeclarationNames(root);
401
+ for (const importStmt of imports) for (const binding of importBindings(importStmt)) if (!removedNames.has(binding.localName)) names.add(binding.localName);
402
+ return names;
403
+ }
404
+ function uniqueNamespaceLocal(mod, root, imports, removedNames) {
405
+ const names = usedNames(root, imports, removedNames);
406
+ if (!names.has(mod.namespace)) return mod.namespace;
407
+ const base = `${mod.namespace}Runtime`;
408
+ if (!names.has(base)) return base;
409
+ for (let i = 2;; i++) {
410
+ const candidate = `${base}${i}`;
411
+ if (!names.has(candidate)) return candidate;
412
+ }
413
+ }
414
+ function selfNamespaceSpec(mod, localName) {
415
+ return localName === mod.namespace ? mod.namespace : `${mod.namespace} as ${localName}`;
416
+ }
417
+ function typeOnlySelfNamespaceSpec(mod, localName) {
418
+ return `type ${selfNamespaceSpec(mod, localName)}`;
419
+ }
420
+ function existingSelfNamespaceImport(importStmt, mod, statementTypeOnly) {
421
+ for (const spec of importStmt.findAll({ rule: { kind: "import_specifier" } })) {
422
+ const names = importSpecNames(spec);
423
+ if (!names || names.importedName !== mod.namespace) continue;
424
+ return {
425
+ localName: names.localName,
426
+ typeOnly: statementTypeOnly || names.typeOnly
427
+ };
428
+ }
429
+ return null;
430
+ }
431
+ function flatImportsFor(importStmt, mod) {
432
+ const statementTypeOnly = isTypeOnlyImport(importStmt);
433
+ const flatImports = [];
434
+ for (const spec of importStmt.findAll({ rule: { kind: "import_specifier" } })) {
435
+ const names = importSpecNames(spec);
436
+ if (!names) continue;
437
+ const memberName = mod.members[names.importedName];
438
+ if (!memberName) continue;
439
+ flatImports.push({
440
+ localName: names.localName,
441
+ memberName,
442
+ typeOnly: statementTypeOnly || names.typeOnly
443
+ });
444
+ }
445
+ return flatImports;
446
+ }
447
+ function plannedValueNamespaceLocal(importStmt, mod, root, imports) {
448
+ const source = importSource(importStmt);
449
+ if (!source) return null;
450
+ for (const candidate of imports) {
451
+ if (sameNode(candidate, importStmt)) continue;
452
+ if (importSource(candidate) !== source || isTypeOnlyImport(candidate)) continue;
453
+ const namespaceName = namespaceImportName(candidate);
454
+ if (namespaceName) return namespaceName;
455
+ const existingSelf = existingSelfNamespaceImport(candidate, mod, false);
456
+ if (existingSelf && !existingSelf.typeOnly) return existingSelf.localName;
457
+ const valueFlatImports = flatImportsFor(candidate, mod).filter((binding) => !binding.typeOnly);
458
+ if (valueFlatImports.length === 0) continue;
459
+ const removedNames = new Set(valueFlatImports.map((binding) => binding.localName));
460
+ const declaredNames = /* @__PURE__ */ new Set([...localDeclarationNames(root), ...localTypeScopeDeclarationNames(root)]);
461
+ if (valueFlatImports.some((binding) => declaredNames.has(binding.localName))) continue;
462
+ if (hasExportSpecifierReference(root, removedNames)) continue;
463
+ return uniqueNamespaceLocal(mod, root, imports, removedNames);
464
+ }
465
+ return null;
466
+ }
467
+ function buildImportReplacement(importStmt, mod, root, imports, sourceText, emittedNamespaceSpecifiers) {
468
+ const source = importSource(importStmt);
469
+ if (!source) return null;
470
+ const statementTypeOnly = isTypeOnlyImport(importStmt);
471
+ const attributes = importAttributeText(importStmt);
472
+ const namespaceName = namespaceImportName(importStmt);
473
+ if (namespaceName) {
474
+ if (hasNamespaceTypeMemberReference(root, namespaceName)) return null;
475
+ return {
476
+ edit: importStmt.replace(formatImport(source, [selfNamespaceSpec(mod, namespaceName)], statementTypeOnly, attributes)),
477
+ flatImports: [],
478
+ namespaceLocal: namespaceName
479
+ };
480
+ }
481
+ if (hasDefaultImport(importStmt)) return null;
482
+ const existingSelf = existingSelfNamespaceImport(importStmt, mod, statementTypeOnly);
483
+ const flatImports = [];
484
+ const keptSpecs = [];
485
+ for (const spec of importStmt.findAll({ rule: { kind: "import_specifier" } })) {
486
+ const names = importSpecNames(spec);
487
+ if (!names) continue;
488
+ const memberName = mod.members[names.importedName];
489
+ if (memberName) {
490
+ flatImports.push({
491
+ localName: names.localName,
492
+ memberName,
493
+ typeOnly: statementTypeOnly || names.typeOnly
494
+ });
495
+ continue;
496
+ }
497
+ keptSpecs.push(spec.text());
498
+ }
499
+ if (flatImports.length === 0) return null;
500
+ const removedNames = new Set(flatImports.map((binding) => binding.localName));
501
+ const declaredNames = /* @__PURE__ */ new Set([...localDeclarationNames(root), ...localTypeScopeDeclarationNames(root)]);
502
+ if (flatImports.some((binding) => declaredNames.has(binding.localName))) return null;
503
+ if (hasExportSpecifierReference(root, removedNames)) return null;
504
+ if (hasNonTypeQueryTypeReference(root, removedNames)) return null;
505
+ const flatImportsAreTypeOnly = flatImports.every((binding) => binding.typeOnly);
506
+ const canUseExistingSelf = existingSelf != null && (!existingSelf.typeOnly || flatImportsAreTypeOnly);
507
+ const plannedValueLocal = flatImportsAreTypeOnly ? plannedValueNamespaceLocal(importStmt, mod, root, imports) : null;
508
+ const namespaceLocal = plannedValueLocal ?? (canUseExistingSelf ? existingSelf.localName : uniqueNamespaceLocal(mod, root, imports, removedNames));
509
+ const namespaceSpecifierKey = [
510
+ source,
511
+ namespaceLocal,
512
+ flatImportsAreTypeOnly ? "type" : "value"
513
+ ].join("\0");
514
+ const namespaceAlreadyEmitted = emittedNamespaceSpecifiers.has(namespaceSpecifierKey);
515
+ const needsNamespaceSpecifier = plannedValueLocal == null && !canUseExistingSelf && !namespaceAlreadyEmitted;
516
+ if (needsNamespaceSpecifier) emittedNamespaceSpecifiers.add(namespaceSpecifierKey);
517
+ const namespaceSpecifier = flatImportsAreTypeOnly && !statementTypeOnly ? typeOnlySelfNamespaceSpec(mod, namespaceLocal) : selfNamespaceSpec(mod, namespaceLocal);
518
+ return {
519
+ edit: replaceImportStatement(importStmt, formatImport(source, needsNamespaceSpecifier ? [namespaceSpecifier, ...keptSpecs] : keptSpecs, statementTypeOnly, attributes), sourceText),
520
+ flatImports,
521
+ namespaceLocal
522
+ };
523
+ }
524
+ function referenceEdits(root, replacements) {
525
+ const byLocalName = /* @__PURE__ */ new Map();
526
+ for (const replacement of replacements) for (const binding of replacement.flatImports) byLocalName.set(binding.localName, {
527
+ namespaceLocal: replacement.namespaceLocal,
528
+ memberName: binding.memberName,
529
+ typeOnly: binding.typeOnly
530
+ });
531
+ const edits = [];
532
+ const replacementFor = (name) => {
533
+ const binding = byLocalName.get(name);
534
+ return binding ? `${binding.namespaceLocal}.${binding.memberName}` : null;
535
+ };
536
+ for (const node of root.findAll({ rule: { kind: "identifier" } })) {
537
+ if (isInsideImportStatement(node)) continue;
538
+ if (isInsideExportSpecifier(node)) continue;
539
+ if (isJsxTagName(node)) continue;
540
+ if (byLocalName.get(node.text())?.typeOnly && !isInsideTypeQuery(node)) continue;
541
+ const replacement = replacementFor(node.text());
542
+ if (!replacement) continue;
543
+ edits.push(node.replace(replacement));
544
+ }
545
+ for (const node of root.findAll({ rule: { kind: "type_identifier" } })) {
546
+ if (isInsideImportStatement(node)) continue;
547
+ if (isInsideExportSpecifier(node)) continue;
548
+ if (!isInsideTypeQuery(node)) continue;
549
+ if (isTypeParameterScoped(node)) continue;
550
+ if (isNestedTypeMember(node)) continue;
551
+ const replacement = replacementFor(node.text());
552
+ if (!replacement) continue;
553
+ edits.push(node.replace(replacement));
554
+ }
555
+ for (const node of root.findAll({ rule: { kind: "shorthand_property_identifier" } })) {
556
+ if (byLocalName.get(node.text())?.typeOnly) continue;
557
+ const replacement = replacementFor(node.text());
558
+ if (!replacement) continue;
559
+ edits.push(node.replace(`${node.text()}: ${replacement}`));
560
+ }
561
+ return edits;
562
+ }
563
+ /**
564
+ * Rewrite v1 runtime subpath imports to the v2 namespace object exports.
565
+ * @param source - File contents
566
+ * @param filePath - Absolute path to the file
567
+ * @returns Transformed source or null when nothing matched.
568
+ */
569
+ function transform(source, filePath) {
570
+ if (!quickFilter(source)) return null;
571
+ const root = parse(sourceLang(filePath, source), source).root();
572
+ const imports = findImportStatements(root);
573
+ const replacements = [];
574
+ const emittedNamespaceSpecifiers = /* @__PURE__ */ new Set();
575
+ for (const importStmt of imports) {
576
+ const sourceName = importSource(importStmt);
577
+ if (!sourceName) continue;
578
+ const mod = MODULES_BY_SOURCE.get(sourceName);
579
+ if (!mod) continue;
580
+ const replacement = buildImportReplacement(importStmt, mod, root, imports, source, emittedNamespaceSpecifiers);
581
+ if (replacement) replacements.push(replacement);
582
+ }
583
+ const aggregateEdits = aggregateFileDeleteEdits(root, imports);
584
+ if (replacements.length === 0 && aggregateEdits.length === 0) return null;
585
+ const edits = [
586
+ ...replacements.map((replacement) => replacement.edit),
587
+ ...referenceEdits(root, replacements),
588
+ ...aggregateEdits
589
+ ];
590
+ const result = root.commitEdits(edits);
591
+ return result === source ? null : result;
592
+ }
593
+ function hasRemovedFlatSpecifier(node, mod) {
594
+ return node.findAll({ rule: { any: [{ kind: "import_specifier" }, { kind: "export_specifier" }] } }).some((spec) => {
595
+ const names = importSpecNames(spec);
596
+ return names != null && mod.members[names.importedName] != null;
597
+ });
598
+ }
599
+ function isExportStar(node) {
600
+ if (node.children().some((child) => child.kind() === "*")) return true;
601
+ return node.children().find((child) => child.kind() === "namespace_export")?.children().some((child) => child.kind() === "*") ?? false;
602
+ }
603
+ function literalModuleSource(node) {
604
+ if (node.kind() === "string") return importSource(node);
605
+ if (node.kind() !== "template_string") return null;
606
+ if (node.children().some((child) => child.kind() === "template_substitution")) return null;
607
+ const text = node.text();
608
+ return text.startsWith("`") && text.endsWith("`") ? text.slice(1, -1) : null;
609
+ }
610
+ function isSourceScopeNode(node) {
611
+ const kind = node.kind();
612
+ return kind === "program" || kind === "statement_block" || kind === "function_declaration" || kind === "arrow_function" || kind === "method_definition";
613
+ }
614
+ function nearestSourceScope(node) {
615
+ let current = node.parent();
616
+ while (current) {
617
+ if (isSourceScopeNode(current)) return current;
618
+ current = current.parent();
619
+ }
620
+ return null;
621
+ }
622
+ function sameRange(left, right) {
623
+ if (!left) return false;
624
+ const leftRange = left.range();
625
+ const rightRange = right.range();
626
+ return leftRange.start.index === rightRange.start.index && leftRange.end.index === rightRange.end.index;
627
+ }
628
+ function isConstVariableDeclarator(node) {
629
+ return node.parent()?.children().some((child) => child.kind() === "const") ?? false;
630
+ }
631
+ function sourceConstInitializerContent(node) {
632
+ const directValue = literalModuleSource(node);
633
+ if (directValue != null) return directValue;
634
+ if (node.kind() !== "as_expression" && node.kind() !== "satisfies_expression" && node.kind() !== "parenthesized_expression") return null;
635
+ for (const child of node.children()) {
636
+ const childValue = sourceConstInitializerContent(child);
637
+ if (childValue != null) return childValue;
638
+ }
639
+ return null;
640
+ }
641
+ function sourceConstVariableDeclaratorContent(node, name) {
642
+ if (!isConstVariableDeclarator(node)) return null;
643
+ const names = /* @__PURE__ */ new Set();
644
+ collectBindingNames(node, names);
645
+ if (!names.has(name)) return null;
646
+ const initializer = node.children().findLast((child) => sourceConstInitializerContent(child) != null);
647
+ return initializer == null ? null : sourceConstInitializerContent(initializer);
648
+ }
649
+ function bindingNames(node) {
650
+ const names = /* @__PURE__ */ new Set();
651
+ collectBindingNames(node, names);
652
+ return names;
653
+ }
654
+ function sourceStringVariableInScope(scope, name, before) {
655
+ const bindings = scope.findAll({ rule: { any: [
656
+ { kind: "variable_declarator" },
657
+ { kind: "required_parameter" },
658
+ { kind: "optional_parameter" },
659
+ { kind: "catch_clause" }
660
+ ] } }).filter((node) => node.range().start.index < before && sameRange(nearestSourceScope(node), scope)).toSorted((a, b) => b.range().start.index - a.range().start.index);
661
+ for (const binding of bindings) {
662
+ if (!bindingNames(binding).has(name)) continue;
663
+ return binding.kind() === "variable_declarator" ? sourceConstVariableDeclaratorContent(binding, name) : null;
664
+ }
665
+ }
666
+ function sourceScopedStringVariableContent(identifier) {
667
+ const name = identifier.text();
668
+ const before = identifier.range().start.index;
669
+ let current = identifier.parent();
670
+ while (current) {
671
+ if (isSourceScopeNode(current)) {
672
+ const value = sourceStringVariableInScope(current, name, before);
673
+ if (value !== void 0) return value;
674
+ }
675
+ current = current.parent();
676
+ }
677
+ return null;
678
+ }
679
+ function isDynamicImportCall(node) {
680
+ return node.kind() === "call_expression" && node.children().some((child) => child.kind() === "import");
681
+ }
682
+ function isRequireCall(node) {
683
+ return node.kind() === "call_expression" && node.children().some((child) => child.kind() === "identifier" && child.text() === "require");
684
+ }
685
+ function isArgumentSyntaxNode(node) {
686
+ const kind = node.kind();
687
+ return kind === "(" || kind === ")" || kind === "," || kind === "comment";
688
+ }
689
+ function firstCallArgument(callExpression) {
690
+ return callExpression.children().find((child) => child.kind() === "arguments")?.children().find((child) => !isArgumentSyntaxNode(child)) ?? null;
691
+ }
692
+ function moduleCallSourceName(callExpression) {
693
+ const sourceArg = firstCallArgument(callExpression);
694
+ if (!sourceArg) return null;
695
+ const sourceName = literalModuleSource(sourceArg);
696
+ if (sourceName != null) return sourceName;
697
+ return sourceArg.kind() === "identifier" ? sourceScopedStringVariableContent(sourceArg) : null;
698
+ }
699
+ function dynamicImportSourceName(callExpression) {
700
+ return moduleCallSourceName(callExpression);
701
+ }
702
+ function dynamicImportExcerptNode(callExpression) {
703
+ let current = callExpression;
704
+ while (current.parent()) {
705
+ const parent = current.parent();
706
+ if (!parent) break;
707
+ if (parent.kind() !== "await_expression" && parent.kind() !== "parenthesized_expression" && parent.kind() !== "member_expression") break;
708
+ current = parent;
709
+ }
710
+ return current;
711
+ }
712
+ function dynamicRuntimeImportFindings(root, relativePath) {
713
+ const findings = [];
714
+ for (const callExpression of root.findAll({ rule: { kind: "call_expression" } })) {
715
+ if (!isDynamicImportCall(callExpression)) continue;
716
+ const sourceName = dynamicImportSourceName(callExpression);
717
+ if (!sourceName || !MODULES_BY_SOURCE.has(sourceName)) continue;
718
+ const excerptNode = dynamicImportExcerptNode(callExpression);
719
+ findings.push({
720
+ file: relativePath,
721
+ line: excerptNode.range().start.line + 1,
722
+ message: "Dynamic runtime subpath import may still access a removed flat value export.",
723
+ excerpt: excerptNode.text().trim()
724
+ });
725
+ }
726
+ return findings;
727
+ }
728
+ function runtimeRequireFindings(root, relativePath) {
729
+ const findings = [];
730
+ for (const callExpression of root.findAll({ rule: { kind: "call_expression" } })) {
731
+ if (isInsideImportStatement(callExpression)) continue;
732
+ if (!isRequireCall(callExpression)) continue;
733
+ const sourceName = moduleCallSourceName(callExpression);
734
+ if (!sourceName || !MODULES_BY_SOURCE.has(sourceName)) continue;
735
+ findings.push({
736
+ file: relativePath,
737
+ line: callExpression.range().start.line + 1,
738
+ message: "CommonJS runtime subpath require may still access a removed flat value export.",
739
+ excerpt: callExpression.text().trim()
740
+ });
741
+ }
742
+ return findings;
743
+ }
744
+ function isImportRequireStatement(importStmt) {
745
+ return importStmt.children().some((child) => child.kind() === "import_require_clause");
746
+ }
747
+ function reviewFindings(source, filePath, relativePath) {
748
+ if (!quickFilter(source)) return [];
749
+ const root = parse(sourceLang(filePath, source), source).root();
750
+ const imports = findImportStatements(root);
751
+ const findings = [];
752
+ findings.push(...dynamicRuntimeImportFindings(root, relativePath));
753
+ findings.push(...runtimeRequireFindings(root, relativePath));
754
+ for (const access of aggregateFileDeleteFindingNodes(root, imports)) findings.push({
755
+ file: relativePath,
756
+ line: access.range().start.line + 1,
757
+ message: "Aggregate runtime file namespace still uses the removed deleteFile alias.",
758
+ excerpt: access.text().trim()
759
+ });
760
+ for (const importStmt of imports) {
761
+ const sourceName = importSource(importStmt);
762
+ if (!sourceName) continue;
763
+ const mod = MODULES_BY_SOURCE.get(sourceName);
764
+ if (!mod) continue;
765
+ const hasImportRequire = isImportRequireStatement(importStmt);
766
+ const hasRemovedDefaultImport = hasDefaultImport(importStmt);
767
+ const hasNamespaceImport = namespaceImportName(importStmt) != null;
768
+ const hasRemovedFlatImport = hasRemovedFlatSpecifier(importStmt, mod);
769
+ if (!hasImportRequire && !hasRemovedDefaultImport && !hasNamespaceImport && !hasRemovedFlatImport) continue;
770
+ findings.push({
771
+ file: relativePath,
772
+ line: importStmt.range().start.line + 1,
773
+ message: hasImportRequire ? "TypeScript runtime subpath import-equals may still access a removed flat value export." : "Runtime subpath import still uses a removed default, namespace-star, or flat value import.",
774
+ excerpt: importStmt.text().trim()
775
+ });
776
+ }
777
+ for (const exportStmt of findExportStatements(root)) {
778
+ const sourceName = importSource(exportStmt);
779
+ if (!sourceName) continue;
780
+ const mod = MODULES_BY_SOURCE.get(sourceName);
781
+ if (!mod || !hasRemovedFlatSpecifier(exportStmt, mod) && !isExportStar(exportStmt)) continue;
782
+ findings.push({
783
+ file: relativePath,
784
+ line: exportStmt.range().start.line + 1,
785
+ message: "Runtime subpath re-export still uses a removed flat value export.",
786
+ excerpt: exportStmt.text().trim()
787
+ });
788
+ }
789
+ return findings;
790
+ }
791
+ //#endregion
792
+ export { transform as default, reviewFindings };