@tailor-platform/sdk-codemod 0.3.0-next.2 → 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 CHANGED
@@ -1,5 +1,64 @@
1
1
  # @tailor-platform/sdk-codemod
2
2
 
3
+ ## 0.3.0-next.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#1559](https://github.com/tailor-platform/sdk/pull/1559) [`ff8ef1c`](https://github.com/tailor-platform/sdk/commit/ff8ef1c1323daf81812c182e146fd53da20e676e) Thanks [@dqn](https://github.com/dqn)! - Rename auth attribute module augmentation from `AttributeMap` to `Attributes`.
8
+
9
+ - [#1584](https://github.com/tailor-platform/sdk/pull/1584) [`7faff07`](https://github.com/tailor-platform/sdk/commit/7faff07982909b63b87185dc1186e2919a06d4bb) Thanks [@dqn](https://github.com/dqn)! - Report the codemod runner identity in the JSON summary, including the source checkout commit and local build command when run from a branch build, so prerelease migration validation can distinguish exact npm packages from branch-head behavior.
10
+
11
+ - [#1599](https://github.com/tailor-platform/sdk/pull/1599) [`b88f6a2`](https://github.com/tailor-platform/sdk/commit/b88f6a2e1c6d8e25a797bec6ca90428f5be3b1b9) Thanks [@dqn](https://github.com/dqn)! - Apply the v2 `rename-bin` codemod to SDK CLI command strings in TypeScript and JavaScript source files.
12
+
13
+ - [#1578](https://github.com/tailor-platform/sdk/pull/1578) [`579cb47`](https://github.com/tailor-platform/sdk/commit/579cb4705cb295c1fcf9bff948d205fb245ff4e5) Thanks [@dqn](https://github.com/dqn)! - Run v2 codemods when the target version is a v2 prerelease.
14
+
15
+ - [#1686](https://github.com/tailor-platform/sdk/pull/1686) [`aecaf8c`](https://github.com/tailor-platform/sdk/commit/aecaf8c1bb7813a32e998ea7d034684541cb1c85) Thanks [@dqn](https://github.com/dqn)! - Replace `tailor skills install` with project-local `tailor skills add`, `list`, `remove`, and `sync` commands for bundled Tailor SDK agent skills.
16
+
17
+ - [#1585](https://github.com/tailor-platform/sdk/pull/1585) [`1c1ca49`](https://github.com/tailor-platform/sdk/commit/1c1ca499b4fd55a616b1531ec7ab280ceed531d3) Thanks [@dqn](https://github.com/dqn)! - Report precise file-local findings for `principal-unify` review follow-ups, including nullable caller call sites and `context.user` helper adapters.
18
+
19
+ - [#1601](https://github.com/tailor-platform/sdk/pull/1601) [`144f3e3`](https://github.com/tailor-platform/sdk/commit/144f3e30f2b0c5dac1a3288ff65c9dc5ca82c13b) Thanks [@dqn](https://github.com/dqn)! - Fix `v2/principal-unify` review findings for nested SDK field parser invoker values and destructured context helper messages.
20
+
21
+ - [#1622](https://github.com/tailor-platform/sdk/pull/1622) [`0fe8bad`](https://github.com/tailor-platform/sdk/commit/0fe8bad9afbb7702bc067ac9635b77c0438497a6) Thanks [@dqn](https://github.com/dqn)! - Remove the deprecated `auth.getConnectionToken()` helper from values returned by `defineAuth()`. Use `authconnection.getConnectionToken(...)` from `@tailor-platform/sdk/runtime` in resolvers, executors, and workflows instead. The v2 codemod rewrites direct `auth.getConnectionToken(...)` calls when the `auth` binding is imported from `tailor.config`.
22
+
23
+ - [#1557](https://github.com/tailor-platform/sdk/pull/1557) [`7ff575f`](https://github.com/tailor-platform/sdk/commit/7ff575fdfa15c00b5fc6282b28c0cb50bfdf927b) Thanks [@toiroakr](https://github.com/toiroakr)! - Rename the CLI binary from `tailor-sdk` to `tailor`.
24
+
25
+ The output directory default changes from `.tailor-sdk` to `.tailor`, and the GitHub Actions lock file path changes from `.github/tailor-sdk.lock` to `.github/tailor.lock`.
26
+
27
+ Run the `v2/rename-bin` codemod to migrate `tailor-sdk` invocations in package.json scripts, shell scripts, CI workflows, and documentation:
28
+
29
+ ```sh
30
+ npx @tailor-platform/sdk-codemod --from 1.x --to 2.0.0
31
+ ```
32
+
33
+ - [#1563](https://github.com/tailor-platform/sdk/pull/1563) [`501e8bf`](https://github.com/tailor-platform/sdk/commit/501e8bfdd2bca7201a1c9b036bf72087476da416) Thanks [@dqn](https://github.com/dqn)! - Standardize SDK-owned environment variables on the `TAILOR_*` namespace.
34
+
35
+ Replace the removed SDK-specific environment variables with their new names: `TAILOR_CONFIG_PATH`, `TAILOR_DTS_PATH`, `TAILOR_CI_ALLOW_ID_INJECTION`, `TAILOR_DEPLOY_BUILD_ONLY`, `TAILOR_BUILD_OUTPUT_DIR`, `TAILOR_SKILLS_SOURCE`, `TAILOR_TEMPLATE_SDK_VERSION`, `TAILOR_PLATFORM_URL`, `TAILOR_PLATFORM_OAUTH2_CLIENT_ID`, `TAILOR_INLINE_SOURCEMAP`, `TAILOR_QUERY_NEWLINE_ON_ENTER`, and `TAILOR_APP_LOG_LEVEL`. The deprecated `TAILOR_TOKEN` fallback is removed; use `TAILOR_PLATFORM_TOKEN`. The v2 codemod rewrites unambiguous removed SDK environment variable names and flags generic names such as `LOG_LEVEL` and `PLATFORM_URL` for manual review.
36
+
37
+ - [#1684](https://github.com/tailor-platform/sdk/pull/1684) [`de3ef5e`](https://github.com/tailor-platform/sdk/commit/de3ef5e7421a998624154df5e90da62e17664524) Thanks [@dqn](https://github.com/dqn)! - Restore Tailor field outputs for UUID, date, datetime, time, and decimal fields to plain string-compatible types and remove the strict scalar string migration guidance.
38
+
39
+ - [#1582](https://github.com/tailor-platform/sdk/pull/1582) [`b8b48a3`](https://github.com/tailor-platform/sdk/commit/b8b48a379a73314c26fbf53c74c2181e77f0565b) Thanks [@dqn](https://github.com/dqn)! - Flag JavaScript files and embedded code strings that still reference ambient Tailor runtime globals during v2 migration review.
40
+
41
+ - [#1583](https://github.com/tailor-platform/sdk/pull/1583) [`006a588`](https://github.com/tailor-platform/sdk/commit/006a5884583f23fc6852714c41e58a7ab6d65a5a) Thanks [@dqn](https://github.com/dqn)! - Automatically migrate simple direct `tailor.idp.Client` runtime global usage to the typed `idp.Client` wrapper during v2 upgrades.
42
+
43
+ - [#1639](https://github.com/tailor-platform/sdk/pull/1639) [`6616674`](https://github.com/tailor-platform/sdk/commit/6616674eb41a53619138603405a4498e3f09d70b) Thanks [@dqn](https://github.com/dqn)! - Keep v2 codemods from reusing type-only runtime helper imports when adding runtime value imports.
44
+
45
+ - [#1581](https://github.com/tailor-platform/sdk/pull/1581) [`79780bc`](https://github.com/tailor-platform/sdk/commit/79780bce19864a238602f4dd7a82fcc84e9f8501) Thanks [@dqn](https://github.com/dqn)! - Add the `v2/tailor-output-ignore-dir` codemod so SDK upgrades rewrite exact `.tailor-sdk/` ignore-file entries to `.tailor/` while leaving other `.tailor-sdk` paths unchanged.
46
+
47
+ - [#1556](https://github.com/tailor-platform/sdk/pull/1556) [`645949e`](https://github.com/tailor-platform/sdk/commit/645949ed64bda8b82fc44c0db54928698b12a2eb) Thanks [@toiroakr](https://github.com/toiroakr)! - Rename `defineWaitPoint` and `defineWaitPoints` to `createWaitPoint` and `createWaitPoints`.
48
+
49
+ These functions create runtime instances with `.wait()` and `.resolve()` methods that call the platform API at runtime, so the `create*` prefix is more accurate. Update any usages:
50
+
51
+ ```diff
52
+ -import { defineWaitPoint, defineWaitPoints } from "@tailor-platform/sdk";
53
+ +import { createWaitPoint, createWaitPoints } from "@tailor-platform/sdk";
54
+
55
+ -export const approval = defineWaitPoint<Payload, Result>("approval");
56
+ +export const approval = createWaitPoint<Payload, Result>("approval");
57
+
58
+ -export const waitPoints = defineWaitPoints((define) => ({ ... }));
59
+ +export const waitPoints = createWaitPoints((define) => ({ ... }));
60
+ ```
61
+
3
62
  ## 0.3.0-next.2
4
63
  ### Minor Changes
5
64
 
@@ -21,9 +80,9 @@
21
80
 
22
81
 
23
82
  - [#1495](https://github.com/tailor-platform/sdk/pull/1495) [`6234022`](https://github.com/tailor-platform/sdk/commit/6234022d7dc03813b8dade831b86f63a5f7a20e6) Thanks [@toiroakr](https://github.com/toiroakr)! - Generate the v2 migration guide (`packages/sdk/docs/migration/v2.md`) from the codemod registry, which is the single source of truth. Each entry renders its name, automation level (Automatic / Partially automatic / Manual), description, optional before/after `examples`, and — for changes the codemods cannot fully migrate on their own — the LLM/manual migration prompt. Run `pnpm codemod:docs:update` to regenerate and `pnpm codemod:docs:check` (wired into `pnpm check`) to verify it is in sync.
24
-
83
+
25
84
  `scriptPath` is now optional, so the registry can also describe codemod-less ("manual") migrations that ship only guidance (`examples` / `prompt` / `suspiciousPatterns`) with no automatic transform. A manual entry with a `prompt` but no scoping pattern is surfaced as a project-wide `llmReviews` entry at runtime.
26
-
85
+
27
86
  Add a `sdk-codemod list` command that prints every registered rule (id, name, kind, version range).
28
87
 
29
88
 
@@ -32,7 +91,7 @@
32
91
 
33
92
 
34
93
  - [#1476](https://github.com/tailor-platform/sdk/pull/1476) [`fa83075`](https://github.com/tailor-platform/sdk/commit/fa83075f5e0e91085c0ef0cb44b7058a28a79ec3) Thanks [@toiroakr](https://github.com/toiroakr)! - `executeScript` now takes its `arg` as a JSON-serializable value instead of a pre-serialized JSON string. Pass the value directly (e.g. `arg: { a: 1 }`) instead of `arg: JSON.stringify({ a: 1 })`.
35
-
94
+
36
95
  Add the `v2/execute-script-arg` codemod, which unwraps `JSON.stringify(...)` passed as the `executeScript` `arg` option. Indirect forms (a stringified value held in a variable, etc.) cannot be rewritten automatically and are surfaced as an LLM-assisted review task with a migration prompt.
37
96
 
38
97
 
@@ -41,7 +100,7 @@
41
100
 
42
101
 
43
102
  - [#1509](https://github.com/tailor-platform/sdk/pull/1509) [`7cadaa7`](https://github.com/tailor-platform/sdk/commit/7cadaa7c4987b81130ca80ba80bc5d5b26276394) Thanks [@dqn](https://github.com/dqn)! - Rename resolver, executor, workflow trigger, and typed workflow start machine-user options from `authInvoker` to `invoker`.
44
-
103
+
45
104
  Update create-sdk templates and the v2 auth invoker codemod to generate the new `invoker` option.
46
105
 
47
106
 
@@ -62,7 +121,7 @@
62
121
 
63
122
 
64
123
  - [#1439](https://github.com/tailor-platform/sdk/pull/1439) [`c5b10d2`](https://github.com/tailor-platform/sdk/commit/c5b10d2841ded08927285bce538c05220cde5e4c) Thanks [@dqn](https://github.com/dqn)! - Unify function principal context around `TailorPrincipal`.
65
-
124
+
66
125
  Resolver contexts now use `caller` and `invoker` as `TailorPrincipal | null`, workflow and executor invokers also use `TailorPrincipal | null`, and event executor `actor` uses `TailorPrincipal | null` with `id`/`type` fields. The legacy `TailorUser`, `TailorInvoker`, `TailorActor`, `TailorActorType`, and `unauthenticatedTailorUser` exports are removed.
67
126
 
68
127
  ## 0.3.0-next.1
@@ -71,12 +130,12 @@
71
130
 
72
131
 
73
132
  - [#1460](https://github.com/tailor-platform/sdk/pull/1460) [`f49c6d1`](https://github.com/tailor-platform/sdk/commit/f49c6d1b5a856969cb4e04ae7d3a87ed34aa020f) Thanks [@dqn](https://github.com/dqn)! - Remove the v1 runtime globals compatibility layer. Importing from `@tailor-platform/sdk` no longer activates the ambient `tailor.*` / `tailordb.*` declarations; opt into globals with `@tailor-platform/sdk/runtime/globals` or use the typed wrappers from `@tailor-platform/sdk/runtime`.
74
-
133
+
75
134
  The capital-cased `Tailordb.*` namespace is removed. If your project still references `Tailordb.QueryResult`, `Tailordb.CommandType`, `Tailordb.Client`, or `typeof Tailordb.Client`, migrate before upgrading: run `pnpm dlx @tailor-platform/sdk-codemod v2/tailordb-namespace` to rewrite them to lowercase `tailordb.*`, then add `import "@tailor-platform/sdk/runtime/globals"` so the rewritten references resolve.
76
135
 
77
136
 
78
137
  - [#1457](https://github.com/tailor-platform/sdk/pull/1457) [`84325f8`](https://github.com/tailor-platform/sdk/commit/84325f8602a5631b7c323c997b1425235509920e) Thanks [@dqn](https://github.com/dqn)! - Remove deprecated CLI aliases for the v2 command surface. Use `tailor-sdk deploy` instead of `tailor-sdk apply`, `tailor-sdk crashreport` instead of `tailor-sdk crash-report`, and the hyphenated `--machine-user` option instead of the hidden `--machineuser` alias.
79
-
138
+
80
139
  Fix the v2 CLI rename codemod to migrate the hidden `--machineuser` option to `--machine-user`.
81
140
 
82
141
  ## 0.3.0-next.0
@@ -91,6 +150,54 @@
91
150
 
92
151
 
93
152
 
153
+ - [#1435](https://github.com/tailor-platform/sdk/pull/1435) [`49c0cc9`](https://github.com/tailor-platform/sdk/commit/49c0cc99171d7e317a50a18804a21067d89f9493) Thanks [@dqn](https://github.com/dqn)! - Add the `v2/plugin-cli-import` codemod so `tailor-sdk upgrade` rewrites deprecated plugin imports from `@tailor-platform/sdk/cli` (`kyselyTypePlugin`, `enumConstantsPlugin`, `fileUtilsPlugin`, `seedPlugin`) to their dedicated `@tailor-platform/sdk/plugin/*` subpaths, splitting any non-plugin specifiers onto a separate import.
154
+
155
+ ## 0.3.5
156
+
157
+ ### Patch Changes
158
+
159
+ - [#1659](https://github.com/tailor-platform/sdk/pull/1659) [`6ba468f`](https://github.com/tailor-platform/sdk/commit/6ba468f4654a723ab4db01d3f3474ae96c25cc71) Thanks [@renovate](https://github.com/apps/renovate)! - fix(deps): update dependency picomatch to v4.0.5
160
+
161
+ ## 0.3.4
162
+
163
+ ### Patch Changes
164
+
165
+ - [#1626](https://github.com/tailor-platform/sdk/pull/1626) [`06cc5f2`](https://github.com/tailor-platform/sdk/commit/06cc5f2960c5a09e9783d6b0923ed8c1b3d606a8) Thanks [@renovate](https://github.com/apps/renovate)! - fix(deps): update dependency politty to v0.11.0
166
+
167
+ ## 0.3.3
168
+ ### Patch Changes
169
+
170
+
171
+
172
+ - [#1598](https://github.com/tailor-platform/sdk/pull/1598) [`a5a4c58`](https://github.com/tailor-platform/sdk/commit/a5a4c58cabc24af3088d85c7a0d975d5be459def) Thanks [@renovate](https://github.com/apps/renovate)! - fix(deps): update dependency politty to v0.10.1
173
+
174
+ ## 0.3.2
175
+ ### Patch Changes
176
+
177
+
178
+
179
+ - [#1525](https://github.com/tailor-platform/sdk/pull/1525) [`425a19d`](https://github.com/tailor-platform/sdk/commit/425a19dd58da6e373b739d3b3e838c2ff3d1736a) Thanks [@renovate](https://github.com/apps/renovate)! - fix(deps): update dependency semver to v7.8.5
180
+
181
+
182
+
183
+ - [#1533](https://github.com/tailor-platform/sdk/pull/1533) [`e3bc2ce`](https://github.com/tailor-platform/sdk/commit/e3bc2ce65ab30ee53e5de0eb48ca6c24049fcd1b) Thanks [@renovate](https://github.com/apps/renovate)! - fix(deps): update dependency politty to v0.9.2
184
+
185
+
186
+
187
+ - [#1554](https://github.com/tailor-platform/sdk/pull/1554) [`a2ca1f9`](https://github.com/tailor-platform/sdk/commit/a2ca1f989a69153138ddef66931f1e8a94c8c3e9) Thanks [@renovate](https://github.com/apps/renovate)! - fix(deps): update dependency @ast-grep/napi to v0.44.0
188
+
189
+ ## 0.3.1
190
+ ### Patch Changes
191
+
192
+
193
+
194
+ - [#1428](https://github.com/tailor-platform/sdk/pull/1428) [`753ac38`](https://github.com/tailor-platform/sdk/commit/753ac3876319d007322c23a7052a2399d194fb72) Thanks [@renovate](https://github.com/apps/renovate)! - fix(deps): update dependency semver to v7.8.4
195
+
196
+ ## 0.3.0
197
+ ### Minor Changes
198
+
199
+
200
+
94
201
  - [#1435](https://github.com/tailor-platform/sdk/pull/1435) [`49c0cc9`](https://github.com/tailor-platform/sdk/commit/49c0cc99171d7e317a50a18804a21067d89f9493) Thanks [@dqn](https://github.com/dqn)! - Add the `v2/plugin-cli-import` codemod so `tailor-sdk upgrade` rewrites deprecated plugin imports from `@tailor-platform/sdk/cli` (`kyselyTypePlugin`, `enumConstantsPlugin`, `fileUtilsPlugin`, `seedPlugin`) to their dedicated `@tailor-platform/sdk/plugin/*` subpaths, splitting any non-plugin specifiers onto a separate import.
95
202
 
96
203
  ## 0.2.7
@@ -0,0 +1,171 @@
1
+ //#region src/ast-grep-helpers.ts
2
+ const DECLARATION_KINDS = [
3
+ "function_declaration",
4
+ "function_expression",
5
+ "class_declaration",
6
+ "class",
7
+ "enum_declaration",
8
+ "interface_declaration",
9
+ "type_alias_declaration",
10
+ "internal_module",
11
+ "import_alias"
12
+ ];
13
+ function isBindingLeafKind(kind) {
14
+ return kind === "identifier" || kind === "type_identifier" || kind === "shorthand_property_identifier_pattern";
15
+ }
16
+ function isBindingPatternKind(kind) {
17
+ return isBindingLeafKind(kind) || kind === "object_pattern" || kind === "array_pattern" || kind === "rest_pattern";
18
+ }
19
+ function stringValue(node) {
20
+ return node?.text().replace(/^['"]|['"]$/g, "") ?? null;
21
+ }
22
+ function importSource(importStmt) {
23
+ return stringValue(importStmt.find({ rule: { kind: "string" } }) ?? null);
24
+ }
25
+ function isTypeOnlyImport(importStmt) {
26
+ return importStmt.children().some((child) => child.kind() === "type");
27
+ }
28
+ function namedImportsNode(importStmt) {
29
+ return importStmt.find({ rule: { kind: "named_imports" } }) ?? null;
30
+ }
31
+ function importSpecNames(spec) {
32
+ const ids = spec.children().filter((child) => child.kind() === "identifier");
33
+ if (ids.length === 0) return null;
34
+ return {
35
+ importedName: ids[0].text(),
36
+ localName: ids[1]?.text() ?? ids[0].text(),
37
+ typeOnly: spec.children().some((child) => child.kind() === "type")
38
+ };
39
+ }
40
+ function findImportStatements(root) {
41
+ return root.findAll({ rule: { kind: "import_statement" } }).filter((stmt) => stmt.parent()?.kind() === "program").toSorted((a, b) => a.range().start.index - b.range().start.index);
42
+ }
43
+ function importBindings(importStmt) {
44
+ const source = importSource(importStmt);
45
+ if (!source) return [];
46
+ const requireClause = importStmt.children().find((child) => child.kind() === "import_require_clause");
47
+ if (requireClause) {
48
+ const local = requireClause.children().find((child) => child.kind() === "identifier");
49
+ return local ? [{
50
+ localName: local.text(),
51
+ source,
52
+ typeOnly: false
53
+ }] : [];
54
+ }
55
+ const typeOnly = isTypeOnlyImport(importStmt);
56
+ const clause = importStmt.children().find((child) => child.kind() === "import_clause");
57
+ if (!clause) return [];
58
+ const bindings = [];
59
+ for (const child of clause.children()) {
60
+ if (child.kind() === "identifier") {
61
+ bindings.push({
62
+ localName: child.text(),
63
+ source,
64
+ typeOnly
65
+ });
66
+ continue;
67
+ }
68
+ if (child.kind() === "namespace_import") {
69
+ const local = child.children().find((grandchild) => grandchild.kind() === "identifier");
70
+ if (local) bindings.push({
71
+ localName: local.text(),
72
+ source,
73
+ typeOnly
74
+ });
75
+ continue;
76
+ }
77
+ if (child.kind() !== "named_imports") continue;
78
+ for (const spec of child.findAll({ rule: { kind: "import_specifier" } })) {
79
+ const names = importSpecNames(spec);
80
+ if (!names) continue;
81
+ bindings.push({
82
+ ...names,
83
+ source,
84
+ typeOnly: typeOnly || names.typeOnly
85
+ });
86
+ }
87
+ }
88
+ return bindings;
89
+ }
90
+ function buildAddNamedImportEdit(options) {
91
+ const { importName, imports, insertionIndex, moduleName, root, source } = options;
92
+ const existingImport = imports.find((importStmt) => importSource(importStmt) === moduleName && !isTypeOnlyImport(importStmt) && namedImportsNode(importStmt)) ?? null;
93
+ const namedImports = existingImport ? namedImportsNode(existingImport) : null;
94
+ if (namedImports) {
95
+ const specTexts = namedImports.findAll({ rule: { kind: "import_specifier" } }).map((spec) => {
96
+ const names = importSpecNames(spec);
97
+ return names?.importedName === importName && names.localName === importName ? importName : spec.text();
98
+ });
99
+ const nextSpecTexts = specTexts.includes(importName) ? specTexts : [...specTexts, importName];
100
+ return namedImports.replace(`{ ${nextSpecTexts.join(", ")} }`);
101
+ }
102
+ const pos = insertionIndex(root, imports, source);
103
+ return {
104
+ startPos: pos,
105
+ endPos: pos,
106
+ insertedText: pos === 0 || source[pos - 1] === "\n" ? `import { ${importName} } from "${moduleName}";\n\n` : `\nimport { ${importName} } from "${moduleName}";`
107
+ };
108
+ }
109
+ function collectBindingNames(node, names) {
110
+ if (isBindingLeafKind(node.kind())) {
111
+ names.add(node.text());
112
+ return;
113
+ }
114
+ for (const child of node.children()) {
115
+ if (child.kind() === "property_identifier") continue;
116
+ if (child.kind() === "=") break;
117
+ collectBindingNames(child, names);
118
+ }
119
+ }
120
+ function firstDeclaratorChild(node) {
121
+ return node.children().find((child) => child.kind() !== "=") ?? null;
122
+ }
123
+ function collectDirectBindingChildren(node, names) {
124
+ for (const child of node.children()) {
125
+ if (child.kind() === "=") break;
126
+ if (isBindingPatternKind(child.kind())) collectBindingNames(child, names);
127
+ }
128
+ }
129
+ function collectParameters(root, names) {
130
+ for (const param of root.findAll({ rule: { any: [{ kind: "required_parameter" }, { kind: "optional_parameter" }] } })) collectDirectBindingChildren(param, names);
131
+ }
132
+ function collectDeclarationNames(root, names) {
133
+ for (const decl of root.findAll({ rule: { any: DECLARATION_KINDS.map((kind) => ({ kind })) } })) {
134
+ const name = decl.children().find((child) => child.kind() === "identifier" || child.kind() === "type_identifier");
135
+ if (name) names.add(name.text());
136
+ }
137
+ }
138
+ function collectArrowParameters(root, names) {
139
+ for (const arrow of root.findAll({ rule: { kind: "arrow_function" } })) {
140
+ const children = arrow.children();
141
+ const arrowIndex = children.findIndex((child) => child.kind() === "=>");
142
+ if (arrowIndex === -1) continue;
143
+ for (const child of children.slice(0, arrowIndex)) {
144
+ if (child.kind() === "=") break;
145
+ if (isBindingPatternKind(child.kind())) collectBindingNames(child, names);
146
+ }
147
+ }
148
+ }
149
+ function collectForInBindings(root, names) {
150
+ for (const loop of root.findAll({ rule: { kind: "for_in_statement" } })) {
151
+ const children = loop.children();
152
+ const keywordIndex = children.findIndex((child) => child.kind() === "in" || child.kind() === "of");
153
+ if (keywordIndex === -1) continue;
154
+ for (const child of children.slice(0, keywordIndex)) collectBindingNames(child, names);
155
+ }
156
+ }
157
+ function localDeclarationNames(root) {
158
+ const names = /* @__PURE__ */ new Set();
159
+ for (const decl of root.findAll({ rule: { kind: "variable_declarator" } })) {
160
+ const binding = firstDeclaratorChild(decl);
161
+ if (binding) collectBindingNames(binding, names);
162
+ }
163
+ collectParameters(root, names);
164
+ collectDeclarationNames(root, names);
165
+ for (const catchClause of root.findAll({ rule: { kind: "catch_clause" } })) collectDirectBindingChildren(catchClause, names);
166
+ collectArrowParameters(root, names);
167
+ collectForInBindings(root, names);
168
+ return names;
169
+ }
170
+ //#endregion
171
+ export { importSpecNames as a, importSource as i, findImportStatements as n, isTypeOnlyImport as o, importBindings as r, localDeclarationNames as s, buildAddNamedImportEdit as t };
@@ -3,7 +3,7 @@ import * as path from "pathe";
3
3
  const ARG_VALUE = `(?:[^\\s'"\`;&|]+|'[^']*'|"(?:(?:\\\\.)|[^"\\\\])*")`;
4
4
  const GLOBAL_ARG_PATTERN = `(?:(?:\\s+(?:--verbose|--json|-j))|(?:\\s+(?:--env-file|--env-file-if-exists|-e)(?:=${ARG_VALUE}|\\s+${ARG_VALUE})))*`;
5
5
  const APPLY_PATTERN = new RegExp(`(?<![\\w-])tailor-sdk(?:@[^\\s'"\`]+)?(?![\\w-])(${GLOBAL_ARG_PATTERN}\\s+)apply(?![-\\w])`, "g");
6
- const SOURCE_EXTENSIONS = new Set([
6
+ const SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
7
7
  ".ts",
8
8
  ".tsx",
9
9
  ".mts",
@@ -0,0 +1,213 @@
1
+ import { Lang, parse } from "@ast-grep/napi";
2
+ //#region codemods/v2/auth-attributes-rename/scripts/transform.ts
3
+ const SDK_MODULE = "@tailor-platform/sdk";
4
+ const TYPE_RENAME_MAP = {
5
+ AttributeMap: "Attributes",
6
+ UserAttributeMap: "UserAttributes",
7
+ InferredAttributeMap: "InferredAttributes"
8
+ };
9
+ function quickFilter(source) {
10
+ return source.includes(SDK_MODULE) && Object.keys(TYPE_RENAME_MAP).some((name) => source.includes(name));
11
+ }
12
+ function isSdkModuleLiteral(node) {
13
+ return node.kind() === "string" && /^["']@tailor-platform\/sdk["']$/.test(node.text());
14
+ }
15
+ function hasSdkModuleLiteral(node) {
16
+ return node.findAll({ rule: { kind: "string" } }).some(isSdkModuleLiteral);
17
+ }
18
+ function moduleSpecifierLiteral(node) {
19
+ const directLiteral = node.children().find((child) => child.kind() === "string");
20
+ if (directLiteral) return directLiteral;
21
+ return node.children().find((child) => child.kind() === "module")?.children().find((child) => child.kind() === "string");
22
+ }
23
+ function hasSdkModuleSpecifier(node) {
24
+ const literal = moduleSpecifierLiteral(node);
25
+ return literal ? isSdkModuleLiteral(literal) : false;
26
+ }
27
+ function identifierChildren(node) {
28
+ return node.children().filter((child) => child.kind() === "identifier");
29
+ }
30
+ function typeIdentifierChildren(node) {
31
+ return node.children().filter((child) => child.kind() === "type_identifier");
32
+ }
33
+ function sameRange(a, b) {
34
+ const ar = a.range();
35
+ const br = b.range();
36
+ return ar.start.index === br.start.index && ar.end.index === br.end.index;
37
+ }
38
+ function addReplacement(edits, editedRanges, node, replacement) {
39
+ if (node.text() === replacement) return;
40
+ const r = node.range();
41
+ const key = `${r.start.index}:${r.end.index}`;
42
+ if (editedRanges.has(key)) return;
43
+ editedRanges.add(key);
44
+ edits.push(node.replace(replacement));
45
+ }
46
+ function renamedType(name) {
47
+ return TYPE_RENAME_MAP[name];
48
+ }
49
+ function isDeclarationName(node) {
50
+ const parent = node.parent();
51
+ if (!parent || ![
52
+ "class_declaration",
53
+ "enum_declaration",
54
+ "interface_declaration",
55
+ "type_alias_declaration",
56
+ "type_parameter"
57
+ ].includes(parent.kind())) return false;
58
+ const name = parent?.field("name");
59
+ return !!name && sameRange(name, node);
60
+ }
61
+ function isNestedTypeName(node) {
62
+ return node.parent()?.kind() === "nested_type_identifier";
63
+ }
64
+ function declarationName(node) {
65
+ if ([
66
+ "class_declaration",
67
+ "enum_declaration",
68
+ "interface_declaration",
69
+ "type_alias_declaration"
70
+ ].includes(node.kind())) return node.field("name") ?? void 0;
71
+ if (node.kind() !== "export_statement") return void 0;
72
+ return node.children().find((child) => [
73
+ "class_declaration",
74
+ "enum_declaration",
75
+ "interface_declaration",
76
+ "type_alias_declaration"
77
+ ].includes(child.kind()))?.field("name") ?? void 0;
78
+ }
79
+ function scopeDeclaresType(scope, name, reference) {
80
+ return scope.children().some((child) => {
81
+ const declaredName = declarationName(child);
82
+ return !!declaredName && declaredName.text() === name && !sameRange(declaredName, reference);
83
+ });
84
+ }
85
+ function hasTypeParameterShadow(node, name) {
86
+ return node.findAll({ rule: { kind: "type_parameter" } }).some((parameter) => typeIdentifierChildren(parameter)[0]?.text() === name);
87
+ }
88
+ function isShadowedTypeReference(node, name) {
89
+ let current = node.parent();
90
+ while (current) {
91
+ if (current.kind() === "statement_block" && scopeDeclaresType(current, name, node)) return true;
92
+ if ([
93
+ "class_declaration",
94
+ "function_declaration",
95
+ "interface_declaration",
96
+ "method_definition",
97
+ "type_alias_declaration"
98
+ ].includes(current.kind()) && hasTypeParameterShadow(current, name)) return true;
99
+ current = current.parent();
100
+ }
101
+ return false;
102
+ }
103
+ function collectSdkImports(root, edits, editedRanges) {
104
+ const localTypeRenames = /* @__PURE__ */ new Map();
105
+ const namespaceNames = /* @__PURE__ */ new Set();
106
+ const importStmts = root.findAll({ rule: { kind: "import_statement" } });
107
+ for (const importStmt of importStmts) {
108
+ if (!hasSdkModuleSpecifier(importStmt)) continue;
109
+ const namespaceImports = importStmt.findAll({ rule: { kind: "namespace_import" } });
110
+ for (const namespaceImport of namespaceImports) {
111
+ const localName = identifierChildren(namespaceImport).at(-1)?.text();
112
+ if (localName) namespaceNames.add(localName);
113
+ }
114
+ const specs = importStmt.findAll({ rule: { kind: "import_specifier" } });
115
+ for (const spec of specs) {
116
+ const identifiers = identifierChildren(spec);
117
+ const imported = identifiers[0];
118
+ if (!imported) continue;
119
+ const replacement = renamedType(imported.text());
120
+ if (!replacement) continue;
121
+ addReplacement(edits, editedRanges, imported, replacement);
122
+ if (identifiers.length === 1) localTypeRenames.set(imported.text(), replacement);
123
+ }
124
+ }
125
+ return {
126
+ localTypeRenames,
127
+ namespaceNames
128
+ };
129
+ }
130
+ function rewriteSdkExports(root, edits, editedRanges) {
131
+ const exportStmts = root.findAll({ rule: { kind: "export_statement" } });
132
+ for (const exportStmt of exportStmts) {
133
+ if (!hasSdkModuleSpecifier(exportStmt)) continue;
134
+ const specs = exportStmt.findAll({ rule: { kind: "export_specifier" } });
135
+ for (const spec of specs) {
136
+ const exported = identifierChildren(spec)[0];
137
+ if (!exported) continue;
138
+ const replacement = renamedType(exported.text());
139
+ if (replacement) addReplacement(edits, editedRanges, exported, replacement);
140
+ }
141
+ }
142
+ }
143
+ function rewriteModuleAugmentations(root, edits, editedRanges) {
144
+ const declarations = root.findAll({ rule: { kind: "ambient_declaration" } });
145
+ for (const declaration of declarations) {
146
+ if (!hasSdkModuleSpecifier(declaration)) continue;
147
+ const interfaces = declaration.findAll({ rule: { kind: "interface_declaration" } });
148
+ for (const iface of interfaces) {
149
+ const name = typeIdentifierChildren(iface)[0];
150
+ if (name?.text() === "AttributeMap") addReplacement(edits, editedRanges, name, "Attributes");
151
+ }
152
+ }
153
+ }
154
+ function rewriteLocalTypeReferences(root, edits, editedRanges, localTypeRenames) {
155
+ if (localTypeRenames.size === 0) return;
156
+ const typeIdentifiers = root.findAll({ rule: { kind: "type_identifier" } });
157
+ for (const typeIdentifier of typeIdentifiers) {
158
+ if (isDeclarationName(typeIdentifier) || isNestedTypeName(typeIdentifier)) continue;
159
+ const replacement = localTypeRenames.get(typeIdentifier.text());
160
+ if (replacement && isShadowedTypeReference(typeIdentifier, typeIdentifier.text())) continue;
161
+ if (replacement) addReplacement(edits, editedRanges, typeIdentifier, replacement);
162
+ }
163
+ }
164
+ function rewriteNamespaceTypeReferences(root, edits, editedRanges, namespaceNames) {
165
+ if (namespaceNames.size === 0) return;
166
+ const nestedTypes = root.findAll({ rule: { kind: "nested_type_identifier" } });
167
+ for (const nestedType of nestedTypes) {
168
+ const namespaceName = identifierChildren(nestedType)[0]?.text();
169
+ if (!namespaceName || !namespaceNames.has(namespaceName)) continue;
170
+ const typeName = typeIdentifierChildren(nestedType).at(-1);
171
+ if (!typeName) continue;
172
+ const replacement = renamedType(typeName.text());
173
+ if (replacement) addReplacement(edits, editedRanges, typeName, replacement);
174
+ }
175
+ }
176
+ function isSdkImportCall(node) {
177
+ return node.kind() === "call_expression" && hasSdkModuleLiteral(node);
178
+ }
179
+ function rewriteImportTypeReferences(root, edits, editedRanges) {
180
+ const members = root.findAll({ rule: { kind: "member_expression" } });
181
+ for (const member of members) {
182
+ const object = member.field("object");
183
+ if (!object || !isSdkImportCall(object)) continue;
184
+ const property = member.field("property");
185
+ if (!property || property.kind() !== "property_identifier") continue;
186
+ const replacement = renamedType(property.text());
187
+ if (replacement) addReplacement(edits, editedRanges, property, replacement);
188
+ }
189
+ }
190
+ /**
191
+ * Rename the v1 auth attribute type API to its v2 names only when a reference
192
+ * can be tied to `@tailor-platform/sdk`.
193
+ * @param source - File contents
194
+ * @param _filePath - Absolute path to the file (kept for the runner signature)
195
+ * @returns Transformed source or null when nothing matched.
196
+ */
197
+ function transform(source, _filePath) {
198
+ if (!quickFilter(source)) return null;
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();
201
+ const edits = [];
202
+ const editedRanges = /* @__PURE__ */ new Set();
203
+ const { localTypeRenames, namespaceNames } = collectSdkImports(root, edits, editedRanges);
204
+ rewriteSdkExports(root, edits, editedRanges);
205
+ rewriteModuleAugmentations(root, edits, editedRanges);
206
+ rewriteLocalTypeReferences(root, edits, editedRanges, localTypeRenames);
207
+ rewriteNamespaceTypeReferences(root, edits, editedRanges, namespaceNames);
208
+ rewriteImportTypeReferences(root, edits, editedRanges);
209
+ if (edits.length === 0) return null;
210
+ return root.commitEdits(edits);
211
+ }
212
+ //#endregion
213
+ export { transform as default };