@tailor-platform/sdk-codemod 0.3.0-next.1 → 0.3.0-next.3
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/CHANGELOG.md +174 -2
- package/dist/codemods/ast-grep-helpers-Bfn39biW.js +171 -0
- package/dist/codemods/v2/apply-to-deploy/scripts/transform.js +17 -1
- package/dist/codemods/v2/auth-attributes-rename/scripts/transform.js +213 -0
- package/dist/codemods/v2/auth-connection-token-helper/scripts/transform.js +243 -0
- package/dist/codemods/v2/auth-invoker-call-unwrap/scripts/transform.js +7 -0
- package/dist/codemods/v2/auth-invoker-unwrap/scripts/transform.js +108 -13
- package/dist/codemods/v2/define-generators-to-plugins/scripts/transform.js +2 -1
- package/dist/codemods/v2/env-var-rename/scripts/transform.js +88 -0
- package/dist/codemods/v2/execute-script-arg/scripts/transform.js +60 -0
- package/dist/codemods/v2/principal-unify/scripts/transform.js +1556 -45
- package/dist/codemods/v2/rename-bin/scripts/transform.js +1087 -0
- package/dist/codemods/v2/runtime-globals-opt-in/scripts/transform.js +103 -0
- package/dist/codemods/v2/sdk-skills-shim/scripts/transform.js +3 -3
- package/dist/codemods/v2/tailor-output-ignore-dir/scripts/transform.js +14 -0
- package/dist/codemods/v2/wait-point-rename/scripts/transform.js +126 -0
- package/dist/index.js +1236 -40
- package/package.json +10 -9
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { n as findImportStatements, r as importBindings, s as localDeclarationNames, t as buildAddNamedImportEdit } from "../../../ast-grep-helpers-Bfn39biW.js";
|
|
2
|
+
import { Lang, parse } from "@ast-grep/napi";
|
|
3
|
+
//#region codemods/v2/runtime-globals-opt-in/scripts/transform.ts
|
|
4
|
+
const RUNTIME_MODULE = "@tailor-platform/sdk/runtime";
|
|
5
|
+
const TAILOR_IDP_CLIENT = "tailor.idp.Client";
|
|
6
|
+
const NON_ARGUMENT_KINDS = /* @__PURE__ */ new Set([
|
|
7
|
+
"(",
|
|
8
|
+
")",
|
|
9
|
+
",",
|
|
10
|
+
"comment"
|
|
11
|
+
]);
|
|
12
|
+
function quickFilter(source) {
|
|
13
|
+
return source.includes(TAILOR_IDP_CLIENT);
|
|
14
|
+
}
|
|
15
|
+
function sourceLang(filePath, source) {
|
|
16
|
+
return filePath.endsWith(".tsx") || filePath.endsWith(".jsx") || source.includes("</") ? Lang.Tsx : Lang.TypeScript;
|
|
17
|
+
}
|
|
18
|
+
function runtimeIdpLocalName(imports) {
|
|
19
|
+
for (const importStmt of imports) for (const binding of importBindings(importStmt)) if (binding.source === RUNTIME_MODULE && binding.importedName === "idp" && !binding.typeOnly) return binding.localName;
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
function isRuntimeIdpBinding(binding) {
|
|
23
|
+
return binding.source === RUNTIME_MODULE && binding.importedName === "idp";
|
|
24
|
+
}
|
|
25
|
+
function hasCollision(imports, localNames, idpLocal, injectingNewIdpName) {
|
|
26
|
+
if (localNames.has("tailor") || injectingNewIdpName && localNames.has("idp") || localNames.has(idpLocal)) return true;
|
|
27
|
+
for (const importStmt of imports) for (const binding of importBindings(importStmt)) {
|
|
28
|
+
if (binding.localName === "tailor") return true;
|
|
29
|
+
if (binding.localName !== "idp") continue;
|
|
30
|
+
if (isRuntimeIdpBinding(binding)) continue;
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
function isDirectiveStatement(node) {
|
|
36
|
+
return node.kind() === "expression_statement" && node.children()[0]?.kind() === "string";
|
|
37
|
+
}
|
|
38
|
+
function importInsertionIndex(root, imports, source) {
|
|
39
|
+
const lastImport = imports.at(-1);
|
|
40
|
+
if (lastImport) return lastImport.range().end.index;
|
|
41
|
+
let pos = 0;
|
|
42
|
+
if (source.startsWith("#!")) {
|
|
43
|
+
const newlineIndex = source.indexOf("\n");
|
|
44
|
+
pos = newlineIndex === -1 ? source.length : newlineIndex + 1;
|
|
45
|
+
}
|
|
46
|
+
for (const child of root.children()) {
|
|
47
|
+
if (child.range().start.index < pos) continue;
|
|
48
|
+
if (child.kind() === "comment") {
|
|
49
|
+
pos = child.range().end.index;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (!isDirectiveStatement(child)) break;
|
|
53
|
+
pos = child.range().end.index;
|
|
54
|
+
}
|
|
55
|
+
return pos;
|
|
56
|
+
}
|
|
57
|
+
function buildAddRuntimeImportEdit(root, source, imports) {
|
|
58
|
+
return buildAddNamedImportEdit({
|
|
59
|
+
importName: "idp",
|
|
60
|
+
imports,
|
|
61
|
+
insertionIndex: importInsertionIndex,
|
|
62
|
+
moduleName: RUNTIME_MODULE,
|
|
63
|
+
root,
|
|
64
|
+
source
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
function argumentExpressions(args) {
|
|
68
|
+
return args.children().filter((child) => !NON_ARGUMENT_KINDS.has(child.kind()));
|
|
69
|
+
}
|
|
70
|
+
function hasConstructorArguments(newExpression) {
|
|
71
|
+
const args = newExpression.field("arguments");
|
|
72
|
+
return args ? argumentExpressions(args).length > 0 : false;
|
|
73
|
+
}
|
|
74
|
+
function findTailorIdpClientConstructors(root) {
|
|
75
|
+
return root.findAll({ rule: { kind: "new_expression" } }).filter(hasConstructorArguments).map((node) => node.field("constructor")).filter((node) => node?.text() === TAILOR_IDP_CLIENT);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Rewrite direct `new tailor.idp.Client(...)` calls to the typed runtime
|
|
79
|
+
* wrapper. Files with local `tailor` or conflicting `idp` bindings are left
|
|
80
|
+
* unchanged for the runtime-globals review prompt.
|
|
81
|
+
* @param source - File contents
|
|
82
|
+
* @param filePath - Absolute path to the file
|
|
83
|
+
* @returns Transformed source or null when nothing matched.
|
|
84
|
+
*/
|
|
85
|
+
function transform(source, filePath) {
|
|
86
|
+
if (!quickFilter(source)) return null;
|
|
87
|
+
const root = parse(sourceLang(filePath, source), source).root();
|
|
88
|
+
const constructors = findTailorIdpClientConstructors(root);
|
|
89
|
+
if (constructors.length === 0) return null;
|
|
90
|
+
const imports = findImportStatements(root);
|
|
91
|
+
const existingIdpLocal = runtimeIdpLocalName(imports);
|
|
92
|
+
const idpLocal = existingIdpLocal ?? "idp";
|
|
93
|
+
if (hasCollision(imports, localDeclarationNames(root), idpLocal, existingIdpLocal === null)) return null;
|
|
94
|
+
const edits = constructors.map((constructor) => constructor.replace(`${idpLocal}.Client`));
|
|
95
|
+
if (!existingIdpLocal) {
|
|
96
|
+
if (filePath.endsWith(".cts")) return null;
|
|
97
|
+
edits.push(buildAddRuntimeImportEdit(root, source, imports));
|
|
98
|
+
}
|
|
99
|
+
const result = root.commitEdits(edits);
|
|
100
|
+
return result === source ? null : result;
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
103
|
+
export { transform as default };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as path from "pathe";
|
|
2
2
|
//#region codemods/v2/sdk-skills-shim/scripts/transform.ts
|
|
3
3
|
const SHIM_PATTERN = /\btailor-sdk-skills(?:@[^\s'"`]+)?(?:[ \t]+install)?\b(?!-)/g;
|
|
4
|
-
const REPLACEMENT = "tailor
|
|
4
|
+
const REPLACEMENT = "tailor skills add";
|
|
5
5
|
function replaceShim(value) {
|
|
6
6
|
return value.replace(SHIM_PATTERN, REPLACEMENT);
|
|
7
7
|
}
|
|
@@ -34,10 +34,10 @@ function transformPackageJson(source) {
|
|
|
34
34
|
return JSON.stringify(parsed, null, 2) + trailing;
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
|
-
* Replace `tailor-sdk-skills` invocations with `tailor
|
|
37
|
+
* Replace `tailor-sdk-skills` invocations with `tailor skills add`.
|
|
38
38
|
*
|
|
39
39
|
* The standalone `tailor-sdk-skills` binary is removed in v2; users must call
|
|
40
|
-
* the subcommand on the main `tailor
|
|
40
|
+
* the subcommand on the main `tailor` CLI instead.
|
|
41
41
|
* @param source - File contents
|
|
42
42
|
* @param filePath - Absolute path to the file (used to dispatch package.json vs text)
|
|
43
43
|
* @returns Transformed source or null when nothing matched.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region codemods/v2/tailor-output-ignore-dir/scripts/transform.ts
|
|
2
|
+
const GENERATED_DIR_IGNORE_ENTRY_RE = /^(!?\/?)\.tailor-sdk(\/?)([ \t]*)$/gm;
|
|
3
|
+
/**
|
|
4
|
+
* Rewrite exact ignore-file entries for the generated SDK output directory.
|
|
5
|
+
* @param source - File contents
|
|
6
|
+
* @returns Transformed source or null when nothing matched.
|
|
7
|
+
*/
|
|
8
|
+
function transform(source) {
|
|
9
|
+
if (!source.includes(".tailor-sdk")) return null;
|
|
10
|
+
const updated = source.replace(GENERATED_DIR_IGNORE_ENTRY_RE, (_match, prefix, slash, trailingWhitespace) => `${prefix}.tailor${slash}${trailingWhitespace}`);
|
|
11
|
+
return updated === source ? null : updated;
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { transform as default };
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { Lang, parse } from "@ast-grep/napi";
|
|
2
|
+
//#region codemods/v2/wait-point-rename/scripts/transform.ts
|
|
3
|
+
const SDK_MODULE = "@tailor-platform/sdk";
|
|
4
|
+
const RENAMES = {
|
|
5
|
+
defineWaitPoint: "createWaitPoint",
|
|
6
|
+
defineWaitPoints: "createWaitPoints"
|
|
7
|
+
};
|
|
8
|
+
function isInsideImportStatement(node) {
|
|
9
|
+
let current = node.parent();
|
|
10
|
+
while (current) {
|
|
11
|
+
if (current.kind() === "import_statement") return true;
|
|
12
|
+
current = current.parent();
|
|
13
|
+
}
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Rename `defineWaitPoint` and `defineWaitPoints` imported from `@tailor-platform/sdk`
|
|
18
|
+
* to `createWaitPoint` and `createWaitPoints`, updating both the import specifiers
|
|
19
|
+
* and all usages in the file body.
|
|
20
|
+
* @param source - File contents
|
|
21
|
+
* @param filePath - Absolute path to the file (kept for the runner signature)
|
|
22
|
+
* @returns Transformed source or null when nothing matched.
|
|
23
|
+
*/
|
|
24
|
+
function transform(source, _filePath) {
|
|
25
|
+
if (!Object.keys(RENAMES).some((name) => source.includes(name))) return null;
|
|
26
|
+
if (!source.includes(SDK_MODULE)) return null;
|
|
27
|
+
const root = parse(source.includes("</") || source.includes("/>") ? Lang.Tsx : Lang.TypeScript, source).root();
|
|
28
|
+
const edits = [];
|
|
29
|
+
const needsBodyRename = /* @__PURE__ */ new Set();
|
|
30
|
+
const importStmts = root.findAll({ rule: {
|
|
31
|
+
kind: "import_statement",
|
|
32
|
+
has: {
|
|
33
|
+
kind: "string",
|
|
34
|
+
regex: `^["']${SDK_MODULE}["']$`
|
|
35
|
+
}
|
|
36
|
+
} });
|
|
37
|
+
for (const importStmt of importStmts) {
|
|
38
|
+
const specs = importStmt.findAll({ rule: { kind: "import_specifier" } });
|
|
39
|
+
for (const spec of specs) {
|
|
40
|
+
const idents = spec.children().filter((c) => c.kind() === "identifier");
|
|
41
|
+
if (idents.length === 0) continue;
|
|
42
|
+
const importedName = idents[0].text();
|
|
43
|
+
const newName = RENAMES[importedName];
|
|
44
|
+
if (!newName) continue;
|
|
45
|
+
const isAliased = idents.length > 1;
|
|
46
|
+
edits.push(idents[0].replace(newName));
|
|
47
|
+
if (!isAliased) needsBodyRename.add(importedName);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (edits.length === 0) return null;
|
|
51
|
+
if (needsBodyRename.size > 0) {
|
|
52
|
+
const shadowedRanges = /* @__PURE__ */ new Map();
|
|
53
|
+
const addShadowedRange = (name, scopeNode) => {
|
|
54
|
+
const r = scopeNode.range();
|
|
55
|
+
if (!shadowedRanges.has(name)) shadowedRanges.set(name, []);
|
|
56
|
+
shadowedRanges.get(name).push({
|
|
57
|
+
start: r.start.index,
|
|
58
|
+
end: r.end.index
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
const localDecls = root.findAll({ rule: { any: [{ kind: "function_declaration" }, { kind: "variable_declarator" }] } });
|
|
62
|
+
for (const decl of localDecls) {
|
|
63
|
+
if (isInsideImportStatement(decl)) continue;
|
|
64
|
+
const nameChild = decl.children().filter((c) => c.kind() === "identifier").find((c) => needsBodyRename.has(c.text())) ?? decl.children().find((c) => c.kind() === "object_pattern")?.children().find((c) => c.kind() === "shorthand_property_identifier_pattern" && needsBodyRename.has(c.text()));
|
|
65
|
+
if (!nameChild || !needsBodyRename.has(nameChild.text())) continue;
|
|
66
|
+
let scopeNode = root;
|
|
67
|
+
let p = decl.parent();
|
|
68
|
+
while (p) {
|
|
69
|
+
const k = p.kind();
|
|
70
|
+
if (k === "statement_block" || k === "program" || k === "for_statement" || k === "for_in_statement") {
|
|
71
|
+
scopeNode = p;
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
p = p.parent();
|
|
75
|
+
}
|
|
76
|
+
addShadowedRange(nameChild.text(), scopeNode);
|
|
77
|
+
}
|
|
78
|
+
const paramNodes = root.findAll({ rule: { any: [{ kind: "required_parameter" }, { kind: "optional_parameter" }] } });
|
|
79
|
+
for (const param of paramNodes) {
|
|
80
|
+
if (isInsideImportStatement(param)) continue;
|
|
81
|
+
const nameChild = param.children().flatMap((c) => c.kind() === "rest_pattern" ? c.children().filter((cc) => cc.kind() === "identifier") : c.kind() === "identifier" ? [c] : []).find((c) => needsBodyRename.has(c.text()));
|
|
82
|
+
if (!nameChild) continue;
|
|
83
|
+
let scopeNode = root;
|
|
84
|
+
let p = param.parent();
|
|
85
|
+
while (p) {
|
|
86
|
+
const k = p.kind();
|
|
87
|
+
if (k === "formal_parameters") {
|
|
88
|
+
p = p.parent();
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (k === "function_declaration" || k === "function_expression" || k === "arrow_function" || k === "method_definition") {
|
|
92
|
+
scopeNode = p;
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
addShadowedRange(nameChild.text(), scopeNode);
|
|
98
|
+
}
|
|
99
|
+
const forInStmts = root.findAll({ rule: { kind: "for_in_statement" } });
|
|
100
|
+
for (const stmt of forInStmts) {
|
|
101
|
+
const children = stmt.children();
|
|
102
|
+
const keywordIdx = children.findIndex((c) => c.kind() === "of" || c.kind() === "in");
|
|
103
|
+
if (keywordIdx < 0) continue;
|
|
104
|
+
for (let i = 0; i < keywordIdx; i++) {
|
|
105
|
+
const child = children[i];
|
|
106
|
+
if (child.kind() === "identifier" && needsBodyRename.has(child.text())) addShadowedRange(child.text(), stmt);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const renameNode = (node) => {
|
|
110
|
+
const name = node.text();
|
|
111
|
+
if (!needsBodyRename.has(name)) return;
|
|
112
|
+
if (isInsideImportStatement(node)) return;
|
|
113
|
+
const ranges = shadowedRanges.get(name);
|
|
114
|
+
if (ranges) {
|
|
115
|
+
const pos = node.range().start.index;
|
|
116
|
+
if (ranges.some((r) => pos >= r.start && pos < r.end)) return;
|
|
117
|
+
}
|
|
118
|
+
edits.push(node.replace(RENAMES[name]));
|
|
119
|
+
};
|
|
120
|
+
for (const ident of root.findAll({ rule: { kind: "identifier" } })) renameNode(ident);
|
|
121
|
+
for (const prop of root.findAll({ rule: { kind: "shorthand_property_identifier" } })) renameNode(prop);
|
|
122
|
+
}
|
|
123
|
+
return root.commitEdits(edits);
|
|
124
|
+
}
|
|
125
|
+
//#endregion
|
|
126
|
+
export { transform as default };
|