@stackable-labs/cli-app-extension 1.36.3 → 1.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +73 -14
  2. package/dist/index.js +839 -923
  3. package/package.json +2 -1
package/dist/index.js CHANGED
@@ -1,20 +1,79 @@
1
1
  #!/usr/bin/env node
2
+ import { createRequire } from 'module';
3
+ import { program } from 'commander';
4
+ import { render, useApp, Box, Text, useInput, useFocus, useFocusManager } from 'ink';
5
+ import { unlink, readFile, writeFile, mkdir, readdir, rm } from 'fs/promises';
6
+ import { join, dirname } from 'path';
7
+ import Spinner5 from 'ink-spinner';
8
+ import { useState, useCallback, useEffect, useRef, useMemo } from 'react';
9
+ import { delay } from '@stackable-labs/lib-utils-js';
10
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
11
+ import TextInput from 'ink-text-input';
12
+ import { execFile, spawn } from 'child_process';
13
+ import { promisify } from 'util';
14
+ import { installDependencies } from 'nypm';
15
+ import { downloadTemplate } from 'giget';
16
+ import { Tunnel } from 'cloudflared';
17
+ import clipboard from 'clipboardy';
18
+ import { existsSync, readFileSync } from 'fs';
19
+ import AdmZip from 'adm-zip';
20
+ import { createServer } from 'http';
21
+ import open from 'open';
22
+ import { homedir } from 'os';
23
+ import https from 'https';
2
24
 
3
- // src/index.tsx
4
- import { createRequire } from "module";
5
- import { program } from "commander";
6
- import { render } from "ink";
7
-
8
- // src/App.tsx
9
- import { readFile as readFile3 } from "fs/promises";
10
- import { join as join3 } from "path";
11
- import { Box as Box15, Text as Text15, useApp } from "ink";
12
- import { useCallback, useEffect as useEffect4, useState as useState10 } from "react";
13
-
14
- // src/components/Confirm.tsx
15
- import { Box as Box2, Text as Text2, useFocus, useFocusManager, useInput as useInput2 } from "ink";
16
- import TextInput from "ink-text-input";
17
- import { useEffect, useState } from "react";
25
+ var WORDMARK = [
26
+ " _ _ _ _ ",
27
+ " ___| |_ __ _ ___| | ____ _| |__ | | ___",
28
+ "/ __| __/ _` |/ __| |/ / _` | '_ \\| |/ _ \\",
29
+ "\\__ \\ || (_| | (__| < (_| | |_) | | __/",
30
+ "|___/\\__\\__,_|\\___|_|\\_\\__,_|_.__/|_|\\___|"
31
+ ];
32
+ var COLORS = [
33
+ [232, 218, 234],
34
+ // Lit Lilac #E8DAEA
35
+ [197, 96, 255],
36
+ // Poppy Purple #C560FF
37
+ [0, 174, 247],
38
+ // Bluetooth Blue #00AEF7
39
+ [70, 224, 177],
40
+ // Tropical Teal #46E0B1
41
+ [252, 248, 161]
42
+ // Not Mellow Yellow #FCF8A1
43
+ ];
44
+ var lerp = (a, b, t) => {
45
+ const r = Math.round(a[0] + (b[0] - a[0]) * t);
46
+ const g = Math.round(a[1] + (b[1] - a[1]) * t);
47
+ const bl = Math.round(a[2] + (b[2] - a[2]) * t);
48
+ return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${bl.toString(16).padStart(2, "0")}`;
49
+ };
50
+ var gradientColor = (row, col, rows, cols) => {
51
+ const t = (row / (rows - 1) + col / (cols - 1)) / 2;
52
+ const idx = t * (COLORS.length - 1);
53
+ const lo = Math.floor(idx);
54
+ const hi = Math.min(lo + 1, COLORS.length - 1);
55
+ return lerp(COLORS[lo], COLORS[hi], idx - lo);
56
+ };
57
+ var Banner = ({ userId, orgId } = {}) => {
58
+ const termWidth = process.stdout.columns ?? 80;
59
+ const maxLen = Math.max(...WORDMARK.map((l) => l.length));
60
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
61
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2500".repeat(termWidth) }),
62
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 1, paddingY: 1, children: [
63
+ WORDMARK.map((line, row) => /* @__PURE__ */ jsx(Box, { children: line.split("").map((ch, col) => /* @__PURE__ */ jsx(Text, { bold: true, color: ch === " " ? void 0 : gradientColor(row, col, WORDMARK.length, maxLen), children: ch }, col)) }, row)),
64
+ userId && orgId && /* @__PURE__ */ jsxs(Box, { gap: 2, marginTop: 1, children: [
65
+ /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
66
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "User:" }),
67
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: userId })
68
+ ] }),
69
+ /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
70
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Org:" }),
71
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: orgId })
72
+ ] })
73
+ ] })
74
+ ] })
75
+ ] });
76
+ };
18
77
 
19
78
  // src/constants.ts
20
79
  var TEMPLATE_SOURCES = {
@@ -49,10 +108,6 @@ var TARGET_PERMISSION_MAP = {
49
108
  "slot.footer": [],
50
109
  "slot.footer-links": []
51
110
  };
52
-
53
- // src/components/StepShell.tsx
54
- import { Box, Text, useInput } from "ink";
55
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
56
111
  var divider = (width) => "\u2500".repeat(width);
57
112
  var INNER_DIVIDER_WIDTH = 40;
58
113
  var StepShell = ({ title, hint, children, footer, onBack }) => {
@@ -82,9 +137,6 @@ var StepShell = ({ title, hint, children, footer, onBack }) => {
82
137
  ] })
83
138
  ] });
84
139
  };
85
-
86
- // src/components/Confirm.tsx
87
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
88
140
  var compareSemver = (a, b) => {
89
141
  const pa = a.split(".").map(Number);
90
142
  const pb = b.split(".").map(Number);
@@ -97,7 +149,7 @@ var compareSemver = (a, b) => {
97
149
  var VersionRow = ({ currentVersion, value, onChange, onFocusChange, onConfirm, onCancel, selected }) => {
98
150
  const { isFocused } = useFocus();
99
151
  const { focusPrevious, focusNext } = useFocusManager();
100
- useInput2((_, key) => {
152
+ useInput((_, key) => {
101
153
  if (!isFocused) return;
102
154
  if (key.upArrow) {
103
155
  focusPrevious();
@@ -120,17 +172,17 @@ var VersionRow = ({ currentVersion, value, onChange, onFocusChange, onConfirm, o
120
172
  const isValid = /^\d+\.\d+\.\d+$/.test(value) && compareSemver(value, currentVersion) > 0;
121
173
  const showError = isFocused && value !== "" && !isValid;
122
174
  const hasChange = value !== currentVersion;
123
- return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
124
- /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
125
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Version " }),
126
- /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
175
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
176
+ /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
177
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Version " }),
178
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
127
179
  currentVersion,
128
180
  hasChange ? " \u2192 " : ""
129
181
  ] }),
130
- isFocused ? /* @__PURE__ */ jsx2(TextInput, { value, onChange, placeholder: value }) : hasChange && /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: value }),
131
- isFocused && /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "(edit to override)" })
182
+ isFocused ? /* @__PURE__ */ jsx(TextInput, { value, onChange, placeholder: value }) : hasChange && /* @__PURE__ */ jsx(Text, { dimColor: true, children: value }),
183
+ isFocused && /* @__PURE__ */ jsx(Text, { dimColor: true, children: "(edit to override)" })
132
184
  ] }),
133
- showError && /* @__PURE__ */ jsx2(Text2, { color: "red", children: " Version must be greater than " + currentVersion })
185
+ showError && /* @__PURE__ */ jsx(Text, { color: "red", children: " Version must be greater than " + currentVersion })
134
186
  ] });
135
187
  };
136
188
  var Confirm = ({
@@ -157,7 +209,7 @@ var Confirm = ({
157
209
  }) => {
158
210
  const [selected, setSelected] = useState("y");
159
211
  const [overrideFocused, setOverrideFocused] = useState(false);
160
- useInput2((input, key) => {
212
+ useInput((input, key) => {
161
213
  if (overrideFocused) return;
162
214
  if (key.leftArrow || key.rightArrow) {
163
215
  setSelected((s) => s === "y" ? "n" : "y");
@@ -181,29 +233,29 @@ var Confirm = ({
181
233
  }
182
234
  }
183
235
  });
184
- return /* @__PURE__ */ jsx2(
236
+ return /* @__PURE__ */ jsx(
185
237
  StepShell,
186
238
  {
187
239
  title: command === "update" /* UPDATE */ ? "Ready to update" : "Ready to scaffold",
188
240
  hint: "Review your settings before proceeding",
189
241
  onBack,
190
- footer: /* @__PURE__ */ jsxs2(Text2, { children: [
242
+ footer: /* @__PURE__ */ jsxs(Text, { children: [
191
243
  "Proceed?",
192
244
  " ",
193
- /* @__PURE__ */ jsx2(Text2, { bold: true, color: "green", inverse: selected === "y", children: "Y" }),
194
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "/" }),
195
- /* @__PURE__ */ jsx2(Text2, { bold: true, color: "red", inverse: selected === "n", children: "n" })
245
+ /* @__PURE__ */ jsx(Text, { bold: true, color: "green", inverse: selected === "y", children: "Y" }),
246
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "/" }),
247
+ /* @__PURE__ */ jsx(Text, { bold: true, color: "red", inverse: selected === "n", children: "n" })
196
248
  ] }),
197
- children: /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", gap: 1, children: [
198
- /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
199
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Name " }),
200
- /* @__PURE__ */ jsx2(Text2, { dimColor: !!extensionVersion, children: name })
249
+ children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
250
+ /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
251
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Name " }),
252
+ /* @__PURE__ */ jsx(Text, { dimColor: !!extensionVersion, children: name })
201
253
  ] }),
202
- templateFlavor && /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
203
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Template " }),
204
- /* @__PURE__ */ jsx2(Text2, { children: TEMPLATE_FLAVOR_META[templateFlavor].label })
254
+ templateFlavor && /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
255
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Template " }),
256
+ /* @__PURE__ */ jsx(Text, { children: TEMPLATE_FLAVOR_META[templateFlavor].label })
205
257
  ] }),
206
- extensionVersion && command === "update" /* UPDATE */ && newVersion && onVersionOverride && /* @__PURE__ */ jsx2(
258
+ extensionVersion && command === "update" /* UPDATE */ && newVersion && onVersionOverride && /* @__PURE__ */ jsx(
207
259
  VersionRow,
208
260
  {
209
261
  currentVersion: extensionVersion,
@@ -215,84 +267,84 @@ var Confirm = ({
215
267
  selected
216
268
  }
217
269
  ),
218
- extensionVersion && !(command === "update" /* UPDATE */ && newVersion && onVersionOverride) && /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
219
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Version " }),
220
- /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
270
+ extensionVersion && !(command === "update" /* UPDATE */ && newVersion && onVersionOverride) && /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
271
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Version " }),
272
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
221
273
  extensionVersion,
222
274
  newVersion && newVersion !== extensionVersion ? ` \u2192 ${newVersion}` : ""
223
275
  ] })
224
276
  ] }),
225
- command !== "update" /* UPDATE */ && outputDir && /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
226
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Directory " }),
227
- /* @__PURE__ */ jsx2(Text2, { children: outputDir })
277
+ command !== "update" /* UPDATE */ && outputDir && /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
278
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Directory " }),
279
+ /* @__PURE__ */ jsx(Text, { children: outputDir })
228
280
  ] }),
229
- command !== "update" /* UPDATE */ && extensionPort !== void 0 && /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
230
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Extension port" }),
231
- /* @__PURE__ */ jsx2(Text2, { children: extensionPort })
281
+ command !== "update" /* UPDATE */ && extensionPort !== void 0 && /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
282
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Extension port" }),
283
+ /* @__PURE__ */ jsx(Text, { children: extensionPort })
232
284
  ] }),
233
- command !== "update" /* UPDATE */ && previewPort !== void 0 && /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
234
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Preview port " }),
235
- /* @__PURE__ */ jsx2(Text2, { children: previewPort })
285
+ command !== "update" /* UPDATE */ && previewPort !== void 0 && /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
286
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Preview port " }),
287
+ /* @__PURE__ */ jsx(Text, { children: previewPort })
236
288
  ] }),
237
- command === "update" /* UPDATE */ && bundleUrl && /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
238
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Bundle URL " }),
239
- /* @__PURE__ */ jsx2(Text2, { children: bundleUrl })
289
+ command === "update" /* UPDATE */ && bundleUrl && /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
290
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Bundle URL " }),
291
+ /* @__PURE__ */ jsx(Text, { children: bundleUrl })
240
292
  ] }),
241
- command === "update" /* UPDATE */ && enabled !== void 0 && /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
242
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Enabled " }),
243
- /* @__PURE__ */ jsx2(Text2, { color: enabled ? "green" : "red", children: enabled ? "Yes" : "No" })
293
+ command === "update" /* UPDATE */ && enabled !== void 0 && /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
294
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Enabled " }),
295
+ /* @__PURE__ */ jsx(Text, { color: enabled ? "green" : "red", children: enabled ? "Yes" : "No" })
244
296
  ] }),
245
- /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
246
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Targets " }),
247
- /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
297
+ /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
298
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Targets " }),
299
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
248
300
  targets.map((t) => {
249
301
  const isAdded = registryTargets && !registryTargets.includes(t);
250
- return /* @__PURE__ */ jsxs2(Box2, { gap: 1, children: [
251
- /* @__PURE__ */ jsx2(Text2, { color: "green", children: "\u2022 " }),
252
- /* @__PURE__ */ jsx2(Text2, { children: t }),
253
- isAdded && /* @__PURE__ */ jsx2(Text2, { color: "green", dimColor: true, children: "(+ added)" })
302
+ return /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
303
+ /* @__PURE__ */ jsx(Text, { color: "green", children: "\u2022 " }),
304
+ /* @__PURE__ */ jsx(Text, { children: t }),
305
+ isAdded && /* @__PURE__ */ jsx(Text, { color: "green", dimColor: true, children: "(+ added)" })
254
306
  ] }, t);
255
307
  }),
256
- registryTargets?.filter((t) => !targets.includes(t)).map((t) => /* @__PURE__ */ jsxs2(Box2, { gap: 1, children: [
257
- /* @__PURE__ */ jsx2(Text2, { color: "red", children: "\u2022 " }),
258
- /* @__PURE__ */ jsx2(Text2, { color: "red", dimColor: true, strikethrough: true, children: t }),
259
- /* @__PURE__ */ jsx2(Text2, { color: "red", dimColor: true, children: "(- removed)" })
308
+ registryTargets?.filter((t) => !targets.includes(t)).map((t) => /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
309
+ /* @__PURE__ */ jsx(Text, { color: "red", children: "\u2022 " }),
310
+ /* @__PURE__ */ jsx(Text, { color: "red", dimColor: true, strikethrough: true, children: t }),
311
+ /* @__PURE__ */ jsx(Text, { color: "red", dimColor: true, children: "(- removed)" })
260
312
  ] }, t))
261
313
  ] })
262
314
  ] }),
263
- permissions && (permissions.length > 0 || registryPermissions?.some((p) => !permissions.includes(p))) && /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
264
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Permissions " }),
265
- /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
315
+ permissions && (permissions.length > 0 || registryPermissions?.some((p) => !permissions.includes(p))) && /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
316
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Permissions " }),
317
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
266
318
  permissions.map((p) => {
267
319
  const isAdded = registryPermissions && !registryPermissions.includes(p);
268
- return /* @__PURE__ */ jsxs2(Box2, { gap: 1, children: [
269
- /* @__PURE__ */ jsx2(Text2, { color: "green", children: "\u2022 " }),
270
- /* @__PURE__ */ jsx2(Text2, { children: p }),
271
- isAdded && /* @__PURE__ */ jsx2(Text2, { color: "green", dimColor: true, children: "(+ added)" })
320
+ return /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
321
+ /* @__PURE__ */ jsx(Text, { color: "green", children: "\u2022 " }),
322
+ /* @__PURE__ */ jsx(Text, { children: p }),
323
+ isAdded && /* @__PURE__ */ jsx(Text, { color: "green", dimColor: true, children: "(+ added)" })
272
324
  ] }, p);
273
325
  }),
274
- registryPermissions?.filter((p) => !permissions.includes(p)).map((p) => /* @__PURE__ */ jsxs2(Box2, { gap: 1, children: [
275
- /* @__PURE__ */ jsx2(Text2, { color: "red", children: "\u2022 " }),
276
- /* @__PURE__ */ jsx2(Text2, { color: "red", dimColor: true, strikethrough: true, children: p }),
277
- /* @__PURE__ */ jsx2(Text2, { color: "red", dimColor: true, children: "(- removed)" })
326
+ registryPermissions?.filter((p) => !permissions.includes(p)).map((p) => /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
327
+ /* @__PURE__ */ jsx(Text, { color: "red", children: "\u2022 " }),
328
+ /* @__PURE__ */ jsx(Text, { color: "red", dimColor: true, strikethrough: true, children: p }),
329
+ /* @__PURE__ */ jsx(Text, { color: "red", dimColor: true, children: "(- removed)" })
278
330
  ] }, p))
279
331
  ] })
280
332
  ] }),
281
- allowedDomains && (allowedDomains.length > 0 || registryAllowedDomains?.some((d) => !allowedDomains.includes(d))) && /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
282
- /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Domains " }),
283
- /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
333
+ allowedDomains && (allowedDomains.length > 0 || registryAllowedDomains?.some((d) => !allowedDomains.includes(d))) && /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
334
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Domains " }),
335
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
284
336
  allowedDomains.map((d) => {
285
337
  const isAdded = registryAllowedDomains && !registryAllowedDomains.includes(d);
286
- return /* @__PURE__ */ jsxs2(Box2, { gap: 1, children: [
287
- /* @__PURE__ */ jsx2(Text2, { color: "green", children: "\u2022 " }),
288
- /* @__PURE__ */ jsx2(Text2, { children: d }),
289
- isAdded && /* @__PURE__ */ jsx2(Text2, { color: "green", dimColor: true, children: "(+ added)" })
338
+ return /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
339
+ /* @__PURE__ */ jsx(Text, { color: "green", children: "\u2022 " }),
340
+ /* @__PURE__ */ jsx(Text, { children: d }),
341
+ isAdded && /* @__PURE__ */ jsx(Text, { color: "green", dimColor: true, children: "(+ added)" })
290
342
  ] }, d);
291
343
  }),
292
- registryAllowedDomains?.filter((d) => !allowedDomains.includes(d)).map((d) => /* @__PURE__ */ jsxs2(Box2, { gap: 1, children: [
293
- /* @__PURE__ */ jsx2(Text2, { color: "red", children: "\u2022 " }),
294
- /* @__PURE__ */ jsx2(Text2, { color: "red", dimColor: true, strikethrough: true, children: d }),
295
- /* @__PURE__ */ jsx2(Text2, { color: "red", dimColor: true, children: "(- removed)" })
344
+ registryAllowedDomains?.filter((d) => !allowedDomains.includes(d)).map((d) => /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
345
+ /* @__PURE__ */ jsx(Text, { color: "red", children: "\u2022 " }),
346
+ /* @__PURE__ */ jsx(Text, { color: "red", dimColor: true, strikethrough: true, children: d }),
347
+ /* @__PURE__ */ jsx(Text, { color: "red", dimColor: true, children: "(- removed)" })
296
348
  ] }, d))
297
349
  ] })
298
350
  ] })
@@ -300,75 +352,59 @@ var Confirm = ({
300
352
  }
301
353
  );
302
354
  };
303
-
304
- // src/components/Done.tsx
305
- import { Box as Box3, Text as Text3 } from "ink";
306
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
307
355
  var FLAVOR_HINTS = {
308
356
  minimal: "A clean slate \u2014 add surfaces and capabilities as you need them.",
309
357
  starter: "Common patterns included \u2014 customize and build from here.",
310
358
  "kitchen-sink": "We threw in everything \u2014 including the kitchen sink. Poke around, steal patterns, then delete what you don't need."
311
359
  };
312
- var Done = ({ name, outputDir, templateFlavor }) => /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", gap: 1, children: [
313
- /* @__PURE__ */ jsxs3(Box3, { gap: 1, children: [
314
- /* @__PURE__ */ jsx3(Text3, { color: "green", bold: true, children: "\u2714" }),
315
- /* @__PURE__ */ jsx3(Text3, { bold: true, children: "Extension scaffolded successfully!" })
360
+ var Done = ({ name, outputDir, templateFlavor }) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
361
+ /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
362
+ /* @__PURE__ */ jsx(Text, { color: "green", bold: true, children: "\u2714" }),
363
+ /* @__PURE__ */ jsx(Text, { bold: true, children: "Extension scaffolded successfully!" })
316
364
  ] }),
317
- /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginLeft: 2, children: [
318
- /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
365
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [
366
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
319
367
  "Created: ",
320
- /* @__PURE__ */ jsx3(Text3, { color: "cyan", children: name })
368
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: name })
321
369
  ] }),
322
- templateFlavor && /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
370
+ templateFlavor && /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
323
371
  "Template: ",
324
- /* @__PURE__ */ jsx3(Text3, { color: "cyan", children: TEMPLATE_FLAVOR_META[templateFlavor].label })
372
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: TEMPLATE_FLAVOR_META[templateFlavor].label })
325
373
  ] }),
326
- /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
374
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
327
375
  "Location: ",
328
- /* @__PURE__ */ jsx3(Text3, { color: "cyan", children: outputDir })
376
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: outputDir })
329
377
  ] })
330
378
  ] }),
331
- templateFlavor && /* @__PURE__ */ jsx3(Box3, { marginLeft: 2, children: /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: FLAVOR_HINTS[templateFlavor] }) }),
332
- /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginTop: 1, borderStyle: "round", borderColor: "green", paddingX: 2, paddingY: 1, children: [
333
- /* @__PURE__ */ jsx3(Text3, { bold: true, children: "Next steps:" }),
334
- /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginTop: 1, gap: 1, children: [
335
- /* @__PURE__ */ jsxs3(Box3, { gap: 1, children: [
336
- /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "1." }),
337
- /* @__PURE__ */ jsxs3(Text3, { children: [
338
- /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "cd " }),
339
- /* @__PURE__ */ jsx3(Text3, { color: "cyan", children: outputDir })
379
+ templateFlavor && /* @__PURE__ */ jsx(Box, { marginLeft: 2, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: FLAVOR_HINTS[templateFlavor] }) }),
380
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, borderStyle: "round", borderColor: "green", paddingX: 2, paddingY: 1, children: [
381
+ /* @__PURE__ */ jsx(Text, { bold: true, children: "Next steps:" }),
382
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, gap: 1, children: [
383
+ /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
384
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "1." }),
385
+ /* @__PURE__ */ jsxs(Text, { children: [
386
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "cd " }),
387
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: outputDir })
340
388
  ] })
341
389
  ] }),
342
- /* @__PURE__ */ jsxs3(Box3, { gap: 1, children: [
343
- /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "2." }),
344
- /* @__PURE__ */ jsx3(Text3, { color: "cyan", children: "pnpm install" })
390
+ /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
391
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "2." }),
392
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: "pnpm install" })
345
393
  ] }),
346
- /* @__PURE__ */ jsxs3(Box3, { gap: 1, children: [
347
- /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "3." }),
348
- /* @__PURE__ */ jsx3(Text3, { color: "cyan", children: "pnpm dev" })
394
+ /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
395
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "3." }),
396
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: "pnpm dev" })
349
397
  ] })
350
398
  ] })
351
399
  ] })
352
400
  ] });
353
-
354
- // src/components/NamePrompt.tsx
355
- import { Box as Box5, Text as Text5 } from "ink";
356
- import TextInput2 from "ink-text-input";
357
- import { useState as useState2 } from "react";
358
-
359
- // src/components/BackableInput.tsx
360
- import { Box as Box4, Text as Text4 } from "ink";
361
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
362
- var BackableInput = ({ label, hint, onBack, children, error }) => /* @__PURE__ */ jsx4(StepShell, { title: label, hint, onBack, children: /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", gap: 1, children: [
401
+ var BackableInput = ({ label, hint, onBack, children, error }) => /* @__PURE__ */ jsx(StepShell, { title: label, hint, onBack, children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
363
402
  children(true),
364
- error && /* @__PURE__ */ jsx4(Text4, { color: "red", children: error })
403
+ error && /* @__PURE__ */ jsx(Text, { color: "red", children: error })
365
404
  ] }) });
366
-
367
- // src/components/NamePrompt.tsx
368
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
369
405
  var NamePrompt = ({ initialValue = "", onSubmit, onBack }) => {
370
- const [value, setValue] = useState2(initialValue);
371
- const [error, setError] = useState2();
406
+ const [value, setValue] = useState(initialValue);
407
+ const [error, setError] = useState();
372
408
  const handleSubmit = (val) => {
373
409
  const trimmed = val.trim();
374
410
  if (trimmed.length === 0) {
@@ -378,33 +414,27 @@ var NamePrompt = ({ initialValue = "", onSubmit, onBack }) => {
378
414
  setError(void 0);
379
415
  onSubmit(trimmed);
380
416
  };
381
- return /* @__PURE__ */ jsx5(BackableInput, { label: "What is your Extension name?", hint: "Press Enter to confirm", onBack, error, children: (isFocused) => /* @__PURE__ */ jsxs5(Box5, { children: [
382
- /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "> " }),
383
- /* @__PURE__ */ jsx5(TextInput2, { value, onChange: setValue, onSubmit: handleSubmit, focus: isFocused })
417
+ return /* @__PURE__ */ jsx(BackableInput, { label: "What is your Extension name?", hint: "Press Enter to confirm", onBack, error, children: (isFocused) => /* @__PURE__ */ jsxs(Box, { children: [
418
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "> " }),
419
+ /* @__PURE__ */ jsx(TextInput, { value, onChange: setValue, onSubmit: handleSubmit, focus: isFocused })
384
420
  ] }) });
385
421
  };
386
-
387
- // src/components/SettingsPrompt.tsx
388
- import { Box as Box6, Text as Text6, useFocus as useFocus2, useFocusManager as useFocusManager2, useInput as useInput3 } from "ink";
389
- import TextInput3 from "ink-text-input";
390
- import { useState as useState3 } from "react";
391
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
392
422
  var DEFAULT_EXTENSION_PORT = 6543;
393
423
  var DEFAULT_PREVIEW_PORT = DEFAULT_EXTENSION_PORT + 1;
394
424
  var FieldRow = ({ label, value, onChange, onSubmit, onConfirm, placeholder, autoFocus, isFirst, isLast }) => {
395
- const { isFocused } = useFocus2({ autoFocus });
396
- const { focusNext, focusPrevious } = useFocusManager2();
397
- useInput3((_input, key) => {
425
+ const { isFocused } = useFocus({ autoFocus });
426
+ const { focusNext, focusPrevious } = useFocusManager();
427
+ useInput((_input, key) => {
398
428
  if (!isFocused) return;
399
429
  if (key.downArrow && !isLast) focusNext();
400
430
  if (key.upArrow && !isFirst) focusPrevious();
401
431
  });
402
- return /* @__PURE__ */ jsxs6(Box6, { gap: 2, children: [
403
- /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: label }),
404
- isFocused ? /* @__PURE__ */ jsxs6(Box6, { children: [
405
- /* @__PURE__ */ jsx6(Text6, { color: "cyan", children: "\u2192 " }),
406
- /* @__PURE__ */ jsx6(
407
- TextInput3,
432
+ return /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
433
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: label }),
434
+ isFocused ? /* @__PURE__ */ jsxs(Box, { children: [
435
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u2192 " }),
436
+ /* @__PURE__ */ jsx(
437
+ TextInput,
408
438
  {
409
439
  value,
410
440
  onChange,
@@ -416,13 +446,13 @@ var FieldRow = ({ label, value, onChange, onSubmit, onConfirm, placeholder, auto
416
446
  focus: isFocused
417
447
  }
418
448
  )
419
- ] }) : /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: value })
449
+ ] }) : /* @__PURE__ */ jsx(Text, { dimColor: true, children: value })
420
450
  ] });
421
451
  };
422
452
  var SettingsPrompt = ({ defaultDir, onSubmit, onBack }) => {
423
- const [extensionPort, setExtensionPort] = useState3(String(DEFAULT_EXTENSION_PORT));
424
- const [previewPort, setPreviewPort] = useState3(String(DEFAULT_PREVIEW_PORT));
425
- const [outputDir, setOutputDir] = useState3(defaultDir);
453
+ const [extensionPort, setExtensionPort] = useState(String(DEFAULT_EXTENSION_PORT));
454
+ const [previewPort, setPreviewPort] = useState(String(DEFAULT_PREVIEW_PORT));
455
+ const [outputDir, setOutputDir] = useState(defaultDir);
426
456
  const handleConfirm = (resolvedExtPort, resolvedPrevPort, resolvedDir) => {
427
457
  const dir = resolvedDir.trim();
428
458
  if (!dir) return;
@@ -453,14 +483,14 @@ var SettingsPrompt = ({ defaultDir, onSubmit, onBack }) => {
453
483
  setOutputDir(trimmed);
454
484
  return [extensionPort, previewPort, trimmed];
455
485
  };
456
- return /* @__PURE__ */ jsx6(
486
+ return /* @__PURE__ */ jsx(
457
487
  StepShell,
458
488
  {
459
489
  title: "Project settings",
460
490
  hint: "\u2191\u2193 or Tab to move between fields, Enter to confirm",
461
491
  onBack,
462
- children: /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", gap: 1, children: [
463
- /* @__PURE__ */ jsx6(
492
+ children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
493
+ /* @__PURE__ */ jsx(
464
494
  FieldRow,
465
495
  {
466
496
  label: "Extension port ",
@@ -473,7 +503,7 @@ var SettingsPrompt = ({ defaultDir, onSubmit, onBack }) => {
473
503
  isFirst: true
474
504
  }
475
505
  ),
476
- /* @__PURE__ */ jsx6(
506
+ /* @__PURE__ */ jsx(
477
507
  FieldRow,
478
508
  {
479
509
  label: "Preview port ",
@@ -484,7 +514,7 @@ var SettingsPrompt = ({ defaultDir, onSubmit, onBack }) => {
484
514
  placeholder: String(DEFAULT_PREVIEW_PORT)
485
515
  }
486
516
  ),
487
- /* @__PURE__ */ jsx6(
517
+ /* @__PURE__ */ jsx(
488
518
  FieldRow,
489
519
  {
490
520
  label: "Output directory",
@@ -500,10 +530,6 @@ var SettingsPrompt = ({ defaultDir, onSubmit, onBack }) => {
500
530
  );
501
531
  };
502
532
 
503
- // src/components/ManifestReviewPrompt.tsx
504
- import { Box as Box7, Text as Text7, useInput as useInput4 } from "ink";
505
- import { useState as useState4 } from "react";
506
-
507
533
  // src/lib/manifest-diff.ts
508
534
  var diffManifestValues = (localValues, registryValues) => {
509
535
  const localSet = new Set(localValues ?? []);
@@ -518,9 +544,6 @@ var diffManifestValues = (localValues, registryValues) => {
518
544
  return inRegistry ? { value, status: "unchanged", enabled: true } : { value, status: "new", enabled: false };
519
545
  });
520
546
  };
521
-
522
- // src/components/ManifestReviewPrompt.tsx
523
- import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
524
547
  var statusLabel = (status) => {
525
548
  switch (status) {
526
549
  case "new":
@@ -547,9 +570,9 @@ var ManifestReviewPrompt = ({
547
570
  onSubmit,
548
571
  onBack
549
572
  }) => {
550
- const [permItems, setPermItems] = useState4(() => diffManifestValues(localManifest?.permissions, registryManifest.permissions));
551
- const [domainItems, setDomainItems] = useState4(() => diffManifestValues(localManifest?.allowedDomains, registryManifest.allowedDomains));
552
- const [cursor, setCursor] = useState4(0);
573
+ const [permItems, setPermItems] = useState(() => diffManifestValues(localManifest?.permissions, registryManifest.permissions));
574
+ const [domainItems, setDomainItems] = useState(() => diffManifestValues(localManifest?.allowedDomains, registryManifest.allowedDomains));
575
+ const [cursor, setCursor] = useState(0);
553
576
  const totalItems = permItems.length + domainItems.length;
554
577
  const cursorInPerms = cursor < permItems.length;
555
578
  const cursorInDomains = cursor >= permItems.length;
@@ -568,7 +591,7 @@ var ManifestReviewPrompt = ({
568
591
  });
569
592
  };
570
593
  const domainSectionStart = permItems.length;
571
- useInput4((input, key) => {
594
+ useInput((input, key) => {
572
595
  if (key.downArrow) {
573
596
  setCursor((c) => Math.min(c + 1, totalItems - 1));
574
597
  return;
@@ -601,49 +624,43 @@ var ManifestReviewPrompt = ({
601
624
  });
602
625
  const renderItem = (item, index) => {
603
626
  const isCursor = index === cursor;
604
- return /* @__PURE__ */ jsxs7(Box7, { gap: 1, children: [
605
- /* @__PURE__ */ jsx7(Text7, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u276F" : " " }),
606
- /* @__PURE__ */ jsx7(Text7, { color: item.enabled ? "green" : "gray", children: item.enabled ? "\u25C9" : "\u25CB" }),
607
- /* @__PURE__ */ jsx7(Text7, { bold: isCursor, children: item.value }),
608
- statusLabel(item.status) && /* @__PURE__ */ jsx7(Text7, { color: statusColor(item.status), dimColor: true, children: statusLabel(item.status) })
627
+ return /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
628
+ /* @__PURE__ */ jsx(Text, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u276F" : " " }),
629
+ /* @__PURE__ */ jsx(Text, { color: item.enabled ? "green" : "gray", children: item.enabled ? "\u25C9" : "\u25CB" }),
630
+ /* @__PURE__ */ jsx(Text, { bold: isCursor, children: item.value }),
631
+ statusLabel(item.status) && /* @__PURE__ */ jsx(Text, { color: statusColor(item.status), dimColor: true, children: statusLabel(item.status) })
609
632
  ] }, item.value);
610
633
  };
611
- return /* @__PURE__ */ jsx7(
634
+ return /* @__PURE__ */ jsx(
612
635
  StepShell,
613
636
  {
614
637
  title: "Review Manifest changes",
615
638
  hint: "Tab/shift-tab to jump section, \u2191/\u2193 navigate. Enter to submit",
616
639
  onBack,
617
- children: /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", gap: 1, children: [
618
- !localManifest && /* @__PURE__ */ jsx7(Text7, { color: "yellow", children: "No local manifest.json found \u2014 showing registry values only" }),
619
- /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
620
- /* @__PURE__ */ jsx7(Text7, { dimColor: !cursorInPerms, bold: cursorInPerms, children: "Permissions".padEnd(14) }),
621
- /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", paddingLeft: 2, children: [
622
- permItems.length > 0 ? permItems.map((item, i) => renderItem(item, i)) : /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: " (none)" }),
623
- cursorInPerms && /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: " (space to toggle)" })
640
+ children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
641
+ !localManifest && /* @__PURE__ */ jsx(Text, { color: "yellow", children: "No local manifest.json found \u2014 showing registry values only" }),
642
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
643
+ /* @__PURE__ */ jsx(Text, { dimColor: !cursorInPerms, bold: cursorInPerms, children: "Permissions".padEnd(14) }),
644
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingLeft: 2, children: [
645
+ permItems.length > 0 ? permItems.map((item, i) => renderItem(item, i)) : /* @__PURE__ */ jsx(Text, { dimColor: true, children: " (none)" }),
646
+ cursorInPerms && /* @__PURE__ */ jsx(Text, { dimColor: true, children: " (space to toggle)" })
624
647
  ] })
625
648
  ] }),
626
- /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
627
- /* @__PURE__ */ jsx7(Text7, { dimColor: !cursorInDomains, bold: cursorInDomains, children: "Allowed Domains".padEnd(14) }),
628
- /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", paddingLeft: 2, children: [
629
- domainItems.length > 0 ? domainItems.map((item, i) => renderItem(item, i + permItems.length)) : /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: " (none)" }),
630
- cursorInDomains && /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: " (space to toggle)" })
649
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
650
+ /* @__PURE__ */ jsx(Text, { dimColor: !cursorInDomains, bold: cursorInDomains, children: "Allowed Domains".padEnd(14) }),
651
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingLeft: 2, children: [
652
+ domainItems.length > 0 ? domainItems.map((item, i) => renderItem(item, i + permItems.length)) : /* @__PURE__ */ jsx(Text, { dimColor: true, children: " (none)" }),
653
+ cursorInDomains && /* @__PURE__ */ jsx(Text, { dimColor: true, children: " (space to toggle)" })
631
654
  ] })
632
655
  ] })
633
656
  ] })
634
657
  }
635
658
  );
636
659
  };
637
-
638
- // src/components/UpdateSettingsPrompt.tsx
639
- import { Box as Box8, Text as Text8, useFocus as useFocus3, useFocusManager as useFocusManager3, useInput as useInput5 } from "ink";
640
- import TextInput4 from "ink-text-input";
641
- import { useState as useState5 } from "react";
642
- import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
643
660
  var FieldRow2 = ({ label, value, onChange, placeholder, autoFocus, isFirst, isLast, onSubmitAll }) => {
644
- const { isFocused } = useFocus3({ autoFocus });
645
- const { focusNext, focusPrevious } = useFocusManager3();
646
- useInput5((_, key) => {
661
+ const { isFocused } = useFocus({ autoFocus });
662
+ const { focusNext, focusPrevious } = useFocusManager();
663
+ useInput((_, key) => {
647
664
  if (!isFocused) return;
648
665
  if (key.downArrow) {
649
666
  if (!isLast) focusNext();
@@ -657,16 +674,16 @@ var FieldRow2 = ({ label, value, onChange, placeholder, autoFocus, isFirst, isLa
657
674
  onSubmitAll();
658
675
  }
659
676
  });
660
- return /* @__PURE__ */ jsxs8(Box8, { gap: 2, children: [
661
- /* @__PURE__ */ jsx8(Text8, { dimColor: !isFocused, bold: isFocused, children: label.padEnd(14) }),
662
- isFocused ? /* @__PURE__ */ jsx8(TextInput4, { value, onChange, placeholder }) : /* @__PURE__ */ jsx8(Text8, { dimColor: true, children: value || placeholder || "" })
677
+ return /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
678
+ /* @__PURE__ */ jsx(Text, { dimColor: !isFocused, bold: isFocused, children: label.padEnd(14) }),
679
+ isFocused ? /* @__PURE__ */ jsx(TextInput, { value, onChange, placeholder }) : /* @__PURE__ */ jsx(Text, { dimColor: true, children: value || placeholder || "" })
663
680
  ] });
664
681
  };
665
682
  var TargetToggleRow = ({ targets, availableTargets, onToggle, autoFocus, isLast, onSubmitAll }) => {
666
- const { isFocused } = useFocus3({ autoFocus });
667
- const { focusNext, focusPrevious } = useFocusManager3();
668
- const [cursor, setCursor] = useState5(0);
669
- useInput5((input, key) => {
683
+ const { isFocused } = useFocus({ autoFocus });
684
+ const { focusNext, focusPrevious } = useFocusManager();
685
+ const [cursor, setCursor] = useState(0);
686
+ useInput((input, key) => {
670
687
  if (!isFocused) return;
671
688
  if (key.downArrow) {
672
689
  if (cursor < availableTargets.length - 1) {
@@ -692,26 +709,26 @@ var TargetToggleRow = ({ targets, availableTargets, onToggle, autoFocus, isLast,
692
709
  onSubmitAll();
693
710
  }
694
711
  });
695
- return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
696
- /* @__PURE__ */ jsx8(Text8, { dimColor: !isFocused, bold: isFocused, children: "Targets".padEnd(14) }),
697
- /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", paddingLeft: 2, children: [
712
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
713
+ /* @__PURE__ */ jsx(Text, { dimColor: !isFocused, bold: isFocused, children: "Targets".padEnd(14) }),
714
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingLeft: 2, children: [
698
715
  availableTargets.map((t, i) => {
699
716
  const selected = targets.includes(t);
700
717
  const isCursor = isFocused && i === cursor;
701
- return /* @__PURE__ */ jsxs8(Box8, { gap: 1, children: [
702
- /* @__PURE__ */ jsx8(Text8, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u276F" : " " }),
703
- /* @__PURE__ */ jsx8(Text8, { color: selected ? "green" : "gray", children: selected ? "\u25C9" : "\u25CB" }),
704
- /* @__PURE__ */ jsx8(Text8, { bold: isCursor, children: t })
718
+ return /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
719
+ /* @__PURE__ */ jsx(Text, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u276F" : " " }),
720
+ /* @__PURE__ */ jsx(Text, { color: selected ? "green" : "gray", children: selected ? "\u25C9" : "\u25CB" }),
721
+ /* @__PURE__ */ jsx(Text, { bold: isCursor, children: t })
705
722
  ] }, t);
706
723
  }),
707
- isFocused && /* @__PURE__ */ jsx8(Text8, { dimColor: true, children: " (space to toggle)" })
724
+ isFocused && /* @__PURE__ */ jsx(Text, { dimColor: true, children: " (space to toggle)" })
708
725
  ] })
709
726
  ] });
710
727
  };
711
728
  var EnabledToggleRow = ({ enabled, onToggle, autoFocus, isLast, onSubmitAll }) => {
712
- const { isFocused } = useFocus3({ autoFocus });
713
- const { focusNext, focusPrevious } = useFocusManager3();
714
- useInput5((input, key) => {
729
+ const { isFocused } = useFocus({ autoFocus });
730
+ const { focusNext, focusPrevious } = useFocusManager();
731
+ useInput((input, key) => {
715
732
  if (!isFocused) return;
716
733
  if (key.downArrow) {
717
734
  if (!isLast) focusNext();
@@ -729,16 +746,16 @@ var EnabledToggleRow = ({ enabled, onToggle, autoFocus, isLast, onSubmitAll }) =
729
746
  onSubmitAll();
730
747
  }
731
748
  });
732
- return /* @__PURE__ */ jsxs8(Box8, { gap: 2, children: [
733
- /* @__PURE__ */ jsx8(Text8, { dimColor: !isFocused, bold: isFocused, children: "Enabled".padEnd(14) }),
734
- /* @__PURE__ */ jsx8(Text8, { color: enabled ? "green" : "red", bold: isFocused, children: enabled ? "Yes" : "No" }),
735
- isFocused && /* @__PURE__ */ jsx8(Text8, { dimColor: true, children: "(space/arrows to toggle)" })
749
+ return /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
750
+ /* @__PURE__ */ jsx(Text, { dimColor: !isFocused, bold: isFocused, children: "Enabled".padEnd(14) }),
751
+ /* @__PURE__ */ jsx(Text, { color: enabled ? "green" : "red", bold: isFocused, children: enabled ? "Yes" : "No" }),
752
+ isFocused && /* @__PURE__ */ jsx(Text, { dimColor: true, children: "(space/arrows to toggle)" })
736
753
  ] });
737
754
  };
738
755
  var ForceMajorToggleRow = ({ forceMajor, onToggle, autoFocus, isLast, onSubmitAll }) => {
739
- const { isFocused } = useFocus3({ autoFocus });
740
- const { focusPrevious, focusNext } = useFocusManager3();
741
- useInput5((input, key) => {
756
+ const { isFocused } = useFocus({ autoFocus });
757
+ const { focusPrevious, focusNext } = useFocusManager();
758
+ useInput((input, key) => {
742
759
  if (!isFocused) return;
743
760
  if (key.downArrow) {
744
761
  if (!isLast) focusNext();
@@ -756,10 +773,10 @@ var ForceMajorToggleRow = ({ forceMajor, onToggle, autoFocus, isLast, onSubmitAl
756
773
  onSubmitAll();
757
774
  }
758
775
  });
759
- return /* @__PURE__ */ jsxs8(Box8, { gap: 2, children: [
760
- /* @__PURE__ */ jsx8(Text8, { dimColor: !isFocused, bold: isFocused, children: "Force major".padEnd(14) }),
761
- /* @__PURE__ */ jsx8(Text8, { color: forceMajor ? "yellow" : "gray", bold: isFocused, children: forceMajor ? "Yes" : "No" }),
762
- isFocused && /* @__PURE__ */ jsx8(Text8, { dimColor: true, children: "(space/arrows to toggle)" })
776
+ return /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
777
+ /* @__PURE__ */ jsx(Text, { dimColor: !isFocused, bold: isFocused, children: "Force major".padEnd(14) }),
778
+ /* @__PURE__ */ jsx(Text, { color: forceMajor ? "yellow" : "gray", bold: isFocused, children: forceMajor ? "Yes" : "No" }),
779
+ isFocused && /* @__PURE__ */ jsx(Text, { dimColor: true, children: "(space/arrows to toggle)" })
763
780
  ] });
764
781
  };
765
782
  var UpdateSettingsPrompt = ({
@@ -767,15 +784,17 @@ var UpdateSettingsPrompt = ({
767
784
  targets: initialTargets,
768
785
  availableTargets,
769
786
  bundleUrl: initialBundleUrl,
787
+ allowedDomains: initialAllowedDomains,
770
788
  enabled: initialEnabled,
771
789
  onSubmit,
772
790
  onBack
773
791
  }) => {
774
- const [nameValue, setNameValue] = useState5(initialName);
775
- const [targetsValue, setTargetsValue] = useState5(initialTargets);
776
- const [bundleUrlValue, setBundleUrlValue] = useState5(initialBundleUrl);
777
- const [enabledValue, setEnabledValue] = useState5(initialEnabled);
778
- const [forceMajorValue, setForceMajorValue] = useState5(false);
792
+ const [nameValue, setNameValue] = useState(initialName);
793
+ const [targetsValue, setTargetsValue] = useState(initialTargets);
794
+ const [bundleUrlValue, setBundleUrlValue] = useState(initialBundleUrl);
795
+ const [allowedDomainsValue, setAllowedDomainsValue] = useState(initialAllowedDomains.join(", "));
796
+ const [enabledValue, setEnabledValue] = useState(initialEnabled);
797
+ const [forceMajorValue, setForceMajorValue] = useState(false);
779
798
  const handleToggleTarget = (target) => {
780
799
  setTargetsValue((prev) => prev.includes(target) ? prev.filter((t) => t !== target) : [...prev, target]);
781
800
  };
@@ -785,18 +804,19 @@ var UpdateSettingsPrompt = ({
785
804
  name: nameValue,
786
805
  targets: targetsValue,
787
806
  bundleUrl: bundleUrlValue,
807
+ allowedDomains: allowedDomainsValue.split(",").map((d) => d.trim()).filter(Boolean),
788
808
  enabled: enabledValue,
789
809
  forceMajor: forceMajorValue
790
810
  });
791
811
  };
792
- return /* @__PURE__ */ jsx8(
812
+ return /* @__PURE__ */ jsx(
793
813
  StepShell,
794
814
  {
795
815
  title: "Update Extension settings",
796
816
  hint: "Tab/shift-tab to jump section, \u2191/\u2193 navigate. Enter to submit",
797
817
  onBack,
798
- children: /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", gap: 1, children: [
799
- /* @__PURE__ */ jsx8(
818
+ children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
819
+ /* @__PURE__ */ jsx(
800
820
  FieldRow2,
801
821
  {
802
822
  label: "Name",
@@ -808,7 +828,7 @@ var UpdateSettingsPrompt = ({
808
828
  onSubmitAll: handleSubmitAll
809
829
  }
810
830
  ),
811
- /* @__PURE__ */ jsx8(
831
+ /* @__PURE__ */ jsx(
812
832
  TargetToggleRow,
813
833
  {
814
834
  targets: targetsValue,
@@ -817,7 +837,7 @@ var UpdateSettingsPrompt = ({
817
837
  onSubmitAll: handleSubmitAll
818
838
  }
819
839
  ),
820
- /* @__PURE__ */ jsx8(
840
+ /* @__PURE__ */ jsx(
821
841
  FieldRow2,
822
842
  {
823
843
  label: "Bundle URL",
@@ -827,7 +847,17 @@ var UpdateSettingsPrompt = ({
827
847
  onSubmitAll: handleSubmitAll
828
848
  }
829
849
  ),
830
- /* @__PURE__ */ jsx8(
850
+ /* @__PURE__ */ jsx(
851
+ FieldRow2,
852
+ {
853
+ label: "Allowed Domains",
854
+ value: allowedDomainsValue,
855
+ onChange: setAllowedDomainsValue,
856
+ placeholder: "api.example.com, cdn.example.com",
857
+ onSubmitAll: handleSubmitAll
858
+ }
859
+ ),
860
+ /* @__PURE__ */ jsx(
831
861
  EnabledToggleRow,
832
862
  {
833
863
  enabled: enabledValue,
@@ -835,7 +865,7 @@ var UpdateSettingsPrompt = ({
835
865
  onSubmitAll: handleSubmitAll
836
866
  }
837
867
  ),
838
- /* @__PURE__ */ jsx8(
868
+ /* @__PURE__ */ jsx(
839
869
  ForceMajorToggleRow,
840
870
  {
841
871
  forceMajor: forceMajorValue,
@@ -848,35 +878,25 @@ var UpdateSettingsPrompt = ({
848
878
  }
849
879
  );
850
880
  };
851
-
852
- // src/components/ScaffoldProgress.tsx
853
- import { Box as Box9, Text as Text9 } from "ink";
854
- import Spinner from "ink-spinner";
855
- import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
856
881
  var stepIcon = (status) => {
857
882
  switch (status) {
858
883
  case "running":
859
- return /* @__PURE__ */ jsx9(Spinner, { type: "dots" });
884
+ return /* @__PURE__ */ jsx(Spinner5, { type: "dots" });
860
885
  case "done":
861
- return /* @__PURE__ */ jsx9(Text9, { color: "green", children: "\u2714" });
886
+ return /* @__PURE__ */ jsx(Text, { color: "green", children: "\u2714" });
862
887
  case "error":
863
- return /* @__PURE__ */ jsx9(Text9, { color: "red", children: "\u2716" });
888
+ return /* @__PURE__ */ jsx(Text, { color: "red", children: "\u2716" });
864
889
  default:
865
- return /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "\u25CB" });
890
+ return /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u25CB" });
866
891
  }
867
892
  };
868
- var ScaffoldProgress = ({ steps }) => /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", gap: 1, children: [
869
- /* @__PURE__ */ jsx9(Text9, { bold: true, children: "Scaffolding your Extension\u2026" }),
870
- /* @__PURE__ */ jsx9(Box9, { flexDirection: "column", children: steps.map((step) => /* @__PURE__ */ jsxs9(Box9, { gap: 2, children: [
893
+ var ScaffoldProgress = ({ steps }) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
894
+ /* @__PURE__ */ jsx(Text, { bold: true, children: "Scaffolding your Extension\u2026" }),
895
+ /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: steps.map((step) => /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
871
896
  stepIcon(step.status),
872
- /* @__PURE__ */ jsx9(Text9, { dimColor: step.status === "pending", color: step.status === "running" ? "cyan" : void 0, children: step.label })
897
+ /* @__PURE__ */ jsx(Text, { dimColor: step.status === "pending", color: step.status === "running" ? "cyan" : void 0, children: step.label })
873
898
  ] }, step.label)) })
874
899
  ] });
875
-
876
- // src/components/TargetSelect.tsx
877
- import { Box as Box10, Text as Text10, useInput as useInput6 } from "ink";
878
- import { useState as useState6 } from "react";
879
- import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
880
900
  var TARGET_DESCRIPTIONS = {
881
901
  "slot.header": "Renders content in the panel header area",
882
902
  "slot.content": "Renders the main panel body (includes store + navigation state)",
@@ -884,12 +904,12 @@ var TARGET_DESCRIPTIONS = {
884
904
  "slot.footer-links": "Renders a link row in the global footer"
885
905
  };
886
906
  var TargetSelect = ({ availableTargets, preSelected, onSubmit, onBack }) => {
887
- const [cursor, setCursor] = useState6(0);
888
- const [selected, setSelected] = useState6(
907
+ const [cursor, setCursor] = useState(0);
908
+ const [selected, setSelected] = useState(
889
909
  new Set(preSelected ?? (availableTargets.includes("slot.content") ? ["slot.content"] : []))
890
910
  );
891
- const [error, setError] = useState6();
892
- useInput6((input, key) => {
911
+ const [error, setError] = useState();
912
+ useInput((input, key) => {
893
913
  if (key.upArrow) {
894
914
  setCursor((c) => Math.max(0, c - 1));
895
915
  return;
@@ -920,39 +940,34 @@ var TargetSelect = ({ availableTargets, preSelected, onSubmit, onBack }) => {
920
940
  onSubmit([...selected]);
921
941
  }
922
942
  });
923
- return /* @__PURE__ */ jsxs10(
943
+ return /* @__PURE__ */ jsxs(
924
944
  StepShell,
925
945
  {
926
946
  title: "Select Surface targets/slots",
927
947
  hint: "Space to toggle, Enter to confirm",
928
948
  onBack,
929
949
  children: [
930
- /* @__PURE__ */ jsx10(Box10, { flexDirection: "column", gap: 1, children: availableTargets.map((target, i) => {
950
+ /* @__PURE__ */ jsx(Box, { flexDirection: "column", gap: 1, children: availableTargets.map((target, i) => {
931
951
  const isSelected = selected.has(target);
932
952
  const isCursor = i === cursor;
933
- return /* @__PURE__ */ jsxs10(Box10, { gap: 1, children: [
934
- /* @__PURE__ */ jsx10(Text10, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u276F" : " " }),
935
- /* @__PURE__ */ jsx10(Text10, { color: isSelected ? "green" : void 0, children: isSelected ? "\u25C9" : "\u25CB" }),
936
- /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
937
- /* @__PURE__ */ jsx10(Text10, { bold: isSelected, children: target }),
938
- /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: TARGET_DESCRIPTIONS[target] ?? target })
953
+ return /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
954
+ /* @__PURE__ */ jsx(Text, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u276F" : " " }),
955
+ /* @__PURE__ */ jsx(Text, { color: isSelected ? "green" : void 0, children: isSelected ? "\u25C9" : "\u25CB" }),
956
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
957
+ /* @__PURE__ */ jsx(Text, { bold: isSelected, children: target }),
958
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: TARGET_DESCRIPTIONS[target] ?? target })
939
959
  ] })
940
960
  ] }, target);
941
961
  }) }),
942
- error && /* @__PURE__ */ jsx10(Text10, { color: "red", children: error })
962
+ error && /* @__PURE__ */ jsx(Text, { color: "red", children: error })
943
963
  ]
944
964
  }
945
965
  );
946
966
  };
947
-
948
- // src/components/TemplateSelect.tsx
949
- import { Box as Box11, Text as Text11, useInput as useInput7 } from "ink";
950
- import { useState as useState7 } from "react";
951
- import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
952
967
  var FLAVORS = ["minimal", "starter", "kitchen-sink"];
953
968
  var TemplateSelect = ({ onSubmit, onBack }) => {
954
- const [cursor, setCursor] = useState7(1);
955
- useInput7((_input, key) => {
969
+ const [cursor, setCursor] = useState(1);
970
+ useInput((_input, key) => {
956
971
  if (key.upArrow) {
957
972
  setCursor((c) => Math.max(0, c - 1));
958
973
  return;
@@ -965,21 +980,21 @@ var TemplateSelect = ({ onSubmit, onBack }) => {
965
980
  onSubmit(FLAVORS[cursor]);
966
981
  }
967
982
  });
968
- return /* @__PURE__ */ jsx11(
983
+ return /* @__PURE__ */ jsx(
969
984
  StepShell,
970
985
  {
971
986
  title: "Choose a template",
972
987
  hint: "\u2191\u2193 to navigate, Enter to select",
973
988
  onBack,
974
- children: /* @__PURE__ */ jsx11(Box11, { flexDirection: "column", gap: 1, children: FLAVORS.map((flavor, i) => {
989
+ children: /* @__PURE__ */ jsx(Box, { flexDirection: "column", gap: 1, children: FLAVORS.map((flavor, i) => {
975
990
  const meta = TEMPLATE_FLAVOR_META[flavor];
976
991
  const isCursor = i === cursor;
977
- return /* @__PURE__ */ jsxs11(Box11, { gap: 1, children: [
978
- /* @__PURE__ */ jsx11(Text11, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u276F" : " " }),
979
- /* @__PURE__ */ jsx11(Text11, { color: isCursor ? "green" : void 0, children: isCursor ? "\u25C9" : "\u25CB" }),
980
- /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
981
- /* @__PURE__ */ jsx11(Text11, { bold: isCursor, children: meta.label }),
982
- /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: meta.description })
992
+ return /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
993
+ /* @__PURE__ */ jsx(Text, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u276F" : " " }),
994
+ /* @__PURE__ */ jsx(Text, { color: isCursor ? "green" : void 0, children: isCursor ? "\u25C9" : "\u25CB" }),
995
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
996
+ /* @__PURE__ */ jsx(Text, { bold: isCursor, children: meta.label }),
997
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: meta.description })
983
998
  ] })
984
999
  ] }, flavor);
985
1000
  }) })
@@ -987,14 +1002,11 @@ var TemplateSelect = ({ onSubmit, onBack }) => {
987
1002
  );
988
1003
  };
989
1004
 
990
- // src/components/AppSelect.tsx
991
- import { Box as Box13, Text as Text13, useInput as useInput8 } from "ink";
992
- import Spinner2 from "ink-spinner";
993
- import { useEffect as useEffect2, useState as useState8 } from "react";
994
-
995
1005
  // src/lib/api.ts
996
1006
  var DEFAULT_ADMIN_API_URL = "https://api-use1.stackablelabs.io/admin";
1007
+ var DEFAULT_PUBLIC_API_URL = "https://api.stackablelabs.io/app-extension/v1";
997
1008
  var getAdminApiBaseUrl = () => process.env.ADMIN_API_BASE_URL ?? DEFAULT_ADMIN_API_URL;
1009
+ var getPublicApiBaseUrl = () => process.env.APP_EXTENSION_API_BASE_URL ?? DEFAULT_PUBLIC_API_URL;
998
1010
  var CLI_CLIENT_NAME = "@stackable-labs/cli-app-extension";
999
1011
  var authHeaders = (token) => ({
1000
1012
  authorization: `Bearer ${token}`,
@@ -1053,6 +1065,26 @@ var fetchExtensions = async (token, appId) => {
1053
1065
  ])
1054
1066
  );
1055
1067
  };
1068
+ var resolveAppForExtension = async (token, extensionId) => {
1069
+ const apps = await fetchApps(token);
1070
+ const publicBaseUrl = getPublicApiBaseUrl();
1071
+ for (const app of apps) {
1072
+ try {
1073
+ const res = await fetch(`${publicBaseUrl}/extensions/${app.id}`, {
1074
+ headers: authHeaders(token)
1075
+ });
1076
+ if (!res.ok) continue;
1077
+ const extensions = await res.json();
1078
+ const ext = extensions[extensionId];
1079
+ if (ext) {
1080
+ return { app, extension: ext };
1081
+ }
1082
+ } catch {
1083
+ continue;
1084
+ }
1085
+ }
1086
+ return null;
1087
+ };
1056
1088
  var fetchProject = async (token, appId, projectId) => {
1057
1089
  const baseUrl = getAdminApiBaseUrl();
1058
1090
  const res = await fetch(`${baseUrl}/app-extension/${appId}/projects/${projectId}`, {
@@ -1101,74 +1133,15 @@ var updateExtension = async (token, appId, extensionId, payload) => {
1101
1133
  throw new Error(`Failed to update extension: ${res.status} ${body}`);
1102
1134
  }
1103
1135
  };
1104
-
1105
- // src/components/Banner.tsx
1106
- import { Box as Box12, Text as Text12 } from "ink";
1107
- import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
1108
- var WORDMARK = [
1109
- " _ _ _ _ ",
1110
- " ___| |_ __ _ ___| | ____ _| |__ | | ___",
1111
- "/ __| __/ _` |/ __| |/ / _` | '_ \\| |/ _ \\",
1112
- "\\__ \\ || (_| | (__| < (_| | |_) | | __/",
1113
- "|___/\\__\\__,_|\\___|_|\\_\\__,_|_.__/|_|\\___|"
1114
- ];
1115
- var COLORS = [
1116
- [232, 218, 234],
1117
- // Lit Lilac #E8DAEA
1118
- [197, 96, 255],
1119
- // Poppy Purple #C560FF
1120
- [0, 174, 247],
1121
- // Bluetooth Blue #00AEF7
1122
- [70, 224, 177],
1123
- // Tropical Teal #46E0B1
1124
- [252, 248, 161]
1125
- // Not Mellow Yellow #FCF8A1
1126
- ];
1127
- var lerp = (a, b, t) => {
1128
- const r = Math.round(a[0] + (b[0] - a[0]) * t);
1129
- const g = Math.round(a[1] + (b[1] - a[1]) * t);
1130
- const bl = Math.round(a[2] + (b[2] - a[2]) * t);
1131
- return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${bl.toString(16).padStart(2, "0")}`;
1132
- };
1133
- var gradientColor = (row, col, rows, cols) => {
1134
- const t = (row / (rows - 1) + col / (cols - 1)) / 2;
1135
- const idx = t * (COLORS.length - 1);
1136
- const lo = Math.floor(idx);
1137
- const hi = Math.min(lo + 1, COLORS.length - 1);
1138
- return lerp(COLORS[lo], COLORS[hi], idx - lo);
1139
- };
1140
- var Banner = ({ userId, orgId } = {}) => {
1141
- const termWidth = process.stdout.columns ?? 80;
1142
- const maxLen = Math.max(...WORDMARK.map((l) => l.length));
1143
- return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", children: [
1144
- /* @__PURE__ */ jsx12(Text12, { dimColor: true, children: "\u2500".repeat(termWidth) }),
1145
- /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", paddingX: 1, paddingY: 1, children: [
1146
- WORDMARK.map((line, row) => /* @__PURE__ */ jsx12(Box12, { children: line.split("").map((ch, col) => /* @__PURE__ */ jsx12(Text12, { bold: true, color: ch === " " ? void 0 : gradientColor(row, col, WORDMARK.length, maxLen), children: ch }, col)) }, row)),
1147
- userId && orgId && /* @__PURE__ */ jsxs12(Box12, { gap: 2, marginTop: 1, children: [
1148
- /* @__PURE__ */ jsxs12(Box12, { gap: 1, children: [
1149
- /* @__PURE__ */ jsx12(Text12, { dimColor: true, children: "User:" }),
1150
- /* @__PURE__ */ jsx12(Text12, { color: "cyan", children: userId })
1151
- ] }),
1152
- /* @__PURE__ */ jsxs12(Box12, { gap: 1, children: [
1153
- /* @__PURE__ */ jsx12(Text12, { dimColor: true, children: "Org:" }),
1154
- /* @__PURE__ */ jsx12(Text12, { color: "cyan", children: orgId })
1155
- ] })
1156
- ] })
1157
- ] })
1158
- ] });
1159
- };
1160
-
1161
- // src/components/AppSelect.tsx
1162
- import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
1163
1136
  var AppSelect = ({ token, userId, orgId, onSubmit }) => {
1164
- const [apps, setApps] = useState8([]);
1165
- const [loading, setLoading] = useState8(true);
1166
- const [error, setError] = useState8();
1167
- const [cursor, setCursor] = useState8(0);
1168
- useEffect2(() => {
1137
+ const [apps, setApps] = useState([]);
1138
+ const [loading, setLoading] = useState(true);
1139
+ const [error, setError] = useState();
1140
+ const [cursor, setCursor] = useState(0);
1141
+ useEffect(() => {
1169
1142
  fetchApps(token).then(setApps).catch((err) => setError(err instanceof Error ? err.message : String(err))).finally(() => setLoading(false));
1170
1143
  }, [token]);
1171
- useInput8((_, key) => {
1144
+ useInput((_, key) => {
1172
1145
  if (loading || error || apps.length === 0) return;
1173
1146
  if (key.upArrow) {
1174
1147
  setCursor((c) => Math.max(0, c - 1));
@@ -1180,26 +1153,26 @@ var AppSelect = ({ token, userId, orgId, onSubmit }) => {
1180
1153
  });
1181
1154
  const renderContent = () => {
1182
1155
  if (loading) {
1183
- return /* @__PURE__ */ jsxs13(Box13, { gap: 2, children: [
1184
- /* @__PURE__ */ jsx13(Spinner2, { type: "dots" }),
1185
- /* @__PURE__ */ jsx13(Text13, { children: "Loading available Apps\u2026" })
1156
+ return /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
1157
+ /* @__PURE__ */ jsx(Spinner5, { type: "dots" }),
1158
+ /* @__PURE__ */ jsx(Text, { children: "Loading available Apps\u2026" })
1186
1159
  ] });
1187
1160
  }
1188
1161
  if (error) {
1189
- return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", gap: 1, children: [
1190
- /* @__PURE__ */ jsx13(Text13, { color: "red", bold: true, children: "Failed to load Apps" }),
1191
- /* @__PURE__ */ jsx13(Text13, { color: "red", children: error })
1162
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
1163
+ /* @__PURE__ */ jsx(Text, { color: "red", bold: true, children: "Failed to load Apps" }),
1164
+ /* @__PURE__ */ jsx(Text, { color: "red", children: error })
1192
1165
  ] });
1193
1166
  }
1194
1167
  if (apps.length === 0) {
1195
- return /* @__PURE__ */ jsx13(Text13, { color: "yellow", children: "No Apps available. Contact your administrator." });
1168
+ return /* @__PURE__ */ jsx(Text, { color: "yellow", children: "No Apps available. Contact your administrator." });
1196
1169
  }
1197
- return /* @__PURE__ */ jsx13(Box13, { flexDirection: "column", children: apps.map((app, i) => {
1170
+ return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: apps.map((app, i) => {
1198
1171
  const isCursor = i === cursor;
1199
- return /* @__PURE__ */ jsxs13(Box13, { gap: 1, children: [
1200
- /* @__PURE__ */ jsx13(Text13, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u276F" : " " }),
1201
- /* @__PURE__ */ jsx13(Text13, { bold: isCursor, children: app.name }),
1202
- /* @__PURE__ */ jsxs13(Text13, { dimColor: true, children: [
1172
+ return /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
1173
+ /* @__PURE__ */ jsx(Text, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u276F" : " " }),
1174
+ /* @__PURE__ */ jsx(Text, { bold: isCursor, children: app.name }),
1175
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1203
1176
  "(",
1204
1177
  app.id,
1205
1178
  ")"
@@ -1207,26 +1180,20 @@ var AppSelect = ({ token, userId, orgId, onSubmit }) => {
1207
1180
  ] }, app.id);
1208
1181
  }) });
1209
1182
  };
1210
- return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", children: [
1211
- /* @__PURE__ */ jsx13(Banner, { userId, orgId }),
1212
- /* @__PURE__ */ jsx13(StepShell, { title: "Select the App you are building an Extension for:", children: renderContent() })
1183
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
1184
+ /* @__PURE__ */ jsx(Banner, { userId, orgId }),
1185
+ /* @__PURE__ */ jsx(StepShell, { title: "Select the App you are building an Extension for:", children: renderContent() })
1213
1186
  ] });
1214
1187
  };
1215
-
1216
- // src/components/ExtensionSelect.tsx
1217
- import { Box as Box14, Text as Text14, useInput as useInput9 } from "ink";
1218
- import Spinner3 from "ink-spinner";
1219
- import { useEffect as useEffect3, useState as useState9 } from "react";
1220
- import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
1221
1188
  var ExtensionSelect = ({ appId, token, command, onSubmit, onBack }) => {
1222
- const [extensions, setExtensions] = useState9([]);
1223
- const [loading, setLoading] = useState9(true);
1224
- const [error, setError] = useState9();
1225
- const [cursor, setCursor] = useState9(0);
1226
- useEffect3(() => {
1189
+ const [extensions, setExtensions] = useState([]);
1190
+ const [loading, setLoading] = useState(true);
1191
+ const [error, setError] = useState();
1192
+ const [cursor, setCursor] = useState(0);
1193
+ useEffect(() => {
1227
1194
  fetchExtensions(token, appId).then((byId) => setExtensions(Object.values(byId))).catch((err) => setError(err instanceof Error ? err.message : String(err))).finally(() => setLoading(false));
1228
1195
  }, [appId, token]);
1229
- useInput9((_, key) => {
1196
+ useInput((_, key) => {
1230
1197
  if (key.upArrow) {
1231
1198
  if (!loading && !error && extensions.length > 0) {
1232
1199
  setCursor((c) => Math.max(0, c - 1));
@@ -1247,30 +1214,30 @@ var ExtensionSelect = ({ appId, token, command, onSubmit, onBack }) => {
1247
1214
  });
1248
1215
  const renderContent = () => {
1249
1216
  if (loading) {
1250
- return /* @__PURE__ */ jsxs14(Box14, { gap: 2, children: [
1251
- /* @__PURE__ */ jsx14(Spinner3, { type: "dots" }),
1252
- /* @__PURE__ */ jsx14(Text14, { children: "Loading Extensions\u2026" })
1217
+ return /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
1218
+ /* @__PURE__ */ jsx(Spinner5, { type: "dots" }),
1219
+ /* @__PURE__ */ jsx(Text, { children: "Loading Extensions\u2026" })
1253
1220
  ] });
1254
1221
  }
1255
1222
  if (error) {
1256
- return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", gap: 1, children: [
1257
- /* @__PURE__ */ jsx14(Text14, { color: "red", bold: true, children: "Failed to load Extensions" }),
1258
- /* @__PURE__ */ jsx14(Text14, { color: "red", children: error })
1223
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
1224
+ /* @__PURE__ */ jsx(Text, { color: "red", bold: true, children: "Failed to load Extensions" }),
1225
+ /* @__PURE__ */ jsx(Text, { color: "red", children: error })
1259
1226
  ] });
1260
1227
  }
1261
1228
  if (extensions.length === 0) {
1262
- return /* @__PURE__ */ jsx14(Text14, { color: "yellow", children: "No Extensions found for this App." });
1229
+ return /* @__PURE__ */ jsx(Text, { color: "yellow", children: "No Extensions found for this App." });
1263
1230
  }
1264
- return /* @__PURE__ */ jsx14(Box14, { flexDirection: "column", children: extensions.map((ext, i) => {
1231
+ return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: extensions.map((ext, i) => {
1265
1232
  const isCursor = i === cursor;
1266
- return /* @__PURE__ */ jsxs14(Box14, { gap: 1, children: [
1267
- /* @__PURE__ */ jsx14(Text14, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u276F" : " " }),
1268
- /* @__PURE__ */ jsx14(Text14, { bold: isCursor, children: ext.manifest.name }),
1269
- /* @__PURE__ */ jsxs14(Text14, { dimColor: true, children: [
1233
+ return /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
1234
+ /* @__PURE__ */ jsx(Text, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u276F" : " " }),
1235
+ /* @__PURE__ */ jsx(Text, { bold: isCursor, children: ext.manifest.name }),
1236
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1270
1237
  "v",
1271
1238
  ext.manifest.version
1272
1239
  ] }),
1273
- /* @__PURE__ */ jsxs14(Text14, { dimColor: true, children: [
1240
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1274
1241
  "(",
1275
1242
  ext.id,
1276
1243
  ")"
@@ -1278,7 +1245,7 @@ var ExtensionSelect = ({ appId, token, command, onSubmit, onBack }) => {
1278
1245
  ] }, ext.id);
1279
1246
  }) });
1280
1247
  };
1281
- return /* @__PURE__ */ jsx14(
1248
+ return /* @__PURE__ */ jsx(
1282
1249
  StepShell,
1283
1250
  {
1284
1251
  title: command === "update" /* UPDATE */ ? "Select an Extension to update:" : "Select an existing Extension to scaffold:",
@@ -1287,11 +1254,87 @@ var ExtensionSelect = ({ appId, token, command, onSubmit, onBack }) => {
1287
1254
  }
1288
1255
  );
1289
1256
  };
1290
-
1291
- // src/lib/postScaffold.ts
1292
- import { execFile } from "child_process";
1293
- import { promisify } from "util";
1294
- import { installDependencies } from "nypm";
1257
+ var STEPS = {
1258
+ ["create" /* CREATE */]: ["app", "name", "template", "targets", "settings", "confirm"],
1259
+ ["scaffold" /* SCAFFOLD */]: ["app", "extensionSelect", "template", "confirmTargets", "settings", "confirm"],
1260
+ ["update" /* UPDATE */]: ["app", "extensionSelect", "updateSettings", "manifestReview", "confirm"],
1261
+ ["dev" /* DEV */]: []
1262
+ };
1263
+ var computeActiveSteps = (conditions) => {
1264
+ const { command, initialName, initialExtensionId, templateFlavor, studioProject, options } = conditions;
1265
+ const base = STEPS[command];
1266
+ const skipped = /* @__PURE__ */ new Set();
1267
+ if (command === "create" /* CREATE */ && initialName) skipped.add("name");
1268
+ if (command === "create" /* CREATE */ && options?.template) skipped.add("template");
1269
+ if (command === "create" /* CREATE */ && TEMPLATE_FLAVOR_META[templateFlavor].skipTargetStep) {
1270
+ skipped.add("targets");
1271
+ }
1272
+ if (options?.extensionPort || options?.previewPort) skipped.add("settings");
1273
+ if (options?.appId) skipped.add("app");
1274
+ if (initialExtensionId && (command === "update" /* UPDATE */ || command === "scaffold" /* SCAFFOLD */)) {
1275
+ skipped.add("app");
1276
+ skipped.add("extensionSelect");
1277
+ }
1278
+ if (studioProject) {
1279
+ if (command === "create" /* CREATE */) {
1280
+ skipped.add("template");
1281
+ }
1282
+ if (command === "scaffold" /* SCAFFOLD */) {
1283
+ skipped.add("template");
1284
+ if (studioProject.extensionId) {
1285
+ skipped.add("extensionSelect");
1286
+ }
1287
+ }
1288
+ }
1289
+ if (command === "scaffold" /* SCAFFOLD */ && (options?.template || conditions.hasLocalProject)) {
1290
+ skipped.add("template");
1291
+ }
1292
+ return base.filter((s) => !skipped.has(s));
1293
+ };
1294
+ var useWizardSteps = (opts) => {
1295
+ const [step, setStep] = useState("app");
1296
+ const activeSteps = useMemo(
1297
+ () => computeActiveSteps(opts),
1298
+ [
1299
+ opts.command,
1300
+ opts.initialName,
1301
+ opts.initialExtensionId,
1302
+ opts.templateFlavor,
1303
+ opts.studioProject,
1304
+ opts.hasLocalProject,
1305
+ opts.options?.template,
1306
+ opts.options?.extensionPort,
1307
+ opts.options?.previewPort,
1308
+ opts.options?.appId
1309
+ ]
1310
+ );
1311
+ const goForward = useCallback(
1312
+ (overrides) => {
1313
+ setStep((prev) => {
1314
+ const steps = computeActiveSteps({ ...opts, ...overrides });
1315
+ const idx = steps.indexOf(prev);
1316
+ if (idx >= 0 && idx < steps.length - 1) {
1317
+ return steps[idx + 1];
1318
+ }
1319
+ if (idx === -1 && steps.length > 0) {
1320
+ return steps[0];
1321
+ }
1322
+ return prev;
1323
+ });
1324
+ },
1325
+ [opts]
1326
+ );
1327
+ const goBack = useCallback(() => {
1328
+ setStep((prev) => {
1329
+ const idx = activeSteps.indexOf(prev);
1330
+ return idx > 0 ? activeSteps[idx - 1] : prev;
1331
+ });
1332
+ }, [activeSteps]);
1333
+ const goTo = useCallback((target) => {
1334
+ setStep(target);
1335
+ }, []);
1336
+ return { step, activeSteps, goForward, goBack, goTo };
1337
+ };
1295
1338
  var execFileAsync = promisify(execFile);
1296
1339
  var gitInit = async (dir) => {
1297
1340
  try {
@@ -1305,19 +1348,10 @@ var postScaffold = async (options) => {
1305
1348
  if (!options.skipGit) {
1306
1349
  await gitInit(options.outputDir);
1307
1350
  }
1308
- if (!options.skipInstall) {
1351
+ {
1309
1352
  await installDependencies({ cwd: options.outputDir, silent: true });
1310
1353
  }
1311
1354
  };
1312
-
1313
- // src/lib/scaffold.ts
1314
- import { readFile as readFile2, readdir, rm, writeFile as writeFile2 } from "fs/promises";
1315
- import { join as join2 } from "path";
1316
- import { downloadTemplate } from "giget";
1317
-
1318
- // src/lib/devContext.ts
1319
- import { readFile, writeFile } from "fs/promises";
1320
- import { join } from "path";
1321
1355
  var parseEnvFile = (content) => {
1322
1356
  const lines = content.split("\n");
1323
1357
  const env = {};
@@ -1421,7 +1455,7 @@ var deriveScaffoldPermissions = (targets) => {
1421
1455
  };
1422
1456
  var upsertOrRemove = async (filePath, shouldExist, content) => {
1423
1457
  if (shouldExist) {
1424
- await writeFile2(filePath, content);
1458
+ await writeFile(filePath, content);
1425
1459
  return;
1426
1460
  }
1427
1461
  await rm(filePath, { force: true });
@@ -1433,7 +1467,7 @@ var walkFiles = async (rootDir) => {
1433
1467
  if (entry.name === ".git" || entry.name === "node_modules" || entry.name === "dist") {
1434
1468
  continue;
1435
1469
  }
1436
- const fullPath = join2(rootDir, entry.name);
1470
+ const fullPath = join(rootDir, entry.name);
1437
1471
  if (entry.isDirectory()) {
1438
1472
  files.push(...await walkFiles(fullPath));
1439
1473
  continue;
@@ -1448,7 +1482,7 @@ var replacePlaceholders = async (rootDir, replacements) => {
1448
1482
  if (!isTextFile(filePath)) {
1449
1483
  continue;
1450
1484
  }
1451
- let content = await readFile2(filePath, "utf8");
1485
+ let content = await readFile(filePath, "utf8");
1452
1486
  let changed = false;
1453
1487
  for (const [needle, value] of Object.entries(replacements)) {
1454
1488
  if (content.includes(needle)) {
@@ -1457,18 +1491,18 @@ var replacePlaceholders = async (rootDir, replacements) => {
1457
1491
  }
1458
1492
  }
1459
1493
  if (changed) {
1460
- await writeFile2(filePath, content);
1494
+ await writeFile(filePath, content);
1461
1495
  }
1462
1496
  }
1463
1497
  };
1464
1498
  var generateManifest = async (rootDir, extensionName, targets, permissions) => {
1465
- const manifestPath = join2(rootDir, "packages/extension/public/manifest.json");
1466
- const raw = await readFile2(manifestPath, "utf8");
1499
+ const manifestPath = join(rootDir, "packages/extension/public/manifest.json");
1500
+ const raw = await readFile(manifestPath, "utf8");
1467
1501
  const manifest = JSON.parse(raw);
1468
1502
  manifest.name = extensionName;
1469
1503
  manifest.targets = targets;
1470
1504
  manifest.permissions = permissions;
1471
- await writeFile2(manifestPath, `${JSON.stringify(manifest, null, 2)}
1505
+ await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}
1472
1506
  `);
1473
1507
  };
1474
1508
  var buildFooterSurface = (targets) => {
@@ -1495,12 +1529,12 @@ ${blocks.join("\n")}
1495
1529
  `;
1496
1530
  };
1497
1531
  var generateSurfaceFiles = async (rootDir, targets) => {
1498
- const surfaceDir = join2(rootDir, "packages/extension/src/surfaces");
1532
+ const surfaceDir = join(rootDir, "packages/extension/src/surfaces");
1499
1533
  const wantsHeader = targets.includes("slot.header");
1500
1534
  const wantsContent = targets.includes("slot.content");
1501
1535
  const wantsFooter = targets.includes("slot.footer") || targets.includes("slot.footer-links");
1502
1536
  await upsertOrRemove(
1503
- join2(surfaceDir, "Header.tsx"),
1537
+ join(surfaceDir, "Header.tsx"),
1504
1538
  wantsHeader,
1505
1539
  `import { ui, Surface } from '@stackable-labs/sdk-extension-react'
1506
1540
 
@@ -1514,7 +1548,7 @@ export function Header() {
1514
1548
  `
1515
1549
  );
1516
1550
  await upsertOrRemove(
1517
- join2(surfaceDir, "Content.tsx"),
1551
+ join(surfaceDir, "Content.tsx"),
1518
1552
  wantsContent,
1519
1553
  `import { ui, useStore, useContextData, Surface } from '@stackable-labs/sdk-extension-react'
1520
1554
  import { appStore } from '../store'
@@ -1547,14 +1581,14 @@ export function Content() {
1547
1581
  `
1548
1582
  );
1549
1583
  await upsertOrRemove(
1550
- join2(rootDir, "packages/extension/src/store.ts"),
1584
+ join(rootDir, "packages/extension/src/store.ts"),
1551
1585
  wantsContent,
1552
1586
  "import { createStore } from '@stackable-labs/sdk-extension-react'\n\nexport type ViewState = { type: 'menu' }\n\nexport interface AppState {\n viewState: ViewState\n}\n\nexport const appStore = createStore<AppState>({\n viewState: { type: 'menu' },\n})\n"
1553
1587
  );
1554
- await upsertOrRemove(join2(surfaceDir, "Footer.tsx"), wantsFooter, buildFooterSurface(targets));
1588
+ await upsertOrRemove(join(surfaceDir, "Footer.tsx"), wantsFooter, buildFooterSurface(targets));
1555
1589
  };
1556
1590
  var rewriteExtensionIndex = async (rootDir, extensionId, targets) => {
1557
- const indexPath = join2(rootDir, "packages/extension/src/index.tsx");
1591
+ const indexPath = join(rootDir, "packages/extension/src/index.tsx");
1558
1592
  const imports = ["import { createExtension } from '@stackable-labs/sdk-extension-react'"];
1559
1593
  const components = [];
1560
1594
  if (targets.includes("slot.header")) {
@@ -1580,10 +1614,10 @@ ${components.join("\n")}
1580
1614
  { extensionId: '${toKebabCase(extensionId)}' },
1581
1615
  )
1582
1616
  `;
1583
- await writeFile2(indexPath, content);
1617
+ await writeFile(indexPath, content);
1584
1618
  };
1585
1619
  var rewritePreviewApp = async (rootDir, targets, permissions) => {
1586
- const appPath = join2(rootDir, "packages/preview/src/App.tsx");
1620
+ const appPath = join(rootDir, "packages/preview/src/App.tsx");
1587
1621
  const includeDataQuery = permissions.includes("data:query");
1588
1622
  const includeToast = permissions.includes("actions:toast");
1589
1623
  const includeInvoke = permissions.includes("actions:invoke");
@@ -1662,17 +1696,17 @@ export default function App() {
1662
1696
  )
1663
1697
  }
1664
1698
  `;
1665
- await writeFile2(appPath, appContent);
1699
+ await writeFile(appPath, appContent);
1666
1700
  };
1667
1701
  var patchViteAllowedHosts = async (rootDir) => {
1668
1702
  const configs = [
1669
- join2(rootDir, "packages/extension/vite.config.ts"),
1670
- join2(rootDir, "packages/preview/vite.config.ts")
1703
+ join(rootDir, "packages/extension/vite.config.ts"),
1704
+ join(rootDir, "packages/preview/vite.config.ts")
1671
1705
  ];
1672
1706
  for (const configPath of configs) {
1673
1707
  let content;
1674
1708
  try {
1675
- content = await readFile2(configPath, "utf8");
1709
+ content = await readFile(configPath, "utf8");
1676
1710
  } catch {
1677
1711
  continue;
1678
1712
  }
@@ -1682,38 +1716,38 @@ var patchViteAllowedHosts = async (rootDir) => {
1682
1716
  "server: {\n allowedHosts: true,"
1683
1717
  );
1684
1718
  if (patched !== content) {
1685
- await writeFile2(configPath, patched);
1719
+ await writeFile(configPath, patched);
1686
1720
  }
1687
1721
  }
1688
1722
  };
1689
1723
  var rewriteTurboJson = async (rootDir) => {
1690
- const turboPath = join2(rootDir, "turbo.json");
1691
- const raw = await readFile2(turboPath, "utf8");
1724
+ const turboPath = join(rootDir, "turbo.json");
1725
+ const raw = await readFile(turboPath, "utf8");
1692
1726
  const turbo = JSON.parse(raw);
1693
1727
  delete turbo["extends"];
1694
1728
  turbo["globalEnv"] = ["VITE_EXTENSION_PORT", "VITE_PREVIEW_PORT", "VITE_EXTENSION_BUNDLE_URL"];
1695
- await writeFile2(turboPath, `${JSON.stringify(turbo, null, 2)}
1729
+ await writeFile(turboPath, `${JSON.stringify(turbo, null, 2)}
1696
1730
  `);
1697
1731
  };
1698
1732
  var writeEnvFile2 = async (dir, extensionPort, previewPort) => {
1699
- const envPath = join2(dir, ".env");
1733
+ const envPath = join(dir, ".env");
1700
1734
  const content = `VITE_EXTENSION_PORT=${extensionPort}
1701
1735
  VITE_PREVIEW_PORT=${previewPort}
1702
1736
  `;
1703
- await writeFile2(envPath, content);
1737
+ await writeFile(envPath, content);
1704
1738
  };
1705
1739
  var updateGitignore = async (dir) => {
1706
- const gitignorePath = join2(dir, ".gitignore");
1740
+ const gitignorePath = join(dir, ".gitignore");
1707
1741
  let gitignore = "";
1708
1742
  try {
1709
- gitignore = await readFile2(gitignorePath, "utf8");
1743
+ gitignore = await readFile(gitignorePath, "utf8");
1710
1744
  } catch {
1711
1745
  }
1712
1746
  if (!gitignore.includes(".env.stackable")) {
1713
1747
  const newGitignore = gitignore ? `${gitignore}
1714
1748
  .env.stackable
1715
1749
  ` : ".env.stackable\n";
1716
- await writeFile2(gitignorePath, newGitignore);
1750
+ await writeFile(gitignorePath, newGitignore);
1717
1751
  }
1718
1752
  };
1719
1753
  var scaffold = async (options) => {
@@ -1743,39 +1777,25 @@ var scaffold = async (options) => {
1743
1777
  await writeEnvFile2(dir, options.extensionPort, options.previewPort);
1744
1778
  await updateGitignore(dir);
1745
1779
  await writeDevContext(dir, {
1746
- projectRoot: dir,
1747
- orgId: null,
1748
1780
  appId: options.appId,
1749
1781
  extensionId: toKebabCase(options.extensionId || options.name),
1750
1782
  appName: options.appName || null,
1751
1783
  extensionName: options.name,
1752
1784
  extensionPort: options.extensionPort,
1753
- previewPort: options.previewPort,
1754
- manifest: null
1755
- });
1785
+ previewPort: options.previewPort});
1756
1786
  if (options.projectFiles) {
1757
- const extensionSrcDir = join2(dir, "packages/extension/src");
1787
+ const extensionSrcDir = join(dir, "packages/extension/src");
1758
1788
  for (const [filename, content] of Object.entries(options.projectFiles)) {
1759
- await writeFile2(join2(extensionSrcDir, filename), content);
1789
+ await writeFile(join(extensionSrcDir, filename), content);
1760
1790
  }
1761
1791
  }
1762
1792
  if (options.projectManifest) {
1763
- const manifestPath = join2(dir, "packages/extension/public/manifest.json");
1764
- await writeFile2(manifestPath, `${JSON.stringify(options.projectManifest, null, 2)}
1793
+ const manifestPath = join(dir, "packages/extension/public/manifest.json");
1794
+ await writeFile(manifestPath, `${JSON.stringify(options.projectManifest, null, 2)}
1765
1795
  `);
1766
1796
  }
1767
1797
  return options;
1768
1798
  };
1769
-
1770
- // src/App.tsx
1771
- import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
1772
- var STEPS = {
1773
- ["create" /* CREATE */]: ["app", "name", "template", "targets", "settings", "confirm"],
1774
- ["scaffold" /* SCAFFOLD */]: ["app", "extensionSelect", "confirmTargets", "settings", "confirm"],
1775
- ["update" /* UPDATE */]: ["app", "extensionSelect", "updateSettings", "manifestReview", "confirm"],
1776
- ["dev" /* DEV */]: []
1777
- // Dev command has no wizard steps
1778
- };
1779
1799
  var PROGRESS_STEPS = {
1780
1800
  ["create" /* CREATE */]: [
1781
1801
  { label: "Registering Extension", status: "pending" },
@@ -1813,115 +1833,72 @@ var deriveRegistryPermissions = (targets) => {
1813
1833
  };
1814
1834
  var App = ({ command, token, userId, orgId, initialName, initialExtensionId, options }) => {
1815
1835
  const { exit } = useApp();
1816
- const [step, setStep] = useState10(() => {
1817
- if (options?.appId) {
1818
- const base = STEPS[command];
1819
- return base.find((s) => s !== "app") ?? "app";
1820
- }
1821
- return "app";
1822
- });
1823
- const [name, setName] = useState10(initialName ?? options?.name ?? "");
1824
- const [extensionId, setExtensionId] = useState10(initialExtensionId ?? "");
1825
- const [extensionVersion, setExtensionVersion] = useState10("");
1826
- const [bundleUrl, setBundleUrl] = useState10(options?.bundleUrl ?? "");
1827
- const [enabled, setEnabled] = useState10(
1836
+ const [name, setName] = useState(initialName ?? options?.name ?? "");
1837
+ const [extensionId, setExtensionId] = useState(initialExtensionId ?? "");
1838
+ const [extensionVersion, setExtensionVersion] = useState("");
1839
+ const [bundleUrl, setBundleUrl] = useState(options?.bundleUrl ?? "");
1840
+ const [enabled, setEnabled] = useState(
1828
1841
  options?.enabled !== void 0 ? options.enabled !== "false" : true
1829
1842
  );
1830
- const [versionOverride, setVersionOverride] = useState10(void 0);
1831
- const [forceMajor, setForceMajor] = useState10(false);
1832
- const [initialExtension, setInitialExtension] = useState10(null);
1833
- const [templateFlavor, setTemplateFlavor] = useState10(
1843
+ const [versionOverride, setVersionOverride] = useState(void 0);
1844
+ const [forceMajor, setForceMajor] = useState(false);
1845
+ const [initialExtension, setInitialExtension] = useState(null);
1846
+ const [templateFlavor, setTemplateFlavor] = useState(
1834
1847
  options?.template ?? "starter"
1835
1848
  );
1836
- const [targets, setTargets] = useState10(
1849
+ const [targets, setTargets] = useState(
1837
1850
  options?.targets ? options.targets.split(",").map((t) => t.trim()) : []
1838
1851
  );
1839
- const [selectedApp, setSelectedApp] = useState10(null);
1840
- const [extensionPort, setExtensionPort] = useState10(
1852
+ const [selectedApp, setSelectedApp] = useState(null);
1853
+ const [extensionPort, setExtensionPort] = useState(
1841
1854
  options?.extensionPort ? parseInt(options.extensionPort, 10) : 6543
1842
1855
  );
1843
- const [previewPort, setPreviewPort] = useState10(
1856
+ const [previewPort, setPreviewPort] = useState(
1844
1857
  options?.previewPort ? parseInt(options.previewPort, 10) : 6544
1845
1858
  );
1846
- const [registryManifest, setRegistryManifest] = useState10(null);
1847
- const [localManifest, setLocalManifest] = useState10(null);
1848
- const [confirmedPermissions, setConfirmedPermissions] = useState10([]);
1849
- const [confirmedAllowedDomains, setConfirmedAllowedDomains] = useState10([]);
1850
- const [outputDir, setOutputDir] = useState10("");
1851
- const [studioProject, setStudioProject] = useState10(null);
1852
- const [progressSteps, setProgressSteps] = useState10(PROGRESS_STEPS[command]);
1853
- const [errorMessage, setErrorMessage] = useState10();
1854
- const updateStep = useCallback((index, status) => {
1855
- setProgressSteps((prev) => prev.map((s, i) => i === index ? { ...s, status } : s));
1856
- }, []);
1857
- const activeSteps = useCallback(() => {
1858
- const base = STEPS[command];
1859
- const skipped = /* @__PURE__ */ new Set();
1860
- if (command === "create" /* CREATE */ && initialName) skipped.add("name");
1861
- if (command === "create" /* CREATE */ && options?.template) skipped.add("template");
1862
- if (command === "create" /* CREATE */ && TEMPLATE_FLAVOR_META[templateFlavor].skipTargetStep) {
1863
- skipped.add("targets");
1864
- }
1865
- if (options?.extensionPort || options?.previewPort) skipped.add("settings");
1866
- if (options?.appId) skipped.add("app");
1867
- if (command === "update" /* UPDATE */ && initialExtensionId) skipped.add("extensionSelect");
1868
- if (studioProject) {
1869
- if (command === "create" /* CREATE */) {
1870
- skipped.add("template");
1871
- skipped.add("targets");
1872
- }
1873
- if (command === "scaffold" /* SCAFFOLD */ && studioProject.extensionId) {
1874
- skipped.add("extensionSelect");
1875
- }
1876
- }
1877
- return base.filter((s) => !skipped.has(s));
1878
- }, [
1859
+ const [registryManifest, setRegistryManifest] = useState(null);
1860
+ const [localManifest, setLocalManifest] = useState(null);
1861
+ const [confirmedPermissions, setConfirmedPermissions] = useState([]);
1862
+ const [confirmedAllowedDomains, setConfirmedAllowedDomains] = useState([]);
1863
+ const [userEditedAllowedDomains, setUserEditedAllowedDomains] = useState([]);
1864
+ const [outputDir, setOutputDir] = useState("");
1865
+ const [studioProject, setStudioProject] = useState(null);
1866
+ const [hasLocalProject, setHasLocalProject] = useState(false);
1867
+ const [progressSteps, setProgressSteps] = useState(PROGRESS_STEPS[command]);
1868
+ const [errorMessage, setErrorMessage] = useState();
1869
+ const { step, goForward, goBack, goTo } = useWizardSteps({
1879
1870
  command,
1880
1871
  initialName,
1881
1872
  initialExtensionId,
1882
1873
  templateFlavor,
1883
1874
  studioProject,
1884
- options?.template,
1885
- options?.extensionPort,
1886
- options?.previewPort,
1887
- options?.appId
1888
- ]);
1889
- const goBack = useCallback(() => {
1890
- setStep((prev) => {
1891
- const steps = activeSteps();
1892
- const idx = steps.indexOf(prev);
1893
- return idx > 0 ? steps[idx - 1] : prev;
1894
- });
1895
- }, [activeSteps]);
1875
+ hasLocalProject,
1876
+ options
1877
+ });
1878
+ const updateStep = useCallback((index, status) => {
1879
+ setProgressSteps((prev) => prev.map((s, i) => i === index ? { ...s, status } : s));
1880
+ }, []);
1896
1881
  const handleAppSelect = async (app) => {
1897
1882
  setSelectedApp(app);
1898
- if (options?.project && (command === "create" /* CREATE */ || command === "scaffold" /* SCAFFOLD */)) {
1883
+ if (options?.projectId && (command === "create" /* CREATE */ || command === "scaffold" /* SCAFFOLD */)) {
1899
1884
  try {
1900
- const project = await fetchProject(token, app.id, options.project);
1885
+ const project = await fetchProject(token, app.id, options.projectId);
1901
1886
  setStudioProject(project);
1902
1887
  setName(project.name);
1903
1888
  setTargets(project.manifest.targets);
1904
1889
  if (project.extensionId) {
1905
1890
  setExtensionId(project.extensionId);
1906
1891
  }
1907
- if (command === "create" /* CREATE */) {
1908
- setStep("name");
1909
- } else if (command === "scaffold" /* SCAFFOLD */) {
1910
- if (project.extensionId) {
1911
- setStep("confirmTargets");
1912
- } else {
1913
- setStep("extensionSelect");
1914
- }
1915
- }
1892
+ goForward({ studioProject: project });
1916
1893
  return;
1917
1894
  } catch (err) {
1918
1895
  const message = err instanceof Error ? err.message : String(err);
1919
1896
  setErrorMessage(`Failed to fetch Studio project: ${message}`);
1920
- setStep("error");
1897
+ goTo("error");
1921
1898
  return;
1922
1899
  }
1923
1900
  }
1924
- if (command === "update" /* UPDATE */ && initialExtensionId) {
1901
+ if ((command === "update" /* UPDATE */ || command === "scaffold" /* SCAFFOLD */) && initialExtensionId) {
1925
1902
  try {
1926
1903
  const extensions = await fetchExtensions(token, app.id);
1927
1904
  const ext = extensions[initialExtensionId];
@@ -1929,7 +1906,7 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
1929
1906
  setErrorMessage(
1930
1907
  `Extension "${initialExtensionId}" not found or is disabled. If disabled, re-enable it in the admin dashboard before updating.`
1931
1908
  );
1932
- setStep("error");
1909
+ goTo("error");
1933
1910
  return;
1934
1911
  }
1935
1912
  setName(ext.manifest.name);
@@ -1944,48 +1921,39 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
1944
1921
  bundleUrl: ext.bundleUrl
1945
1922
  });
1946
1923
  setRegistryManifest(ext.manifest);
1947
- const projectRoot = options?.dir || process.cwd();
1948
- try {
1949
- const manifestPath = join3(projectRoot, "packages/extension/public/manifest.json");
1950
- const content = await readFile3(manifestPath, "utf8");
1951
- setLocalManifest(JSON.parse(content));
1952
- } catch {
1953
- setLocalManifest(null);
1924
+ let localProjectFound = false;
1925
+ if (command === "update" /* UPDATE */ || command === "scaffold" /* SCAFFOLD */) {
1926
+ const projectRoot = options?.dir || process.cwd();
1927
+ try {
1928
+ const manifestPath = join(projectRoot, "packages/extension/public/manifest.json");
1929
+ const content = await readFile(manifestPath, "utf8");
1930
+ setLocalManifest(JSON.parse(content));
1931
+ setHasLocalProject(true);
1932
+ localProjectFound = true;
1933
+ } catch {
1934
+ setLocalManifest(null);
1935
+ }
1954
1936
  }
1955
- setStep("updateSettings");
1937
+ goForward({ hasLocalProject: localProjectFound });
1956
1938
  } catch (err) {
1957
1939
  const message = err instanceof Error ? err.message : String(err);
1958
1940
  setErrorMessage(message);
1959
- setStep("error");
1941
+ goTo("error");
1960
1942
  }
1961
1943
  return;
1962
1944
  }
1963
- if (command === "scaffold" /* SCAFFOLD */ || command === "update" /* UPDATE */) {
1964
- setStep("extensionSelect");
1965
- return;
1966
- }
1967
- if (initialName) {
1968
- if (options?.template) {
1969
- const meta = TEMPLATE_FLAVOR_META[templateFlavor];
1970
- if (meta.skipTargetStep && meta.defaultTargets) {
1971
- setTargets(meta.defaultTargets);
1972
- if (options?.extensionPort || options?.previewPort) {
1973
- setOutputDir(join3(process.cwd(), toKebabCase(initialName)));
1974
- setStep("confirm");
1975
- } else {
1976
- setStep("settings");
1977
- }
1978
- return;
1945
+ if (initialName && options?.template) {
1946
+ const meta = TEMPLATE_FLAVOR_META[templateFlavor];
1947
+ if (meta.skipTargetStep && meta.defaultTargets) {
1948
+ setTargets(meta.defaultTargets);
1949
+ if (options?.extensionPort || options?.previewPort) {
1950
+ setOutputDir(join(process.cwd(), toKebabCase(initialName)));
1979
1951
  }
1980
- setStep("targets");
1981
- } else {
1982
- setStep("template");
1983
1952
  }
1984
- } else {
1985
- setStep("name");
1986
1953
  }
1954
+ goForward();
1987
1955
  };
1988
- useEffect4(() => {
1956
+ useEffect(() => {
1989
1957
  if (!options?.appId) return;
1990
1958
  fetchApps(token).then((apps) => {
1991
1959
  const app = apps.find((a) => a.id === options.appId);
@@ -1993,11 +1961,28 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
1993
1961
  handleAppSelect(app);
1994
1962
  } else {
1995
1963
  setErrorMessage(`App "${options.appId}" not found or is disabled.`);
1996
- setStep("error");
1964
+ goTo("error");
1965
+ }
1966
+ }).catch((err) => {
1967
+ setErrorMessage(err instanceof Error ? err.message : String(err));
1968
+ goTo("error");
1969
+ });
1970
+ }, []);
1971
+ useEffect(() => {
1972
+ if (options?.appId || !initialExtensionId) return;
1973
+ if (command !== "update" /* UPDATE */ && command !== "scaffold" /* SCAFFOLD */) return;
1974
+ resolveAppForExtension(token, initialExtensionId).then((result) => {
1975
+ if (result) {
1976
+ handleAppSelect(result.app);
1977
+ } else {
1978
+ setErrorMessage(
1979
+ `Extension "${initialExtensionId}" not found across your apps. Verify the extension ID or provide --app-id explicitly.`
1980
+ );
1981
+ goTo("error");
1997
1982
  }
1998
1983
  }).catch((err) => {
1999
1984
  setErrorMessage(err instanceof Error ? err.message : String(err));
2000
- setStep("error");
1985
+ goTo("error");
2001
1986
  });
2002
1987
  }, []);
2003
1988
  const handleExtensionSelect = async (ext) => {
@@ -2013,28 +1998,25 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
2013
1998
  bundleUrl: ext.bundleUrl
2014
1999
  });
2015
2000
  setRegistryManifest(ext.manifest);
2001
+ let localProjectFound = false;
2016
2002
  const projectRoot = options?.dir || process.cwd();
2017
2003
  try {
2018
- const manifestPath = join3(projectRoot, "packages/extension/public/manifest.json");
2019
- const content = await readFile3(manifestPath, "utf8");
2004
+ const manifestPath = join(projectRoot, "packages/extension/public/manifest.json");
2005
+ const content = await readFile(manifestPath, "utf8");
2020
2006
  setLocalManifest(JSON.parse(content));
2007
+ setHasLocalProject(true);
2008
+ localProjectFound = true;
2021
2009
  } catch {
2022
2010
  setLocalManifest(null);
2023
2011
  }
2024
- if (command === "scaffold" /* SCAFFOLD */) {
2025
- setStep("confirmTargets");
2026
- } else if (command === "update" /* UPDATE */) {
2027
- setStep("updateSettings");
2028
- }
2012
+ goForward({ hasLocalProject: localProjectFound });
2029
2013
  };
2030
2014
  const handleConfirmTargets = (value) => {
2031
2015
  setTargets(value);
2032
2016
  if (options?.extensionPort || options?.previewPort) {
2033
- setOutputDir(join3(process.cwd(), toKebabCase(extensionId || name)));
2034
- setStep("confirm");
2035
- } else {
2036
- setStep("settings");
2017
+ setOutputDir(join(process.cwd(), toKebabCase(name || extensionId)));
2037
2018
  }
2019
+ goForward();
2038
2020
  };
2039
2021
  const handleName = (value) => {
2040
2022
  setName(value);
@@ -2043,48 +2025,36 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
2043
2025
  const meta = TEMPLATE_FLAVOR_META[templateFlavor];
2044
2026
  if (meta.skipTargetStep && meta.defaultTargets) {
2045
2027
  setTargets(meta.defaultTargets);
2046
- if (options?.extensionPort || options?.previewPort) {
2047
- setOutputDir(join3(process.cwd(), toKebabCase(value)));
2048
- setStep("confirm");
2049
- } else {
2050
- setStep("settings");
2051
- }
2052
- return;
2053
2028
  }
2054
- setStep("targets");
2055
- } else {
2056
- setStep("template");
2057
2029
  }
2030
+ if (options?.extensionPort || options?.previewPort) {
2031
+ setOutputDir(join(process.cwd(), toKebabCase(value)));
2032
+ }
2033
+ goForward();
2058
2034
  };
2059
2035
  const handleTemplateSelect = (flavor) => {
2060
2036
  setTemplateFlavor(flavor);
2061
2037
  const meta = TEMPLATE_FLAVOR_META[flavor];
2062
2038
  if (meta.skipTargetStep && meta.defaultTargets) {
2063
2039
  setTargets(meta.defaultTargets);
2064
- if (options?.extensionPort || options?.previewPort) {
2065
- setOutputDir(join3(process.cwd(), toKebabCase(extensionId || name)));
2066
- setStep("confirm");
2067
- } else {
2068
- setStep("settings");
2069
- }
2070
- return;
2071
2040
  }
2072
- setStep("targets");
2041
+ if (options?.extensionPort || options?.previewPort) {
2042
+ setOutputDir(join(process.cwd(), toKebabCase(name || extensionId)));
2043
+ }
2044
+ goForward({ templateFlavor: flavor });
2073
2045
  };
2074
2046
  const handleTargets = (value) => {
2075
2047
  setTargets(value);
2076
2048
  if (options?.extensionPort || options?.previewPort) {
2077
- setOutputDir(join3(process.cwd(), toKebabCase(extensionId || name)));
2078
- setStep("confirm");
2079
- } else {
2080
- setStep("settings");
2049
+ setOutputDir(join(process.cwd(), toKebabCase(name || extensionId)));
2081
2050
  }
2051
+ goForward();
2082
2052
  };
2083
2053
  const handleSettings = (extPort, prevPort, dir) => {
2084
2054
  setExtensionPort(extPort);
2085
2055
  setPreviewPort(prevPort);
2086
2056
  setOutputDir(dir);
2087
- setStep("confirm");
2057
+ goForward();
2088
2058
  };
2089
2059
  const computeVersionBump = (currentVersion, newName, newTargets, newBundleUrl, isForceMajor) => {
2090
2060
  const [major, minor, patch] = currentVersion.split(".").map(Number);
@@ -2100,7 +2070,7 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
2100
2070
  };
2101
2071
  const handleConfirm = async () => {
2102
2072
  if (command === "update" /* UPDATE */) {
2103
- setStep("updating");
2073
+ goTo("updating");
2104
2074
  setProgressSteps(PROGRESS_STEPS[command]);
2105
2075
  try {
2106
2076
  updateStep(0, "running");
@@ -2118,15 +2088,15 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
2118
2088
  });
2119
2089
  updateStep(0, "done");
2120
2090
  setExtensionVersion(resolvedVersion);
2121
- setStep("updateDone");
2091
+ goTo("updateDone");
2122
2092
  } catch (err) {
2123
2093
  const message = err instanceof Error ? err.message : String(err);
2124
2094
  setErrorMessage(message);
2125
- setStep("error");
2095
+ goTo("error");
2126
2096
  }
2127
2097
  return;
2128
2098
  }
2129
- setStep("scaffolding");
2099
+ goTo("scaffolding");
2130
2100
  setProgressSteps(PROGRESS_STEPS[command]);
2131
2101
  try {
2132
2102
  let resolvedExtensionId = extensionId || toKebabCase(name);
@@ -2155,7 +2125,7 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
2155
2125
  name,
2156
2126
  extensionId: resolvedExtensionId,
2157
2127
  targets,
2158
- templateFlavor: command === "create" /* CREATE */ ? templateFlavor : void 0,
2128
+ templateFlavor: command === "create" /* CREATE */ || command === "scaffold" /* SCAFFOLD */ ? templateFlavor : void 0,
2159
2129
  outputDir,
2160
2130
  extensionPort,
2161
2131
  previewPort,
@@ -2174,9 +2144,9 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
2174
2144
  }
2175
2145
  }
2176
2146
  if (command === "create" /* CREATE */) {
2177
- const manifestPath = join3(outputDir, "packages/extension/public/manifest.json");
2147
+ const manifestPath = join(outputDir, "packages/extension/public/manifest.json");
2178
2148
  try {
2179
- const manifestContent = await readFile3(manifestPath, "utf8");
2149
+ const manifestContent = await readFile(manifestPath, "utf8");
2180
2150
  const manifest = JSON.parse(manifestContent);
2181
2151
  await updateExtension(token, selectedApp.id, resolvedExtensionId, {
2182
2152
  manifest: { ...manifest, allowedDomains: [] }
@@ -2185,7 +2155,7 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
2185
2155
  }
2186
2156
  }
2187
2157
  updateStep(scaffoldStepOffset + 1, "running");
2188
- await new Promise((r) => setTimeout(r, 200));
2158
+ await delay(200);
2189
2159
  updateStep(scaffoldStepOffset + 1, "done");
2190
2160
  if (!options?.skipInstall) {
2191
2161
  updateStep(scaffoldStepOffset + 2, "running");
@@ -2194,11 +2164,11 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
2194
2164
  } else {
2195
2165
  updateStep(scaffoldStepOffset + 2, "done");
2196
2166
  }
2197
- setStep("done");
2167
+ goTo("done");
2198
2168
  } catch (err) {
2199
2169
  const message = err instanceof Error ? err.message : String(err);
2200
2170
  setErrorMessage(message);
2201
- setStep("error");
2171
+ goTo("error");
2202
2172
  }
2203
2173
  };
2204
2174
  const handleCancel = () => {
@@ -2206,7 +2176,16 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
2206
2176
  };
2207
2177
  switch (step) {
2208
2178
  case "app": {
2209
- return /* @__PURE__ */ jsx15(
2179
+ if (options?.appId || initialExtensionId && (command === "update" /* UPDATE */ || command === "scaffold" /* SCAFFOLD */)) {
2180
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
2181
+ /* @__PURE__ */ jsx(Banner, { userId, orgId }),
2182
+ /* @__PURE__ */ jsx(StepShell, { title: "Loading App\u2026", children: /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
2183
+ /* @__PURE__ */ jsx(Spinner5, { type: "dots" }),
2184
+ /* @__PURE__ */ jsx(Text, { children: options?.appId ? "Fetching app details\u2026" : "Resolving app from extension\u2026" })
2185
+ ] }) })
2186
+ ] });
2187
+ }
2188
+ return /* @__PURE__ */ jsx(
2210
2189
  AppSelect,
2211
2190
  {
2212
2191
  token,
@@ -2217,7 +2196,7 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
2217
2196
  );
2218
2197
  }
2219
2198
  case "extensionSelect": {
2220
- return /* @__PURE__ */ jsx15(
2199
+ return /* @__PURE__ */ jsx(
2221
2200
  ExtensionSelect,
2222
2201
  {
2223
2202
  appId: selectedApp.id,
@@ -2229,7 +2208,7 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
2229
2208
  );
2230
2209
  }
2231
2210
  case "confirmTargets": {
2232
- return /* @__PURE__ */ jsx15(
2211
+ return /* @__PURE__ */ jsx(
2233
2212
  TargetSelect,
2234
2213
  {
2235
2214
  availableTargets: selectedApp?.targets ?? [],
@@ -2240,7 +2219,7 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
2240
2219
  );
2241
2220
  }
2242
2221
  case "name": {
2243
- return /* @__PURE__ */ jsx15(
2222
+ return /* @__PURE__ */ jsx(
2244
2223
  NamePrompt,
2245
2224
  {
2246
2225
  initialValue: name,
@@ -2250,7 +2229,7 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
2250
2229
  );
2251
2230
  }
2252
2231
  case "template": {
2253
- return /* @__PURE__ */ jsx15(
2232
+ return /* @__PURE__ */ jsx(
2254
2233
  TemplateSelect,
2255
2234
  {
2256
2235
  onSubmit: handleTemplateSelect,
@@ -2259,27 +2238,28 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
2259
2238
  );
2260
2239
  }
2261
2240
  case "targets": {
2262
- return /* @__PURE__ */ jsx15(
2241
+ return /* @__PURE__ */ jsx(
2263
2242
  TargetSelect,
2264
2243
  {
2265
2244
  availableTargets: selectedApp?.targets ?? [],
2245
+ preSelected: targets,
2266
2246
  onSubmit: handleTargets,
2267
2247
  onBack: goBack
2268
2248
  }
2269
2249
  );
2270
2250
  }
2271
2251
  case "settings": {
2272
- return /* @__PURE__ */ jsx15(
2252
+ return /* @__PURE__ */ jsx(
2273
2253
  SettingsPrompt,
2274
2254
  {
2275
- defaultDir: join3(process.cwd(), toKebabCase(extensionId || name)),
2255
+ defaultDir: join(process.cwd(), toKebabCase(name || extensionId)),
2276
2256
  onSubmit: handleSettings,
2277
2257
  onBack: goBack
2278
2258
  }
2279
2259
  );
2280
2260
  }
2281
2261
  case "confirm": {
2282
- return /* @__PURE__ */ jsx15(
2262
+ return /* @__PURE__ */ jsx(
2283
2263
  Confirm,
2284
2264
  {
2285
2265
  command,
@@ -2306,89 +2286,94 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
2306
2286
  );
2307
2287
  }
2308
2288
  case "scaffolding": {
2309
- return /* @__PURE__ */ jsx15(ScaffoldProgress, { steps: progressSteps });
2289
+ return /* @__PURE__ */ jsx(ScaffoldProgress, { steps: progressSteps });
2310
2290
  }
2311
2291
  case "updateSettings": {
2312
- return /* @__PURE__ */ jsx15(
2292
+ return /* @__PURE__ */ jsx(
2313
2293
  UpdateSettingsPrompt,
2314
2294
  {
2315
2295
  name,
2316
2296
  targets,
2317
2297
  enabled,
2318
2298
  bundleUrl,
2299
+ allowedDomains: registryManifest?.allowedDomains ?? [],
2319
2300
  availableTargets: selectedApp?.targets ?? [],
2320
2301
  onSubmit: (updated) => {
2321
2302
  setName(updated.name);
2322
2303
  setTargets(updated.targets);
2323
2304
  setBundleUrl(updated.bundleUrl);
2305
+ setUserEditedAllowedDomains(updated.allowedDomains);
2324
2306
  setEnabled(updated.enabled);
2325
2307
  setForceMajor(updated.forceMajor);
2326
2308
  setVersionOverride(void 0);
2327
- setStep("manifestReview");
2309
+ goForward();
2328
2310
  },
2329
2311
  onBack: goBack
2330
2312
  }
2331
2313
  );
2332
2314
  }
2333
2315
  case "manifestReview": {
2334
- return /* @__PURE__ */ jsx15(
2316
+ const buildEffectiveManifest = () => {
2317
+ if (localManifest) {
2318
+ return { ...localManifest, allowedDomains: userEditedAllowedDomains };
2319
+ }
2320
+ if (userEditedAllowedDomains.length > 0) {
2321
+ return { name, version: "0.0.0", targets, permissions: [], allowedDomains: userEditedAllowedDomains };
2322
+ }
2323
+ return localManifest;
2324
+ };
2325
+ const effectiveLocalManifest = buildEffectiveManifest();
2326
+ return /* @__PURE__ */ jsx(
2335
2327
  ManifestReviewPrompt,
2336
2328
  {
2337
- localManifest,
2329
+ localManifest: effectiveLocalManifest,
2338
2330
  registryManifest,
2339
2331
  onSubmit: (result) => {
2340
2332
  setConfirmedPermissions(result.permissions);
2341
2333
  setConfirmedAllowedDomains(result.allowedDomains);
2342
- setStep("confirm");
2334
+ goForward();
2343
2335
  },
2344
2336
  onBack: goBack
2345
2337
  }
2346
2338
  );
2347
2339
  }
2348
2340
  case "updating": {
2349
- return /* @__PURE__ */ jsx15(ScaffoldProgress, { steps: progressSteps });
2341
+ return /* @__PURE__ */ jsx(ScaffoldProgress, { steps: progressSteps });
2350
2342
  }
2351
2343
  case "updateDone": {
2352
- return /* @__PURE__ */ jsx15(StepShell, { title: "Extension updated", onBack: goBack, children: /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", gap: 1, children: [
2353
- /* @__PURE__ */ jsx15(Text15, { color: "green", bold: true, children: "Extension updated successfully!" }),
2354
- /* @__PURE__ */ jsxs15(Text15, { dimColor: true, children: [
2344
+ return /* @__PURE__ */ jsx(StepShell, { title: "Extension updated", onBack: goBack, children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
2345
+ /* @__PURE__ */ jsx(Text, { color: "green", bold: true, children: "Extension updated successfully!" }),
2346
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
2355
2347
  "Name: ",
2356
2348
  name
2357
2349
  ] }),
2358
- /* @__PURE__ */ jsxs15(Text15, { dimColor: true, children: [
2350
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
2359
2351
  "ID: ",
2360
2352
  extensionId
2361
2353
  ] }),
2362
- /* @__PURE__ */ jsxs15(Text15, { dimColor: true, children: [
2354
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
2363
2355
  "Version: ",
2364
2356
  extensionVersion
2365
2357
  ] })
2366
2358
  ] }) });
2367
2359
  }
2368
2360
  case "done": {
2369
- return /* @__PURE__ */ jsx15(Done, { name, outputDir, templateFlavor: command === "create" /* CREATE */ ? templateFlavor : void 0 });
2361
+ return /* @__PURE__ */ jsx(Done, { name, outputDir, templateFlavor: command === "create" /* CREATE */ ? templateFlavor : void 0 });
2370
2362
  }
2371
2363
  case "error": {
2372
- return /* @__PURE__ */ jsx15(StepShell, { title: "Operation failed", onBack: goBack, children: /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", gap: 1, children: [
2373
- /* @__PURE__ */ jsx15(Text15, { color: "red", bold: true, children: "An error occurred" }),
2374
- errorMessage && /* @__PURE__ */ jsx15(Text15, { color: "red", children: errorMessage })
2364
+ return /* @__PURE__ */ jsx(StepShell, { title: "Operation failed", onBack: goBack, children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
2365
+ /* @__PURE__ */ jsx(Text, { color: "red", bold: true, children: "An error occurred" }),
2366
+ errorMessage && /* @__PURE__ */ jsx(Text, { color: "red", children: errorMessage })
2375
2367
  ] }) });
2376
2368
  }
2377
2369
  default: {
2378
- return /* @__PURE__ */ jsx15(StepShell, { title: "Scaffold failed", onBack: goBack, children: /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", gap: 1, children: [
2379
- /* @__PURE__ */ jsx15(Text15, { color: "red", bold: true, children: "An error occurred" }),
2380
- errorMessage && /* @__PURE__ */ jsx15(Text15, { color: "red", children: errorMessage })
2370
+ return /* @__PURE__ */ jsx(StepShell, { title: "Scaffold failed", onBack: goBack, children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
2371
+ /* @__PURE__ */ jsx(Text, { color: "red", bold: true, children: "An error occurred" }),
2372
+ errorMessage && /* @__PURE__ */ jsx(Text, { color: "red", children: errorMessage })
2381
2373
  ] }) });
2382
2374
  }
2383
2375
  }
2384
2376
  };
2385
-
2386
- // src/components/DevApp.tsx
2387
- import { useRef, useState as useState13, useEffect as useEffect7, useCallback as useCallback3 } from "react";
2388
- import { useInput as useInput12, Box as Box19, Text as Text19 } from "ink";
2389
-
2390
- // src/lib/devServer.ts
2391
- import { spawn } from "child_process";
2392
2377
  var startDevServer = (projectRoot) => {
2393
2378
  const child = spawn("pnpm", ["dev"], {
2394
2379
  cwd: projectRoot,
@@ -2399,9 +2384,6 @@ var startDevServer = (projectRoot) => {
2399
2384
  };
2400
2385
  return { process: child, stop };
2401
2386
  };
2402
-
2403
- // src/lib/tunnel.ts
2404
- import { Tunnel } from "cloudflared";
2405
2387
  var MAX_RETRIES = 3;
2406
2388
  var RETRY_DELAY_MS = 2e3;
2407
2389
  var isValidTunnelUrl = (url) => {
@@ -2438,7 +2420,6 @@ var startTunnelOnce = (port) => new Promise((resolve, reject) => {
2438
2420
  reject(err);
2439
2421
  });
2440
2422
  });
2441
- var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
2442
2423
  var startTunnel = async (port) => {
2443
2424
  for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
2444
2425
  try {
@@ -2455,15 +2436,10 @@ var startTunnel = async (port) => {
2455
2436
  }
2456
2437
  throw new Error(`Tunnel failed to return a valid URL after ${MAX_RETRIES} attempts`);
2457
2438
  };
2458
-
2459
- // src/components/DevSetup.tsx
2460
- import { Box as Box16, Text as Text16 } from "ink";
2461
- import { useState as useState11, useEffect as useEffect5 } from "react";
2462
- import { jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
2463
2439
  var DevSetup = ({ initialContext, token, onReady }) => {
2464
- const [step, setStep] = useState11("app");
2465
- const [selectedApp, setSelectedApp] = useState11(null);
2466
- useEffect5(() => {
2440
+ const [step, setStep] = useState("app");
2441
+ const [selectedApp, setSelectedApp] = useState(null);
2442
+ useEffect(() => {
2467
2443
  if (initialContext.appId) {
2468
2444
  setStep("extension");
2469
2445
  }
@@ -2480,9 +2456,9 @@ var DevSetup = ({ initialContext, token, onReady }) => {
2480
2456
  });
2481
2457
  };
2482
2458
  if (step === "app") {
2483
- return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
2484
- /* @__PURE__ */ jsx16(Box16, { marginBottom: 1, children: /* @__PURE__ */ jsx16(Text16, { children: "Select the App for your extension:" }) }),
2485
- /* @__PURE__ */ jsx16(
2459
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
2460
+ /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { children: "Select the App for your extension:" }) }),
2461
+ /* @__PURE__ */ jsx(
2486
2462
  AppSelect,
2487
2463
  {
2488
2464
  token,
@@ -2491,9 +2467,9 @@ var DevSetup = ({ initialContext, token, onReady }) => {
2491
2467
  )
2492
2468
  ] });
2493
2469
  }
2494
- return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
2495
- /* @__PURE__ */ jsx16(Box16, { marginBottom: 1, children: /* @__PURE__ */ jsx16(Text16, { children: "Select the Extension to develop:" }) }),
2496
- /* @__PURE__ */ jsx16(
2470
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
2471
+ /* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { children: "Select the Extension to develop:" }) }),
2472
+ /* @__PURE__ */ jsx(
2497
2473
  ExtensionSelect,
2498
2474
  {
2499
2475
  token,
@@ -2503,16 +2479,6 @@ var DevSetup = ({ initialContext, token, onReady }) => {
2503
2479
  )
2504
2480
  ] });
2505
2481
  };
2506
-
2507
- // src/components/DevDashboard.tsx
2508
- import { Box as Box18, Text as Text18, useInput as useInput11 } from "ink";
2509
- import { useEffect as useEffect6, useMemo } from "react";
2510
-
2511
- // src/components/CopyableField.tsx
2512
- import { useState as useState12, useCallback as useCallback2 } from "react";
2513
- import { useInput as useInput10, Box as Box17, Text as Text17 } from "ink";
2514
- import clipboard from "clipboardy";
2515
- import { jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
2516
2482
  var CopyableField = ({
2517
2483
  label,
2518
2484
  value,
@@ -2522,9 +2488,9 @@ var CopyableField = ({
2522
2488
  labelColor,
2523
2489
  children
2524
2490
  }) => {
2525
- const [expanded, setExpanded] = useState12(false);
2526
- const [copied, setCopied] = useState12(false);
2527
- const handleCopy = useCallback2(async () => {
2491
+ const [expanded, setExpanded] = useState(false);
2492
+ const [copied, setCopied] = useState(false);
2493
+ const handleCopy = useCallback(async () => {
2528
2494
  if (expanded) {
2529
2495
  setExpanded(false);
2530
2496
  setCopied(false);
@@ -2542,20 +2508,20 @@ var CopyableField = ({
2542
2508
  setExpanded(true);
2543
2509
  }
2544
2510
  }, [expanded, value]);
2545
- useInput10((input) => {
2511
+ useInput((input) => {
2546
2512
  if (input === shortcutKey) {
2547
2513
  handleCopy();
2548
2514
  }
2549
2515
  });
2550
2516
  const truncated = value.length > maxLength ? `${value.slice(0, maxLength)}...` : value;
2551
2517
  const keyHint = shortcutLabel || shortcutKey;
2552
- return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", children: [
2553
- /* @__PURE__ */ jsxs17(Box17, { gap: 2, children: [
2554
- /* @__PURE__ */ jsx17(Text17, { dimColor: true, children: label }),
2555
- copied && /* @__PURE__ */ jsx17(Text17, { color: "green", bold: true, children: "Copied!" }),
2556
- !copied && /* @__PURE__ */ jsxs17(Text17, { dimColor: true, children: [
2518
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
2519
+ /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
2520
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: label }),
2521
+ copied && /* @__PURE__ */ jsx(Text, { color: "green", bold: true, children: "Copied!" }),
2522
+ !copied && /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
2557
2523
  "press ",
2558
- /* @__PURE__ */ jsxs17(Text17, { bold: true, color: "yellow", children: [
2524
+ /* @__PURE__ */ jsxs(Text, { bold: true, color: "yellow", children: [
2559
2525
  "[",
2560
2526
  keyHint,
2561
2527
  "]"
@@ -2563,12 +2529,9 @@ var CopyableField = ({
2563
2529
  " to copy (and see full value)"
2564
2530
  ] })
2565
2531
  ] }),
2566
- /* @__PURE__ */ jsx17(Box17, { paddingLeft: 2, children: expanded ? /* @__PURE__ */ jsx17(Text17, { wrap: "wrap", children: value }) : children || /* @__PURE__ */ jsx17(Text17, { children: labelColor ? /* @__PURE__ */ jsx17(Text17, { color: labelColor, children: truncated }) : truncated }) })
2532
+ /* @__PURE__ */ jsx(Box, { paddingLeft: 2, children: expanded ? /* @__PURE__ */ jsx(Text, { wrap: "wrap", children: value }) : children || /* @__PURE__ */ jsx(Text, { children: labelColor ? /* @__PURE__ */ jsx(Text, { color: labelColor, children: truncated }) : truncated }) })
2567
2533
  ] });
2568
2534
  };
2569
-
2570
- // src/components/DevDashboard.tsx
2571
- import { Fragment as Fragment2, jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
2572
2535
  var toBase64Url = (input) => btoa(input).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
2573
2536
  var DevDashboard = ({
2574
2537
  previewTunnelUrl,
@@ -2585,7 +2548,7 @@ var DevDashboard = ({
2585
2548
  devSessionToken,
2586
2549
  onQuit
2587
2550
  }) => {
2588
- useEffect6(() => {
2551
+ useEffect(() => {
2589
2552
  const handler = () => {
2590
2553
  onQuit();
2591
2554
  };
@@ -2598,103 +2561,103 @@ var DevDashboard = ({
2598
2561
  if (!tunnelUrl || !devSessionToken) return "";
2599
2562
  return toBase64Url(JSON.stringify({ url: tunnelUrl, token: devSessionToken }));
2600
2563
  }, [tunnelUrl, devSessionToken]);
2601
- useInput11((input, key) => {
2564
+ useInput((input, key) => {
2602
2565
  if (input === "q" || key.ctrl && input === "c") {
2603
2566
  onQuit();
2604
2567
  }
2605
2568
  });
2606
- return /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
2607
- /* @__PURE__ */ jsx18(Banner, { userId, orgId }),
2608
- /* @__PURE__ */ jsxs18(
2569
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
2570
+ /* @__PURE__ */ jsx(Banner, { userId, orgId }),
2571
+ /* @__PURE__ */ jsxs(
2609
2572
  StepShell,
2610
2573
  {
2611
2574
  title: "dev",
2612
2575
  hint: `Live development ${tunnelUrl ? "with" : "w/o"} Tunnel \u2014 ${appName ? `${appName} ` : ""}(${appId})`,
2613
- footer: /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", gap: 1, children: [
2614
- devParamBlob && /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
2576
+ footer: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
2577
+ devParamBlob && /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
2615
2578
  "Press ",
2616
- /* @__PURE__ */ jsx18(Text18, { bold: true, color: "yellow", children: "[d]" }),
2579
+ /* @__PURE__ */ jsx(Text, { bold: true, color: "yellow", children: "[d]" }),
2617
2580
  " to copy Dev Param, ",
2618
- /* @__PURE__ */ jsx18(Text18, { bold: true, color: "yellow", children: "[s]" }),
2581
+ /* @__PURE__ */ jsx(Text, { bold: true, color: "yellow", children: "[s]" }),
2619
2582
  " to copy Staging Param"
2620
2583
  ] }),
2621
- /* @__PURE__ */ jsxs18(Text18, { dimColor: true, children: [
2584
+ /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
2622
2585
  "Press ",
2623
- /* @__PURE__ */ jsx18(Text18, { bold: true, color: "yellow", children: "[q]" }),
2586
+ /* @__PURE__ */ jsx(Text, { bold: true, color: "yellow", children: "[q]" }),
2624
2587
  " or Ctrl-C to quit"
2625
2588
  ] })
2626
2589
  ] }),
2627
2590
  children: [
2628
- /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
2629
- /* @__PURE__ */ jsxs18(Box18, { gap: 2, children: [
2630
- /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: "Extension:" }),
2631
- /* @__PURE__ */ jsxs18(Text18, { children: [
2591
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
2592
+ /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
2593
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Extension:" }),
2594
+ /* @__PURE__ */ jsxs(Text, { children: [
2632
2595
  extensionName,
2633
2596
  " (",
2634
2597
  extensionId,
2635
2598
  ")"
2636
2599
  ] })
2637
2600
  ] }),
2638
- /* @__PURE__ */ jsxs18(Box18, { gap: 2, children: [
2639
- /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: "Bundle URL:" }),
2640
- /* @__PURE__ */ jsx18(Text18, { children: tunnelUrl || `http://localhost:${extensionPort}` })
2601
+ /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
2602
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Bundle URL:" }),
2603
+ /* @__PURE__ */ jsx(Text, { children: tunnelUrl || `http://localhost:${extensionPort}` })
2641
2604
  ] })
2642
2605
  ] }),
2643
- /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
2644
- previewTunnelUrl && /* @__PURE__ */ jsxs18(Box18, { gap: 2, children: [
2645
- /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: "Tunnel Dev - Preview:" }),
2646
- /* @__PURE__ */ jsx18(Text18, { children: previewTunnelUrl })
2606
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
2607
+ previewTunnelUrl && /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
2608
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Tunnel Dev - Preview:" }),
2609
+ /* @__PURE__ */ jsx(Text, { children: previewTunnelUrl })
2647
2610
  ] }),
2648
- /* @__PURE__ */ jsxs18(Box18, { gap: 2, children: [
2649
- /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: "Local Dev - Preview:" }),
2650
- /* @__PURE__ */ jsxs18(Text18, { children: [
2611
+ /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
2612
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Local Dev - Preview:" }),
2613
+ /* @__PURE__ */ jsxs(Text, { children: [
2651
2614
  "http://localhost:",
2652
2615
  previewPort
2653
2616
  ] })
2654
2617
  ] })
2655
2618
  ] }),
2656
- /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", children: [
2657
- tunnelUrl && /* @__PURE__ */ jsxs18(Box18, { gap: 2, children: [
2658
- /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: "Tunnel Dev - Extension:" }),
2659
- /* @__PURE__ */ jsx18(Text18, { children: tunnelUrl })
2619
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
2620
+ tunnelUrl && /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
2621
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Tunnel Dev - Extension:" }),
2622
+ /* @__PURE__ */ jsx(Text, { children: tunnelUrl })
2660
2623
  ] }),
2661
- /* @__PURE__ */ jsxs18(Box18, { gap: 2, children: [
2662
- /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: "Local Dev - Extension:" }),
2663
- /* @__PURE__ */ jsxs18(Text18, { children: [
2624
+ /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
2625
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Local Dev - Extension:" }),
2626
+ /* @__PURE__ */ jsxs(Text, { children: [
2664
2627
  "http://localhost:",
2665
2628
  extensionPort
2666
2629
  ] })
2667
2630
  ] })
2668
2631
  ] }),
2669
- tunnelUrl && devSessionToken && /* @__PURE__ */ jsxs18(Fragment2, { children: [
2670
- /* @__PURE__ */ jsx18(
2632
+ tunnelUrl && devSessionToken && /* @__PURE__ */ jsxs(Fragment, { children: [
2633
+ /* @__PURE__ */ jsx(
2671
2634
  CopyableField,
2672
2635
  {
2673
2636
  label: "Dev Param (no encryption):",
2674
2637
  value: `?_stackable_dev=${extensionId}:${devParamBlob}`,
2675
2638
  shortcutKey: "d",
2676
- children: /* @__PURE__ */ jsxs18(Text18, { children: [
2639
+ children: /* @__PURE__ */ jsxs(Text, { children: [
2677
2640
  "?",
2678
- /* @__PURE__ */ jsx18(Text18, { color: "yellow", children: "_stackable_dev" }),
2641
+ /* @__PURE__ */ jsx(Text, { color: "yellow", children: "_stackable_dev" }),
2679
2642
  "=",
2680
- /* @__PURE__ */ jsx18(Text18, { color: "cyan", children: extensionId }),
2643
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: extensionId }),
2681
2644
  ":",
2682
2645
  devParamBlob.slice(0, 20),
2683
2646
  "..."
2684
2647
  ] })
2685
2648
  }
2686
2649
  ),
2687
- /* @__PURE__ */ jsx18(
2650
+ /* @__PURE__ */ jsx(
2688
2651
  CopyableField,
2689
2652
  {
2690
2653
  label: "Staging Param (with encryption):",
2691
2654
  value: `?_stackable_staging=${extensionId}:${devParamBlob}`,
2692
2655
  shortcutKey: "s",
2693
- children: /* @__PURE__ */ jsxs18(Text18, { children: [
2656
+ children: /* @__PURE__ */ jsxs(Text, { children: [
2694
2657
  "?",
2695
- /* @__PURE__ */ jsx18(Text18, { color: "yellow", children: "_stackable_staging" }),
2658
+ /* @__PURE__ */ jsx(Text, { color: "yellow", children: "_stackable_staging" }),
2696
2659
  "=",
2697
- /* @__PURE__ */ jsx18(Text18, { color: "cyan", children: extensionId }),
2660
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: extensionId }),
2698
2661
  ":",
2699
2662
  devParamBlob.slice(0, 20),
2700
2663
  "..."
@@ -2702,47 +2665,44 @@ var DevDashboard = ({
2702
2665
  }
2703
2666
  )
2704
2667
  ] }),
2705
- tunnelUrl && !devSessionToken && /* @__PURE__ */ jsxs18(Box18, { gap: 2, children: [
2706
- /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: "Host Dev - Query Param:" }),
2707
- /* @__PURE__ */ jsxs18(Text18, { children: [
2668
+ tunnelUrl && !devSessionToken && /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
2669
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Host Dev - Query Param:" }),
2670
+ /* @__PURE__ */ jsxs(Text, { children: [
2708
2671
  "?",
2709
- /* @__PURE__ */ jsx18(Text18, { color: "yellow", children: "_stackable_dev" }),
2672
+ /* @__PURE__ */ jsx(Text, { color: "yellow", children: "_stackable_dev" }),
2710
2673
  "=",
2711
- /* @__PURE__ */ jsx18(Text18, { color: "cyan", children: extensionId }),
2674
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: extensionId }),
2712
2675
  ":",
2713
2676
  tunnelUrl
2714
2677
  ] })
2715
2678
  ] }),
2716
- manifestWarnings.length > 0 && /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
2717
- /* @__PURE__ */ jsx18(Text18, { color: "yellow", bold: true, children: "Local manifest differs from registry:" }),
2718
- manifestWarnings.map((w, i) => /* @__PURE__ */ jsxs18(Text18, { color: "yellow", children: [
2679
+ manifestWarnings.length > 0 && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
2680
+ /* @__PURE__ */ jsx(Text, { color: "yellow", bold: true, children: "Local manifest differs from registry:" }),
2681
+ manifestWarnings.map((w, i) => /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
2719
2682
  " ",
2720
2683
  w
2721
2684
  ] }, i)),
2722
- /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: " Run `pnpm --config.dlx-cache-max-age=0 dlx @stackable-labs/cli-app-extension@latest update` to review and sync." })
2685
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: " Run `pnpm --config.dlx-cache-max-age=0 dlx @stackable-labs/cli-app-extension@latest update` to review and sync." })
2723
2686
  ] })
2724
2687
  ]
2725
2688
  }
2726
2689
  )
2727
2690
  ] });
2728
2691
  };
2729
-
2730
- // src/components/DevApp.tsx
2731
- import { jsx as jsx19 } from "react/jsx-runtime";
2732
2692
  var DevApp = ({ token, userId, orgId, options = {} }) => {
2733
- const [state, setState] = useState13("setup");
2734
- const [devContext, setDevContext] = useState13(null);
2735
- const [resolvedContext, setResolvedContext] = useState13(null);
2736
- const [tunnelUrl, setTunnelUrl] = useState13(null);
2737
- const [previewTunnelUrl, setPreviewTunnelUrl] = useState13(null);
2738
- const [tunnelHandle, setTunnelHandle] = useState13(null);
2739
- const [previewTunnelHandle, setPreviewTunnelHandle] = useState13(null);
2740
- const [devServerHandle, setDevServerHandle] = useState13(null);
2741
- const [manifestWarnings, setManifestWarnings] = useState13([]);
2742
- const [devSessionToken, setDevSessionToken] = useState13(null);
2693
+ const [state, setState] = useState("setup");
2694
+ const [devContext, setDevContext] = useState(null);
2695
+ const [resolvedContext, setResolvedContext] = useState(null);
2696
+ const [tunnelUrl, setTunnelUrl] = useState(null);
2697
+ const [previewTunnelUrl, setPreviewTunnelUrl] = useState(null);
2698
+ const [tunnelHandle, setTunnelHandle] = useState(null);
2699
+ const [previewTunnelHandle, setPreviewTunnelHandle] = useState(null);
2700
+ const [devServerHandle, setDevServerHandle] = useState(null);
2701
+ const [manifestWarnings, setManifestWarnings] = useState([]);
2702
+ const [devSessionToken, setDevSessionToken] = useState(null);
2743
2703
  const shuttingDown = useRef(false);
2744
2704
  const useTunnel = options.tunnel !== false;
2745
- useEffect7(() => {
2705
+ useEffect(() => {
2746
2706
  const projectRoot = options.dir || process.cwd();
2747
2707
  console.log(`[dev] Reading context from ${projectRoot}`);
2748
2708
  readDevContext(projectRoot).then((ctx) => {
@@ -2750,7 +2710,7 @@ var DevApp = ({ token, userId, orgId, options = {} }) => {
2750
2710
  setDevContext(ctx);
2751
2711
  });
2752
2712
  }, [options.dir]);
2753
- const handleSetupReady = useCallback3(async (resolved) => {
2713
+ const handleSetupReady = useCallback(async (resolved) => {
2754
2714
  if (!devContext) return;
2755
2715
  setResolvedContext(resolved);
2756
2716
  console.log(`[dev] Saving context: appId=${resolved.appId} extensionId=${resolved.extensionId}`);
@@ -2822,7 +2782,7 @@ var DevApp = ({ token, userId, orgId, options = {} }) => {
2822
2782
  console.log("[dev] Ready");
2823
2783
  setState("running");
2824
2784
  }, [devContext, token, options.extensionPort, options.previewPort, useTunnel]);
2825
- useEffect7(() => {
2785
+ useEffect(() => {
2826
2786
  if (state === "setup" && devContext && devContext.appId && devContext.extensionId) {
2827
2787
  handleSetupReady({
2828
2788
  appId: devContext.appId,
@@ -2857,7 +2817,7 @@ var DevApp = ({ token, userId, orgId, options = {} }) => {
2857
2817
  console.log("[dev] Done");
2858
2818
  process.exit(0);
2859
2819
  };
2860
- useInput12((input, key) => {
2820
+ useInput((input, key) => {
2861
2821
  if (input === "c" && key.ctrl) {
2862
2822
  if (state === "running") {
2863
2823
  handleQuit();
@@ -2868,7 +2828,7 @@ var DevApp = ({ token, userId, orgId, options = {} }) => {
2868
2828
  });
2869
2829
  if (state === "setup" && devContext) {
2870
2830
  if (!devContext.appId || !devContext.extensionId) {
2871
- return /* @__PURE__ */ jsx19(
2831
+ return /* @__PURE__ */ jsx(
2872
2832
  DevSetup,
2873
2833
  {
2874
2834
  token,
@@ -2880,7 +2840,7 @@ var DevApp = ({ token, userId, orgId, options = {} }) => {
2880
2840
  return null;
2881
2841
  }
2882
2842
  if (state === "running" && devContext && resolvedContext) {
2883
- return /* @__PURE__ */ jsx19(
2843
+ return /* @__PURE__ */ jsx(
2884
2844
  DevDashboard,
2885
2845
  {
2886
2846
  previewTunnelUrl,
@@ -2902,19 +2862,8 @@ var DevApp = ({ token, userId, orgId, options = {} }) => {
2902
2862
  if (state === "stopping") {
2903
2863
  return null;
2904
2864
  }
2905
- return /* @__PURE__ */ jsx19(Box19, { children: /* @__PURE__ */ jsx19(Text19, { children: "Loading..." }) });
2865
+ return /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { children: "Loading..." }) });
2906
2866
  };
2907
-
2908
- // src/components/AIScaffold.tsx
2909
- import { Box as Box20, Text as Text20, useApp as useApp2 } from "ink";
2910
- import Spinner4 from "ink-spinner";
2911
- import { useState as useState14, useEffect as useEffect8 } from "react";
2912
-
2913
- // src/lib/aiDocs.ts
2914
- import { existsSync, readFileSync } from "fs";
2915
- import { join as join4, dirname } from "path";
2916
- import { mkdir, writeFile as writeFile3 } from "fs/promises";
2917
- import AdmZip from "adm-zip";
2918
2867
  var DEFAULT_STATIC_CDN_URL = "https://static.stackablelabs.io";
2919
2868
  var AI_DOCS_FILENAME = "extension-ai-docs.zip";
2920
2869
  var getStaticCdnBaseUrl = () => process.env.STATIC_CDN_BASE_URL ?? DEFAULT_STATIC_CDN_URL;
@@ -2924,7 +2873,7 @@ var isValidManifest = (data) => {
2924
2873
  return typeof m.name === "string" && m.name.length > 0 && typeof m.version === "string" && Array.isArray(m.targets) && Array.isArray(m.permissions) && Array.isArray(m.allowedDomains);
2925
2874
  };
2926
2875
  var isExtensionProject = (dir) => {
2927
- const manifestPath = join4(dir, "packages/extension/public/manifest.json");
2876
+ const manifestPath = join(dir, "packages/extension/public/manifest.json");
2928
2877
  if (!existsSync(manifestPath)) {
2929
2878
  return { valid: false, reason: "No manifest.json found at packages/extension/public/manifest.json \u2014 is this an Extension project?" };
2930
2879
  }
@@ -2952,22 +2901,19 @@ var downloadAndExtractAiDocs = async (targetDir, version2) => {
2952
2901
  const extractedFiles = [];
2953
2902
  for (const entry of entries) {
2954
2903
  if (entry.isDirectory) continue;
2955
- const targetPath = join4(targetDir, entry.entryName);
2904
+ const targetPath = join(targetDir, entry.entryName);
2956
2905
  await mkdir(dirname(targetPath), { recursive: true });
2957
- await writeFile3(targetPath, entry.getData());
2906
+ await writeFile(targetPath, entry.getData());
2958
2907
  extractedFiles.push(entry.entryName);
2959
2908
  }
2960
2909
  return { files: extractedFiles.sort() };
2961
2910
  };
2962
-
2963
- // src/components/AIScaffold.tsx
2964
- import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
2965
2911
  var AIScaffold = ({ version: version2 }) => {
2966
- const { exit } = useApp2();
2967
- const [state, setState] = useState14("validating");
2968
- const [files, setFiles] = useState14([]);
2969
- const [errorMessage, setErrorMessage] = useState14("");
2970
- useEffect8(() => {
2912
+ const { exit } = useApp();
2913
+ const [state, setState] = useState("validating");
2914
+ const [files, setFiles] = useState([]);
2915
+ const [errorMessage, setErrorMessage] = useState("");
2916
+ useEffect(() => {
2971
2917
  const run = async () => {
2972
2918
  const projectDir = process.cwd();
2973
2919
  const check = isExtensionProject(projectDir);
@@ -2990,64 +2936,52 @@ var AIScaffold = ({ version: version2 }) => {
2990
2936
  };
2991
2937
  run();
2992
2938
  }, []);
2993
- return /* @__PURE__ */ jsxs19(Box20, { flexDirection: "column", children: [
2994
- /* @__PURE__ */ jsx20(Banner, {}),
2995
- /* @__PURE__ */ jsxs19(StepShell, { title: "AI Editor Config", children: [
2996
- state === "validating" && /* @__PURE__ */ jsxs19(Box20, { gap: 1, children: [
2997
- /* @__PURE__ */ jsx20(Text20, { color: "cyan", children: /* @__PURE__ */ jsx20(Spinner4, { type: "dots" }) }),
2998
- /* @__PURE__ */ jsx20(Text20, { children: "Checking project..." })
2939
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
2940
+ /* @__PURE__ */ jsx(Banner, {}),
2941
+ /* @__PURE__ */ jsxs(StepShell, { title: "AI Editor Config", children: [
2942
+ state === "validating" && /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
2943
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: /* @__PURE__ */ jsx(Spinner5, { type: "dots" }) }),
2944
+ /* @__PURE__ */ jsx(Text, { children: "Checking project..." })
2999
2945
  ] }),
3000
- state === "downloading" && /* @__PURE__ */ jsxs19(Box20, { gap: 1, children: [
3001
- /* @__PURE__ */ jsx20(Text20, { color: "cyan", children: /* @__PURE__ */ jsx20(Spinner4, { type: "dots" }) }),
3002
- /* @__PURE__ */ jsxs19(Text20, { children: [
2946
+ state === "downloading" && /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
2947
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: /* @__PURE__ */ jsx(Spinner5, { type: "dots" }) }),
2948
+ /* @__PURE__ */ jsxs(Text, { children: [
3003
2949
  "Downloading AI editor configs (",
3004
2950
  version2,
3005
2951
  ")..."
3006
2952
  ] })
3007
2953
  ] }),
3008
- state === "done" && /* @__PURE__ */ jsxs19(Box20, { flexDirection: "column", gap: 1, children: [
3009
- /* @__PURE__ */ jsxs19(Box20, { gap: 1, children: [
3010
- /* @__PURE__ */ jsx20(Text20, { color: "green", bold: true, children: "\u2714" }),
3011
- /* @__PURE__ */ jsxs19(Text20, { bold: true, children: [
2954
+ state === "done" && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
2955
+ /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
2956
+ /* @__PURE__ */ jsx(Text, { color: "green", bold: true, children: "\u2714" }),
2957
+ /* @__PURE__ */ jsxs(Text, { bold: true, children: [
3012
2958
  "AI editor configs installed (",
3013
2959
  files.length,
3014
2960
  " files)"
3015
2961
  ] })
3016
2962
  ] }),
3017
- /* @__PURE__ */ jsx20(Box20, { flexDirection: "column", marginLeft: 2, children: files.map((f) => /* @__PURE__ */ jsx20(Text20, { dimColor: true, children: f }, f)) })
2963
+ /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginLeft: 2, children: files.map((f) => /* @__PURE__ */ jsx(Text, { dimColor: true, children: f }, f)) })
3018
2964
  ] }),
3019
- state === "error" && /* @__PURE__ */ jsxs19(Box20, { gap: 1, children: [
3020
- /* @__PURE__ */ jsx20(Text20, { color: "red", children: "\u2716" }),
3021
- /* @__PURE__ */ jsx20(Text20, { children: errorMessage })
2965
+ state === "error" && /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
2966
+ /* @__PURE__ */ jsx(Text, { color: "red", children: "\u2716" }),
2967
+ /* @__PURE__ */ jsx(Text, { children: errorMessage })
3022
2968
  ] })
3023
2969
  ] })
3024
2970
  ] });
3025
2971
  };
3026
-
3027
- // src/components/AuthLogin.tsx
3028
- import { createServer } from "http";
3029
- import { Box as Box21, Text as Text21, useApp as useApp3 } from "ink";
3030
- import Spinner5 from "ink-spinner";
3031
- import open from "open";
3032
- import { useState as useState15, useEffect as useEffect9 } from "react";
3033
-
3034
- // src/lib/auth.ts
3035
- import { readFile as readFile4, writeFile as writeFile4, mkdir as mkdir2, unlink } from "fs/promises";
3036
- import { join as join5 } from "path";
3037
- import { homedir } from "os";
3038
- var AUTH_DIR = join5(homedir(), ".stackable");
3039
- var AUTH_FILE = join5(AUTH_DIR, "auth.json");
2972
+ var AUTH_DIR = join(homedir(), ".stackable");
2973
+ var AUTH_FILE = join(AUTH_DIR, "auth.json");
3040
2974
  var readAuthState = async () => {
3041
2975
  try {
3042
- const content = await readFile4(AUTH_FILE, "utf8");
2976
+ const content = await readFile(AUTH_FILE, "utf8");
3043
2977
  return JSON.parse(content);
3044
2978
  } catch {
3045
2979
  return null;
3046
2980
  }
3047
2981
  };
3048
2982
  var writeAuthState = async (state) => {
3049
- await mkdir2(AUTH_DIR, { recursive: true, mode: 448 });
3050
- await writeFile4(AUTH_FILE, JSON.stringify(state, null, 2), { mode: 384 });
2983
+ await mkdir(AUTH_DIR, { recursive: true, mode: 448 });
2984
+ await writeFile(AUTH_FILE, JSON.stringify(state, null, 2), { mode: 384 });
3051
2985
  };
3052
2986
  var clearAuthState = async () => {
3053
2987
  try {
@@ -3080,9 +3014,6 @@ var getToken = async () => {
3080
3014
  }
3081
3015
  return state.token;
3082
3016
  };
3083
-
3084
- // src/components/AuthLogin.tsx
3085
- import { jsx as jsx21, jsxs as jsxs20 } from "react/jsx-runtime";
3086
3017
  var LOGIN_TIMEOUT_MS = 5 * 60 * 1e3;
3087
3018
  var callbackPage = (heading, sub, redirectUrl) => `<!DOCTYPE html>
3088
3019
  <html><head><meta charset="utf-8"><title>Stackable CLI</title>
@@ -3092,13 +3023,13 @@ var callbackPage = (heading, sub, redirectUrl) => `<!DOCTYPE html>
3092
3023
  ${redirectUrl ? `<script>(function(){var s=3,el=document.getElementById('h');function t(){if(s<=0){location.href='${redirectUrl}';return}el.textContent='Redirecting in '+s+'s\u2026';s--;setTimeout(t,1000)}t()})()</script>` : ""}
3093
3024
  </body></html>`;
3094
3025
  var AuthLogin = ({ dashboardUrl }) => {
3095
- const { exit } = useApp3();
3096
- const [state, setState] = useState15("waiting");
3097
- const [loginUrl, setLoginUrl] = useState15("");
3098
- const [userIdLabel, setUserIdLabel] = useState15("");
3099
- const [orgIdLabel, setOrgIdLabel] = useState15("");
3100
- const [errorMessage, setErrorMessage] = useState15("");
3101
- useEffect9(() => {
3026
+ const { exit } = useApp();
3027
+ const [state, setState] = useState("waiting");
3028
+ const [loginUrl, setLoginUrl] = useState("");
3029
+ const [userIdLabel, setUserIdLabel] = useState("");
3030
+ const [orgIdLabel, setOrgIdLabel] = useState("");
3031
+ const [errorMessage, setErrorMessage] = useState("");
3032
+ useEffect(() => {
3102
3033
  let server;
3103
3034
  let timeout;
3104
3035
  const run = async () => {
@@ -3173,116 +3104,103 @@ var AuthLogin = ({ dashboardUrl }) => {
3173
3104
  server?.close();
3174
3105
  };
3175
3106
  }, []);
3176
- return /* @__PURE__ */ jsxs20(Box21, { flexDirection: "column", children: [
3177
- /* @__PURE__ */ jsx21(Banner, {}),
3178
- /* @__PURE__ */ jsxs20(StepShell, { title: "Authenticate with Stackable", children: [
3179
- state === "waiting" && /* @__PURE__ */ jsxs20(Box21, { flexDirection: "column", gap: 1, children: [
3180
- /* @__PURE__ */ jsxs20(Box21, { gap: 1, children: [
3181
- /* @__PURE__ */ jsx21(Text21, { color: "cyan", children: /* @__PURE__ */ jsx21(Spinner5, { type: "dots" }) }),
3182
- /* @__PURE__ */ jsx21(Text21, { children: "Waiting for browser authentication..." })
3107
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
3108
+ /* @__PURE__ */ jsx(Banner, {}),
3109
+ /* @__PURE__ */ jsxs(StepShell, { title: "Authenticate with Stackable", children: [
3110
+ state === "waiting" && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
3111
+ /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
3112
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: /* @__PURE__ */ jsx(Spinner5, { type: "dots" }) }),
3113
+ /* @__PURE__ */ jsx(Text, { children: "Waiting for browser authentication..." })
3183
3114
  ] }),
3184
- loginUrl && /* @__PURE__ */ jsxs20(Text21, { dimColor: true, children: [
3115
+ loginUrl && /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
3185
3116
  " ",
3186
3117
  loginUrl
3187
3118
  ] })
3188
3119
  ] }),
3189
- state === "success" && /* @__PURE__ */ jsxs20(Box21, { flexDirection: "column", gap: 1, children: [
3190
- /* @__PURE__ */ jsxs20(Box21, { flexDirection: "column", children: [
3191
- /* @__PURE__ */ jsxs20(Box21, { gap: 2, children: [
3192
- /* @__PURE__ */ jsx21(Text21, { dimColor: true, children: "User:" }),
3193
- /* @__PURE__ */ jsx21(Text21, { color: "cyan", children: userIdLabel })
3120
+ state === "success" && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
3121
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
3122
+ /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
3123
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "User:" }),
3124
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: userIdLabel })
3194
3125
  ] }),
3195
- /* @__PURE__ */ jsxs20(Box21, { gap: 2, children: [
3196
- /* @__PURE__ */ jsx21(Text21, { dimColor: true, children: "Org: " }),
3197
- /* @__PURE__ */ jsx21(Text21, { color: "cyan", children: orgIdLabel })
3126
+ /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
3127
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Org: " }),
3128
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: orgIdLabel })
3198
3129
  ] })
3199
3130
  ] }),
3200
- /* @__PURE__ */ jsxs20(Box21, { gap: 1, children: [
3201
- /* @__PURE__ */ jsx21(Text21, { color: "green", bold: true, children: "\u2714" }),
3202
- /* @__PURE__ */ jsx21(Text21, { bold: true, children: "Authenticated" })
3131
+ /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
3132
+ /* @__PURE__ */ jsx(Text, { color: "green", bold: true, children: "\u2714" }),
3133
+ /* @__PURE__ */ jsx(Text, { bold: true, children: "Authenticated" })
3203
3134
  ] })
3204
3135
  ] }),
3205
- state === "error" && /* @__PURE__ */ jsxs20(Box21, { gap: 1, children: [
3206
- /* @__PURE__ */ jsx21(Text21, { color: "red", children: "\u2716" }),
3207
- /* @__PURE__ */ jsx21(Text21, { children: errorMessage })
3136
+ state === "error" && /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
3137
+ /* @__PURE__ */ jsx(Text, { color: "red", children: "\u2716" }),
3138
+ /* @__PURE__ */ jsx(Text, { children: errorMessage })
3208
3139
  ] })
3209
3140
  ] })
3210
3141
  ] });
3211
3142
  };
3212
-
3213
- // src/components/AuthLogout.tsx
3214
- import { useEffect as useEffect10 } from "react";
3215
- import { Box as Box22, Text as Text22, useApp as useApp4 } from "ink";
3216
- import { jsx as jsx22, jsxs as jsxs21 } from "react/jsx-runtime";
3217
3143
  var AuthLogout = () => {
3218
- const { exit } = useApp4();
3219
- useEffect10(() => {
3144
+ const { exit } = useApp();
3145
+ useEffect(() => {
3220
3146
  exit();
3221
3147
  }, [exit]);
3222
- return /* @__PURE__ */ jsxs21(Box22, { flexDirection: "column", children: [
3223
- /* @__PURE__ */ jsx22(Banner, {}),
3224
- /* @__PURE__ */ jsx22(StepShell, { title: "Authenticate with Stackable", children: /* @__PURE__ */ jsxs21(Box22, { gap: 1, children: [
3225
- /* @__PURE__ */ jsx22(Text22, { color: "green", bold: true, children: "\u2714" }),
3226
- /* @__PURE__ */ jsx22(Text22, { bold: true, children: "Logged out" })
3148
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
3149
+ /* @__PURE__ */ jsx(Banner, {}),
3150
+ /* @__PURE__ */ jsx(StepShell, { title: "Authenticate with Stackable", children: /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
3151
+ /* @__PURE__ */ jsx(Text, { color: "green", bold: true, children: "\u2714" }),
3152
+ /* @__PURE__ */ jsx(Text, { bold: true, children: "Logged out" })
3227
3153
  ] }) })
3228
3154
  ] });
3229
3155
  };
3230
-
3231
- // src/components/AuthStatus.tsx
3232
- import { useEffect as useEffect11 } from "react";
3233
- import { useApp as useApp5, Box as Box23, Text as Text23 } from "ink";
3234
- import { jsx as jsx23, jsxs as jsxs22 } from "react/jsx-runtime";
3235
3156
  var AuthStatus = ({ state, userId, orgId, expiry }) => {
3236
- const { exit } = useApp5();
3237
- useEffect11(() => {
3157
+ const { exit } = useApp();
3158
+ useEffect(() => {
3238
3159
  exit();
3239
3160
  }, [exit]);
3240
- return /* @__PURE__ */ jsxs22(Box23, { flexDirection: "column", children: [
3241
- /* @__PURE__ */ jsx23(Banner, {}),
3242
- /* @__PURE__ */ jsxs22(StepShell, { title: "Authenticate with Stackable", children: [
3243
- state === "authenticated" && /* @__PURE__ */ jsxs22(Box23, { flexDirection: "column", gap: 1, children: [
3244
- /* @__PURE__ */ jsxs22(Box23, { flexDirection: "column", children: [
3245
- /* @__PURE__ */ jsxs22(Box23, { gap: 2, children: [
3246
- /* @__PURE__ */ jsx23(Text23, { dimColor: true, children: "User:" }),
3247
- /* @__PURE__ */ jsx23(Text23, { color: "cyan", children: userId })
3161
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
3162
+ /* @__PURE__ */ jsx(Banner, {}),
3163
+ /* @__PURE__ */ jsxs(StepShell, { title: "Authenticate with Stackable", children: [
3164
+ state === "authenticated" && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
3165
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
3166
+ /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
3167
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "User:" }),
3168
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: userId })
3248
3169
  ] }),
3249
- /* @__PURE__ */ jsxs22(Box23, { gap: 2, children: [
3250
- /* @__PURE__ */ jsx23(Text23, { dimColor: true, children: "Org: " }),
3251
- /* @__PURE__ */ jsx23(Text23, { color: "cyan", children: orgId })
3170
+ /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
3171
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Org: " }),
3172
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: orgId })
3252
3173
  ] }),
3253
- expiry && /* @__PURE__ */ jsxs22(Box23, { gap: 2, children: [
3254
- /* @__PURE__ */ jsx23(Text23, { dimColor: true, children: "Exp: " }),
3255
- /* @__PURE__ */ jsx23(Text23, { color: "cyan", children: expiry.toLocaleDateString() })
3174
+ expiry && /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
3175
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Exp: " }),
3176
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: expiry.toLocaleDateString() })
3256
3177
  ] })
3257
3178
  ] }),
3258
- /* @__PURE__ */ jsxs22(Box23, { gap: 1, children: [
3259
- /* @__PURE__ */ jsx23(Text23, { color: "green", bold: true, children: "\u2714" }),
3260
- /* @__PURE__ */ jsx23(Text23, { bold: true, children: "Authenticated" })
3179
+ /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
3180
+ /* @__PURE__ */ jsx(Text, { color: "green", bold: true, children: "\u2714" }),
3181
+ /* @__PURE__ */ jsx(Text, { bold: true, children: "Authenticated" })
3261
3182
  ] })
3262
3183
  ] }),
3263
- state === "expired" && /* @__PURE__ */ jsxs22(Box23, { flexDirection: "column", gap: 1, children: [
3264
- /* @__PURE__ */ jsxs22(Box23, { gap: 1, children: [
3265
- /* @__PURE__ */ jsx23(Text23, { color: "red", children: "\u2716" }),
3266
- /* @__PURE__ */ jsxs22(Text23, { children: [
3184
+ state === "expired" && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
3185
+ /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
3186
+ /* @__PURE__ */ jsx(Text, { color: "red", children: "\u2716" }),
3187
+ /* @__PURE__ */ jsxs(Text, { children: [
3267
3188
  "Session expired",
3268
3189
  expiry ? ` (${expiry.toLocaleDateString()})` : ""
3269
3190
  ] })
3270
3191
  ] }),
3271
- /* @__PURE__ */ jsx23(Text23, { dimColor: true, children: "Run `stackable-app-extension auth login` to re-authenticate." })
3192
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Run `stackable-app-extension auth login` to re-authenticate." })
3272
3193
  ] }),
3273
- state === "not-logged-in" && /* @__PURE__ */ jsxs22(Box23, { flexDirection: "column", gap: 1, children: [
3274
- /* @__PURE__ */ jsxs22(Box23, { gap: 1, children: [
3275
- /* @__PURE__ */ jsx23(Text23, { color: "red", children: "\u2716" }),
3276
- /* @__PURE__ */ jsx23(Text23, { children: "Not logged in" })
3194
+ state === "not-logged-in" && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", gap: 1, children: [
3195
+ /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
3196
+ /* @__PURE__ */ jsx(Text, { color: "red", children: "\u2716" }),
3197
+ /* @__PURE__ */ jsx(Text, { children: "Not logged in" })
3277
3198
  ] }),
3278
- /* @__PURE__ */ jsx23(Text23, { dimColor: true, children: "Run `stackable-app-extension auth login`" })
3199
+ /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Run `stackable-app-extension auth login`" })
3279
3200
  ] })
3280
3201
  ] })
3281
3202
  ] });
3282
3203
  };
3283
-
3284
- // src/lib/versionCheck.ts
3285
- import https from "https";
3286
3204
  var PACKAGE_NAME = "@stackable-labs/cli-app-extension";
3287
3205
  var REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
3288
3206
  var TIMEOUT_MS = 3e3;
@@ -3327,9 +3245,6 @@ var checkForUpdate = (currentVersion) => {
3327
3245
  } catch {
3328
3246
  }
3329
3247
  };
3330
-
3331
- // src/index.tsx
3332
- import { jsx as jsx24 } from "react/jsx-runtime";
3333
3248
  var require2 = createRequire(import.meta.url);
3334
3249
  var { version } = require2("../package.json");
3335
3250
  checkForUpdate(version);
@@ -3342,20 +3257,20 @@ var ensureToken = async () => {
3342
3257
  const message = err instanceof Error ? err.message : String(err);
3343
3258
  const isExpired = message.toLowerCase().includes("expired");
3344
3259
  render(
3345
- /* @__PURE__ */ jsx24(AuthStatus, { state: isExpired ? "expired" : "not-logged-in" })
3260
+ /* @__PURE__ */ jsx(AuthStatus, { state: isExpired ? "expired" : "not-logged-in" })
3346
3261
  );
3347
3262
  return null;
3348
3263
  }
3349
3264
  };
3350
3265
  program.name("stackable-app-extension").description("Stackable Labs - App Extension developer CLI").version(version);
3351
- program.command("create" /* CREATE */).description("Create a new Extension project").argument("[name]", "Extension project name").option("--app-id <id>", "Skip App selection").option("--project <id>", "Studio project ID (fetches files/manifest from Studio)").option("--template <flavor>", "Template flavor: minimal, starter, kitchen-sink").option("--extension-port <port>", "Extension dev server port (default: 6543)").option("--preview-port <port>", "Preview dev server port").option("--skip-install", "Skip package manager install").option("--skip-git", "Skip git initialization").action(async (name, options) => {
3266
+ program.command("create" /* CREATE */).description("Create a new Extension project").argument("[name]", "Extension project name").option("--app-id <id>", "Skip App selection").option("--project-id <id>", "Studio project ID (fetches files/manifest from Studio)").option("--template <flavor>", "Template flavor: minimal, starter, kitchen-sink").option("--extension-port <port>", "Extension dev server port (default: 6543)").option("--preview-port <port>", "Preview dev server port").option("--skip-install", "Skip package manager install").option("--skip-git", "Skip git initialization").action(async (name, options) => {
3352
3267
  const auth2 = await ensureToken();
3353
3268
  if (!auth2) {
3354
3269
  return;
3355
3270
  }
3356
3271
  const { token, userId, orgId } = auth2;
3357
3272
  render(
3358
- /* @__PURE__ */ jsx24(
3273
+ /* @__PURE__ */ jsx(
3359
3274
  App,
3360
3275
  {
3361
3276
  command: "create" /* CREATE */,
@@ -3368,17 +3283,18 @@ program.command("create" /* CREATE */).description("Create a new Extension proje
3368
3283
  )
3369
3284
  );
3370
3285
  });
3371
- program.command("scaffold" /* SCAFFOLD */).description("Scaffold a local project from an existing Extension").option("--app-id <id>", "Skip App selection").option("--project <id>", "Studio project ID (fetches files/manifest from Studio)").option("--extension-port <port>", "Extension dev server port (default: 6543)").option("--preview-port <port>", "Preview dev server port").option("--skip-install", "Skip package manager install").option("--skip-git", "Skip git initialization").action(async (options) => {
3286
+ program.command("scaffold" /* SCAFFOLD */).description("Scaffold a local project from an existing Extension").argument("[extensionId]", "Extension ID to scaffold from").option("--app-id <id>", "App ID (auto-resolved from extensionId if omitted)").option("--project-id <id>", "Studio project ID (fetches files/manifest from Studio)").option("--template <flavor>", "Template flavor: minimal, starter, kitchen-sink").option("--extension-port <port>", "Extension dev server port (default: 6543)").option("--preview-port <port>", "Preview dev server port").option("--skip-install", "Skip package manager install").option("--skip-git", "Skip git initialization").action(async (extensionId, options) => {
3372
3287
  const auth2 = await ensureToken();
3373
3288
  if (!auth2) {
3374
3289
  return;
3375
3290
  }
3376
3291
  const { token, userId, orgId } = auth2;
3377
3292
  render(
3378
- /* @__PURE__ */ jsx24(
3293
+ /* @__PURE__ */ jsx(
3379
3294
  App,
3380
3295
  {
3381
3296
  command: "scaffold" /* SCAFFOLD */,
3297
+ initialExtensionId: extensionId,
3382
3298
  options,
3383
3299
  token,
3384
3300
  orgId,
@@ -3387,14 +3303,14 @@ program.command("scaffold" /* SCAFFOLD */).description("Scaffold a local project
3387
3303
  )
3388
3304
  );
3389
3305
  });
3390
- program.command("update" /* UPDATE */).description("Update an existing Extension").argument("[extensionId]", "Extension ID to update").option("--app-id <id>", "Skip App selection").option("--name <name>", "New Extension name").option("--targets <targets>", "Comma-separated target slots (validated against app)").option("--bundle-url <url>", "New bundle URL").option("--enabled <bool>", "Enable/disable Extension").option("--set-version <version>", "Explicit version (skips auto-compute)").option("--dir <path>", "Project root (default: cwd)").action(async (extensionId, options) => {
3306
+ program.command("update" /* UPDATE */).description("Update an existing Extension").argument("[extensionId]", "Extension ID to update").option("--app-id <id>", "App ID (auto-resolved from extensionId if omitted)").option("--name <name>", "New Extension name").option("--targets <targets>", "Comma-separated target slots (validated against app)").option("--bundle-url <url>", "New bundle URL").option("--enabled <bool>", "Enable/disable Extension").option("--set-version <version>", "Explicit version (skips auto-compute)").option("--dir <path>", "Project root (default: cwd)").action(async (extensionId, options) => {
3391
3307
  const auth2 = await ensureToken();
3392
3308
  if (!auth2) {
3393
3309
  return;
3394
3310
  }
3395
3311
  const { token, userId, orgId } = auth2;
3396
3312
  render(
3397
- /* @__PURE__ */ jsx24(
3313
+ /* @__PURE__ */ jsx(
3398
3314
  App,
3399
3315
  {
3400
3316
  command: "update" /* UPDATE */,
@@ -3414,7 +3330,7 @@ program.command("dev" /* DEV */).description("Start dev servers with a public tu
3414
3330
  }
3415
3331
  const { token, userId, orgId } = auth2;
3416
3332
  render(
3417
- /* @__PURE__ */ jsx24(
3333
+ /* @__PURE__ */ jsx(
3418
3334
  DevApp,
3419
3335
  {
3420
3336
  options,
@@ -3429,17 +3345,17 @@ program.command("dev" /* DEV */).description("Start dev servers with a public tu
3429
3345
  var DASHBOARD_URL = process.env.ADMIN_DASHBOARD_URL ?? "https://admin.stackablelabs.io";
3430
3346
  var auth = program.command("auth").description("Manage CLI authentication");
3431
3347
  auth.command("login").description("Authenticate with Stackable via browser").action(async () => {
3432
- render(/* @__PURE__ */ jsx24(AuthLogin, { dashboardUrl: DASHBOARD_URL }));
3348
+ render(/* @__PURE__ */ jsx(AuthLogin, { dashboardUrl: DASHBOARD_URL }));
3433
3349
  });
3434
3350
  auth.command("logout").description("Clear stored CLI credentials").action(async () => {
3435
3351
  await clearAuthState();
3436
- render(/* @__PURE__ */ jsx24(AuthLogout, {}));
3352
+ render(/* @__PURE__ */ jsx(AuthLogout, {}));
3437
3353
  });
3438
3354
  auth.command("status").description("Show current authentication status").action(async () => {
3439
3355
  const state = await readAuthState();
3440
3356
  if (!state) {
3441
3357
  render(
3442
- /* @__PURE__ */ jsx24(AuthStatus, { state: "not-logged-in" })
3358
+ /* @__PURE__ */ jsx(AuthStatus, { state: "not-logged-in" })
3443
3359
  );
3444
3360
  return;
3445
3361
  }
@@ -3447,11 +3363,11 @@ auth.command("status").description("Show current authentication status").action(
3447
3363
  const payload = JSON.parse(Buffer.from(payloadB64, "base64url").toString());
3448
3364
  const expiry = payload.exp ? new Date(payload.exp * 1e3) : null;
3449
3365
  if (expiry && Date.now() >= expiry.getTime()) {
3450
- render(/* @__PURE__ */ jsx24(AuthStatus, { state: "expired", expiry }));
3366
+ render(/* @__PURE__ */ jsx(AuthStatus, { state: "expired", expiry }));
3451
3367
  return;
3452
3368
  }
3453
3369
  render(
3454
- /* @__PURE__ */ jsx24(
3370
+ /* @__PURE__ */ jsx(
3455
3371
  AuthStatus,
3456
3372
  {
3457
3373
  state: "authenticated",
@@ -3464,6 +3380,6 @@ auth.command("status").description("Show current authentication status").action(
3464
3380
  });
3465
3381
  var ai = program.command("ai").description("AI editor configuration tools");
3466
3382
  ai.command("scaffold").description("Download AI editor config files into your Extension project").option("--version <version>", 'AI docs version (semver or "latest")', "latest").action(async (options) => {
3467
- render(/* @__PURE__ */ jsx24(AIScaffold, { version: options.version }));
3383
+ render(/* @__PURE__ */ jsx(AIScaffold, { version: options.version }));
3468
3384
  });
3469
3385
  program.parse(process.argv.filter((arg) => arg !== "--"));