assistant-ui 0.0.120 → 0.0.122

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 (133) hide show
  1. package/README.md +60 -1
  2. package/dist/commands/add.d.ts.map +1 -1
  3. package/dist/commands/add.js +1 -2
  4. package/dist/commands/add.js.map +1 -1
  5. package/dist/commands/cloud.d.ts +25 -0
  6. package/dist/commands/cloud.d.ts.map +1 -0
  7. package/dist/commands/cloud.js +194 -0
  8. package/dist/commands/cloud.js.map +1 -0
  9. package/dist/commands/create.d.ts.map +1 -1
  10. package/dist/commands/create.js +10 -2
  11. package/dist/commands/create.js.map +1 -1
  12. package/dist/commands/info.js +2 -2
  13. package/dist/commands/init.d.ts.map +1 -1
  14. package/dist/commands/init.js +1 -2
  15. package/dist/commands/init.js.map +1 -1
  16. package/dist/commands/mcp.d.ts.map +1 -1
  17. package/dist/commands/mcp.js +95 -23
  18. package/dist/commands/mcp.js.map +1 -1
  19. package/dist/lib/agent-skill.d.ts +2 -2
  20. package/dist/lib/agent-skill.d.ts.map +1 -1
  21. package/dist/lib/agent-skill.js +10 -28
  22. package/dist/lib/agent-skill.js.map +1 -1
  23. package/dist/lib/cloud-abort.d.ts +2 -0
  24. package/dist/lib/cloud-abort.d.ts.map +1 -0
  25. package/dist/lib/cloud-abort.js +13 -0
  26. package/dist/lib/cloud-abort.js.map +1 -0
  27. package/dist/lib/cloud-auth.d.ts +28 -0
  28. package/dist/lib/cloud-auth.d.ts.map +1 -0
  29. package/dist/lib/cloud-auth.js +169 -0
  30. package/dist/lib/cloud-auth.js.map +1 -0
  31. package/dist/lib/cloud-config.d.ts +21 -0
  32. package/dist/lib/cloud-config.d.ts.map +1 -0
  33. package/dist/lib/cloud-config.js +76 -0
  34. package/dist/lib/cloud-config.js.map +1 -0
  35. package/dist/lib/cloud-provision.d.ts +20 -0
  36. package/dist/lib/cloud-provision.d.ts.map +1 -0
  37. package/dist/lib/cloud-provision.js +55 -0
  38. package/dist/lib/cloud-provision.js.map +1 -0
  39. package/dist/lib/cloud-setup-login.d.ts +9 -0
  40. package/dist/lib/cloud-setup-login.d.ts.map +1 -0
  41. package/dist/lib/cloud-setup-login.js +137 -0
  42. package/dist/lib/cloud-setup-login.js.map +1 -0
  43. package/dist/lib/cloud-url.d.ts +2 -0
  44. package/dist/lib/cloud-url.d.ts.map +1 -0
  45. package/dist/lib/cloud-url.js +14 -0
  46. package/dist/lib/cloud-url.js.map +1 -0
  47. package/dist/lib/create-project.d.ts +0 -9
  48. package/dist/lib/create-project.d.ts.map +1 -1
  49. package/dist/lib/create-project.js +15 -46
  50. package/dist/lib/create-project.js.map +1 -1
  51. package/dist/lib/transform.d.ts +0 -4
  52. package/dist/lib/transform.d.ts.map +1 -1
  53. package/dist/lib/transform.js +8 -17
  54. package/dist/lib/transform.js.map +1 -1
  55. package/dist/lib/utils/download.d.ts +5 -0
  56. package/dist/lib/utils/download.d.ts.map +1 -0
  57. package/dist/lib/utils/download.js +41 -0
  58. package/dist/lib/utils/download.js.map +1 -0
  59. package/dist/lib/utils/file-scanner.d.ts +0 -1
  60. package/dist/lib/utils/file-scanner.d.ts.map +1 -1
  61. package/dist/lib/utils/file-scanner.js +1 -16
  62. package/dist/lib/utils/file-scanner.js.map +1 -1
  63. package/dist/lib/utils/package-manager.d.ts +7 -0
  64. package/dist/lib/utils/package-manager.d.ts.map +1 -1
  65. package/dist/lib/utils/package-manager.js +15 -1
  66. package/dist/lib/utils/package-manager.js.map +1 -1
  67. package/dist/program.d.ts.map +1 -1
  68. package/dist/program.js +2 -1
  69. package/dist/program.js.map +1 -1
  70. package/package.json +12 -8
  71. package/src/commands/add.ts +2 -1
  72. package/src/commands/cloud.test.ts +238 -0
  73. package/src/commands/cloud.ts +455 -0
  74. package/src/commands/create.ts +13 -3
  75. package/src/commands/init.ts +5 -2
  76. package/src/commands/mcp.ts +223 -56
  77. package/src/lib/agent-skill.ts +18 -44
  78. package/src/lib/cloud-abort.ts +12 -0
  79. package/src/lib/cloud-auth.test.ts +500 -0
  80. package/src/lib/cloud-auth.ts +273 -0
  81. package/src/lib/cloud-config.test.ts +82 -0
  82. package/src/lib/cloud-config.ts +138 -0
  83. package/src/lib/cloud-provision.test.ts +132 -0
  84. package/src/lib/cloud-provision.ts +93 -0
  85. package/src/lib/cloud-setup-login.test.ts +361 -0
  86. package/src/lib/cloud-setup-login.ts +240 -0
  87. package/src/lib/cloud-url.ts +19 -0
  88. package/src/lib/create-project.test.ts +0 -17
  89. package/src/lib/create-project.ts +33 -98
  90. package/src/lib/transform-files.test.ts +1 -3
  91. package/src/lib/transform.ts +6 -20
  92. package/src/lib/utils/download.ts +57 -0
  93. package/src/lib/utils/file-scanner.ts +0 -26
  94. package/src/lib/utils/package-manager.ts +26 -0
  95. package/src/lib/utils/registry.test.ts +0 -6
  96. package/src/program.ts +2 -0
  97. package/templates/cloud-harness/.assistant-ui/template.json +3 -0
  98. package/templates/cloud-harness/.env.example +1 -0
  99. package/templates/cloud-harness/.gitignore +42 -0
  100. package/templates/cloud-harness/README.md +28 -0
  101. package/templates/cloud-harness/app/api/chat/route.ts +14 -0
  102. package/templates/cloud-harness/app/api/credential/route.ts +14 -0
  103. package/templates/cloud-harness/app/assistant.tsx +83 -0
  104. package/templates/cloud-harness/app/favicon.ico +0 -0
  105. package/templates/cloud-harness/app/globals.css +139 -0
  106. package/templates/cloud-harness/app/layout.tsx +37 -0
  107. package/templates/cloud-harness/app/page.tsx +5 -0
  108. package/templates/cloud-harness/components/assistant-ui/elements/attachment.aui.tsx +279 -0
  109. package/templates/cloud-harness/components/assistant-ui/elements/collapsible-root.tsx +19 -0
  110. package/templates/cloud-harness/components/assistant-ui/elements/markdown-text.tsx +238 -0
  111. package/templates/cloud-harness/components/assistant-ui/elements/thread.aui.tsx +521 -0
  112. package/templates/cloud-harness/components/assistant-ui/elements/tool-fallback.aui.tsx +1321 -0
  113. package/templates/cloud-harness/components/assistant-ui/elements/tooltip-icon-button.tsx +49 -0
  114. package/templates/cloud-harness/components/ui/avatar.tsx +109 -0
  115. package/templates/cloud-harness/components/ui/button.tsx +58 -0
  116. package/templates/cloud-harness/components/ui/collapsible.tsx +21 -0
  117. package/templates/cloud-harness/components/ui/dialog.tsx +159 -0
  118. package/templates/cloud-harness/components/ui/textarea.tsx +18 -0
  119. package/templates/cloud-harness/components/ui/tooltip.tsx +69 -0
  120. package/templates/cloud-harness/components.json +24 -0
  121. package/templates/cloud-harness/hooks/use-attachment-src.ts +46 -0
  122. package/templates/cloud-harness/hooks/use-copy-to-clipboard.ts +54 -0
  123. package/templates/cloud-harness/lib/utils.ts +1 -0
  124. package/templates/cloud-harness/next.config.ts +6 -0
  125. package/templates/cloud-harness/package.json +51 -0
  126. package/templates/cloud-harness/postcss.config.mjs +5 -0
  127. package/templates/cloud-harness/tsconfig.json +33 -0
  128. package/templates/cloud-harness/vendor/README.md +13 -0
  129. package/templates/cloud-harness/vendor/assistant-ui-react-harness-sdk-0.0.2.tgz +0 -0
  130. package/templates/cloud-harness/vendor/harness-sdk-0.3.1.tgz +0 -0
  131. package/templates/cloud-harness/vendor/provenance.json +38 -0
  132. package/templates/cloud-harness/vendor/statewire-0.19.3.tgz +0 -0
  133. /package/{LICENSE → templates/cloud-harness/vendor/LICENSE} +0 -0
@@ -0,0 +1,137 @@
1
+ import { abortable } from "./cloud-abort.js";
2
+ import { validateCloudUrl } from "./cloud-url.js";
3
+ import { randomUUID } from "node:crypto";
4
+ import { StatewireClient, StatewireHttp } from "statewire";
5
+ //#region src/lib/cloud-setup-login.ts
6
+ const validInputs = (inputs) => Array.isArray(inputs) && inputs.every((input) => input !== null && typeof input === "object" && typeof input.id === "string" && typeof input.status === "string");
7
+ const setupLoginUrl = (authorization, issuer, attempt = randomUUID()) => {
8
+ const url = new URL(authorization.verificationUriComplete);
9
+ const issuerOrigin = new URL(issuer).origin;
10
+ if (!["https://accounts.assistant-ui.com", "https://accounts.aui.dev"].includes(issuerOrigin) || url.origin !== issuerOrigin || !/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(attempt) || !/^[A-Z0-9-]{4,32}$/.test(authorization.userCode) || url.pathname !== "/device" || url.username || url.password || url.hash || url.searchParams.get("user_code") !== authorization.userCode || url.searchParams.getAll("user_code").length !== 1 || !Number.isFinite(authorization.expiresAt) || authorization.expiresAt <= Date.now() || authorization.expiresAt > Date.now() + 6e5) throw new Error("Accounts returned an invalid device approval link.");
11
+ const publicUrl = new URL("/device", url.origin);
12
+ publicUrl.searchParams.set("user_code", authorization.userCode);
13
+ publicUrl.searchParams.set("setup_attempt", attempt);
14
+ publicUrl.searchParams.set("setup_expires", String(authorization.expiresAt));
15
+ return publicUrl.href;
16
+ };
17
+ const connectCloudLoginSetup = async (url) => {
18
+ const target = validateCloudUrl(url);
19
+ const controller = new AbortController();
20
+ const client = new StatewireClient({
21
+ transport: StatewireHttp({ url: target }),
22
+ onError: (error) => controller.abort(error)
23
+ });
24
+ let unsubscribe = () => {};
25
+ let inputId;
26
+ let sessionId;
27
+ let pendingHref;
28
+ let pendingAsk;
29
+ let terminalResult;
30
+ let completion;
31
+ let disposed = false;
32
+ const reconcile = () => {
33
+ const state = client.state;
34
+ if (state && !validInputs(state.inputs)) {
35
+ controller.abort(/* @__PURE__ */ new Error("The setup returned invalid inputs."));
36
+ return Promise.resolve();
37
+ }
38
+ if (disposed || inputId === void 0 || terminalResult === void 0 || state?.id !== sessionId || !Array.isArray(state.inputs) || !["planning", "installing"].includes(state.status) || ["dismissed", "answered"].includes(state.inputs.find((input) => input.id === inputId)?.status ?? "")) return Promise.resolve();
39
+ completion ??= abortable(client.commands["checkout/answer"]({
40
+ inputId,
41
+ answer: terminalResult
42
+ }), AbortSignal.timeout(1e4));
43
+ return completion;
44
+ };
45
+ const checkSession = () => {
46
+ const next = client.state;
47
+ if (next && !validInputs(next.inputs)) {
48
+ controller.abort(/* @__PURE__ */ new Error("The setup returned invalid inputs."));
49
+ return;
50
+ }
51
+ if (next?.id === sessionId && Array.isArray(next.inputs) && pendingHref) inputId ??= next.inputs.find((input) => input.preset === "assistant-ui-cli-login" && input.help?.href === pendingHref)?.id;
52
+ if (next?.version !== 2 || next.id !== sessionId || !Array.isArray(next.inputs) || !["planning", "installing"].includes(next.status) || inputId !== void 0 && next.inputs.find((input) => input.id === inputId)?.status === "dismissed") controller.abort(/* @__PURE__ */ new Error("The setup login was cancelled."));
53
+ if (client.connection.status === "stopped") controller.abort(/* @__PURE__ */ new Error("The setup connection stopped."));
54
+ reconcile().catch(() => {});
55
+ };
56
+ const dispose = async () => {
57
+ try {
58
+ if (pendingAsk && terminalResult) {
59
+ await abortable(pendingAsk, AbortSignal.timeout(1e4)).catch(() => {});
60
+ await reconcile().catch(() => {});
61
+ }
62
+ } finally {
63
+ disposed = true;
64
+ unsubscribe();
65
+ client.dispose();
66
+ }
67
+ };
68
+ try {
69
+ let resolveReady;
70
+ const ready = new Promise((resolve) => {
71
+ resolveReady = resolve;
72
+ });
73
+ unsubscribe = client.subscribe(() => {
74
+ if (client.state !== void 0) resolveReady();
75
+ if (client.connection.status === "stopped") controller.abort(/* @__PURE__ */ new Error("The setup connection stopped."));
76
+ });
77
+ if (client.state !== void 0) resolveReady();
78
+ if (client.connection.status === "stopped") controller.abort(/* @__PURE__ */ new Error("The setup connection stopped."));
79
+ await abortable(ready, AbortSignal.any([controller.signal, AbortSignal.timeout(1e4)]));
80
+ const state = client.state;
81
+ if (state?.version !== 2 || !state.id || !validInputs(state.inputs) || !["planning", "installing"].includes(state.status)) throw new Error("Start the setup in the wizard before signing in the CLI.");
82
+ sessionId = state.id;
83
+ unsubscribe();
84
+ unsubscribe = client.subscribe(checkSession);
85
+ checkSession();
86
+ } catch (error) {
87
+ await dispose();
88
+ throw error;
89
+ }
90
+ const command = (run) => {
91
+ controller.signal.throwIfAborted();
92
+ return abortable(run(), AbortSignal.any([controller.signal, AbortSignal.timeout(1e4)]));
93
+ };
94
+ return {
95
+ signal: controller.signal,
96
+ async publish(authorization, issuer) {
97
+ controller.signal.throwIfAborted();
98
+ const href = setupLoginUrl(authorization, issuer);
99
+ pendingHref = href;
100
+ pendingAsk = client.commands["agent/ask"]({
101
+ kind: "text",
102
+ preset: "assistant-ui-cli-login",
103
+ prompt: "Sign in to Assistant Cloud",
104
+ help: {
105
+ summary: "Authorize the CLI in your browser, then return to this setup.",
106
+ href
107
+ }
108
+ }).then(async (result) => {
109
+ if (!disposed && client.state?.id === sessionId) {
110
+ inputId = result.inputId;
111
+ checkSession();
112
+ await reconcile().catch(() => {});
113
+ }
114
+ return result;
115
+ });
116
+ try {
117
+ await command(() => pendingAsk);
118
+ checkSession();
119
+ controller.signal.throwIfAborted();
120
+ } catch (error) {
121
+ terminalResult = controller.signal.aborted ? "cancelled" : "failed";
122
+ await reconcile().catch(() => {});
123
+ throw error;
124
+ }
125
+ return href;
126
+ },
127
+ async complete(result) {
128
+ terminalResult = result;
129
+ await reconcile();
130
+ },
131
+ dispose
132
+ };
133
+ };
134
+ //#endregion
135
+ export { connectCloudLoginSetup, setupLoginUrl };
136
+
137
+ //# sourceMappingURL=cloud-setup-login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud-setup-login.js","names":[],"sources":["../../src/lib/cloud-setup-login.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport type { DeviceAuthorization } from \"aui-auth/device\";\nimport { StatewireClient, StatewireHttp } from \"statewire\";\nimport { abortable } from \"./cloud-abort\";\nimport { validateCloudUrl } from \"./cloud-url\";\n\ntype SetupState = {\n version: number;\n id: string | null;\n status: string;\n inputs: {\n id: string;\n status: string;\n preset?: string;\n help?: { href?: string };\n }[];\n};\n\ntype SetupCommands = {\n \"agent/ask\": (input: {\n kind: \"text\";\n preset: string;\n prompt: string;\n help: { summary: string; href: string };\n }) => { inputId: string };\n \"checkout/answer\": (answer: { inputId: string; answer: string }) => void;\n};\n\nconst validInputs = (inputs: unknown): inputs is SetupState[\"inputs\"] =>\n Array.isArray(inputs) &&\n inputs.every(\n (input) =>\n input !== null &&\n typeof input === \"object\" &&\n typeof input.id === \"string\" &&\n typeof input.status === \"string\",\n );\n\nexport const setupLoginUrl = (\n authorization: DeviceAuthorization,\n issuer: string,\n attempt: string = randomUUID(),\n) => {\n const url = new URL(authorization.verificationUriComplete);\n const issuerOrigin = new URL(issuer).origin;\n if (\n ![\"https://accounts.assistant-ui.com\", \"https://accounts.aui.dev\"].includes(\n issuerOrigin,\n ) ||\n url.origin !== issuerOrigin ||\n !/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(\n attempt,\n ) ||\n !/^[A-Z0-9-]{4,32}$/.test(authorization.userCode) ||\n url.pathname !== \"/device\" ||\n url.username ||\n url.password ||\n url.hash ||\n url.searchParams.get(\"user_code\") !== authorization.userCode ||\n url.searchParams.getAll(\"user_code\").length !== 1 ||\n !Number.isFinite(authorization.expiresAt) ||\n authorization.expiresAt <= Date.now() ||\n authorization.expiresAt > Date.now() + 10 * 60 * 1000\n ) {\n throw new Error(\"Accounts returned an invalid device approval link.\");\n }\n const publicUrl = new URL(\"/device\", url.origin);\n publicUrl.searchParams.set(\"user_code\", authorization.userCode);\n publicUrl.searchParams.set(\"setup_attempt\", attempt);\n publicUrl.searchParams.set(\"setup_expires\", String(authorization.expiresAt));\n return publicUrl.href;\n};\n\nexport const connectCloudLoginSetup = async (url: string) => {\n const target = validateCloudUrl(url);\n const controller = new AbortController();\n const client = new StatewireClient<SetupState | undefined, SetupCommands>({\n transport: StatewireHttp({ url: target }),\n onError: (error) => controller.abort(error),\n });\n let unsubscribe = () => {};\n let inputId: string | undefined;\n let sessionId: string;\n let pendingHref: string | undefined;\n let pendingAsk: Promise<{ inputId: string }> | undefined;\n let terminalResult: \"signed-in\" | \"cancelled\" | \"failed\" | undefined;\n let completion: Promise<void> | undefined;\n let disposed = false;\n const reconcile = () => {\n const state = client.state;\n if (state && !validInputs(state.inputs)) {\n controller.abort(new Error(\"The setup returned invalid inputs.\"));\n return Promise.resolve();\n }\n if (\n disposed ||\n inputId === undefined ||\n terminalResult === undefined ||\n state?.id !== sessionId ||\n !Array.isArray(state.inputs) ||\n ![\"planning\", \"installing\"].includes(state.status) ||\n [\"dismissed\", \"answered\"].includes(\n state.inputs.find((input) => input.id === inputId)?.status ?? \"\",\n )\n )\n return Promise.resolve();\n completion ??= abortable(\n client.commands[\"checkout/answer\"]({ inputId, answer: terminalResult }),\n AbortSignal.timeout(10_000),\n );\n return completion;\n };\n const checkSession = () => {\n const next = client.state;\n if (next && !validInputs(next.inputs)) {\n controller.abort(new Error(\"The setup returned invalid inputs.\"));\n return;\n }\n if (next?.id === sessionId && Array.isArray(next.inputs) && pendingHref) {\n inputId ??= next.inputs.find(\n (input) =>\n input.preset === \"assistant-ui-cli-login\" &&\n input.help?.href === pendingHref,\n )?.id;\n }\n if (\n next?.version !== 2 ||\n next.id !== sessionId ||\n !Array.isArray(next.inputs) ||\n ![\"planning\", \"installing\"].includes(next.status) ||\n (inputId !== undefined &&\n next.inputs.find((input) => input.id === inputId)?.status ===\n \"dismissed\")\n ) {\n controller.abort(new Error(\"The setup login was cancelled.\"));\n }\n if (client.connection.status === \"stopped\")\n controller.abort(new Error(\"The setup connection stopped.\"));\n void reconcile().catch(() => {});\n };\n const dispose = async () => {\n try {\n if (pendingAsk && terminalResult) {\n await abortable(pendingAsk, AbortSignal.timeout(10_000)).catch(\n () => {},\n );\n await reconcile().catch(() => {});\n }\n } finally {\n disposed = true;\n unsubscribe();\n client.dispose();\n }\n };\n try {\n let resolveReady!: () => void;\n const ready = new Promise<void>((resolve) => {\n resolveReady = resolve;\n });\n unsubscribe = client.subscribe(() => {\n if (client.state !== undefined) resolveReady();\n if (client.connection.status === \"stopped\") {\n controller.abort(new Error(\"The setup connection stopped.\"));\n }\n });\n if (client.state !== undefined) resolveReady();\n if (client.connection.status === \"stopped\") {\n controller.abort(new Error(\"The setup connection stopped.\"));\n }\n await abortable(\n ready,\n AbortSignal.any([controller.signal, AbortSignal.timeout(10_000)]),\n );\n const state = client.state!;\n if (\n state?.version !== 2 ||\n !state.id ||\n !validInputs(state.inputs) ||\n ![\"planning\", \"installing\"].includes(state.status)\n ) {\n throw new Error(\n \"Start the setup in the wizard before signing in the CLI.\",\n );\n }\n sessionId = state.id;\n unsubscribe();\n unsubscribe = client.subscribe(checkSession);\n checkSession();\n } catch (error) {\n await dispose();\n throw error;\n }\n const command = <T>(run: () => Promise<T>) => {\n controller.signal.throwIfAborted();\n return abortable(\n run(),\n AbortSignal.any([controller.signal, AbortSignal.timeout(10_000)]),\n );\n };\n return {\n signal: controller.signal,\n async publish(authorization: DeviceAuthorization, issuer: string) {\n controller.signal.throwIfAborted();\n const href = setupLoginUrl(authorization, issuer);\n pendingHref = href;\n pendingAsk = client.commands[\"agent/ask\"]({\n kind: \"text\",\n preset: \"assistant-ui-cli-login\",\n prompt: \"Sign in to Assistant Cloud\",\n help: {\n summary:\n \"Authorize the CLI in your browser, then return to this setup.\",\n href,\n },\n }).then(async (result) => {\n if (!disposed && client.state?.id === sessionId) {\n inputId = result.inputId;\n checkSession();\n await reconcile().catch(() => {});\n }\n return result;\n });\n try {\n await command(() => pendingAsk!);\n checkSession();\n controller.signal.throwIfAborted();\n } catch (error) {\n terminalResult = controller.signal.aborted ? \"cancelled\" : \"failed\";\n await reconcile().catch(() => {});\n throw error;\n }\n return href;\n },\n async complete(result: \"signed-in\" | \"cancelled\" | \"failed\") {\n terminalResult = result;\n await reconcile();\n },\n dispose,\n };\n};\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const validateCloudUrl: (value: string) => string;
2
+ //# sourceMappingURL=cloud-url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud-url.d.ts","sourceRoot":"","sources":["../../src/lib/cloud-url.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,GAAI,OAAO,MAAM,KAAG,MAkBhD,CAAC"}
@@ -0,0 +1,14 @@
1
+ //#region src/lib/cloud-url.ts
2
+ const validateCloudUrl = (value) => {
3
+ const url = new URL(value);
4
+ if (url.username || url.password || url.search || url.hash || url.protocol !== "https:" && !(url.protocol === "http:" && [
5
+ "localhost",
6
+ "127.0.0.1",
7
+ "[::1]"
8
+ ].includes(url.hostname))) throw new Error("Cloud, accounts and setup URLs must use HTTPS or HTTP localhost for development.");
9
+ return value.replace(/\/+$/, "");
10
+ };
11
+ //#endregion
12
+ export { validateCloudUrl };
13
+
14
+ //# sourceMappingURL=cloud-url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud-url.js","names":[],"sources":["../../src/lib/cloud-url.ts"],"sourcesContent":["export const validateCloudUrl = (value: string): string => {\n const url = new URL(value);\n if (\n url.username ||\n url.password ||\n url.search ||\n url.hash ||\n (url.protocol !== \"https:\" &&\n !(\n url.protocol === \"http:\" &&\n [\"localhost\", \"127.0.0.1\", \"[::1]\"].includes(url.hostname)\n ))\n ) {\n throw new Error(\n \"Cloud, accounts and setup URLs must use HTTPS or HTTP localhost for development.\",\n );\n }\n return value.replace(/\\/+$/, \"\");\n};\n"],"mappings":";AAAA,MAAa,oBAAoB,UAA0B;CACzD,MAAM,MAAM,IAAI,IAAI,KAAK;CACzB,IACE,IAAI,YACJ,IAAI,YACJ,IAAI,UACJ,IAAI,QACH,IAAI,aAAa,YAChB,EACE,IAAI,aAAa,WACjB;EAAC;EAAa;EAAa;CAAO,CAAC,CAAC,SAAS,IAAI,QAAQ,IAG7D,MAAM,IAAI,MACR,kFACF;CAEF,OAAO,MAAM,QAAQ,QAAQ,EAAE;AACjC"}
@@ -1,5 +1,4 @@
1
1
  import { type PackageManagerName } from "./utils/package-manager.js";
2
- export declare function dlxCommand(pm: PackageManagerName): [string, string[]];
3
2
  export interface TransformOptions {
4
3
  hasLocalComponents: boolean;
5
4
  skipInstall?: boolean;
@@ -12,15 +11,7 @@ export type ProjectSource = {
12
11
  kind: "local";
13
12
  rootDir: string;
14
13
  };
15
- export declare function resolvePackageManager(opts: {
16
- useNpm?: boolean;
17
- usePnpm?: boolean;
18
- useYarn?: boolean;
19
- useBun?: boolean;
20
- }): PackageManagerName | undefined;
21
- export declare function resolveGitHubAuthToken(): string | undefined;
22
14
  export declare function resolveLatestReleaseRef(): Promise<string | undefined>;
23
- export declare const DOWNLOAD_TIMEOUT_MS = 30000;
24
15
  export declare function cleanupPendingProjectDownloads(): void;
25
16
  export declare function downloadProject(repoPath: string, destDir: string, ref?: string): Promise<void>;
26
17
  export declare function scaffoldProject(repoPath: string, destDir: string, source: ProjectSource): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"create-project.d.ts","sourceRoot":"","sources":["../../src/lib/create-project.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,KAAK,kBAAkB,EAAE,mCAAgC;AAOlE,wBAAgB,UAAU,CAAC,EAAE,EAAE,kBAAkB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAWrE;AAED,MAAM,WAAW,gBAAgB;IAC/B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,EAAE,kBAAkB,CAAC;CACpC;AAED,MAAM,MAAM,aAAa,GACrB;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;CACzB,GACD;IACE,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAaN,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,GAAG,kBAAkB,GAAG,SAAS,CAMjC;AAED,wBAAgB,sBAAsB,IAAI,MAAM,GAAG,SAAS,CAK3D;AAMD,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAe3E;AAED,eAAO,MAAM,mBAAmB,QAAS,CAAC;AAG1C,wBAAgB,8BAA8B,IAAI,IAAI,CAMrD;AAED,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAgIf;AAYD,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,IAAI,CAAC,CAyBf;AAED,MAAM,WAAW,eAAe;IAC9B,sBAAsB,CAAC,EAAE;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,eAAe,CAAC,CAoC1B;AA6JD,UAAU,kBAAkB;IAC1B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AA4CD;;;;;;;GAOG;AACH,wBAAsB,gCAAgC,CACpD,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CA8Gf;AAED,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB,CA8B7E"}
1
+ {"version":3,"file":"create-project.d.ts","sourceRoot":"","sources":["../../src/lib/create-project.ts"],"names":[],"mappings":"AAUA,OAAO,EAAc,KAAK,kBAAkB,EAAE,mCAAgC;AAQ9E,MAAM,WAAW,gBAAgB;IAC/B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,EAAE,kBAAkB,CAAC;CACpC;AAED,MAAM,MAAM,aAAa,GACrB;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;CACzB,GACD;IACE,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAiBN,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAe3E;AAID,wBAAgB,8BAA8B,IAAI,IAAI,CAMrD;AAED,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAiGf;AAYD,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,IAAI,CAAC,CAyBf;AAED,MAAM,WAAW,eAAe;IAC9B,sBAAsB,CAAC,EAAE;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,eAAe,CAAC,CAoC1B;AA6JD,UAAU,kBAAkB;IAC1B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AA4CD;;;;;;;GAOG;AACH,wBAAsB,gCAAgC,CACpD,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CA8Gf;AAED,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB,CA8B7E"}
@@ -1,21 +1,14 @@
1
1
  import { logger } from "./utils/logger.js";
2
2
  import { detectRegistryPlatform, resolveRegistryItemUrl } from "./utils/registry.js";
3
3
  import { SpawnExitError, SpawnSignalError, runSpawn } from "./run-spawn.js";
4
+ import { dlxCommand } from "./utils/package-manager.js";
5
+ import { resolveGitHubAuthToken, withStagedDownload } from "./utils/download.js";
4
6
  import { readProjectFiles } from "./utils/file-scanner.js";
5
7
  import * as fs$1 from "node:fs";
6
8
  import * as path$1 from "node:path";
7
9
  import * as os$1 from "node:os";
8
- import { downloadTemplate } from "giget";
9
10
  import { parse, printParseErrorCode } from "jsonc-parser";
10
11
  //#region src/lib/create-project.ts
11
- function dlxCommand(pm) {
12
- switch (pm) {
13
- case "pnpm": return ["pnpm", ["dlx"]];
14
- case "yarn": return ["yarn", ["dlx"]];
15
- case "bun": return ["bunx", []];
16
- case "npm": return ["npx", ["--yes"]];
17
- }
18
- }
19
12
  const LOCAL_PROJECT_ARTIFACT_DIRS = [
20
13
  "node_modules",
21
14
  ".next",
@@ -23,15 +16,6 @@ const LOCAL_PROJECT_ARTIFACT_DIRS = [
23
16
  "build"
24
17
  ];
25
18
  const LOCAL_PROJECT_ARTIFACT_GLOB_IGNORES = LOCAL_PROJECT_ARTIFACT_DIRS.map((dir) => `**/${dir}/**`);
26
- function resolvePackageManager(opts) {
27
- if (opts.useNpm) return "npm";
28
- if (opts.usePnpm) return "pnpm";
29
- if (opts.useYarn) return "yarn";
30
- if (opts.useBun) return "bun";
31
- }
32
- function resolveGitHubAuthToken() {
33
- return (process.env.GIGET_AUTH ?? process.env.GITHUB_TOKEN ?? process.env.GH_TOKEN)?.trim() || void 0;
34
- }
35
19
  function toBearerAuthHeader(token) {
36
20
  return token.toLowerCase().startsWith("bearer ") ? token : `Bearer ${token}`;
37
21
  }
@@ -45,7 +29,6 @@ async function resolveLatestReleaseRef() {
45
29
  return;
46
30
  }
47
31
  }
48
- const DOWNLOAD_TIMEOUT_MS = 3e4;
49
32
  const pendingDownloadCleanups = /* @__PURE__ */ new Set();
50
33
  function cleanupPendingProjectDownloads() {
51
34
  for (const cleanup of pendingDownloadCleanups) {
@@ -56,12 +39,9 @@ function cleanupPendingProjectDownloads() {
56
39
  }
57
40
  async function downloadProject(repoPath, destDir, ref) {
58
41
  const source = ref ? `gh:assistant-ui/assistant-ui/${repoPath}#${ref}` : `gh:assistant-ui/assistant-ui/${repoPath}`;
59
- const origDebug = process.env.DEBUG;
60
- delete process.env.DEBUG;
61
42
  let destinationCreated = false;
62
43
  let stagingDir;
63
- let downloadPromise;
64
- let downloadFinished = false;
44
+ let downloadStarted = false;
65
45
  let downloadCommitted = false;
66
46
  let cleanupRequested = false;
67
47
  const removeCleanupListeners = () => {
@@ -107,27 +87,20 @@ async function downloadProject(repoPath, destDir, ref) {
107
87
  }
108
88
  process.once("exit", cleanupOnExit);
109
89
  pendingDownloadCleanups.add(cleanupOnExit);
110
- const authToken = resolveGitHubAuthToken();
111
- downloadPromise = downloadTemplate(source, {
112
- dir: stagingDir,
90
+ const currentStagingDir = stagingDir;
91
+ downloadStarted = true;
92
+ await withStagedDownload(source, {
93
+ dir: currentStagingDir,
113
94
  force: true,
114
- silent: true,
115
- ...authToken ? { auth: authToken } : {}
116
- }).finally(() => {
117
- downloadFinished = true;
118
- });
119
- let timer;
120
- const timeoutPromise = new Promise((_, reject) => {
121
- timer = setTimeout(() => reject(/* @__PURE__ */ new Error("Download timed out. This may be due to GitHub rate limiting or a network issue. Try again in a few minutes.")), DOWNLOAD_TIMEOUT_MS);
122
- });
123
- try {
124
- await Promise.race([downloadPromise, timeoutPromise]);
95
+ silent: true
96
+ }, "Download timed out. This may be due to GitHub rate limiting or a network issue. Try again in a few minutes.", removeStagingDir, async (download) => {
97
+ await download;
125
98
  if (cleanupRequested) throw new Error("Download was interrupted.");
126
99
  destinationCreated = !fs$1.existsSync(destDir);
127
100
  await fs$1.promises.mkdir(destDir, { recursive: true });
128
- for (const entry of await fs$1.promises.readdir(stagingDir)) {
101
+ for (const entry of await fs$1.promises.readdir(currentStagingDir)) {
129
102
  const target = path$1.join(destDir, entry);
130
- const sourceEntry = path$1.join(stagingDir, entry);
103
+ const sourceEntry = path$1.join(currentStagingDir, entry);
131
104
  await fs$1.promises.rm(target, {
132
105
  recursive: true,
133
106
  force: true
@@ -147,13 +120,9 @@ async function downloadProject(repoPath, destDir, ref) {
147
120
  }
148
121
  }
149
122
  downloadCommitted = true;
150
- } finally {
151
- clearTimeout(timer);
152
- }
123
+ });
153
124
  } finally {
154
- if (!downloadPromise || downloadFinished) await removeStagingDir();
155
- else downloadPromise.then(removeStagingDir, removeStagingDir);
156
- if (origDebug !== void 0) process.env.DEBUG = origDebug;
125
+ if (!downloadStarted) await removeStagingDir();
157
126
  }
158
127
  }
159
128
  function shouldCopyLocalProjectPath(src, projectDir) {
@@ -455,6 +424,6 @@ async function installShadcnRegistry(projectDir, components, label, pm) {
455
424
  }
456
425
  }
457
426
  //#endregion
458
- export { DOWNLOAD_TIMEOUT_MS, cleanupPendingProjectDownloads, dlxCommand, downloadProject, reconcileAssistantUIImportLayout, resolveGitHubAuthToken, resolveLatestReleaseRef, resolvePackageManager, scaffoldProject, scanRequiredComponents, transformProject };
427
+ export { cleanupPendingProjectDownloads, downloadProject, reconcileAssistantUIImportLayout, resolveLatestReleaseRef, scaffoldProject, scanRequiredComponents, transformProject };
459
428
 
460
429
  //# sourceMappingURL=create-project.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-project.js","names":["fs","path","os","parseJsonc"],"sources":["../../src/lib/create-project.ts"],"sourcesContent":["import * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { downloadTemplate } from \"giget\";\nimport {\n parse as parseJsonc,\n printParseErrorCode,\n type ParseError,\n} from \"jsonc-parser\";\nimport { logger } from \"./utils/logger\";\nimport { runSpawn, SpawnExitError, SpawnSignalError } from \"./run-spawn\";\nimport { type PackageManagerName } from \"./utils/package-manager\";\nimport { readProjectFiles } from \"./utils/file-scanner\";\nimport {\n detectRegistryPlatform,\n resolveRegistryItemUrl,\n} from \"./utils/registry\";\n\nexport function dlxCommand(pm: PackageManagerName): [string, string[]] {\n switch (pm) {\n case \"pnpm\":\n return [\"pnpm\", [\"dlx\"]];\n case \"yarn\":\n return [\"yarn\", [\"dlx\"]];\n case \"bun\":\n return [\"bunx\", []];\n case \"npm\":\n return [\"npx\", [\"--yes\"]];\n }\n}\n\nexport interface TransformOptions {\n hasLocalComponents: boolean;\n skipInstall?: boolean;\n packageManager: PackageManagerName;\n}\n\nexport type ProjectSource =\n | {\n kind: \"github\";\n ref: string | undefined;\n }\n | {\n kind: \"local\";\n rootDir: string;\n };\n\nconst LOCAL_PROJECT_ARTIFACT_DIRS: readonly string[] = [\n \"node_modules\",\n \".next\",\n \"dist\",\n \"build\",\n];\n\nconst LOCAL_PROJECT_ARTIFACT_GLOB_IGNORES = LOCAL_PROJECT_ARTIFACT_DIRS.map(\n (dir) => `**/${dir}/**`,\n);\n\nexport function resolvePackageManager(opts: {\n useNpm?: boolean;\n usePnpm?: boolean;\n useYarn?: boolean;\n useBun?: boolean;\n}): PackageManagerName | undefined {\n if (opts.useNpm) return \"npm\";\n if (opts.usePnpm) return \"pnpm\";\n if (opts.useYarn) return \"yarn\";\n if (opts.useBun) return \"bun\";\n return undefined;\n}\n\nexport function resolveGitHubAuthToken(): string | undefined {\n const token =\n process.env.GIGET_AUTH ?? process.env.GITHUB_TOKEN ?? process.env.GH_TOKEN;\n const trimmed = token?.trim();\n return trimmed || undefined;\n}\n\nfunction toBearerAuthHeader(token: string): string {\n return token.toLowerCase().startsWith(\"bearer \") ? token : `Bearer ${token}`;\n}\n\nexport async function resolveLatestReleaseRef(): Promise<string | undefined> {\n try {\n const authToken = resolveGitHubAuthToken();\n const res = await fetch(\n \"https://api.github.com/repos/assistant-ui/assistant-ui/releases/latest\",\n authToken\n ? { headers: { Authorization: toBearerAuthHeader(authToken) } }\n : undefined,\n );\n if (!res.ok) return undefined;\n const release = (await res.json()) as { tag_name: string };\n return release.tag_name || undefined;\n } catch {\n return undefined;\n }\n}\n\nexport const DOWNLOAD_TIMEOUT_MS = 30_000;\nconst pendingDownloadCleanups = new Set<() => void>();\n\nexport function cleanupPendingProjectDownloads(): void {\n for (const cleanup of pendingDownloadCleanups) {\n pendingDownloadCleanups.delete(cleanup);\n process.removeListener(\"exit\", cleanup);\n cleanup();\n }\n}\n\nexport async function downloadProject(\n repoPath: string,\n destDir: string,\n ref?: string,\n): Promise<void> {\n const source = ref\n ? `gh:assistant-ui/assistant-ui/${repoPath}#${ref}`\n : `gh:assistant-ui/assistant-ui/${repoPath}`;\n\n // Suppress giget's debug output. The `debug` package (used by the upgrade\n // command) sets process.env.DEBUG at module-load time, and giget logs to\n // console.debug whenever that env var is truthy — even for unrelated\n // namespaces. Temporarily unsetting it targets the root cause.\n const origDebug = process.env.DEBUG;\n delete process.env.DEBUG;\n let destinationCreated = false;\n let stagingDir: string | undefined;\n let downloadPromise: Promise<unknown> | undefined;\n let downloadFinished = false;\n let downloadCommitted = false;\n let cleanupRequested = false;\n const removeCleanupListeners = () => {\n process.removeListener(\"exit\", cleanupOnExit);\n pendingDownloadCleanups.delete(cleanupOnExit);\n };\n const attemptSyncCleanup = (cleanup: () => void) => {\n try {\n cleanup();\n } catch {\n return;\n }\n };\n const cleanupOnExit = () => {\n cleanupRequested = true;\n const currentStagingDir = stagingDir;\n if (currentStagingDir) {\n attemptSyncCleanup(() => {\n fs.rmSync(currentStagingDir, { recursive: true, force: true });\n });\n }\n if (destinationCreated && !downloadCommitted) {\n attemptSyncCleanup(() => {\n fs.rmdirSync(destDir);\n });\n }\n };\n const removeStagingDir = async () => {\n if (stagingDir) {\n await fs.promises\n .rm(stagingDir, { recursive: true, force: true })\n .catch(() => undefined);\n }\n removeCleanupListeners();\n if (destinationCreated && !downloadCommitted) {\n await fs.promises.rmdir(destDir).catch(() => undefined);\n }\n };\n try {\n await fs.promises.mkdir(path.dirname(destDir), { recursive: true });\n try {\n stagingDir = await fs.promises.mkdtemp(\n path.join(path.dirname(destDir), \".assistant-ui-download-\"),\n );\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== \"EACCES\" && code !== \"EPERM\" && code !== \"EROFS\") {\n throw error;\n }\n stagingDir = await fs.promises.mkdtemp(\n path.join(os.tmpdir(), \".assistant-ui-download-\"),\n );\n }\n process.once(\"exit\", cleanupOnExit);\n pendingDownloadCleanups.add(cleanupOnExit);\n\n const authToken = resolveGitHubAuthToken();\n downloadPromise = downloadTemplate(source, {\n dir: stagingDir,\n force: true,\n silent: true,\n ...(authToken ? { auth: authToken } : {}),\n }).finally(() => {\n downloadFinished = true;\n });\n\n let timer: ReturnType<typeof setTimeout>;\n const timeoutPromise = new Promise<never>((_, reject) => {\n timer = setTimeout(\n () =>\n reject(\n new Error(\n \"Download timed out. This may be due to GitHub rate limiting or a network issue. Try again in a few minutes.\",\n ),\n ),\n DOWNLOAD_TIMEOUT_MS,\n );\n });\n\n try {\n await Promise.race([downloadPromise, timeoutPromise]);\n if (cleanupRequested) throw new Error(\"Download was interrupted.\");\n destinationCreated = !fs.existsSync(destDir);\n await fs.promises.mkdir(destDir, { recursive: true });\n for (const entry of await fs.promises.readdir(stagingDir)) {\n const target = path.join(destDir, entry);\n const sourceEntry = path.join(stagingDir, entry);\n await fs.promises.rm(target, { recursive: true, force: true });\n try {\n await fs.promises.rename(sourceEntry, target);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EXDEV\") throw error;\n await fs.promises.cp(sourceEntry, target, {\n recursive: true,\n force: true,\n });\n await fs.promises.rm(sourceEntry, { recursive: true, force: true });\n }\n }\n downloadCommitted = true;\n } finally {\n clearTimeout(timer!);\n }\n } finally {\n if (!downloadPromise || downloadFinished) {\n await removeStagingDir();\n } else {\n void downloadPromise.then(removeStagingDir, removeStagingDir);\n }\n if (origDebug !== undefined) {\n process.env.DEBUG = origDebug;\n }\n }\n}\n\nfunction shouldCopyLocalProjectPath(src: string, projectDir: string): boolean {\n const relative = path.relative(projectDir, src);\n if (!relative) return true;\n\n const segments = relative.split(path.sep);\n return !segments.some((segment) =>\n LOCAL_PROJECT_ARTIFACT_DIRS.includes(segment),\n );\n}\n\nexport async function scaffoldProject(\n repoPath: string,\n destDir: string,\n source: ProjectSource,\n): Promise<void> {\n if (source.kind === \"github\") {\n await downloadProject(repoPath, destDir, source.ref);\n return;\n }\n\n const localProjectDir = path.resolve(source.rootDir, repoPath);\n try {\n fs.cpSync(localProjectDir, destDir, {\n recursive: true,\n force: true,\n filter: (src) => shouldCopyLocalProjectPath(src, localProjectDir),\n });\n } catch (error) {\n const code =\n error instanceof Error\n ? (error as NodeJS.ErrnoException).code\n : undefined;\n if (code === \"ENOENT\") {\n throw new Error(\n `Local project source does not exist: ${localProjectDir}`,\n );\n }\n throw error;\n }\n}\n\nexport interface TransformResult {\n registryInstallFailure?: { retryCommand: string };\n registryInstallCommand?: string;\n}\n\nexport async function transformProject(\n projectDir: string,\n opts: TransformOptions,\n): Promise<TransformResult> {\n logger.step(\"Transforming package.json...\");\n transformPackageJson(projectDir);\n\n logger.step(\"Transforming project files...\");\n transformTsConfig(projectDir);\n transformCssFiles(projectDir);\n\n const components = opts.hasLocalComponents\n ? undefined\n : resolveRegistryComponents(projectDir, scanRequiredComponents(projectDir));\n\n const pm = opts.packageManager;\n if (opts.skipInstall) {\n if (!components) return {};\n const [cmd, dlxArgs] = dlxCommand(pm);\n return {\n registryInstallCommand: `${cmd} ${[...dlxArgs, \"shadcn@latest\", \"add\", ...components].join(\" \")}`,\n };\n }\n\n logger.step(\"Installing dependencies...\");\n await installDependencies(projectDir, pm);\n\n if (components) {\n logger.step(`Installing components: ${components.join(\", \")}...`);\n const failure = await installShadcnRegistry(\n projectDir,\n components,\n \"components\",\n pm,\n );\n if (failure) return { registryInstallFailure: failure };\n await reconcileAssistantUIImportLayout(projectDir);\n }\n return {};\n}\n\nfunction resolveRegistryComponents(\n projectDir: string,\n { assistantUI, shadcnUI }: RequiredComponents,\n): string[] {\n if (detectRegistryPlatform(projectDir) === \"native\") {\n return [\"utils\", ...shadcnUI, ...assistantUI].map((component) =>\n resolveRegistryItemUrl(component, undefined, \"native\"),\n );\n }\n return [\n \"@assistant-ui/utils\",\n ...shadcnUI,\n ...assistantUI.map((component) => `@assistant-ui/${component}`),\n ];\n}\n\nfunction transformPackageJson(projectDir: string): void {\n const pkgPath = path.join(projectDir, \"package.json\");\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\"));\n\n // Remove @assistant-ui/ui dependency\n if (pkg.dependencies?.[\"@assistant-ui/ui\"]) {\n delete pkg.dependencies[\"@assistant-ui/ui\"];\n }\n\n // Transform workspace dependencies to latest\n for (const depType of [\"dependencies\", \"devDependencies\"] as const) {\n const deps = pkg[depType];\n if (!deps) continue;\n\n for (const [name, version] of Object.entries(deps)) {\n if (String(version).includes(\"workspace:\")) {\n deps[name] = \"latest\";\n }\n }\n }\n\n // Remove devDependencies that are workspace-only\n if (pkg.devDependencies?.[\"@assistant-ui/x-buildutils\"]) {\n delete pkg.devDependencies[\"@assistant-ui/x-buildutils\"];\n }\n\n // Update package name to be unique\n const dirName = path.basename(projectDir);\n pkg.name = dirName;\n\n fs.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\\n`);\n}\n\nfunction parseTsConfig(content: string): any {\n const errors: ParseError[] = [];\n const tsconfig = parseJsonc(content, errors, { allowTrailingComma: true });\n const error = errors[0];\n if (error) {\n throw new SyntaxError(\n `Invalid tsconfig.json: ${printParseErrorCode(error.error)} at offset ${error.offset}`,\n );\n }\n return tsconfig;\n}\n\nfunction transformTsConfig(projectDir: string): void {\n const tsconfigPath = path.join(projectDir, \"tsconfig.json\");\n\n if (!fs.existsSync(tsconfigPath)) {\n return;\n }\n\n const content = fs.readFileSync(tsconfigPath, \"utf-8\");\n const tsconfig = parseTsConfig(content);\n\n // Remove workspace paths\n if (tsconfig.compilerOptions?.paths) {\n const workspaceKeys = new Set([\n \"@/components/assistant-ui/*\",\n \"@/components/icons/*\",\n \"@/components/ui/*\",\n \"@/components/ui/radix/*\",\n \"@/hooks/*\",\n \"@/lib/utils\",\n \"@assistant-ui/ui/*\",\n ]);\n for (const [key, targets] of Object.entries(\n tsconfig.compilerOptions.paths as Record<string, unknown>,\n )) {\n const targetsWorkspace =\n Array.isArray(targets) &&\n targets.some(\n (target) =>\n typeof target === \"string\" &&\n (target.includes(\"packages/ui/\") || target.startsWith(\"../\")),\n );\n if (workspaceKeys.has(key) || targetsWorkspace) {\n delete tsconfig.compilerOptions.paths[key];\n }\n }\n\n if (Object.keys(tsconfig.compilerOptions.paths).length === 0) {\n delete tsconfig.compilerOptions.paths;\n }\n }\n\n // If extends uses @assistant-ui/x-buildutils, replace with inline config\n if (tsconfig.extends?.includes(\"@assistant-ui/x-buildutils\")) {\n const isNext = tsconfig.extends.includes(\"ts/next\");\n delete tsconfig.extends;\n\n const inlinedCompilerOptions = {\n target: \"ESNext\",\n lib: [\"dom\", \"dom.iterable\", \"ES2023\"],\n skipLibCheck: true,\n strict: true,\n noEmit: true,\n esModuleInterop: true,\n module: \"ESNext\",\n moduleResolution: \"bundler\",\n resolveJsonModule: true,\n isolatedModules: true,\n jsx: \"react-jsx\",\n ...(isNext ? { plugins: [{ name: \"next\" }] } : {}),\n };\n\n tsconfig.compilerOptions = {\n ...inlinedCompilerOptions,\n ...tsconfig.compilerOptions,\n paths: {\n \"@/*\": [\"./*\"],\n ...(tsconfig.compilerOptions?.paths || {}),\n },\n };\n }\n\n fs.writeFileSync(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}\\n`);\n}\n\nfunction transformCssFiles(projectDir: string): void {\n for (const { fullPath, content } of readProjectFiles(\"**/*.css\", {\n cwd: projectDir,\n ignore: LOCAL_PROJECT_ARTIFACT_GLOB_IGNORES,\n })) {\n try {\n const newContent = content.replace(\n /@source\\s+[\"'][^\"']*packages\\/ui\\/src[^\"']*[\"'];\\s*\\n?/g,\n \"\",\n );\n\n if (newContent !== content) {\n fs.writeFileSync(fullPath, newContent);\n }\n } catch {\n continue;\n }\n }\n}\n\ninterface RequiredComponents {\n assistantUI: string[];\n shadcnUI: string[];\n}\n\nfunction stripImportExtension(component: string): string {\n return component.replace(/\\.[cm]?[tj]sx?$/, \"\");\n}\n\nconst ASSISTANT_UI_OWNED_UI = new Set([\n \"accordion\",\n \"badge\",\n \"diff-viewer\",\n \"direction\",\n \"dot-matrix\",\n \"number-roll\",\n \"select\",\n \"tabs\",\n]);\n\nconst BARE_ELEMENT_ITEMS = new Set([\n \"file\",\n \"generative-ui\",\n \"heat-graph\",\n \"image\",\n \"logos\",\n \"markdown-text\",\n \"syntax-highlighter\",\n \"tooltip-icon-button\",\n]);\n\nfunction toAssistantUIItem(specifier: string): string | null {\n let name = stripImportExtension(specifier);\n const inElements = name.startsWith(\"elements/\");\n if (inElements) {\n name = name.slice(\"elements/\".length);\n } else if (name.includes(\"/\")) {\n return null;\n }\n if (name.endsWith(\".aui\")) {\n return name.slice(0, -\".aui\".length);\n }\n return inElements && !BARE_ELEMENT_ITEMS.has(name)\n ? `elements-${name}`\n : name;\n}\n\n/**\n * Example snapshots are downloaded at a release tag while the shadcn registry\n * is live, so a snapshot may import components at the legacy flat path\n * (`@/components/assistant-ui/<name>`) after the registry has moved the file\n * to `components/assistant-ui/elements/<name>.aui.tsx`. Resolve each legacy\n * specifier against the files the registry actually installed and rewrite it\n * only when the legacy path is absent and the elements layout has it.\n */\nexport async function reconcileAssistantUIImportLayout(\n projectDir: string,\n): Promise<void> {\n const componentRoots = [\"components\", \"src/components\"]\n .map((dir) => path.join(projectDir, dir, \"assistant-ui\"))\n .filter((dir) => fs.existsSync(dir));\n if (componentRoots.length === 0) return;\n\n const resolvesAtLegacyPath = (name: string) =>\n componentRoots.some((root) =>\n [\".tsx\", \".ts\", \"/index.tsx\", \"/index.ts\"].some((suffix) =>\n fs.existsSync(path.join(root, `${name}${suffix}`)),\n ),\n );\n\n // Index the installed tree by import name so the rewrite follows whatever\n // layout the registry delivered — some items install as\n // elements/<name>.aui.tsx, others as elements/<name>.tsx, and a future\n // layout move should not require new knowledge here.\n const installedByName = new Map<string, string>();\n for (const root of componentRoots) {\n for (const { file } of readProjectFiles(\"**/*.{ts,tsx}\", { cwd: root })) {\n const normalized = file.split(path.sep).join(\"/\");\n if (!normalized.includes(\"/\")) continue;\n const specifier = normalized.replace(/\\.[cm]?[tj]sx?$/, \"\");\n const name = path.posix.basename(specifier).replace(/\\.aui$/, \"\");\n // A flat legacy import maps to the registry's `<name>` item, which is\n // the `.aui` file; a colliding bare file with the same basename belongs\n // to the distinct `elements-<name>` item, so the `.aui` variant wins.\n const existing = installedByName.get(name);\n if (\n existing === undefined ||\n (!existing.endsWith(\".aui\") && specifier.endsWith(\".aui\"))\n ) {\n installedByName.set(name, specifier);\n }\n }\n }\n if (installedByName.size === 0) return;\n\n const { default: jscodeshift } = await import(\"jscodeshift\");\n const parsers = {\n ts: jscodeshift.withParser(\"ts\"),\n tsx: jscodeshift.withParser(\"tsx\"),\n };\n\n for (const { fullPath, content } of readProjectFiles(\"**/*.{ts,tsx}\", {\n cwd: projectDir,\n ignore: LOCAL_PROJECT_ARTIFACT_GLOB_IGNORES,\n })) {\n if (!content.includes(\"@/components/assistant-ui/\")) continue;\n\n const replacements: Array<{ start: number; end: number; value: string }> =\n [];\n const collectReplacement = (source: {\n value?: unknown;\n start?: number | null;\n end?: number | null;\n }) => {\n if (\n typeof source.value !== \"string\" ||\n source.start == null ||\n source.end == null\n ) {\n return;\n }\n\n const prefix = \"@/components/assistant-ui/\";\n if (!source.value.startsWith(prefix)) return;\n const specifier = source.value.slice(prefix.length);\n if (specifier.includes(\"/\")) return;\n\n const name = stripImportExtension(specifier);\n const installed = installedByName.get(name);\n if (resolvesAtLegacyPath(name) || installed === undefined) return;\n\n const raw = content.slice(source.start, source.end);\n const quote = raw[0];\n if ((quote !== '\"' && quote !== \"'\") || raw.at(-1) !== quote) return;\n replacements.push({\n start: source.start,\n end: source.end,\n value: `${quote}@/components/assistant-ui/${installed}${quote}`,\n });\n };\n\n const j = fullPath.endsWith(\".tsx\") ? parsers.tsx : parsers.ts;\n let root;\n try {\n root = j(content);\n } catch {\n continue;\n }\n root\n .find(j.ImportDeclaration)\n .forEach(({ node }) => collectReplacement(node.source));\n root\n .find(j.ExportNamedDeclaration)\n .forEach(({ node }) => node.source && collectReplacement(node.source));\n root\n .find(j.ExportAllDeclaration)\n .forEach(({ node }) => collectReplacement(node.source));\n\n let next = content;\n for (const replacement of replacements.sort((a, b) => b.start - a.start)) {\n next =\n next.slice(0, replacement.start) +\n replacement.value +\n next.slice(replacement.end);\n }\n if (next !== content) fs.writeFileSync(fullPath, next);\n }\n}\n\nexport function scanRequiredComponents(projectDir: string): RequiredComponents {\n const assistantUIComponents = new Set<string>();\n const shadcnUIComponents = new Set<string>();\n\n for (const { content } of readProjectFiles(\"**/*.{ts,tsx}\", {\n cwd: projectDir,\n ignore: LOCAL_PROJECT_ARTIFACT_GLOB_IGNORES,\n })) {\n const assistantUIRegex =\n /from\\s+[\"']@\\/components\\/assistant-ui\\/([^\"']+)[\"']/g;\n for (const match of content.matchAll(assistantUIRegex)) {\n const item = toAssistantUIItem(match[1]!);\n if (item) assistantUIComponents.add(item);\n }\n\n const uiRegex = /from\\s+[\"']@\\/components\\/ui\\/([^\"']+)[\"']/g;\n for (const match of content.matchAll(uiRegex)) {\n const name = stripImportExtension(match[1]!);\n if (ASSISTANT_UI_OWNED_UI.has(name)) {\n assistantUIComponents.add(name);\n } else {\n shadcnUIComponents.add(name);\n }\n }\n }\n\n return {\n assistantUI: Array.from(assistantUIComponents),\n shadcnUI: Array.from(shadcnUIComponents),\n };\n}\n\nasync function installDependencies(\n projectDir: string,\n pm: PackageManagerName,\n): Promise<void> {\n const args = pm === \"yarn\" ? [] : [\"install\"];\n try {\n await runSpawn(pm, args, projectDir);\n } catch (error) {\n if (error instanceof SpawnSignalError) {\n throw error;\n }\n if (error instanceof SpawnExitError) {\n throw new Error(`${pm} install exited with code ${error.code}`);\n }\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to install dependencies: ${message}`);\n }\n}\n\nasync function installShadcnRegistry(\n projectDir: string,\n components: string[],\n label: string,\n pm: PackageManagerName,\n): Promise<{ retryCommand: string } | undefined> {\n const [cmd, dlxArgs] = dlxCommand(pm);\n // For npm, dlxArgs may already include `--yes` for npx auto-install.\n // The trailing `--yes` is for shadcn's own confirmation prompt.\n const retryArgs = [...dlxArgs, \"shadcn@latest\", \"add\", ...components];\n const addArgs = [...retryArgs, \"--yes\"];\n\n try {\n await runSpawn(cmd, addArgs, projectDir);\n return undefined;\n } catch (error) {\n if (error instanceof SpawnSignalError) {\n throw error;\n }\n if (error instanceof SpawnExitError) {\n logger.warn(`shadcn exited with code ${error.code}.`);\n return { retryCommand: `${cmd} ${retryArgs.join(\" \")}` };\n }\n\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to install ${label}: ${message}`);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"create-project.js","names":["fs","path","os","parseJsonc"],"sources":["../../src/lib/create-project.ts"],"sourcesContent":["import * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport {\n parse as parseJsonc,\n printParseErrorCode,\n type ParseError,\n} from \"jsonc-parser\";\nimport { logger } from \"./utils/logger\";\nimport { runSpawn, SpawnExitError, SpawnSignalError } from \"./run-spawn\";\nimport { dlxCommand, type PackageManagerName } from \"./utils/package-manager\";\nimport { resolveGitHubAuthToken, withStagedDownload } from \"./utils/download\";\nimport { readProjectFiles } from \"./utils/file-scanner\";\nimport {\n detectRegistryPlatform,\n resolveRegistryItemUrl,\n} from \"./utils/registry\";\n\nexport interface TransformOptions {\n hasLocalComponents: boolean;\n skipInstall?: boolean;\n packageManager: PackageManagerName;\n}\n\nexport type ProjectSource =\n | {\n kind: \"github\";\n ref: string | undefined;\n }\n | {\n kind: \"local\";\n rootDir: string;\n };\n\nconst LOCAL_PROJECT_ARTIFACT_DIRS: readonly string[] = [\n \"node_modules\",\n \".next\",\n \"dist\",\n \"build\",\n];\n\nconst LOCAL_PROJECT_ARTIFACT_GLOB_IGNORES = LOCAL_PROJECT_ARTIFACT_DIRS.map(\n (dir) => `**/${dir}/**`,\n);\n\nfunction toBearerAuthHeader(token: string): string {\n return token.toLowerCase().startsWith(\"bearer \") ? token : `Bearer ${token}`;\n}\n\nexport async function resolveLatestReleaseRef(): Promise<string | undefined> {\n try {\n const authToken = resolveGitHubAuthToken();\n const res = await fetch(\n \"https://api.github.com/repos/assistant-ui/assistant-ui/releases/latest\",\n authToken\n ? { headers: { Authorization: toBearerAuthHeader(authToken) } }\n : undefined,\n );\n if (!res.ok) return undefined;\n const release = (await res.json()) as { tag_name: string };\n return release.tag_name || undefined;\n } catch {\n return undefined;\n }\n}\n\nconst pendingDownloadCleanups = new Set<() => void>();\n\nexport function cleanupPendingProjectDownloads(): void {\n for (const cleanup of pendingDownloadCleanups) {\n pendingDownloadCleanups.delete(cleanup);\n process.removeListener(\"exit\", cleanup);\n cleanup();\n }\n}\n\nexport async function downloadProject(\n repoPath: string,\n destDir: string,\n ref?: string,\n): Promise<void> {\n const source = ref\n ? `gh:assistant-ui/assistant-ui/${repoPath}#${ref}`\n : `gh:assistant-ui/assistant-ui/${repoPath}`;\n\n let destinationCreated = false;\n let stagingDir: string | undefined;\n let downloadStarted = false;\n let downloadCommitted = false;\n let cleanupRequested = false;\n const removeCleanupListeners = () => {\n process.removeListener(\"exit\", cleanupOnExit);\n pendingDownloadCleanups.delete(cleanupOnExit);\n };\n const attemptSyncCleanup = (cleanup: () => void) => {\n try {\n cleanup();\n } catch {\n return;\n }\n };\n const cleanupOnExit = () => {\n cleanupRequested = true;\n const currentStagingDir = stagingDir;\n if (currentStagingDir) {\n attemptSyncCleanup(() => {\n fs.rmSync(currentStagingDir, { recursive: true, force: true });\n });\n }\n if (destinationCreated && !downloadCommitted) {\n attemptSyncCleanup(() => {\n fs.rmdirSync(destDir);\n });\n }\n };\n const removeStagingDir = async () => {\n if (stagingDir) {\n await fs.promises\n .rm(stagingDir, { recursive: true, force: true })\n .catch(() => undefined);\n }\n removeCleanupListeners();\n if (destinationCreated && !downloadCommitted) {\n await fs.promises.rmdir(destDir).catch(() => undefined);\n }\n };\n try {\n await fs.promises.mkdir(path.dirname(destDir), { recursive: true });\n try {\n stagingDir = await fs.promises.mkdtemp(\n path.join(path.dirname(destDir), \".assistant-ui-download-\"),\n );\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== \"EACCES\" && code !== \"EPERM\" && code !== \"EROFS\") {\n throw error;\n }\n stagingDir = await fs.promises.mkdtemp(\n path.join(os.tmpdir(), \".assistant-ui-download-\"),\n );\n }\n process.once(\"exit\", cleanupOnExit);\n pendingDownloadCleanups.add(cleanupOnExit);\n\n const currentStagingDir = stagingDir;\n downloadStarted = true;\n await withStagedDownload(\n source,\n { dir: currentStagingDir, force: true, silent: true },\n \"Download timed out. This may be due to GitHub rate limiting or a network issue. Try again in a few minutes.\",\n removeStagingDir,\n async (download) => {\n await download;\n if (cleanupRequested) throw new Error(\"Download was interrupted.\");\n destinationCreated = !fs.existsSync(destDir);\n await fs.promises.mkdir(destDir, { recursive: true });\n for (const entry of await fs.promises.readdir(currentStagingDir)) {\n const target = path.join(destDir, entry);\n const sourceEntry = path.join(currentStagingDir, entry);\n await fs.promises.rm(target, { recursive: true, force: true });\n try {\n await fs.promises.rename(sourceEntry, target);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"EXDEV\") throw error;\n await fs.promises.cp(sourceEntry, target, {\n recursive: true,\n force: true,\n });\n await fs.promises.rm(sourceEntry, { recursive: true, force: true });\n }\n }\n downloadCommitted = true;\n },\n );\n } finally {\n if (!downloadStarted) await removeStagingDir();\n }\n}\n\nfunction shouldCopyLocalProjectPath(src: string, projectDir: string): boolean {\n const relative = path.relative(projectDir, src);\n if (!relative) return true;\n\n const segments = relative.split(path.sep);\n return !segments.some((segment) =>\n LOCAL_PROJECT_ARTIFACT_DIRS.includes(segment),\n );\n}\n\nexport async function scaffoldProject(\n repoPath: string,\n destDir: string,\n source: ProjectSource,\n): Promise<void> {\n if (source.kind === \"github\") {\n await downloadProject(repoPath, destDir, source.ref);\n return;\n }\n\n const localProjectDir = path.resolve(source.rootDir, repoPath);\n try {\n fs.cpSync(localProjectDir, destDir, {\n recursive: true,\n force: true,\n filter: (src) => shouldCopyLocalProjectPath(src, localProjectDir),\n });\n } catch (error) {\n const code =\n error instanceof Error\n ? (error as NodeJS.ErrnoException).code\n : undefined;\n if (code === \"ENOENT\") {\n throw new Error(\n `Local project source does not exist: ${localProjectDir}`,\n );\n }\n throw error;\n }\n}\n\nexport interface TransformResult {\n registryInstallFailure?: { retryCommand: string };\n registryInstallCommand?: string;\n}\n\nexport async function transformProject(\n projectDir: string,\n opts: TransformOptions,\n): Promise<TransformResult> {\n logger.step(\"Transforming package.json...\");\n transformPackageJson(projectDir);\n\n logger.step(\"Transforming project files...\");\n transformTsConfig(projectDir);\n transformCssFiles(projectDir);\n\n const components = opts.hasLocalComponents\n ? undefined\n : resolveRegistryComponents(projectDir, scanRequiredComponents(projectDir));\n\n const pm = opts.packageManager;\n if (opts.skipInstall) {\n if (!components) return {};\n const [cmd, dlxArgs] = dlxCommand(pm);\n return {\n registryInstallCommand: `${cmd} ${[...dlxArgs, \"shadcn@latest\", \"add\", ...components].join(\" \")}`,\n };\n }\n\n logger.step(\"Installing dependencies...\");\n await installDependencies(projectDir, pm);\n\n if (components) {\n logger.step(`Installing components: ${components.join(\", \")}...`);\n const failure = await installShadcnRegistry(\n projectDir,\n components,\n \"components\",\n pm,\n );\n if (failure) return { registryInstallFailure: failure };\n await reconcileAssistantUIImportLayout(projectDir);\n }\n return {};\n}\n\nfunction resolveRegistryComponents(\n projectDir: string,\n { assistantUI, shadcnUI }: RequiredComponents,\n): string[] {\n if (detectRegistryPlatform(projectDir) === \"native\") {\n return [\"utils\", ...shadcnUI, ...assistantUI].map((component) =>\n resolveRegistryItemUrl(component, undefined, \"native\"),\n );\n }\n return [\n \"@assistant-ui/utils\",\n ...shadcnUI,\n ...assistantUI.map((component) => `@assistant-ui/${component}`),\n ];\n}\n\nfunction transformPackageJson(projectDir: string): void {\n const pkgPath = path.join(projectDir, \"package.json\");\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\"));\n\n // Remove @assistant-ui/ui dependency\n if (pkg.dependencies?.[\"@assistant-ui/ui\"]) {\n delete pkg.dependencies[\"@assistant-ui/ui\"];\n }\n\n // Transform workspace dependencies to latest\n for (const depType of [\"dependencies\", \"devDependencies\"] as const) {\n const deps = pkg[depType];\n if (!deps) continue;\n\n for (const [name, version] of Object.entries(deps)) {\n if (String(version).includes(\"workspace:\")) {\n deps[name] = \"latest\";\n }\n }\n }\n\n // Remove devDependencies that are workspace-only\n if (pkg.devDependencies?.[\"@assistant-ui/x-buildutils\"]) {\n delete pkg.devDependencies[\"@assistant-ui/x-buildutils\"];\n }\n\n // Update package name to be unique\n const dirName = path.basename(projectDir);\n pkg.name = dirName;\n\n fs.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\\n`);\n}\n\nfunction parseTsConfig(content: string): any {\n const errors: ParseError[] = [];\n const tsconfig = parseJsonc(content, errors, { allowTrailingComma: true });\n const error = errors[0];\n if (error) {\n throw new SyntaxError(\n `Invalid tsconfig.json: ${printParseErrorCode(error.error)} at offset ${error.offset}`,\n );\n }\n return tsconfig;\n}\n\nfunction transformTsConfig(projectDir: string): void {\n const tsconfigPath = path.join(projectDir, \"tsconfig.json\");\n\n if (!fs.existsSync(tsconfigPath)) {\n return;\n }\n\n const content = fs.readFileSync(tsconfigPath, \"utf-8\");\n const tsconfig = parseTsConfig(content);\n\n // Remove workspace paths\n if (tsconfig.compilerOptions?.paths) {\n const workspaceKeys = new Set([\n \"@/components/assistant-ui/*\",\n \"@/components/icons/*\",\n \"@/components/ui/*\",\n \"@/components/ui/radix/*\",\n \"@/hooks/*\",\n \"@/lib/utils\",\n \"@assistant-ui/ui/*\",\n ]);\n for (const [key, targets] of Object.entries(\n tsconfig.compilerOptions.paths as Record<string, unknown>,\n )) {\n const targetsWorkspace =\n Array.isArray(targets) &&\n targets.some(\n (target) =>\n typeof target === \"string\" &&\n (target.includes(\"packages/ui/\") || target.startsWith(\"../\")),\n );\n if (workspaceKeys.has(key) || targetsWorkspace) {\n delete tsconfig.compilerOptions.paths[key];\n }\n }\n\n if (Object.keys(tsconfig.compilerOptions.paths).length === 0) {\n delete tsconfig.compilerOptions.paths;\n }\n }\n\n // If extends uses @assistant-ui/x-buildutils, replace with inline config\n if (tsconfig.extends?.includes(\"@assistant-ui/x-buildutils\")) {\n const isNext = tsconfig.extends.includes(\"ts/next\");\n delete tsconfig.extends;\n\n const inlinedCompilerOptions = {\n target: \"ESNext\",\n lib: [\"dom\", \"dom.iterable\", \"ES2023\"],\n skipLibCheck: true,\n strict: true,\n noEmit: true,\n esModuleInterop: true,\n module: \"ESNext\",\n moduleResolution: \"bundler\",\n resolveJsonModule: true,\n isolatedModules: true,\n jsx: \"react-jsx\",\n ...(isNext ? { plugins: [{ name: \"next\" }] } : {}),\n };\n\n tsconfig.compilerOptions = {\n ...inlinedCompilerOptions,\n ...tsconfig.compilerOptions,\n paths: {\n \"@/*\": [\"./*\"],\n ...(tsconfig.compilerOptions?.paths || {}),\n },\n };\n }\n\n fs.writeFileSync(tsconfigPath, `${JSON.stringify(tsconfig, null, 2)}\\n`);\n}\n\nfunction transformCssFiles(projectDir: string): void {\n for (const { fullPath, content } of readProjectFiles(\"**/*.css\", {\n cwd: projectDir,\n ignore: LOCAL_PROJECT_ARTIFACT_GLOB_IGNORES,\n })) {\n try {\n const newContent = content.replace(\n /@source\\s+[\"'][^\"']*packages\\/ui\\/src[^\"']*[\"'];\\s*\\n?/g,\n \"\",\n );\n\n if (newContent !== content) {\n fs.writeFileSync(fullPath, newContent);\n }\n } catch {\n continue;\n }\n }\n}\n\ninterface RequiredComponents {\n assistantUI: string[];\n shadcnUI: string[];\n}\n\nfunction stripImportExtension(component: string): string {\n return component.replace(/\\.[cm]?[tj]sx?$/, \"\");\n}\n\nconst ASSISTANT_UI_OWNED_UI = new Set([\n \"accordion\",\n \"badge\",\n \"diff-viewer\",\n \"direction\",\n \"dot-matrix\",\n \"number-roll\",\n \"select\",\n \"tabs\",\n]);\n\nconst BARE_ELEMENT_ITEMS = new Set([\n \"file\",\n \"generative-ui\",\n \"heat-graph\",\n \"image\",\n \"logos\",\n \"markdown-text\",\n \"syntax-highlighter\",\n \"tooltip-icon-button\",\n]);\n\nfunction toAssistantUIItem(specifier: string): string | null {\n let name = stripImportExtension(specifier);\n const inElements = name.startsWith(\"elements/\");\n if (inElements) {\n name = name.slice(\"elements/\".length);\n } else if (name.includes(\"/\")) {\n return null;\n }\n if (name.endsWith(\".aui\")) {\n return name.slice(0, -\".aui\".length);\n }\n return inElements && !BARE_ELEMENT_ITEMS.has(name)\n ? `elements-${name}`\n : name;\n}\n\n/**\n * Example snapshots are downloaded at a release tag while the shadcn registry\n * is live, so a snapshot may import components at the legacy flat path\n * (`@/components/assistant-ui/<name>`) after the registry has moved the file\n * to `components/assistant-ui/elements/<name>.aui.tsx`. Resolve each legacy\n * specifier against the files the registry actually installed and rewrite it\n * only when the legacy path is absent and the elements layout has it.\n */\nexport async function reconcileAssistantUIImportLayout(\n projectDir: string,\n): Promise<void> {\n const componentRoots = [\"components\", \"src/components\"]\n .map((dir) => path.join(projectDir, dir, \"assistant-ui\"))\n .filter((dir) => fs.existsSync(dir));\n if (componentRoots.length === 0) return;\n\n const resolvesAtLegacyPath = (name: string) =>\n componentRoots.some((root) =>\n [\".tsx\", \".ts\", \"/index.tsx\", \"/index.ts\"].some((suffix) =>\n fs.existsSync(path.join(root, `${name}${suffix}`)),\n ),\n );\n\n // Index the installed tree by import name so the rewrite follows whatever\n // layout the registry delivered — some items install as\n // elements/<name>.aui.tsx, others as elements/<name>.tsx, and a future\n // layout move should not require new knowledge here.\n const installedByName = new Map<string, string>();\n for (const root of componentRoots) {\n for (const { file } of readProjectFiles(\"**/*.{ts,tsx}\", { cwd: root })) {\n const normalized = file.split(path.sep).join(\"/\");\n if (!normalized.includes(\"/\")) continue;\n const specifier = normalized.replace(/\\.[cm]?[tj]sx?$/, \"\");\n const name = path.posix.basename(specifier).replace(/\\.aui$/, \"\");\n // A flat legacy import maps to the registry's `<name>` item, which is\n // the `.aui` file; a colliding bare file with the same basename belongs\n // to the distinct `elements-<name>` item, so the `.aui` variant wins.\n const existing = installedByName.get(name);\n if (\n existing === undefined ||\n (!existing.endsWith(\".aui\") && specifier.endsWith(\".aui\"))\n ) {\n installedByName.set(name, specifier);\n }\n }\n }\n if (installedByName.size === 0) return;\n\n const { default: jscodeshift } = await import(\"jscodeshift\");\n const parsers = {\n ts: jscodeshift.withParser(\"ts\"),\n tsx: jscodeshift.withParser(\"tsx\"),\n };\n\n for (const { fullPath, content } of readProjectFiles(\"**/*.{ts,tsx}\", {\n cwd: projectDir,\n ignore: LOCAL_PROJECT_ARTIFACT_GLOB_IGNORES,\n })) {\n if (!content.includes(\"@/components/assistant-ui/\")) continue;\n\n const replacements: Array<{ start: number; end: number; value: string }> =\n [];\n const collectReplacement = (source: {\n value?: unknown;\n start?: number | null;\n end?: number | null;\n }) => {\n if (\n typeof source.value !== \"string\" ||\n source.start == null ||\n source.end == null\n ) {\n return;\n }\n\n const prefix = \"@/components/assistant-ui/\";\n if (!source.value.startsWith(prefix)) return;\n const specifier = source.value.slice(prefix.length);\n if (specifier.includes(\"/\")) return;\n\n const name = stripImportExtension(specifier);\n const installed = installedByName.get(name);\n if (resolvesAtLegacyPath(name) || installed === undefined) return;\n\n const raw = content.slice(source.start, source.end);\n const quote = raw[0];\n if ((quote !== '\"' && quote !== \"'\") || raw.at(-1) !== quote) return;\n replacements.push({\n start: source.start,\n end: source.end,\n value: `${quote}@/components/assistant-ui/${installed}${quote}`,\n });\n };\n\n const j = fullPath.endsWith(\".tsx\") ? parsers.tsx : parsers.ts;\n let root;\n try {\n root = j(content);\n } catch {\n continue;\n }\n root\n .find(j.ImportDeclaration)\n .forEach(({ node }) => collectReplacement(node.source));\n root\n .find(j.ExportNamedDeclaration)\n .forEach(({ node }) => node.source && collectReplacement(node.source));\n root\n .find(j.ExportAllDeclaration)\n .forEach(({ node }) => collectReplacement(node.source));\n\n let next = content;\n for (const replacement of replacements.sort((a, b) => b.start - a.start)) {\n next =\n next.slice(0, replacement.start) +\n replacement.value +\n next.slice(replacement.end);\n }\n if (next !== content) fs.writeFileSync(fullPath, next);\n }\n}\n\nexport function scanRequiredComponents(projectDir: string): RequiredComponents {\n const assistantUIComponents = new Set<string>();\n const shadcnUIComponents = new Set<string>();\n\n for (const { content } of readProjectFiles(\"**/*.{ts,tsx}\", {\n cwd: projectDir,\n ignore: LOCAL_PROJECT_ARTIFACT_GLOB_IGNORES,\n })) {\n const assistantUIRegex =\n /from\\s+[\"']@\\/components\\/assistant-ui\\/([^\"']+)[\"']/g;\n for (const match of content.matchAll(assistantUIRegex)) {\n const item = toAssistantUIItem(match[1]!);\n if (item) assistantUIComponents.add(item);\n }\n\n const uiRegex = /from\\s+[\"']@\\/components\\/ui\\/([^\"']+)[\"']/g;\n for (const match of content.matchAll(uiRegex)) {\n const name = stripImportExtension(match[1]!);\n if (ASSISTANT_UI_OWNED_UI.has(name)) {\n assistantUIComponents.add(name);\n } else {\n shadcnUIComponents.add(name);\n }\n }\n }\n\n return {\n assistantUI: Array.from(assistantUIComponents),\n shadcnUI: Array.from(shadcnUIComponents),\n };\n}\n\nasync function installDependencies(\n projectDir: string,\n pm: PackageManagerName,\n): Promise<void> {\n const args = pm === \"yarn\" ? [] : [\"install\"];\n try {\n await runSpawn(pm, args, projectDir);\n } catch (error) {\n if (error instanceof SpawnSignalError) {\n throw error;\n }\n if (error instanceof SpawnExitError) {\n throw new Error(`${pm} install exited with code ${error.code}`);\n }\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to install dependencies: ${message}`);\n }\n}\n\nasync function installShadcnRegistry(\n projectDir: string,\n components: string[],\n label: string,\n pm: PackageManagerName,\n): Promise<{ retryCommand: string } | undefined> {\n const [cmd, dlxArgs] = dlxCommand(pm);\n // For npm, dlxArgs may already include `--yes` for npx auto-install.\n // The trailing `--yes` is for shadcn's own confirmation prompt.\n const retryArgs = [...dlxArgs, \"shadcn@latest\", \"add\", ...components];\n const addArgs = [...retryArgs, \"--yes\"];\n\n try {\n await runSpawn(cmd, addArgs, projectDir);\n return undefined;\n } catch (error) {\n if (error instanceof SpawnSignalError) {\n throw error;\n }\n if (error instanceof SpawnExitError) {\n logger.warn(`shadcn exited with code ${error.code}.`);\n return { retryCommand: `${cmd} ${retryArgs.join(\" \")}` };\n }\n\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to install ${label}: ${message}`);\n }\n}\n"],"mappings":";;;;;;;;;;;AAkCA,MAAM,8BAAiD;CACrD;CACA;CACA;CACA;AACF;AAEA,MAAM,sCAAsC,4BAA4B,KACrE,QAAQ,MAAM,IAAI,IACrB;AAEA,SAAS,mBAAmB,OAAuB;CACjD,OAAO,MAAM,YAAY,CAAC,CAAC,WAAW,SAAS,IAAI,QAAQ,UAAU;AACvE;AAEA,eAAsB,0BAAuD;CAC3E,IAAI;EACF,MAAM,YAAY,uBAAuB;EACzC,MAAM,MAAM,MAAM,MAChB,0EACA,YACI,EAAE,SAAS,EAAE,eAAe,mBAAmB,SAAS,EAAE,EAAE,IAC5D,KAAA,CACN;EACA,IAAI,CAAC,IAAI,IAAI,OAAO,KAAA;EAEpB,QAAO,MADgB,IAAI,KAAK,EAAA,CACjB,YAAY,KAAA;CAC7B,QAAQ;EACN;CACF;AACF;AAEA,MAAM,0CAA0B,IAAI,IAAgB;AAEpD,SAAgB,iCAAuC;CACrD,KAAK,MAAM,WAAW,yBAAyB;EAC7C,wBAAwB,OAAO,OAAO;EACtC,QAAQ,eAAe,QAAQ,OAAO;EACtC,QAAQ;CACV;AACF;AAEA,eAAsB,gBACpB,UACA,SACA,KACe;CACf,MAAM,SAAS,MACX,gCAAgC,SAAS,GAAG,QAC5C,gCAAgC;CAEpC,IAAI,qBAAqB;CACzB,IAAI;CACJ,IAAI,kBAAkB;CACtB,IAAI,oBAAoB;CACxB,IAAI,mBAAmB;CACvB,MAAM,+BAA+B;EACnC,QAAQ,eAAe,QAAQ,aAAa;EAC5C,wBAAwB,OAAO,aAAa;CAC9C;CACA,MAAM,sBAAsB,YAAwB;EAClD,IAAI;GACF,QAAQ;EACV,QAAQ;GACN;EACF;CACF;CACA,MAAM,sBAAsB;EAC1B,mBAAmB;EACnB,MAAM,oBAAoB;EAC1B,IAAI,mBACF,yBAAyB;GACvB,KAAG,OAAO,mBAAmB;IAAE,WAAW;IAAM,OAAO;GAAK,CAAC;EAC/D,CAAC;EAEH,IAAI,sBAAsB,CAAC,mBACzB,yBAAyB;GACvB,KAAG,UAAU,OAAO;EACtB,CAAC;CAEL;CACA,MAAM,mBAAmB,YAAY;EACnC,IAAI,YACF,MAAMA,KAAG,SACN,GAAG,YAAY;GAAE,WAAW;GAAM,OAAO;EAAK,CAAC,CAAC,CAChD,YAAY,KAAA,CAAS;EAE1B,uBAAuB;EACvB,IAAI,sBAAsB,CAAC,mBACzB,MAAMA,KAAG,SAAS,MAAM,OAAO,CAAC,CAAC,YAAY,KAAA,CAAS;CAE1D;CACA,IAAI;EACF,MAAMA,KAAG,SAAS,MAAMC,OAAK,QAAQ,OAAO,GAAG,EAAE,WAAW,KAAK,CAAC;EAClE,IAAI;GACF,aAAa,MAAMD,KAAG,SAAS,QAC7BC,OAAK,KAAKA,OAAK,QAAQ,OAAO,GAAG,yBAAyB,CAC5D;EACF,SAAS,OAAO;GACd,MAAM,OAAQ,MAAgC;GAC9C,IAAI,SAAS,YAAY,SAAS,WAAW,SAAS,SACpD,MAAM;GAER,aAAa,MAAMD,KAAG,SAAS,QAC7BC,OAAK,KAAKC,KAAG,OAAO,GAAG,yBAAyB,CAClD;EACF;EACA,QAAQ,KAAK,QAAQ,aAAa;EAClC,wBAAwB,IAAI,aAAa;EAEzC,MAAM,oBAAoB;EAC1B,kBAAkB;EAClB,MAAM,mBACJ,QACA;GAAE,KAAK;GAAmB,OAAO;GAAM,QAAQ;EAAK,GACpD,+GACA,kBACA,OAAO,aAAa;GAClB,MAAM;GACN,IAAI,kBAAkB,MAAM,IAAI,MAAM,2BAA2B;GACjE,qBAAqB,CAACF,KAAG,WAAW,OAAO;GAC3C,MAAMA,KAAG,SAAS,MAAM,SAAS,EAAE,WAAW,KAAK,CAAC;GACpD,KAAK,MAAM,SAAS,MAAMA,KAAG,SAAS,QAAQ,iBAAiB,GAAG;IAChE,MAAM,SAASC,OAAK,KAAK,SAAS,KAAK;IACvC,MAAM,cAAcA,OAAK,KAAK,mBAAmB,KAAK;IACtD,MAAMD,KAAG,SAAS,GAAG,QAAQ;KAAE,WAAW;KAAM,OAAO;IAAK,CAAC;IAC7D,IAAI;KACF,MAAMA,KAAG,SAAS,OAAO,aAAa,MAAM;IAC9C,SAAS,OAAO;KACd,IAAK,MAAgC,SAAS,SAAS,MAAM;KAC7D,MAAMA,KAAG,SAAS,GAAG,aAAa,QAAQ;MACxC,WAAW;MACX,OAAO;KACT,CAAC;KACD,MAAMA,KAAG,SAAS,GAAG,aAAa;MAAE,WAAW;MAAM,OAAO;KAAK,CAAC;IACpE;GACF;GACA,oBAAoB;EACtB,CACF;CACF,UAAU;EACR,IAAI,CAAC,iBAAiB,MAAM,iBAAiB;CAC/C;AACF;AAEA,SAAS,2BAA2B,KAAa,YAA6B;CAC5E,MAAM,WAAWC,OAAK,SAAS,YAAY,GAAG;CAC9C,IAAI,CAAC,UAAU,OAAO;CAGtB,OAAO,CADU,SAAS,MAAMA,OAAK,GACtB,CAAC,CAAC,MAAM,YACrB,4BAA4B,SAAS,OAAO,CAC9C;AACF;AAEA,eAAsB,gBACpB,UACA,SACA,QACe;CACf,IAAI,OAAO,SAAS,UAAU;EAC5B,MAAM,gBAAgB,UAAU,SAAS,OAAO,GAAG;EACnD;CACF;CAEA,MAAM,kBAAkBA,OAAK,QAAQ,OAAO,SAAS,QAAQ;CAC7D,IAAI;EACF,KAAG,OAAO,iBAAiB,SAAS;GAClC,WAAW;GACX,OAAO;GACP,SAAS,QAAQ,2BAA2B,KAAK,eAAe;EAClE,CAAC;CACH,SAAS,OAAO;EAKd,KAHE,iBAAiB,QACZ,MAAgC,OACjC,KAAA,OACO,UACX,MAAM,IAAI,MACR,wCAAwC,iBAC1C;EAEF,MAAM;CACR;AACF;AAOA,eAAsB,iBACpB,YACA,MAC0B;CAC1B,OAAO,KAAK,8BAA8B;CAC1C,qBAAqB,UAAU;CAE/B,OAAO,KAAK,+BAA+B;CAC3C,kBAAkB,UAAU;CAC5B,kBAAkB,UAAU;CAE5B,MAAM,aAAa,KAAK,qBACpB,KAAA,IACA,0BAA0B,YAAY,uBAAuB,UAAU,CAAC;CAE5E,MAAM,KAAK,KAAK;CAChB,IAAI,KAAK,aAAa;EACpB,IAAI,CAAC,YAAY,OAAO,CAAC;EACzB,MAAM,CAAC,KAAK,WAAW,WAAW,EAAE;EACpC,OAAO,EACL,wBAAwB,GAAG,IAAI,GAAG;GAAC,GAAG;GAAS;GAAiB;GAAO,GAAG;EAAU,CAAC,CAAC,KAAK,GAAG,IAChG;CACF;CAEA,OAAO,KAAK,4BAA4B;CACxC,MAAM,oBAAoB,YAAY,EAAE;CAExC,IAAI,YAAY;EACd,OAAO,KAAK,0BAA0B,WAAW,KAAK,IAAI,EAAE,IAAI;EAChE,MAAM,UAAU,MAAM,sBACpB,YACA,YACA,cACA,EACF;EACA,IAAI,SAAS,OAAO,EAAE,wBAAwB,QAAQ;EACtD,MAAM,iCAAiC,UAAU;CACnD;CACA,OAAO,CAAC;AACV;AAEA,SAAS,0BACP,YACA,EAAE,aAAa,YACL;CACV,IAAI,uBAAuB,UAAU,MAAM,UACzC,OAAO;EAAC;EAAS,GAAG;EAAU,GAAG;CAAW,CAAC,CAAC,KAAK,cACjD,uBAAuB,WAAW,KAAA,GAAW,QAAQ,CACvD;CAEF,OAAO;EACL;EACA,GAAG;EACH,GAAG,YAAY,KAAK,cAAc,iBAAiB,WAAW;CAChE;AACF;AAEA,SAAS,qBAAqB,YAA0B;CACtD,MAAM,UAAUA,OAAK,KAAK,YAAY,cAAc;CACpD,MAAM,MAAM,KAAK,MAAMD,KAAG,aAAa,SAAS,OAAO,CAAC;CAGxD,IAAI,IAAI,eAAe,qBACrB,OAAO,IAAI,aAAa;CAI1B,KAAK,MAAM,WAAW,CAAC,gBAAgB,iBAAiB,GAAY;EAClE,MAAM,OAAO,IAAI;EACjB,IAAI,CAAC,MAAM;EAEX,KAAK,MAAM,CAAC,MAAM,YAAY,OAAO,QAAQ,IAAI,GAC/C,IAAI,OAAO,OAAO,CAAC,CAAC,SAAS,YAAY,GACvC,KAAK,QAAQ;CAGnB;CAGA,IAAI,IAAI,kBAAkB,+BACxB,OAAO,IAAI,gBAAgB;CAK7B,IAAI,OADYC,OAAK,SAAS,UACb;CAEjB,KAAG,cAAc,SAAS,GAAG,KAAK,UAAU,KAAK,MAAM,CAAC,EAAE,GAAG;AAC/D;AAEA,SAAS,cAAc,SAAsB;CAC3C,MAAM,SAAuB,CAAC;CAC9B,MAAM,WAAWE,MAAW,SAAS,QAAQ,EAAE,oBAAoB,KAAK,CAAC;CACzE,MAAM,QAAQ,OAAO;CACrB,IAAI,OACF,MAAM,IAAI,YACR,0BAA0B,oBAAoB,MAAM,KAAK,EAAE,aAAa,MAAM,QAChF;CAEF,OAAO;AACT;AAEA,SAAS,kBAAkB,YAA0B;CACnD,MAAM,eAAeF,OAAK,KAAK,YAAY,eAAe;CAE1D,IAAI,CAACD,KAAG,WAAW,YAAY,GAC7B;CAIF,MAAM,WAAW,cADDA,KAAG,aAAa,cAAc,OACT,CAAC;CAGtC,IAAI,SAAS,iBAAiB,OAAO;EACnC,MAAM,gCAAgB,IAAI,IAAI;GAC5B;GACA;GACA;GACA;GACA;GACA;GACA;EACF,CAAC;EACD,KAAK,MAAM,CAAC,KAAK,YAAY,OAAO,QAClC,SAAS,gBAAgB,KAC3B,GAAG;GACD,MAAM,mBACJ,MAAM,QAAQ,OAAO,KACrB,QAAQ,MACL,WACC,OAAO,WAAW,aACjB,OAAO,SAAS,cAAc,KAAK,OAAO,WAAW,KAAK,EAC/D;GACF,IAAI,cAAc,IAAI,GAAG,KAAK,kBAC5B,OAAO,SAAS,gBAAgB,MAAM;EAE1C;EAEA,IAAI,OAAO,KAAK,SAAS,gBAAgB,KAAK,CAAC,CAAC,WAAW,GACzD,OAAO,SAAS,gBAAgB;CAEpC;CAGA,IAAI,SAAS,SAAS,SAAS,4BAA4B,GAAG;EAC5D,MAAM,SAAS,SAAS,QAAQ,SAAS,SAAS;EAClD,OAAO,SAAS;EAiBhB,SAAS,kBAAkB;GAdzB,QAAQ;GACR,KAAK;IAAC;IAAO;IAAgB;GAAQ;GACrC,cAAc;GACd,QAAQ;GACR,QAAQ;GACR,iBAAiB;GACjB,QAAQ;GACR,kBAAkB;GAClB,mBAAmB;GACnB,iBAAiB;GACjB,KAAK;GACL,GAAI,SAAS,EAAE,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,EAAE,IAAI,CAAC;GAKhD,GAAG,SAAS;GACZ,OAAO;IACL,OAAO,CAAC,KAAK;IACb,GAAI,SAAS,iBAAiB,SAAS,CAAC;GAC1C;EACF;CACF;CAEA,KAAG,cAAc,cAAc,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,EAAE,GAAG;AACzE;AAEA,SAAS,kBAAkB,YAA0B;CACnD,KAAK,MAAM,EAAE,UAAU,aAAa,iBAAiB,YAAY;EAC/D,KAAK;EACL,QAAQ;CACV,CAAC,GACC,IAAI;EACF,MAAM,aAAa,QAAQ,QACzB,2DACA,EACF;EAEA,IAAI,eAAe,SACjB,KAAG,cAAc,UAAU,UAAU;CAEzC,QAAQ;EACN;CACF;AAEJ;AAOA,SAAS,qBAAqB,WAA2B;CACvD,OAAO,UAAU,QAAQ,mBAAmB,EAAE;AAChD;AAEA,MAAM,wCAAwB,IAAI,IAAI;CACpC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,MAAM,qCAAqB,IAAI,IAAI;CACjC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAED,SAAS,kBAAkB,WAAkC;CAC3D,IAAI,OAAO,qBAAqB,SAAS;CACzC,MAAM,aAAa,KAAK,WAAW,WAAW;CAC9C,IAAI,YACF,OAAO,KAAK,MAAM,CAAkB;MAC/B,IAAI,KAAK,SAAS,GAAG,GAC1B,OAAO;CAET,IAAI,KAAK,SAAS,MAAM,GACtB,OAAO,KAAK,MAAM,GAAG,EAAc;CAErC,OAAO,cAAc,CAAC,mBAAmB,IAAI,IAAI,IAC7C,YAAY,SACZ;AACN;;;;;;;;;AAUA,eAAsB,iCACpB,YACe;CACf,MAAM,iBAAiB,CAAC,cAAc,gBAAgB,CAAC,CACpD,KAAK,QAAQC,OAAK,KAAK,YAAY,KAAK,cAAc,CAAC,CAAC,CACxD,QAAQ,QAAQD,KAAG,WAAW,GAAG,CAAC;CACrC,IAAI,eAAe,WAAW,GAAG;CAEjC,MAAM,wBAAwB,SAC5B,eAAe,MAAM,SACnB;EAAC;EAAQ;EAAO;EAAc;CAAW,CAAC,CAAC,MAAM,WAC/CA,KAAG,WAAWC,OAAK,KAAK,MAAM,GAAG,OAAO,QAAQ,CAAC,CACnD,CACF;CAMF,MAAM,kCAAkB,IAAI,IAAoB;CAChD,KAAK,MAAM,QAAQ,gBACjB,KAAK,MAAM,EAAE,UAAU,iBAAiB,iBAAiB,EAAE,KAAK,KAAK,CAAC,GAAG;EACvE,MAAM,aAAa,KAAK,MAAMA,OAAK,GAAG,CAAC,CAAC,KAAK,GAAG;EAChD,IAAI,CAAC,WAAW,SAAS,GAAG,GAAG;EAC/B,MAAM,YAAY,WAAW,QAAQ,mBAAmB,EAAE;EAC1D,MAAM,OAAOA,OAAK,MAAM,SAAS,SAAS,CAAC,CAAC,QAAQ,UAAU,EAAE;EAIhE,MAAM,WAAW,gBAAgB,IAAI,IAAI;EACzC,IACE,aAAa,KAAA,KACZ,CAAC,SAAS,SAAS,MAAM,KAAK,UAAU,SAAS,MAAM,GAExD,gBAAgB,IAAI,MAAM,SAAS;CAEvC;CAEF,IAAI,gBAAgB,SAAS,GAAG;CAEhC,MAAM,EAAE,SAAS,gBAAgB,MAAM,OAAO;CAC9C,MAAM,UAAU;EACd,IAAI,YAAY,WAAW,IAAI;EAC/B,KAAK,YAAY,WAAW,KAAK;CACnC;CAEA,KAAK,MAAM,EAAE,UAAU,aAAa,iBAAiB,iBAAiB;EACpE,KAAK;EACL,QAAQ;CACV,CAAC,GAAG;EACF,IAAI,CAAC,QAAQ,SAAS,4BAA4B,GAAG;EAErD,MAAM,eACJ,CAAC;EACH,MAAM,sBAAsB,WAItB;GACJ,IACE,OAAO,OAAO,UAAU,YACxB,OAAO,SAAS,QAChB,OAAO,OAAO,MAEd;GAIF,IAAI,CAAC,OAAO,MAAM,WAAW,4BAAM,GAAG;GACtC,MAAM,YAAY,OAAO,MAAM,MAAM,EAAa;GAClD,IAAI,UAAU,SAAS,GAAG,GAAG;GAE7B,MAAM,OAAO,qBAAqB,SAAS;GAC3C,MAAM,YAAY,gBAAgB,IAAI,IAAI;GAC1C,IAAI,qBAAqB,IAAI,KAAK,cAAc,KAAA,GAAW;GAE3D,MAAM,MAAM,QAAQ,MAAM,OAAO,OAAO,OAAO,GAAG;GAClD,MAAM,QAAQ,IAAI;GAClB,IAAK,UAAU,QAAO,UAAU,OAAQ,IAAI,GAAG,EAAE,MAAM,OAAO;GAC9D,aAAa,KAAK;IAChB,OAAO,OAAO;IACd,KAAK,OAAO;IACZ,OAAO,GAAG,MAAM,4BAA4B,YAAY;GAC1D,CAAC;EACH;EAEA,MAAM,IAAI,SAAS,SAAS,MAAM,IAAI,QAAQ,MAAM,QAAQ;EAC5D,IAAI;EACJ,IAAI;GACF,OAAO,EAAE,OAAO;EAClB,QAAQ;GACN;EACF;EACA,KACG,KAAK,EAAE,iBAAiB,CAAC,CACzB,SAAS,EAAE,WAAW,mBAAmB,KAAK,MAAM,CAAC;EACxD,KACG,KAAK,EAAE,sBAAsB,CAAC,CAC9B,SAAS,EAAE,WAAW,KAAK,UAAU,mBAAmB,KAAK,MAAM,CAAC;EACvE,KACG,KAAK,EAAE,oBAAoB,CAAC,CAC5B,SAAS,EAAE,WAAW,mBAAmB,KAAK,MAAM,CAAC;EAExD,IAAI,OAAO;EACX,KAAK,MAAM,eAAe,aAAa,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,GACrE,OACE,KAAK,MAAM,GAAG,YAAY,KAAK,IAC/B,YAAY,QACZ,KAAK,MAAM,YAAY,GAAG;EAE9B,IAAI,SAAS,SAAS,KAAG,cAAc,UAAU,IAAI;CACvD;AACF;AAEA,SAAgB,uBAAuB,YAAwC;CAC7E,MAAM,wCAAwB,IAAI,IAAY;CAC9C,MAAM,qCAAqB,IAAI,IAAY;CAE3C,KAAK,MAAM,EAAE,aAAa,iBAAiB,iBAAiB;EAC1D,KAAK;EACL,QAAQ;CACV,CAAC,GAAG;EAGF,KAAK,MAAM,SAAS,QAAQ,SAAS,uDAAgB,GAAG;GACtD,MAAM,OAAO,kBAAkB,MAAM,EAAG;GACxC,IAAI,MAAM,sBAAsB,IAAI,IAAI;EAC1C;EAGA,KAAK,MAAM,SAAS,QAAQ,SAAS,6CAAO,GAAG;GAC7C,MAAM,OAAO,qBAAqB,MAAM,EAAG;GAC3C,IAAI,sBAAsB,IAAI,IAAI,GAChC,sBAAsB,IAAI,IAAI;QAE9B,mBAAmB,IAAI,IAAI;EAE/B;CACF;CAEA,OAAO;EACL,aAAa,MAAM,KAAK,qBAAqB;EAC7C,UAAU,MAAM,KAAK,kBAAkB;CACzC;AACF;AAEA,eAAe,oBACb,YACA,IACe;CACf,MAAM,OAAO,OAAO,SAAS,CAAC,IAAI,CAAC,SAAS;CAC5C,IAAI;EACF,MAAM,SAAS,IAAI,MAAM,UAAU;CACrC,SAAS,OAAO;EACd,IAAI,iBAAiB,kBACnB,MAAM;EAER,IAAI,iBAAiB,gBACnB,MAAM,IAAI,MAAM,GAAG,GAAG,4BAA4B,MAAM,MAAM;EAEhE,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EACrE,MAAM,IAAI,MAAM,mCAAmC,SAAS;CAC9D;AACF;AAEA,eAAe,sBACb,YACA,YACA,OACA,IAC+C;CAC/C,MAAM,CAAC,KAAK,WAAW,WAAW,EAAE;CAGpC,MAAM,YAAY;EAAC,GAAG;EAAS;EAAiB;EAAO,GAAG;CAAU;CACpE,MAAM,UAAU,CAAC,GAAG,WAAW,OAAO;CAEtC,IAAI;EACF,MAAM,SAAS,KAAK,SAAS,UAAU;EACvC;CACF,SAAS,OAAO;EACd,IAAI,iBAAiB,kBACnB,MAAM;EAER,IAAI,iBAAiB,gBAAgB;GACnC,OAAO,KAAK,2BAA2B,MAAM,KAAK,EAAE;GACpD,OAAO,EAAE,cAAc,GAAG,IAAI,GAAG,UAAU,KAAK,GAAG,IAAI;EACzD;EAEA,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EACrE,MAAM,IAAI,MAAM,qBAAqB,MAAM,IAAI,SAAS;CAC1D;AACF"}
@@ -4,10 +4,6 @@ import type { TransformOptions } from "./transform-options.js";
4
4
  * Directory scans only include files containing "assistant-ui".
5
5
  */
6
6
  export declare function getRelevantFiles(source: string): string[];
7
- /**
8
- * Counts the number of files that need to be processed
9
- */
10
- export declare function countFilesToProcess(source: string): number;
11
7
  export type TransformErrors = {
12
8
  transform: string;
13
9
  filename: string;
@@ -1 +1 @@
1
- {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../src/lib/transform.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,+BAA4B;AAW5D;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CA4BzD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE1D;AAqCD,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB,EAAE,CAAC;AAEJ,wBAAsB,SAAS,CAC7B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,gBAAgB,EAClC,OAAO,GAAE;IACP,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CACJ,GACtB,OAAO,CAAC,eAAe,CAAC,CAwC1B"}
1
+ {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../src/lib/transform.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,+BAA4B;AAW5D;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAqBzD;AAqCD,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB,EAAE,CAAC;AAEJ,wBAAsB,SAAS,CAC7B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,gBAAgB,EAClC,OAAO,GAAE;IACP,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CACJ,GACtB,OAAO,CAAC,eAAe,CAAC,CAwC1B"}
@@ -1,9 +1,9 @@
1
1
  import { SpawnExitError, SpawnSignalError, runSpawnCapture } from "./run-spawn.js";
2
+ import { readProjectFiles } from "./utils/file-scanner.js";
2
3
  import * as fs$1 from "node:fs";
3
4
  import path from "node:path";
4
- import { sync } from "glob";
5
- import debug from "debug";
6
5
  import { fileURLToPath } from "node:url";
6
+ import debug from "debug";
7
7
  //#region src/lib/transform.ts
8
8
  const log = debug("codemod:transform");
9
9
  const __filename = fileURLToPath(import.meta.url);
@@ -15,7 +15,9 @@ const __dirname = path.dirname(__filename);
15
15
  function getRelevantFiles(source) {
16
16
  const target = path.resolve(source);
17
17
  if (fs$1.statSync(target).isFile()) return /\.(js|jsx|ts|tsx)$/.test(target) ? [target] : [];
18
- return sync("**/*.{js,jsx,ts,tsx}", {
18
+ const pattern = "**/*.{js,jsx,ts,tsx}";
19
+ const relevantFiles = [];
20
+ for (const { fullPath, content } of readProjectFiles(pattern, {
19
21
  cwd: target,
20
22
  ignore: [
21
23
  "**/node_modules/**",
@@ -24,19 +26,8 @@ function getRelevantFiles(source) {
24
26
  "**/*.min.js",
25
27
  "**/*.bundle.js"
26
28
  ]
27
- }).map((file) => path.join(target, file)).filter((file) => {
28
- try {
29
- return fs$1.readFileSync(file, "utf8").includes("assistant-ui");
30
- } catch {
31
- return false;
32
- }
33
- });
34
- }
35
- /**
36
- * Counts the number of files that need to be processed
37
- */
38
- function countFilesToProcess(source) {
39
- return getRelevantFiles(source).length;
29
+ })) if (content.includes("assistant-ui")) relevantFiles.push(fullPath);
30
+ return relevantFiles;
40
31
  }
41
32
  function buildCommand(codemodPath, targetFiles, options) {
42
33
  const command = [
@@ -80,6 +71,6 @@ async function transform(codemod, source, transformOptions, options = { logStatu
80
71
  return [];
81
72
  }
82
73
  //#endregion
83
- export { countFilesToProcess, getRelevantFiles, transform };
74
+ export { getRelevantFiles, transform };
84
75
 
85
76
  //# sourceMappingURL=transform.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"transform.js","names":["fs","globSync"],"sources":["../../src/lib/transform.ts"],"sourcesContent":["import debug from \"debug\";\nimport path from \"node:path\";\nimport type { TransformOptions } from \"./transform-options\";\nimport { fileURLToPath } from \"node:url\";\nimport * as fs from \"node:fs\";\nimport { sync as globSync } from \"glob\";\nimport { runSpawnCapture, SpawnExitError, SpawnSignalError } from \"./run-spawn\";\n\nconst log = debug(\"codemod:transform\");\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n/**\n * Gets relevant source files from an explicit file or directory target.\n * Directory scans only include files containing \"assistant-ui\".\n */\nexport function getRelevantFiles(source: string): string[] {\n const target = path.resolve(source);\n if (fs.statSync(target).isFile()) {\n return /\\.(js|jsx|ts|tsx)$/.test(target) ? [target] : [];\n }\n\n const pattern = \"**/*.{js,jsx,ts,tsx}\";\n const files = globSync(pattern, {\n cwd: target,\n ignore: [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/*.min.js\",\n \"**/*.bundle.js\",\n ],\n }).map((file) => path.join(target, file));\n\n const relevantFiles = files.filter((file) => {\n try {\n const content = fs.readFileSync(file, \"utf8\");\n return content.includes(\"assistant-ui\");\n } catch {\n return false;\n }\n });\n\n return relevantFiles;\n}\n\n/**\n * Counts the number of files that need to be processed\n */\nexport function countFilesToProcess(source: string): number {\n return getRelevantFiles(source).length;\n}\n\nfunction buildCommand(\n codemodPath: string,\n targetFiles: string[],\n options: TransformOptions,\n): string[] {\n const command = [\n \"npx\",\n \"jscodeshift\",\n \"-t\",\n codemodPath,\n ...targetFiles,\n \"--parser\",\n \"tsx\",\n \"--fail-on-error\",\n ];\n\n if (options.dry) {\n command.push(\"--dry\");\n }\n\n if (options.print) {\n command.push(\"--print\");\n }\n\n if (options.verbose) {\n command.push(\"--verbose\");\n }\n\n if (options.jscodeshift) {\n command.push(options.jscodeshift);\n }\n\n return command;\n}\n\nexport type TransformErrors = {\n transform: string;\n filename: string;\n summary: string;\n}[];\n\nexport async function transform(\n codemod: string,\n source: string,\n transformOptions: TransformOptions,\n options: {\n logStatus: boolean;\n onProgress?: (processedFiles: number) => void;\n relevantFiles?: string[];\n } = { logStatus: true },\n): Promise<TransformErrors> {\n if (options.logStatus) {\n log(`Applying codemod '${codemod}': ${source}`);\n }\n const codemodPath = path.resolve(__dirname, `../codemods/${codemod}.js`);\n\n // Use pre-computed relevant files if provided, otherwise get them\n const targetFiles = options.relevantFiles || getRelevantFiles(source);\n\n if (targetFiles.length === 0) {\n log(`No relevant files found for codemod '${codemod}'`);\n return [];\n }\n\n log(`Found ${targetFiles.length} relevant files for codemod '${codemod}'`);\n\n const command = buildCommand(codemodPath, targetFiles, transformOptions);\n\n const result = await runSpawnCapture(command[0]!, command.slice(1));\n if (result.signal !== null) {\n throw new SpawnSignalError(result.signal, false);\n }\n if (result.code !== 0) {\n const failure = new SpawnExitError(\n result.code || 1,\n result.stderr,\n result.stdout,\n );\n failure.message = `Codemod '${codemod}' failed\\n${failure.message}`;\n throw failure;\n }\n\n const { stdout } = result;\n\n if (options.onProgress) {\n const processedFiles = (stdout.match(/Processing file/g) || []).length;\n options.onProgress(processedFiles);\n }\n\n return [];\n}\n"],"mappings":";;;;;;;AAQA,MAAM,MAAM,MAAM,mBAAmB;AAErC,MAAM,aAAa,cAAc,YAAY,GAAG;AAChD,MAAM,YAAY,KAAK,QAAQ,UAAU;;;;;AAMzC,SAAgB,iBAAiB,QAA0B;CACzD,MAAM,SAAS,KAAK,QAAQ,MAAM;CAClC,IAAIA,KAAG,SAAS,MAAM,CAAC,CAAC,OAAO,GAC7B,OAAO,qBAAqB,KAAK,MAAM,IAAI,CAAC,MAAM,IAAI,CAAC;CAwBzD,OApBcC,KAAS,wBAAS;EAC9B,KAAK;EACL,QAAQ;GACN;GACA;GACA;GACA;GACA;EACF;CACF,CAAC,CAAC,CAAC,KAAK,SAAS,KAAK,KAAK,QAAQ,IAAI,CAEb,CAAC,CAAC,QAAQ,SAAS;EAC3C,IAAI;GAEF,OADgBD,KAAG,aAAa,MAAM,MACzB,CAAC,CAAC,SAAS,cAAc;EACxC,QAAQ;GACN,OAAO;EACT;CACF,CAEmB;AACrB;;;;AAKA,SAAgB,oBAAoB,QAAwB;CAC1D,OAAO,iBAAiB,MAAM,CAAC,CAAC;AAClC;AAEA,SAAS,aACP,aACA,aACA,SACU;CACV,MAAM,UAAU;EACd;EACA;EACA;EACA;EACA,GAAG;EACH;EACA;EACA;CACF;CAEA,IAAI,QAAQ,KACV,QAAQ,KAAK,OAAO;CAGtB,IAAI,QAAQ,OACV,QAAQ,KAAK,SAAS;CAGxB,IAAI,QAAQ,SACV,QAAQ,KAAK,WAAW;CAG1B,IAAI,QAAQ,aACV,QAAQ,KAAK,QAAQ,WAAW;CAGlC,OAAO;AACT;AAQA,eAAsB,UACpB,SACA,QACA,kBACA,UAII,EAAE,WAAW,KAAK,GACI;CAC1B,IAAI,QAAQ,WACV,IAAI,qBAAqB,QAAQ,KAAK,QAAQ;CAEhD,MAAM,cAAc,KAAK,QAAQ,WAAW,eAAe,QAAQ,IAAI;CAGvE,MAAM,cAAc,QAAQ,iBAAiB,iBAAiB,MAAM;CAEpE,IAAI,YAAY,WAAW,GAAG;EAC5B,IAAI,wCAAwC,QAAQ,EAAE;EACtD,OAAO,CAAC;CACV;CAEA,IAAI,SAAS,YAAY,OAAO,+BAA+B,QAAQ,EAAE;CAEzE,MAAM,UAAU,aAAa,aAAa,aAAa,gBAAgB;CAEvE,MAAM,SAAS,MAAM,gBAAgB,QAAQ,IAAK,QAAQ,MAAM,CAAC,CAAC;CAClE,IAAI,OAAO,WAAW,MACpB,MAAM,IAAI,iBAAiB,OAAO,QAAQ,KAAK;CAEjD,IAAI,OAAO,SAAS,GAAG;EACrB,MAAM,UAAU,IAAI,eAClB,OAAO,QAAQ,GACf,OAAO,QACP,OAAO,MACT;EACA,QAAQ,UAAU,YAAY,QAAQ,YAAY,QAAQ;EAC1D,MAAM;CACR;CAEA,MAAM,EAAE,WAAW;CAEnB,IAAI,QAAQ,YAAY;EACtB,MAAM,kBAAkB,OAAO,MAAM,kBAAkB,KAAK,CAAC,EAAA,CAAG;EAChE,QAAQ,WAAW,cAAc;CACnC;CAEA,OAAO,CAAC;AACV"}
1
+ {"version":3,"file":"transform.js","names":["fs"],"sources":["../../src/lib/transform.ts"],"sourcesContent":["import debug from \"debug\";\nimport path from \"node:path\";\nimport type { TransformOptions } from \"./transform-options\";\nimport { fileURLToPath } from \"node:url\";\nimport * as fs from \"node:fs\";\nimport { runSpawnCapture, SpawnExitError, SpawnSignalError } from \"./run-spawn\";\nimport { readProjectFiles } from \"./utils/file-scanner\";\n\nconst log = debug(\"codemod:transform\");\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n/**\n * Gets relevant source files from an explicit file or directory target.\n * Directory scans only include files containing \"assistant-ui\".\n */\nexport function getRelevantFiles(source: string): string[] {\n const target = path.resolve(source);\n if (fs.statSync(target).isFile()) {\n return /\\.(js|jsx|ts|tsx)$/.test(target) ? [target] : [];\n }\n\n const pattern = \"**/*.{js,jsx,ts,tsx}\";\n const relevantFiles: string[] = [];\n for (const { fullPath, content } of readProjectFiles(pattern, {\n cwd: target,\n ignore: [\n \"**/node_modules/**\",\n \"**/dist/**\",\n \"**/build/**\",\n \"**/*.min.js\",\n \"**/*.bundle.js\",\n ],\n })) {\n if (content.includes(\"assistant-ui\")) relevantFiles.push(fullPath);\n }\n return relevantFiles;\n}\n\nfunction buildCommand(\n codemodPath: string,\n targetFiles: string[],\n options: TransformOptions,\n): string[] {\n const command = [\n \"npx\",\n \"jscodeshift\",\n \"-t\",\n codemodPath,\n ...targetFiles,\n \"--parser\",\n \"tsx\",\n \"--fail-on-error\",\n ];\n\n if (options.dry) {\n command.push(\"--dry\");\n }\n\n if (options.print) {\n command.push(\"--print\");\n }\n\n if (options.verbose) {\n command.push(\"--verbose\");\n }\n\n if (options.jscodeshift) {\n command.push(options.jscodeshift);\n }\n\n return command;\n}\n\nexport type TransformErrors = {\n transform: string;\n filename: string;\n summary: string;\n}[];\n\nexport async function transform(\n codemod: string,\n source: string,\n transformOptions: TransformOptions,\n options: {\n logStatus: boolean;\n onProgress?: (processedFiles: number) => void;\n relevantFiles?: string[];\n } = { logStatus: true },\n): Promise<TransformErrors> {\n if (options.logStatus) {\n log(`Applying codemod '${codemod}': ${source}`);\n }\n const codemodPath = path.resolve(__dirname, `../codemods/${codemod}.js`);\n\n // Use pre-computed relevant files if provided, otherwise get them\n const targetFiles = options.relevantFiles || getRelevantFiles(source);\n\n if (targetFiles.length === 0) {\n log(`No relevant files found for codemod '${codemod}'`);\n return [];\n }\n\n log(`Found ${targetFiles.length} relevant files for codemod '${codemod}'`);\n\n const command = buildCommand(codemodPath, targetFiles, transformOptions);\n\n const result = await runSpawnCapture(command[0]!, command.slice(1));\n if (result.signal !== null) {\n throw new SpawnSignalError(result.signal, false);\n }\n if (result.code !== 0) {\n const failure = new SpawnExitError(\n result.code || 1,\n result.stderr,\n result.stdout,\n );\n failure.message = `Codemod '${codemod}' failed\\n${failure.message}`;\n throw failure;\n }\n\n const { stdout } = result;\n\n if (options.onProgress) {\n const processedFiles = (stdout.match(/Processing file/g) || []).length;\n options.onProgress(processedFiles);\n }\n\n return [];\n}\n"],"mappings":";;;;;;;AAQA,MAAM,MAAM,MAAM,mBAAmB;AAErC,MAAM,aAAa,cAAc,YAAY,GAAG;AAChD,MAAM,YAAY,KAAK,QAAQ,UAAU;;;;;AAMzC,SAAgB,iBAAiB,QAA0B;CACzD,MAAM,SAAS,KAAK,QAAQ,MAAM;CAClC,IAAIA,KAAG,SAAS,MAAM,CAAC,CAAC,OAAO,GAC7B,OAAO,qBAAqB,KAAK,MAAM,IAAI,CAAC,MAAM,IAAI,CAAC;CAGzD,MAAM,UAAU;CAChB,MAAM,gBAA0B,CAAC;CACjC,KAAK,MAAM,EAAE,UAAU,aAAa,iBAAiB,SAAS;EAC5D,KAAK;EACL,QAAQ;GACN;GACA;GACA;GACA;GACA;EACF;CACF,CAAC,GACC,IAAI,QAAQ,SAAS,cAAc,GAAG,cAAc,KAAK,QAAQ;CAEnE,OAAO;AACT;AAEA,SAAS,aACP,aACA,aACA,SACU;CACV,MAAM,UAAU;EACd;EACA;EACA;EACA;EACA,GAAG;EACH;EACA;EACA;CACF;CAEA,IAAI,QAAQ,KACV,QAAQ,KAAK,OAAO;CAGtB,IAAI,QAAQ,OACV,QAAQ,KAAK,SAAS;CAGxB,IAAI,QAAQ,SACV,QAAQ,KAAK,WAAW;CAG1B,IAAI,QAAQ,aACV,QAAQ,KAAK,QAAQ,WAAW;CAGlC,OAAO;AACT;AAQA,eAAsB,UACpB,SACA,QACA,kBACA,UAII,EAAE,WAAW,KAAK,GACI;CAC1B,IAAI,QAAQ,WACV,IAAI,qBAAqB,QAAQ,KAAK,QAAQ;CAEhD,MAAM,cAAc,KAAK,QAAQ,WAAW,eAAe,QAAQ,IAAI;CAGvE,MAAM,cAAc,QAAQ,iBAAiB,iBAAiB,MAAM;CAEpE,IAAI,YAAY,WAAW,GAAG;EAC5B,IAAI,wCAAwC,QAAQ,EAAE;EACtD,OAAO,CAAC;CACV;CAEA,IAAI,SAAS,YAAY,OAAO,+BAA+B,QAAQ,EAAE;CAEzE,MAAM,UAAU,aAAa,aAAa,aAAa,gBAAgB;CAEvE,MAAM,SAAS,MAAM,gBAAgB,QAAQ,IAAK,QAAQ,MAAM,CAAC,CAAC;CAClE,IAAI,OAAO,WAAW,MACpB,MAAM,IAAI,iBAAiB,OAAO,QAAQ,KAAK;CAEjD,IAAI,OAAO,SAAS,GAAG;EACrB,MAAM,UAAU,IAAI,eAClB,OAAO,QAAQ,GACf,OAAO,QACP,OAAO,MACT;EACA,QAAQ,UAAU,YAAY,QAAQ,YAAY,QAAQ;EAC1D,MAAM;CACR;CAEA,MAAM,EAAE,WAAW;CAEnB,IAAI,QAAQ,YAAY;EACtB,MAAM,kBAAkB,OAAO,MAAM,kBAAkB,KAAK,CAAC,EAAA,CAAG;EAChE,QAAQ,WAAW,cAAc;CACnC;CAEA,OAAO,CAAC;AACV"}
@@ -0,0 +1,5 @@
1
+ import { downloadTemplate } from "giget";
2
+ export declare const DOWNLOAD_TIMEOUT_MS = 30000;
3
+ export declare function resolveGitHubAuthToken(): string | undefined;
4
+ export declare function withStagedDownload<T>(source: string, options: NonNullable<Parameters<typeof downloadTemplate>[1]>, timeoutMessage: string, cleanup: () => void | Promise<void>, consumeDownload: (download: Promise<unknown>) => Promise<T>): Promise<T>;
5
+ //# sourceMappingURL=download.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../../../src/lib/utils/download.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAC;AAEzC,eAAO,MAAM,mBAAmB,QAAS,CAAC;AAE1C,wBAAgB,sBAAsB,IAAI,MAAM,GAAG,SAAS,CAK3D;AAED,wBAAsB,kBAAkB,CAAC,CAAC,EACxC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,WAAW,CAAC,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,EAC5D,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EACnC,eAAe,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAC1D,OAAO,CAAC,CAAC,CAAC,CAuCZ"}