@tailor-platform/sdk-codemod 0.5.0 → 0.6.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @tailor-platform/sdk-codemod
2
2
 
3
+ ## 0.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#2075](https://github.com/tailor-platform/sdk/pull/2075) [`bd0e397`](https://github.com/tailor-platform/sdk/commit/bd0e39720015248e6ebb2c31efca49f9238b7060) Thanks [@dqn](https://github.com/dqn)! - `tailor function test-run` is renamed to `tailor function run`. The old name keeps working as a deprecated alias until v3 and prints a deprecation warning when used; `tailor upgrade` offers the `v3/function-test-run-rename` codemod to rewrite `function test-run` invocations across package.json scripts, shell and Windows scripts, YAML, Markdown, and JavaScript/TypeScript sources.
8
+
9
+ ### Patch Changes
10
+
11
+ - [#2031](https://github.com/tailor-platform/sdk/pull/2031) [`ecc18ee`](https://github.com/tailor-platform/sdk/commit/ecc18eebc4e5c03c78e362a9b17bacc31bc88a31) Thanks [@renovate](https://github.com/apps/renovate)! - fix(deps): update dependency @ast-grep/napi to v0.45.1
12
+
13
+ - [#2065](https://github.com/tailor-platform/sdk/pull/2065) [`5a3a0e1`](https://github.com/tailor-platform/sdk/commit/5a3a0e1ce8bfadb769dc4540ef257e944f0c077e) Thanks [@toiroakr](https://github.com/toiroakr)! - Raise the minimum supported Node.js version to 22.18.0 (from 22.15.0).
14
+
15
+ `tailor seed validate` crashed on Node 22.15.0–22.17.x with `Expected a string, an ArrayBuffer, or a TypedArray to be returned for the "source" from the "load" hook but got null`. This is a Node.js bug ([nodejs/node#58607](https://github.com/nodejs/node/issues/58607)): requiring a `node:`-scheme-only builtin (`node:sqlite`, used internally by the seed validator) while both a synchronous `resolve` and `load` hook are registered via `module.registerHooks()` crashes the loader on those versions. The SDK always registers both hooks, so any project on Node 22.15.0–22.17.x hit this. Node fixed it upstream in 22.18.0 ([nodejs/node#58612](https://github.com/nodejs/node/pull/58612)); this release raises `engines.node` to match, since Node 22.15.0–22.17.x never actually supported `tailor seed validate`.
16
+
3
17
  ## 0.5.0
4
18
 
5
19
  ### Minor Changes
@@ -197,7 +197,8 @@ function rewriteImportTypeReferences(root, edits, editedRanges) {
197
197
  function transform(source, _filePath) {
198
198
  if (!quickFilter(source)) return null;
199
199
  const filePath = _filePath?.toLowerCase();
200
- const root = parse(filePath?.endsWith(".tsx") || filePath?.endsWith(".jsx") ? Lang.Tsx : filePath ? Lang.TypeScript : source.includes("</") || source.includes("/>") ? Lang.Tsx : Lang.TypeScript, source).root();
200
+ const lang = filePath?.endsWith(".tsx") || filePath?.endsWith(".jsx") ? Lang.Tsx : filePath ? Lang.TypeScript : source.includes("</") || source.includes("/>") ? Lang.Tsx : Lang.TypeScript;
201
+ const root = parse(lang, source).root();
201
202
  const edits = [];
202
203
  const editedRanges = /* @__PURE__ */ new Set();
203
204
  const { localTypeRenames, namespaceNames } = collectSdkImports(root, edits, editedRanges);
@@ -224,7 +224,8 @@ function renameQuotedKey(node) {
224
224
  function transformAuthInvoker(source, _filePath, options = {}) {
225
225
  if (!quickFilter(source)) return null;
226
226
  const renameOptionKeys = options.renameOptionKeys ?? true;
227
- const root = parse(source.includes("</") || source.includes("/>") ? Lang.Tsx : Lang.TypeScript, source).root();
227
+ const lang = source.includes("</") || source.includes("/>") ? Lang.Tsx : Lang.TypeScript;
228
+ const root = parse(lang, source).root();
228
229
  const calls = findInvokerCalls(root).filter((c) => isSupportedInvokerValueCall(c.callNode));
229
230
  const edits = calls.map((c) => c.callNode.replace(c.argText));
230
231
  if (renameOptionKeys) {
@@ -44,7 +44,8 @@ function isExecuteScriptArg(stringifyCall) {
44
44
  */
45
45
  function transform(source, _filePath) {
46
46
  if (!quickFilter(source)) return null;
47
- const root = parse(source.includes("</") || source.includes("/>") ? Lang.Tsx : Lang.TypeScript, source).root();
47
+ const lang = source.includes("</") || source.includes("/>") ? Lang.Tsx : Lang.TypeScript;
48
+ const root = parse(lang, source).root();
48
49
  const edits = [];
49
50
  for (const match of root.findAll({ rule: { pattern: "JSON.stringify($X)" } })) {
50
51
  if (!isExecuteScriptArg(match)) continue;
@@ -43,7 +43,8 @@ function hasNonNamedBinding(importStmt) {
43
43
  */
44
44
  function transform(source, _filePath) {
45
45
  if (!source.includes(CLI_MODULE)) return null;
46
- const root = parse(source.includes("</") || source.includes("/>") ? Lang.Tsx : Lang.TypeScript, source).root();
46
+ const lang = source.includes("</") || source.includes("/>") ? Lang.Tsx : Lang.TypeScript;
47
+ const root = parse(lang, source).root();
47
48
  const edits = [];
48
49
  const importStmts = root.findAll({ rule: {
49
50
  kind: "import_statement",
@@ -699,18 +699,19 @@ function transformResolverBody(arrowNode, edits, parseContext) {
699
699
  const principalAliasBindings = [];
700
700
  for (const child of pattern.children()) {
701
701
  const kind = child.kind();
702
- if (kind === "shorthand_property_identifier_pattern" && child.text() === "user") if (aliasRenamedUser) {
703
- edits.push(child.replace("caller: user"));
704
- aliasedShorthandUser = true;
705
- principalAliasBindings.push({
706
- name: "user",
707
- bindingStart: child.range().start.index
708
- });
709
- } else {
710
- edits.push(child.replace("caller"));
711
- renamedShorthandUser = true;
712
- }
713
- else if (kind === "pair_pattern") {
702
+ if (kind === "shorthand_property_identifier_pattern" && child.text() === "user") {
703
+ if (aliasRenamedUser) {
704
+ edits.push(child.replace("caller: user"));
705
+ aliasedShorthandUser = true;
706
+ principalAliasBindings.push({
707
+ name: "user",
708
+ bindingStart: child.range().start.index
709
+ });
710
+ } else {
711
+ edits.push(child.replace("caller"));
712
+ renamedShorthandUser = true;
713
+ }
714
+ } else if (kind === "pair_pattern") {
714
715
  const key = child.field("key");
715
716
  if (key && key.text() === "user") {
716
717
  edits.push(key.replace("caller"));
@@ -722,16 +723,18 @@ function transformResolverBody(arrowNode, edits, parseContext) {
722
723
  }
723
724
  } else if (kind === "object_assignment_pattern") {
724
725
  const inner = child.children().find((c) => c.kind() === "shorthand_property_identifier_pattern");
725
- if (inner && inner.text() === "user") if (aliasRenamedUser) {
726
- edits.push(inner.replace("caller: user"));
727
- aliasedShorthandUser = true;
728
- principalAliasBindings.push({
729
- name: "user",
730
- bindingStart: inner.range().start.index
731
- });
732
- } else {
733
- edits.push(inner.replace("caller"));
734
- renamedShorthandUser = true;
726
+ if (inner && inner.text() === "user") {
727
+ if (aliasRenamedUser) {
728
+ edits.push(inner.replace("caller: user"));
729
+ aliasedShorthandUser = true;
730
+ principalAliasBindings.push({
731
+ name: "user",
732
+ bindingStart: inner.range().start.index
733
+ });
734
+ } else {
735
+ edits.push(inner.replace("caller"));
736
+ renamedShorthandUser = true;
737
+ }
735
738
  }
736
739
  }
737
740
  }
@@ -1061,33 +1064,36 @@ function transformPrincipalCallbackParam(fn, edits, typeContext) {
1061
1064
  let renamedShorthandUser = false;
1062
1065
  for (const child of pattern.children()) {
1063
1066
  const kind = child.kind();
1064
- if (kind === "shorthand_property_identifier_pattern" && child.text() === "user") if (aliasRenamedUser) {
1065
- edits.push(child.replace("invoker: user"));
1066
- aliasedShorthandUser = true;
1067
- principalAliasBindings.push({
1068
- name: "user",
1069
- bindingStart: child.range().start.index
1070
- });
1071
- } else {
1072
- edits.push(child.replace("invoker"));
1073
- renamedShorthandUser = true;
1074
- }
1075
- else if (kind === "pair_pattern") {
1076
- const key = child.field("key");
1077
- if (key?.text() === "user") edits.push(key.replace("invoker"));
1078
- } else if (kind === "object_assignment_pattern") {
1079
- const inner = child.children().find((c) => c.kind() === "shorthand_property_identifier_pattern");
1080
- if (inner?.text() === "user") if (aliasRenamedUser) {
1081
- edits.push(inner.replace("invoker: user"));
1067
+ if (kind === "shorthand_property_identifier_pattern" && child.text() === "user") {
1068
+ if (aliasRenamedUser) {
1069
+ edits.push(child.replace("invoker: user"));
1082
1070
  aliasedShorthandUser = true;
1083
1071
  principalAliasBindings.push({
1084
1072
  name: "user",
1085
- bindingStart: inner.range().start.index
1073
+ bindingStart: child.range().start.index
1086
1074
  });
1087
1075
  } else {
1088
- edits.push(inner.replace("invoker"));
1076
+ edits.push(child.replace("invoker"));
1089
1077
  renamedShorthandUser = true;
1090
1078
  }
1079
+ } else if (kind === "pair_pattern") {
1080
+ const key = child.field("key");
1081
+ if (key?.text() === "user") edits.push(key.replace("invoker"));
1082
+ } else if (kind === "object_assignment_pattern") {
1083
+ const inner = child.children().find((c) => c.kind() === "shorthand_property_identifier_pattern");
1084
+ if (inner?.text() === "user") {
1085
+ if (aliasRenamedUser) {
1086
+ edits.push(inner.replace("invoker: user"));
1087
+ aliasedShorthandUser = true;
1088
+ principalAliasBindings.push({
1089
+ name: "user",
1090
+ bindingStart: inner.range().start.index
1091
+ });
1092
+ } else {
1093
+ edits.push(inner.replace("invoker"));
1094
+ renamedShorthandUser = true;
1095
+ }
1096
+ }
1091
1097
  }
1092
1098
  }
1093
1099
  if (!renamedShorthandUser) {
@@ -24,7 +24,8 @@ function isInsideImportStatement(node) {
24
24
  function transform(source, _filePath) {
25
25
  if (!Object.keys(RENAMES).some((name) => source.includes(name))) return null;
26
26
  if (!source.includes(SDK_MODULE)) return null;
27
- const root = parse(source.includes("</") || source.includes("/>") ? Lang.Tsx : Lang.TypeScript, source).root();
27
+ const lang = source.includes("</") || source.includes("/>") ? Lang.Tsx : Lang.TypeScript;
28
+ const root = parse(lang, source).root();
28
29
  const edits = [];
29
30
  const needsBodyRename = /* @__PURE__ */ new Set();
30
31
  const importStmts = root.findAll({ rule: {
@@ -0,0 +1,48 @@
1
+ import * as path from "pathe";
2
+ //#region codemods/v3/function-test-run-rename/scripts/transform.ts
3
+ const TOKEN_SEPARATOR = "(?:[ \\t]|\\\\\\r?\\n)+";
4
+ const COMMAND_PATTERN = new RegExp(`(?<![\\w.-])(tailor(?:-sdk)?(?:\\.(?:cmd|ps1|exe))?${TOKEN_SEPARATOR}function${TOKEN_SEPARATOR})test-run(?![\\w.-])`, "g");
5
+ function replaceCommand(value) {
6
+ return value.replace(COMMAND_PATTERN, "$1run");
7
+ }
8
+ function transformText(source) {
9
+ const updated = replaceCommand(source);
10
+ return updated === source ? null : updated;
11
+ }
12
+ function transformPackageJson(source) {
13
+ let parsed;
14
+ try {
15
+ parsed = JSON.parse(source);
16
+ } catch {
17
+ return null;
18
+ }
19
+ let modified = false;
20
+ const scripts = parsed.scripts;
21
+ if (typeof scripts === "object" && scripts != null && !Array.isArray(scripts)) for (const [name, value] of Object.entries(scripts)) {
22
+ if (typeof value !== "string") continue;
23
+ const updated = replaceCommand(value);
24
+ if (updated !== value) {
25
+ scripts[name] = updated;
26
+ modified = true;
27
+ }
28
+ }
29
+ if (!modified) return null;
30
+ const trailing = source.endsWith("\n") ? "\n" : "";
31
+ return JSON.stringify(parsed, null, 2) + trailing;
32
+ }
33
+ /**
34
+ * Rename `tailor function test-run` invocations to `tailor function run`.
35
+ *
36
+ * `test-run` remains as a deprecated alias until v3, where only `run` is
37
+ * recognized.
38
+ * @param source - File contents
39
+ * @param filePath - Absolute path to the file (used to dispatch package.json vs text)
40
+ * @returns Transformed source or null when nothing matched.
41
+ */
42
+ function transform(source, filePath) {
43
+ if (!source.includes("test-run")) return null;
44
+ if (path.extname(filePath).toLowerCase() === ".json") return transformPackageJson(source);
45
+ return transformText(source);
46
+ }
47
+ //#endregion
48
+ export { transform as default };
package/dist/index.js CHANGED
@@ -1303,7 +1303,7 @@ const allCodemods = [
1303
1303
  {
1304
1304
  id: "v2/seed-exec-to-cli-plugin",
1305
1305
  name: "Generated seed exec.mjs → tailor seed CLI plugin",
1306
- description: "`seedPlugin` no longer generates the `exec.mjs` seed runner. Seeding and validation move to the `tailor seed` commands provided by the `@tailor-platform/sdk-plugin-seed` CLI plugin: install it as a devDependency, replace `node <distPath>/exec.mjs` invocations with `tailor seed apply` and `node <distPath>/exec.mjs validate` with `tailor seed validate`, and delete the stale generated `<distPath>/exec.mjs` file. Seed data and schema generation (`data/*.jsonl`, `data/*.schema.ts`) is unchanged, and the `tailor seed apply` options mirror the old script (`--machine-user`, `--namespace`, `--skip-idp`, `--truncate`, `--yes`, type-name arguments), plus a new `--upsert` flag to update existing rows instead of failing on duplicate ids.",
1306
+ description: "`seedPlugin` no longer generates the `exec.mjs` seed runner. Seeding and validation move to the `tailor seed` commands provided by the `@tailor-platform/sdk-plugin-seed` CLI plugin: install it as a devDependency, replace `node <distPath>/exec.mjs` invocations with `tailor seed apply` and `node <distPath>/exec.mjs validate` with `tailor seed validate`, and delete the stale generated `<distPath>/exec.mjs` file. Seed data and schema generation (`data/*.jsonl`, `data/*.schema.ts`) is unchanged, and the `tailor seed apply` options mirror the old script (`--machine-user`, `--namespace`, `--skip-idp`, `--truncate`, `--yes`, entity-name arguments), plus a new `--upsert` flag to update existing rows instead of failing on duplicate ids.",
1307
1307
  since: "1.0.0",
1308
1308
  until: "2.0.0",
1309
1309
  prereleaseUntil: V2_NEXT_9,
@@ -1328,8 +1328,8 @@ const allCodemods = [
1328
1328
  "- Install @tailor-platform/sdk-plugin-seed as a devDependency next to",
1329
1329
  " @tailor-platform/sdk.",
1330
1330
  "- Replace `node <distPath>/exec.mjs [options] [types...]` invocations with",
1331
- " `tailor seed apply [options] [types...]` (same options: --machine-user/-m,",
1332
- " --namespace/-n, --skip-idp, --truncate, --yes, and type-name arguments,",
1331
+ " `tailor seed apply [options] [entities...]` (same options: --machine-user/-m,",
1332
+ " --namespace/-n, --skip-idp, --truncate, --yes, and entity-name arguments,",
1333
1333
  " plus a new --upsert flag to update existing rows instead of failing on",
1334
1334
  " duplicate ids).",
1335
1335
  "- Replace `node <distPath>/exec.mjs validate [path]` with",
@@ -1450,7 +1450,7 @@ const allCodemods = [
1450
1450
  {
1451
1451
  id: "v2/node-minimum-22-15-0",
1452
1452
  name: "Node.js minimum version raised to 22.15.0",
1453
- description: "v2 requires Node.js **22.15.0** or later. This is the first version that includes `module.registerHooks()`, which the SDK uses to register its TypeScript loader hook synchronously in the main thread. No source change is required; ensure your environment runs Node.js 22.15.0+.",
1453
+ description: "v2 requires Node.js **22.15.0** or later. This is the first version that includes `module.registerHooks()`, which the SDK uses to register its TypeScript loader hook synchronously in the main thread. The actual floor is now **22.18.0**: Node 22.15.0–22.17.x has a bug ([nodejs/node#58607](https://github.com/nodejs/node/issues/58607)) that crashes `tailor seed validate` when requiring `node:`-scheme-only builtins such as `node:sqlite`, fixed upstream in 22.18.0. No source change is required; ensure your environment runs Node.js 22.18.0+.",
1454
1454
  since: "1.0.0",
1455
1455
  until: "2.0.0",
1456
1456
  notice: true
@@ -1496,6 +1496,35 @@ const allCodemods = [
1496
1496
  "editing `tailor.d.ts`: it is generated and will be overwritten, and embedding",
1497
1497
  "env values there is what leaked configured secrets into version control."
1498
1498
  ].join("\n")
1499
+ },
1500
+ {
1501
+ id: "v3/function-test-run-rename",
1502
+ name: "function test-run → function run",
1503
+ description: "Rename `tailor function test-run` invocations to `tailor function run`. `test-run` remains as a deprecated alias until it is removed in v3.",
1504
+ since: "1.22.0",
1505
+ until: "3.0.0",
1506
+ scriptPath: "v3/function-test-run-rename/scripts/transform.js",
1507
+ filePatterns: [
1508
+ "**/package.json",
1509
+ "**/*.{sh,bash,zsh,ps1,cmd,bat,yml,yaml}",
1510
+ "**/*.md",
1511
+ "**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}"
1512
+ ],
1513
+ legacyPatterns: [/\bfunction[\s\\]{1,16}test-run(?![\w.-])/],
1514
+ sourceStringLegacyPatterns: [/\bfunction[\s\\]{1,16}test-run(?![\w.-])/],
1515
+ examples: [{
1516
+ lang: "sh",
1517
+ before: "tailor function test-run resolvers/add.ts --arg '{\"a\":1,\"b\":2}'",
1518
+ after: "tailor function run resolvers/add.ts --arg '{\"a\":1,\"b\":2}'"
1519
+ }],
1520
+ prompt: [
1521
+ "The `tailor function test-run` subcommand is renamed to `tailor function run`;",
1522
+ "the old name is removed in v3. Replace any remaining `function test-run`",
1523
+ "invocations the codemod did not rewrite (e.g. wrapped across lines or invoked",
1524
+ "through a package runner such as `npx @tailor-platform/sdk`) with",
1525
+ "`function run`. Leave prose that merely mentions the old subcommand name",
1526
+ "unchanged unless it documents a command to type."
1527
+ ].join("\n")
1499
1528
  }
1500
1529
  ];
1501
1530
  /**
@@ -2219,7 +2248,7 @@ function printLlmReview(review) {
2219
2248
  }
2220
2249
  process.stderr.write(`\nPrompt for an LLM:\n${review.prompt.trim()}\n`);
2221
2250
  }
2222
- runMain(defineCommand({
2251
+ const main = defineCommand({
2223
2252
  name: packageName,
2224
2253
  description: packageJson.description ?? "Codemod runner for Tailor Platform SDK upgrades",
2225
2254
  subCommands: { list: listCommand },
@@ -2301,6 +2330,7 @@ human-readable form, so \`stdout\` stays pure JSON for piping.`,
2301
2330
  process.stdout.write(JSON.stringify(output) + "\n");
2302
2331
  if (output.errors.length > 0) process.exit(1);
2303
2332
  }
2304
- }), { version: packageVersion });
2333
+ });
2334
+ runMain(main, { version: packageVersion });
2305
2335
  //#endregion
2306
2336
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tailor-platform/sdk-codemod",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Codemod runner for Tailor Platform SDK upgrades",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -16,7 +16,7 @@
16
16
  ],
17
17
  "type": "module",
18
18
  "dependencies": {
19
- "@ast-grep/napi": "0.45.0",
19
+ "@ast-grep/napi": "0.45.1",
20
20
  "diff": "9.0.0",
21
21
  "pathe": "2.0.3",
22
22
  "picomatch": "4.0.5",
@@ -29,7 +29,7 @@
29
29
  "@types/node": "24.13.3",
30
30
  "@types/picomatch": "4.0.3",
31
31
  "@types/semver": "7.8.0",
32
- "eslint-plugin-zod": "4.9.0",
32
+ "eslint-plugin-zod": "4.9.1",
33
33
  "oxlint": "1.76.0",
34
34
  "tsdown": "0.22.14",
35
35
  "typescript": "6.0.3",
@@ -38,7 +38,7 @@
38
38
  },
39
39
  "engines": {
40
40
  "bun": ">=1.2.0",
41
- "node": ">=22.15.0"
41
+ "node": ">=22.18.0"
42
42
  },
43
43
  "scripts": {
44
44
  "build": "tsdown",