@tailor-platform/sdk-codemod 0.3.8 → 0.4.0-next.9

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.
Files changed (24) hide show
  1. package/CHANGELOG.md +261 -0
  2. package/dist/codemods/ast-grep-helpers-CXtWn3RB.js +171 -0
  3. package/dist/codemods/v2/apply-to-deploy/scripts/transform.js +22 -4
  4. package/dist/codemods/v2/auth-attributes-rename/scripts/transform.js +213 -0
  5. package/dist/codemods/v2/auth-connection-token-helper/scripts/transform.js +243 -0
  6. package/dist/codemods/v2/auth-invoker-call-unwrap/scripts/transform.js +7 -0
  7. package/dist/codemods/v2/auth-invoker-unwrap/scripts/transform.js +108 -13
  8. package/dist/codemods/v2/cli-rename/scripts/transform.js +373 -14
  9. package/dist/codemods/v2/db-type-to-table/scripts/transform.js +383 -0
  10. package/dist/codemods/v2/env-var-rename/scripts/transform.js +88 -0
  11. package/dist/codemods/v2/erd-site-to-plugin/scripts/transform.js +195 -0
  12. package/dist/codemods/v2/execute-script-arg/scripts/transform.js +60 -0
  13. package/dist/codemods/v2/forward-relation-name/scripts/transform.js +115 -0
  14. package/dist/codemods/v2/principal-unify/scripts/transform.js +1555 -44
  15. package/dist/codemods/v2/rename-bin/scripts/transform.js +1087 -0
  16. package/dist/codemods/v2/runtime-globals-opt-in/scripts/transform.js +103 -0
  17. package/dist/codemods/v2/runtime-subpath-namespace/scripts/transform.js +792 -0
  18. package/dist/codemods/v2/sdk-skills-shim/scripts/transform.js +3 -3
  19. package/dist/codemods/v2/tailor-output-ignore-dir/scripts/transform.js +14 -0
  20. package/dist/codemods/v2/tailordb-namespace/scripts/transform.js +5 -4
  21. package/dist/codemods/v2/wait-point-rename/scripts/transform.js +126 -0
  22. package/dist/codemods/v2/workflow-trigger-rename/scripts/transform.js +122 -0
  23. package/dist/index.js +1713 -51
  24. package/package.json +5 -4
@@ -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-sdk skills install";
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-sdk skills install`.
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-sdk` CLI instead.
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 };
@@ -6,10 +6,11 @@ const MEMBER_GROUP = [
6
6
  ].join("|");
7
7
  const PATTERN = new RegExp(String.raw`\bTailordb\.(${MEMBER_GROUP})\b`, "g");
8
8
  /**
9
- * Rewrite references to the deprecated capital-cased `Tailordb` ambient
10
- * namespace to the new lowercase `tailordb` namespace. The capital-cased
11
- * namespace was inherited from `@tailor-platform/function-types`; the SDK
12
- * keeps it as a `@deprecated` alias in v1 and removes it in v2.
9
+ * Rewrite references to the capital-cased `Tailordb` ambient namespace to the
10
+ * lowercase `tailordb` namespace. The capital-cased namespace was inherited
11
+ * from `@tailor-platform/function-types`; the SDK kept it as a `@deprecated`
12
+ * alias in v1 and removed it in v2, leaving only the lowercase `tailordb.*`
13
+ * namespace exposed by `@tailor-platform/sdk/runtime/globals`.
13
14
  *
14
15
  * Only the known type-only members (`QueryResult`, `CommandType`, `Client`)
15
16
  * are rewritten so that unrelated user-defined symbols sharing the
@@ -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 };
@@ -0,0 +1,122 @@
1
+ import { c as localDeclarationNames, i as importBindings, r as findImportStatements } from "../../../ast-grep-helpers-CXtWn3RB.js";
2
+ import { Lang, parse } from "@ast-grep/napi";
3
+ //#region codemods/v2/workflow-trigger-rename/scripts/transform.ts
4
+ const RENAMES = {
5
+ triggerWorkflow: "startWorkflow",
6
+ triggerJobFunction: "startJobFunction",
7
+ resumeWorkflow: "resumeWorkflowExecution"
8
+ };
9
+ const WORKFLOW_MODULE_SOURCES = /* @__PURE__ */ new Set(["@tailor-platform/sdk/runtime", "@tailor-platform/sdk/runtime/workflow"]);
10
+ function quickFilter(source) {
11
+ return Object.keys(RENAMES).some((name) => source.includes(name));
12
+ }
13
+ function sourceLang(filePath, source) {
14
+ const lower = filePath.toLowerCase();
15
+ if (lower.endsWith(".tsx") || lower.endsWith(".jsx")) return Lang.Tsx;
16
+ return source.includes("</") || source.includes("/>") ? Lang.Tsx : Lang.TypeScript;
17
+ }
18
+ function collectWorkflowLocals(root, imports) {
19
+ const locals = /* @__PURE__ */ new Set();
20
+ for (const importStmt of imports) for (const binding of importBindings(importStmt)) if (binding.importedName === "workflow" && WORKFLOW_MODULE_SOURCES.has(binding.source)) locals.add(binding.localName);
21
+ const declaredNames = localDeclarationNames(root);
22
+ for (const name of locals) if (declaredNames.has(name)) locals.delete(name);
23
+ return locals;
24
+ }
25
+ function tailorIsAmbientGlobal(root, imports) {
26
+ if (localDeclarationNames(root).has("tailor")) return false;
27
+ return !imports.some((stmt) => importBindings(stmt).some((b) => b.localName === "tailor"));
28
+ }
29
+ function isAmbientTailorWorkflow(object) {
30
+ if (!object || object.kind() !== "member_expression") return false;
31
+ const base = object.field("object");
32
+ const property = object.field("property");
33
+ return base?.kind() === "identifier" && base.text() === "tailor" && property?.text() === "workflow";
34
+ }
35
+ function expressionArguments(args) {
36
+ return args.children().filter((child) => ![
37
+ "(",
38
+ ")",
39
+ ","
40
+ ].includes(child.kind()));
41
+ }
42
+ function thirdArgument(member) {
43
+ const call = member.parent();
44
+ if (call?.kind() !== "call_expression") return null;
45
+ const args = call.field("arguments");
46
+ if (!args) return null;
47
+ return expressionArguments(args)[2] ?? null;
48
+ }
49
+ /**
50
+ * A `triggerWorkflow(name, args, options)` call whose third argument is not a
51
+ * literal object (e.g. a variable), or is an object literal that spreads one
52
+ * (`{ ...rest }`), cannot be safely renamed: we cannot tell whether it carries
53
+ * an `invoker` key that also needs renaming to `authInvoker`, and renaming
54
+ * just the method name would erase the `triggerWorkflow` token that flags the
55
+ * call for manual review, while the option silently stops working at
56
+ * runtime. Such calls are left entirely unrenamed.
57
+ * @param member - The `.triggerWorkflow` member-expression node being considered
58
+ * @returns Whether the call must be skipped
59
+ */
60
+ function hasUnsafeThirdArgument(member) {
61
+ const optionsArg = thirdArgument(member);
62
+ if (optionsArg === null) return false;
63
+ if (optionsArg.kind() !== "object") return true;
64
+ return optionsArg.children().some((child) => child.kind() === "spread_element");
65
+ }
66
+ /**
67
+ * `triggerWorkflow`'s removed SDK wrapper converted an `invoker` option to
68
+ * the platform's `authInvoker` shape before calling through; `startWorkflow`
69
+ * expects `authInvoker` directly. Build an edit renaming a literal `invoker`
70
+ * key (or shorthand) in the third argument of a `triggerWorkflow(...)` call
71
+ * being renamed to `startWorkflow`, so the option keeps working.
72
+ * @param member - The `.triggerWorkflow` member-expression node being renamed
73
+ * @returns An edit renaming the `invoker` key, or null when not applicable
74
+ */
75
+ function findInvokerOptionEdit(member) {
76
+ const optionsArg = thirdArgument(member);
77
+ if (!optionsArg || optionsArg.kind() !== "object") return null;
78
+ for (const child of optionsArg.children()) if (child.kind() === "pair") {
79
+ const key = child.field("key");
80
+ if (key?.kind() === "property_identifier" && key.text() === "invoker") return key.replace("authInvoker");
81
+ } else if (child.kind() === "shorthand_property_identifier" && child.text() === "invoker") return child.replace("authInvoker: invoker");
82
+ return null;
83
+ }
84
+ /**
85
+ * Rewrite `.triggerWorkflow(`, `.triggerJobFunction(`, and `.resumeWorkflow(`
86
+ * member accesses to their canonical `start*`/`resumeWorkflowExecution` names,
87
+ * either on the ambient `tailor.workflow` global or on a `workflow` value
88
+ * imported from `@tailor-platform/sdk/runtime(/workflow)`.
89
+ * @param source - File contents
90
+ * @param filePath - Absolute path to the file
91
+ * @returns Transformed source or null when nothing matched.
92
+ */
93
+ function transform(source, filePath) {
94
+ if (!quickFilter(source)) return null;
95
+ const root = parse(sourceLang(filePath ?? "", source), source).root();
96
+ const imports = findImportStatements(root);
97
+ const workflowLocals = collectWorkflowLocals(root, imports);
98
+ const tailorIsAmbient = tailorIsAmbientGlobal(root, imports);
99
+ const edits = [];
100
+ for (const member of root.findAll({ rule: { kind: "member_expression" } })) {
101
+ const property = member.field("property");
102
+ if (!property || property.kind() !== "property_identifier") continue;
103
+ const newName = RENAMES[property.text()];
104
+ if (!newName) continue;
105
+ const object = member.field("object");
106
+ if (!object) continue;
107
+ const isWorkflowImportReceiver = object.kind() === "identifier" && workflowLocals.has(object.text());
108
+ const isAmbientReceiver = tailorIsAmbient && isAmbientTailorWorkflow(object);
109
+ if (!isWorkflowImportReceiver && !isAmbientReceiver) continue;
110
+ if (newName === "startWorkflow") {
111
+ if (hasUnsafeThirdArgument(member)) continue;
112
+ edits.push(property.replace(newName));
113
+ const invokerEdit = findInvokerOptionEdit(member);
114
+ if (invokerEdit) edits.push(invokerEdit);
115
+ } else edits.push(property.replace(newName));
116
+ }
117
+ if (edits.length === 0) return null;
118
+ const result = root.commitEdits(edits);
119
+ return result === source ? null : result;
120
+ }
121
+ //#endregion
122
+ export { transform as default };