@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
@@ -0,0 +1,60 @@
1
+ import { Lang, parse } from "@ast-grep/napi";
2
+ //#region codemods/v2/execute-script-arg/scripts/transform.ts
3
+ const NEEDLE = "executeScript";
4
+ function quickFilter(source) {
5
+ return source.includes(NEEDLE) && source.includes("JSON.stringify");
6
+ }
7
+ function pairKeyText(pair) {
8
+ const key = pair.children()[0];
9
+ if (!key) return null;
10
+ return key.text().replace(/^['"]|['"]$/g, "");
11
+ }
12
+ /**
13
+ * True when `stringifyCall` is the value of a top-level `arg:` property in the
14
+ * object literal passed directly to `executeScript(...)`. The chain checked is
15
+ * `JSON.stringify(...)` → pair (`arg:`) → object → arguments → `executeScript`
16
+ * call, so a nested `arg:` (e.g. `executeScript({ opts: { arg: ... } })`) or an
17
+ * unrelated `JSON.stringify` is left untouched.
18
+ */
19
+ function isExecuteScriptArg(stringifyCall) {
20
+ const pair = stringifyCall.parent();
21
+ if (!pair || pair.kind() !== "pair") return false;
22
+ if (pairKeyText(pair) !== "arg") return false;
23
+ const obj = pair.parent();
24
+ if (!obj || obj.kind() !== "object") return false;
25
+ const args = obj.parent();
26
+ if (!args || args.kind() !== "arguments") return false;
27
+ const call = args.parent();
28
+ if (!call || call.kind() !== "call_expression") return false;
29
+ const callee = call.children()[0];
30
+ return !!callee && callee.text() === NEEDLE;
31
+ }
32
+ /**
33
+ * Rewrite `executeScript({ ..., arg: JSON.stringify(X), ... })` to
34
+ * `executeScript({ ..., arg: X, ... })`.
35
+ *
36
+ * In v2 the `executeScript` `arg` option takes a JSON-serializable value and
37
+ * serializes it internally, so a pre-stringified argument double-encodes. Only
38
+ * the literal `arg: JSON.stringify(<single expr>)` form is rewritten; indirect
39
+ * forms (a stringified value held in a variable, `JSON.stringify(x, null, 2)`,
40
+ * etc.) are left for manual migration.
41
+ * @param source - File contents
42
+ * @param _filePath - Absolute path to the file (kept for the runner signature)
43
+ * @returns Transformed source or null when nothing matched.
44
+ */
45
+ function transform(source, _filePath) {
46
+ if (!quickFilter(source)) return null;
47
+ const root = parse(source.includes("</") || source.includes("/>") ? Lang.Tsx : Lang.TypeScript, source).root();
48
+ const edits = [];
49
+ for (const match of root.findAll({ rule: { pattern: "JSON.stringify($X)" } })) {
50
+ if (!isExecuteScriptArg(match)) continue;
51
+ const inner = match.getMatch("X");
52
+ if (!inner) continue;
53
+ edits.push(match.replace(inner.text()));
54
+ }
55
+ if (edits.length === 0) return null;
56
+ const result = root.commitEdits(edits);
57
+ return result === source ? null : result;
58
+ }
59
+ //#endregion
60
+ export { transform as default };
@@ -0,0 +1,115 @@
1
+ import { l as stringValue } from "../../../ast-grep-helpers-CXtWn3RB.js";
2
+ import { Lang, parse } from "@ast-grep/napi";
3
+ //#region codemods/v2/forward-relation-name/scripts/transform.ts
4
+ function sourceLang(filePath, source) {
5
+ const lowerPath = filePath.toLowerCase();
6
+ if (/\.(?:ts|mts|cts)$/u.test(lowerPath)) return Lang.TypeScript;
7
+ if (/\.(?:tsx|jsx|js)$/u.test(lowerPath)) return Lang.Tsx;
8
+ return source.includes("</") ? Lang.Tsx : Lang.TypeScript;
9
+ }
10
+ function isRelationCall(call, aliases) {
11
+ const callee = call.children()[0];
12
+ if (!callee) return false;
13
+ if (callee.kind() === "identifier") return aliases.has(callee.text());
14
+ if (callee.kind() === "subscript_expression") {
15
+ const property = literalStringValue(callee.field("index"));
16
+ return property === null || property === "relation";
17
+ }
18
+ if (callee.kind() !== "member_expression") return false;
19
+ return callee.children().findLast((child) => child.kind() === "property_identifier" || child.kind() === "identifier")?.text() === "relation";
20
+ }
21
+ function relationBindingName(pattern) {
22
+ if (pattern.kind() !== "object_pattern") return null;
23
+ for (const child of pattern.children()) {
24
+ if (child.kind() === "shorthand_property_identifier_pattern" && child.text() === "relation") return child.text();
25
+ if (child.kind() === "pair_pattern" && stringValue(child.field("key")) === "relation") {
26
+ const value = child.field("value");
27
+ return value?.kind() === "identifier" ? value.text() : null;
28
+ }
29
+ if (child.kind() === "object_assignment_pattern") {
30
+ const binding = child.children().find((node) => node.kind() === "shorthand_property_identifier_pattern");
31
+ if (binding?.text() === "relation") return binding.text();
32
+ }
33
+ }
34
+ return null;
35
+ }
36
+ function relationAliases(root) {
37
+ const aliases = /* @__PURE__ */ new Set();
38
+ for (const pattern of root.findAll({ rule: { kind: "object_pattern" } })) {
39
+ const name = relationBindingName(pattern);
40
+ if (name) aliases.add(name);
41
+ }
42
+ return aliases;
43
+ }
44
+ function callArgument(call) {
45
+ const args = call.children().find((child) => child.kind() === "arguments");
46
+ if (!args) return null;
47
+ const values = args.children().filter((child) => {
48
+ const kind = child.kind();
49
+ return kind !== "(" && kind !== ")" && kind !== "," && kind !== "comment";
50
+ });
51
+ return values.length === 1 ? values[0] : null;
52
+ }
53
+ function pairKey(pair) {
54
+ const key = pair.children()[0];
55
+ return stringValue(key ?? null);
56
+ }
57
+ function pairValue(pair) {
58
+ const children = pair.children();
59
+ const colonIndex = children.findIndex((child) => child.kind() === ":");
60
+ if (colonIndex === -1) return null;
61
+ return children.slice(colonIndex + 1).find((child) => child.kind() !== "comment") ?? null;
62
+ }
63
+ function objectPair(object, key) {
64
+ return object.children().find((child) => child.kind() === "pair" && pairKey(child) === key) ?? null;
65
+ }
66
+ function literalStringValue(node) {
67
+ if (node?.kind() !== "string") return null;
68
+ return stringValue(node);
69
+ }
70
+ function hasDynamicProperties(object) {
71
+ return object.children().some((child) => {
72
+ const kind = child.kind();
73
+ if (kind === "{" || kind === "}" || kind === "," || kind === "comment") return false;
74
+ if (kind !== "pair") return true;
75
+ const keyKind = child.children()[0]?.kind();
76
+ return keyKind !== "property_identifier" && keyKind !== "string";
77
+ });
78
+ }
79
+ function needsReview(call) {
80
+ const config = callArgument(call);
81
+ if (config?.kind() !== "object") return config != null;
82
+ if (hasDynamicProperties(config)) return true;
83
+ const relationType = objectPair(config, "type");
84
+ const toward = objectPair(config, "toward");
85
+ if (!relationType || !toward) return false;
86
+ if (literalStringValue(pairValue(relationType)) === "keyOnly") return false;
87
+ const towardConfig = pairValue(toward);
88
+ if (towardConfig?.kind() !== "object") return towardConfig != null;
89
+ if (hasDynamicProperties(towardConfig)) return true;
90
+ const targetType = objectPair(towardConfig, "type");
91
+ if (targetType && literalStringValue(pairValue(targetType)) === "self") return false;
92
+ const as = objectPair(towardConfig, "as");
93
+ if (as) {
94
+ const explicitName = literalStringValue(pairValue(as));
95
+ return explicitName === null || explicitName.length === 0;
96
+ }
97
+ if (!targetType) return false;
98
+ return true;
99
+ }
100
+ function transform(_source, _filePath) {
101
+ return null;
102
+ }
103
+ function reviewFindings(source, filePath, relativePath) {
104
+ if (!source.includes("relation")) return [];
105
+ const root = parse(sourceLang(filePath, source), source).root();
106
+ const aliases = relationAliases(root);
107
+ return root.findAll({ rule: { kind: "call_expression" } }).filter((call) => isRelationCall(call, aliases) && needsReview(call)).map((call) => ({
108
+ file: relativePath,
109
+ line: call.range().start.line + 1,
110
+ message: "Review the v2 forward GraphQL field name or add an explicit toward.as.",
111
+ excerpt: call.text().split("\n", 1)[0].trim()
112
+ }));
113
+ }
114
+ //#endregion
115
+ export { transform as default, reviewFindings };