@stackable-labs/cli-app-extension 1.2.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +437 -375
- package/package.json +2 -4
package/dist/index.js
CHANGED
|
@@ -6,8 +6,8 @@ import { render } from "ink";
|
|
|
6
6
|
|
|
7
7
|
// src/App.tsx
|
|
8
8
|
import { join as join2 } from "path";
|
|
9
|
-
import { Box as
|
|
10
|
-
import { useCallback, useState as
|
|
9
|
+
import { Box as Box12, Text as Text12, useApp } from "ink";
|
|
10
|
+
import { useCallback, useState as useState8 } from "react";
|
|
11
11
|
|
|
12
12
|
// src/components/Confirm.tsx
|
|
13
13
|
import { Box as Box2, Text as Text2, useInput } from "ink";
|
|
@@ -43,8 +43,9 @@ var StepShell = ({ title, hint, children, footer, onBack, backFocused }) => {
|
|
|
43
43
|
|
|
44
44
|
// src/components/Confirm.tsx
|
|
45
45
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
46
|
-
var Confirm = ({ name, extensionPort, previewPort, targets, outputDir, onConfirm, onCancel, onBack }) => {
|
|
46
|
+
var Confirm = ({ name, extensionVersion, extensionPort, previewPort, targets, outputDir, onConfirm, onCancel, onBack }) => {
|
|
47
47
|
const [backFocused, setBackFocused] = useState(false);
|
|
48
|
+
const [selected, setSelected] = useState("y");
|
|
48
49
|
useInput((input, key) => {
|
|
49
50
|
if (key.upArrow && onBack) {
|
|
50
51
|
setBackFocused(true);
|
|
@@ -59,12 +60,21 @@ var Confirm = ({ name, extensionPort, previewPort, targets, outputDir, onConfirm
|
|
|
59
60
|
return;
|
|
60
61
|
}
|
|
61
62
|
if (backFocused) return;
|
|
62
|
-
if (
|
|
63
|
-
|
|
63
|
+
if (key.leftArrow || key.rightArrow) {
|
|
64
|
+
setSelected((s) => s === "y" ? "n" : "y");
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (input === "y") {
|
|
68
|
+
setSelected("y");
|
|
64
69
|
return;
|
|
65
70
|
}
|
|
66
71
|
if (input === "n") {
|
|
67
|
-
|
|
72
|
+
setSelected("n");
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (key.return) {
|
|
76
|
+
if (selected === "y") onConfirm();
|
|
77
|
+
else onCancel();
|
|
68
78
|
}
|
|
69
79
|
});
|
|
70
80
|
return /* @__PURE__ */ jsx2(
|
|
@@ -75,15 +85,20 @@ var Confirm = ({ name, extensionPort, previewPort, targets, outputDir, onConfirm
|
|
|
75
85
|
onBack,
|
|
76
86
|
backFocused,
|
|
77
87
|
footer: /* @__PURE__ */ jsxs2(Text2, { children: [
|
|
78
|
-
"Proceed?
|
|
79
|
-
|
|
80
|
-
"
|
|
81
|
-
/* @__PURE__ */ jsx2(Text2, {
|
|
88
|
+
"Proceed?",
|
|
89
|
+
" ",
|
|
90
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, color: "green", inverse: selected === "y", children: "Y" }),
|
|
91
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "/" }),
|
|
92
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, color: "red", inverse: selected === "n", children: "n" })
|
|
82
93
|
] }),
|
|
83
94
|
children: /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", gap: 1, children: [
|
|
84
95
|
/* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
|
|
85
96
|
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Name " }),
|
|
86
|
-
/* @__PURE__ */ jsx2(Text2, { children: name })
|
|
97
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: !!extensionVersion, children: name })
|
|
98
|
+
] }),
|
|
99
|
+
extensionVersion && /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
|
|
100
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Version " }),
|
|
101
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: extensionVersion })
|
|
87
102
|
] }),
|
|
88
103
|
/* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
|
|
89
104
|
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Directory " }),
|
|
@@ -109,15 +124,55 @@ var Confirm = ({ name, extensionPort, previewPort, targets, outputDir, onConfirm
|
|
|
109
124
|
);
|
|
110
125
|
};
|
|
111
126
|
|
|
112
|
-
// src/components/
|
|
113
|
-
import { Box as
|
|
127
|
+
// src/components/Done.tsx
|
|
128
|
+
import { Box as Box3, Text as Text3 } from "ink";
|
|
129
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
130
|
+
var Done = ({ name, outputDir }) => /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", gap: 1, children: [
|
|
131
|
+
/* @__PURE__ */ jsxs3(Box3, { gap: 1, children: [
|
|
132
|
+
/* @__PURE__ */ jsx3(Text3, { color: "green", bold: true, children: "\u2714" }),
|
|
133
|
+
/* @__PURE__ */ jsx3(Text3, { bold: true, children: "Extension scaffolded successfully!" })
|
|
134
|
+
] }),
|
|
135
|
+
/* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginLeft: 2, children: [
|
|
136
|
+
/* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
|
|
137
|
+
"Created: ",
|
|
138
|
+
/* @__PURE__ */ jsx3(Text3, { color: "cyan", children: name })
|
|
139
|
+
] }),
|
|
140
|
+
/* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
|
|
141
|
+
"Location: ",
|
|
142
|
+
/* @__PURE__ */ jsx3(Text3, { color: "cyan", children: outputDir })
|
|
143
|
+
] })
|
|
144
|
+
] }),
|
|
145
|
+
/* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginTop: 1, borderStyle: "round", borderColor: "green", paddingX: 2, paddingY: 1, children: [
|
|
146
|
+
/* @__PURE__ */ jsx3(Text3, { bold: true, children: "Next steps:" }),
|
|
147
|
+
/* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginTop: 1, gap: 1, children: [
|
|
148
|
+
/* @__PURE__ */ jsxs3(Box3, { gap: 1, children: [
|
|
149
|
+
/* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "1." }),
|
|
150
|
+
/* @__PURE__ */ jsxs3(Text3, { children: [
|
|
151
|
+
/* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "cd " }),
|
|
152
|
+
/* @__PURE__ */ jsx3(Text3, { color: "cyan", children: outputDir })
|
|
153
|
+
] })
|
|
154
|
+
] }),
|
|
155
|
+
/* @__PURE__ */ jsxs3(Box3, { gap: 1, children: [
|
|
156
|
+
/* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "2." }),
|
|
157
|
+
/* @__PURE__ */ jsx3(Text3, { color: "cyan", children: "pnpm install" })
|
|
158
|
+
] }),
|
|
159
|
+
/* @__PURE__ */ jsxs3(Box3, { gap: 1, children: [
|
|
160
|
+
/* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "3." }),
|
|
161
|
+
/* @__PURE__ */ jsx3(Text3, { color: "cyan", children: "pnpm dev" })
|
|
162
|
+
] })
|
|
163
|
+
] })
|
|
164
|
+
] })
|
|
165
|
+
] });
|
|
166
|
+
|
|
167
|
+
// src/components/NamePrompt.tsx
|
|
168
|
+
import { Box as Box5, Text as Text5 } from "ink";
|
|
114
169
|
import TextInput from "ink-text-input";
|
|
115
170
|
import { useState as useState3 } from "react";
|
|
116
171
|
|
|
117
172
|
// src/components/BackableInput.tsx
|
|
118
|
-
import { Box as
|
|
173
|
+
import { Box as Box4, Text as Text4, useInput as useInput2 } from "ink";
|
|
119
174
|
import { useState as useState2 } from "react";
|
|
120
|
-
import { jsx as
|
|
175
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
121
176
|
var BackableInput = ({ label, hint, onBack, children, error }) => {
|
|
122
177
|
const [focus, setFocus] = useState2("input");
|
|
123
178
|
useInput2((_input, key) => {
|
|
@@ -133,77 +188,17 @@ var BackableInput = ({ label, hint, onBack, children, error }) => {
|
|
|
133
188
|
onBack?.();
|
|
134
189
|
}
|
|
135
190
|
});
|
|
136
|
-
return /* @__PURE__ */
|
|
191
|
+
return /* @__PURE__ */ jsx4(StepShell, { title: label, hint, onBack, backFocused: focus === "back", children: /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", gap: 1, children: [
|
|
137
192
|
children(focus === "input"),
|
|
138
|
-
error && /* @__PURE__ */
|
|
193
|
+
error && /* @__PURE__ */ jsx4(Text4, { color: "red", children: error })
|
|
139
194
|
] }) });
|
|
140
195
|
};
|
|
141
196
|
|
|
142
|
-
// src/components/DirPrompt.tsx
|
|
143
|
-
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
144
|
-
var DirPrompt = ({ defaultDir, onSubmit, onBack }) => {
|
|
145
|
-
const [value, setValue] = useState3(defaultDir);
|
|
146
|
-
const handleSubmit = (val) => {
|
|
147
|
-
const trimmed = val.trim();
|
|
148
|
-
if (trimmed.length === 0) {
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
onSubmit(trimmed);
|
|
152
|
-
};
|
|
153
|
-
return /* @__PURE__ */ jsx4(BackableInput, { label: "Output directory:", hint: "Press Enter to confirm", onBack, children: (isFocused) => /* @__PURE__ */ jsxs4(Box4, { children: [
|
|
154
|
-
/* @__PURE__ */ jsx4(Text4, { color: "cyan", children: "\u2192 " }),
|
|
155
|
-
/* @__PURE__ */ jsx4(TextInput, { value, onChange: setValue, onSubmit: handleSubmit, focus: isFocused })
|
|
156
|
-
] }) });
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
// src/components/Done.tsx
|
|
160
|
-
import { Box as Box5, Text as Text5 } from "ink";
|
|
161
|
-
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
162
|
-
var Done = ({ name, outputDir }) => /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", gap: 1, children: [
|
|
163
|
-
/* @__PURE__ */ jsxs5(Box5, { gap: 1, children: [
|
|
164
|
-
/* @__PURE__ */ jsx5(Text5, { color: "green", bold: true, children: "\u2714" }),
|
|
165
|
-
/* @__PURE__ */ jsx5(Text5, { bold: true, children: "Extension scaffolded successfully!" })
|
|
166
|
-
] }),
|
|
167
|
-
/* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginLeft: 2, children: [
|
|
168
|
-
/* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
|
|
169
|
-
"Created: ",
|
|
170
|
-
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: name })
|
|
171
|
-
] }),
|
|
172
|
-
/* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
|
|
173
|
-
"Location: ",
|
|
174
|
-
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: outputDir })
|
|
175
|
-
] })
|
|
176
|
-
] }),
|
|
177
|
-
/* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginTop: 1, borderStyle: "round", borderColor: "green", paddingX: 2, paddingY: 1, children: [
|
|
178
|
-
/* @__PURE__ */ jsx5(Text5, { bold: true, children: "Next steps:" }),
|
|
179
|
-
/* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginTop: 1, gap: 1, children: [
|
|
180
|
-
/* @__PURE__ */ jsxs5(Box5, { gap: 1, children: [
|
|
181
|
-
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "1." }),
|
|
182
|
-
/* @__PURE__ */ jsxs5(Text5, { children: [
|
|
183
|
-
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "cd " }),
|
|
184
|
-
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: outputDir })
|
|
185
|
-
] })
|
|
186
|
-
] }),
|
|
187
|
-
/* @__PURE__ */ jsxs5(Box5, { gap: 1, children: [
|
|
188
|
-
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "2." }),
|
|
189
|
-
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "pnpm install" })
|
|
190
|
-
] }),
|
|
191
|
-
/* @__PURE__ */ jsxs5(Box5, { gap: 1, children: [
|
|
192
|
-
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "3." }),
|
|
193
|
-
/* @__PURE__ */ jsx5(Text5, { color: "cyan", children: "pnpm dev" })
|
|
194
|
-
] })
|
|
195
|
-
] })
|
|
196
|
-
] })
|
|
197
|
-
] });
|
|
198
|
-
|
|
199
197
|
// src/components/NamePrompt.tsx
|
|
200
|
-
import {
|
|
201
|
-
import TextInput2 from "ink-text-input";
|
|
202
|
-
import { useState as useState4 } from "react";
|
|
203
|
-
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
198
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
204
199
|
var NamePrompt = ({ initialValue = "", onSubmit, onBack }) => {
|
|
205
|
-
const [value, setValue] =
|
|
206
|
-
const [error, setError] =
|
|
200
|
+
const [value, setValue] = useState3(initialValue);
|
|
201
|
+
const [error, setError] = useState3();
|
|
207
202
|
const handleSubmit = (val) => {
|
|
208
203
|
const trimmed = val.trim();
|
|
209
204
|
if (trimmed.length === 0) {
|
|
@@ -213,88 +208,143 @@ var NamePrompt = ({ initialValue = "", onSubmit, onBack }) => {
|
|
|
213
208
|
setError(void 0);
|
|
214
209
|
onSubmit(trimmed);
|
|
215
210
|
};
|
|
216
|
-
return /* @__PURE__ */
|
|
217
|
-
/* @__PURE__ */
|
|
218
|
-
/* @__PURE__ */
|
|
211
|
+
return /* @__PURE__ */ jsx5(BackableInput, { label: "What is your Extension name?", hint: "Press Enter to confirm", onBack, error, children: (isFocused) => /* @__PURE__ */ jsxs5(Box5, { children: [
|
|
212
|
+
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "> " }),
|
|
213
|
+
/* @__PURE__ */ jsx5(TextInput, { value, onChange: setValue, onSubmit: handleSubmit, focus: isFocused })
|
|
219
214
|
] }) });
|
|
220
215
|
};
|
|
221
216
|
|
|
222
|
-
// src/components/
|
|
223
|
-
import { Box as
|
|
224
|
-
import
|
|
225
|
-
import { useState as
|
|
226
|
-
import { jsx as
|
|
217
|
+
// src/components/SettingsPrompt.tsx
|
|
218
|
+
import { Box as Box6, Text as Text6, useFocus, useFocusManager, useInput as useInput3 } from "ink";
|
|
219
|
+
import TextInput2 from "ink-text-input";
|
|
220
|
+
import { useState as useState4 } from "react";
|
|
221
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
227
222
|
var DEFAULT_EXTENSION_PORT = 5173;
|
|
228
223
|
var DEFAULT_PREVIEW_PORT = DEFAULT_EXTENSION_PORT + 1;
|
|
229
|
-
var
|
|
230
|
-
const
|
|
231
|
-
const
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
224
|
+
var FieldRow = ({ label, value, onChange, onSubmit, onConfirm, placeholder, autoFocus, isFirst, isLast, onFocusBack }) => {
|
|
225
|
+
const { isFocused } = useFocus({ autoFocus });
|
|
226
|
+
const { focusNext, focusPrevious } = useFocusManager();
|
|
227
|
+
useInput3((_input, key) => {
|
|
228
|
+
if (!isFocused) return;
|
|
229
|
+
if (key.downArrow && !isLast) focusNext();
|
|
230
|
+
if (key.upArrow) {
|
|
231
|
+
if (isFirst && onFocusBack) {
|
|
232
|
+
onFocusBack();
|
|
233
|
+
} else if (!isFirst) {
|
|
234
|
+
focusPrevious();
|
|
235
|
+
}
|
|
238
236
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
237
|
+
});
|
|
238
|
+
return /* @__PURE__ */ jsxs6(Box6, { gap: 2, children: [
|
|
239
|
+
/* @__PURE__ */ jsx6(Text6, { dimColor: true, children: label }),
|
|
240
|
+
isFocused ? /* @__PURE__ */ jsxs6(Box6, { children: [
|
|
241
|
+
/* @__PURE__ */ jsx6(Text6, { color: "cyan", children: "\u2192 " }),
|
|
242
|
+
/* @__PURE__ */ jsx6(
|
|
243
|
+
TextInput2,
|
|
244
|
+
{
|
|
245
|
+
value,
|
|
246
|
+
onChange,
|
|
247
|
+
onSubmit: (val) => {
|
|
248
|
+
const result = onSubmit(val);
|
|
249
|
+
if (result) onConfirm(...result);
|
|
250
|
+
},
|
|
251
|
+
placeholder,
|
|
252
|
+
focus: isFocused
|
|
253
|
+
}
|
|
254
|
+
)
|
|
255
|
+
] }) : /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: value })
|
|
256
|
+
] });
|
|
257
|
+
};
|
|
258
|
+
var SettingsPrompt = ({ defaultDir, onSubmit, onBack }) => {
|
|
259
|
+
const [backFocused, setBackFocused] = useState4(false);
|
|
260
|
+
const [extensionPort, setExtensionPort] = useState4(String(DEFAULT_EXTENSION_PORT));
|
|
261
|
+
const [previewPort, setPreviewPort] = useState4(String(DEFAULT_PREVIEW_PORT));
|
|
262
|
+
const [outputDir, setOutputDir] = useState4(defaultDir);
|
|
263
|
+
const handleFocusBack = () => {
|
|
264
|
+
if (onBack) setBackFocused(true);
|
|
242
265
|
};
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
const prevPort = trimmed === "" ? extPort + 1 : parseInt(trimmed, 10);
|
|
247
|
-
if (isNaN(prevPort) || prevPort < 1024 || prevPort > 65535) {
|
|
266
|
+
useInput3((_input, key) => {
|
|
267
|
+
if (key.downArrow && backFocused) {
|
|
268
|
+
setBackFocused(false);
|
|
248
269
|
return;
|
|
249
270
|
}
|
|
250
|
-
|
|
251
|
-
};
|
|
252
|
-
const handleBack = () => {
|
|
253
|
-
if (step === "preview") {
|
|
254
|
-
setStep("extension");
|
|
255
|
-
} else {
|
|
271
|
+
if (key.return && backFocused) {
|
|
256
272
|
onBack?.();
|
|
273
|
+
return;
|
|
257
274
|
}
|
|
275
|
+
});
|
|
276
|
+
const handleConfirm = (resolvedExtPort, resolvedPrevPort, resolvedDir) => {
|
|
277
|
+
const dir = resolvedDir.trim();
|
|
278
|
+
if (!dir) return;
|
|
279
|
+
onSubmit(parseInt(resolvedExtPort, 10), parseInt(resolvedPrevPort, 10), dir);
|
|
258
280
|
};
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
);
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
281
|
+
const handleExtensionPortSubmit = (value) => {
|
|
282
|
+
const trimmed = value.trim();
|
|
283
|
+
const port = trimmed === "" ? DEFAULT_EXTENSION_PORT : parseInt(trimmed, 10);
|
|
284
|
+
if (isNaN(port) || port < 1024 || port > 65535) return false;
|
|
285
|
+
const newExtPort = String(port);
|
|
286
|
+
const newPrevPort = String(port + 1);
|
|
287
|
+
setExtensionPort(newExtPort);
|
|
288
|
+
setPreviewPort(newPrevPort);
|
|
289
|
+
return [newExtPort, newPrevPort, outputDir];
|
|
290
|
+
};
|
|
291
|
+
const handlePreviewPortSubmit = (value) => {
|
|
292
|
+
const extPort = parseInt(extensionPort, 10);
|
|
293
|
+
const trimmed = value.trim();
|
|
294
|
+
const port = trimmed === "" ? extPort + 1 : parseInt(trimmed, 10);
|
|
295
|
+
if (isNaN(port) || port < 1024 || port > 65535) return false;
|
|
296
|
+
const newPrevPort = String(port);
|
|
297
|
+
setPreviewPort(newPrevPort);
|
|
298
|
+
return [extensionPort, newPrevPort, outputDir];
|
|
299
|
+
};
|
|
300
|
+
const handleOutputDirSubmit = (value) => {
|
|
301
|
+
const trimmed = value.trim();
|
|
302
|
+
if (trimmed.length === 0) return false;
|
|
303
|
+
setOutputDir(trimmed);
|
|
304
|
+
return [extensionPort, previewPort, trimmed];
|
|
305
|
+
};
|
|
306
|
+
return /* @__PURE__ */ jsx6(
|
|
307
|
+
StepShell,
|
|
284
308
|
{
|
|
285
|
-
|
|
286
|
-
hint: "
|
|
287
|
-
onBack
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
/* @__PURE__ */
|
|
291
|
-
|
|
309
|
+
title: "Project settings",
|
|
310
|
+
hint: "\u2191\u2193 or Tab to move between fields, Enter to confirm",
|
|
311
|
+
onBack,
|
|
312
|
+
backFocused,
|
|
313
|
+
children: /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", gap: 1, children: [
|
|
314
|
+
/* @__PURE__ */ jsx6(
|
|
315
|
+
FieldRow,
|
|
316
|
+
{
|
|
317
|
+
label: "Extension port ",
|
|
318
|
+
value: extensionPort,
|
|
319
|
+
onChange: setExtensionPort,
|
|
320
|
+
onSubmit: handleExtensionPortSubmit,
|
|
321
|
+
onConfirm: handleConfirm,
|
|
322
|
+
placeholder: String(DEFAULT_EXTENSION_PORT),
|
|
323
|
+
autoFocus: true,
|
|
324
|
+
isFirst: true,
|
|
325
|
+
onFocusBack: handleFocusBack
|
|
326
|
+
}
|
|
327
|
+
),
|
|
328
|
+
/* @__PURE__ */ jsx6(
|
|
329
|
+
FieldRow,
|
|
292
330
|
{
|
|
331
|
+
label: "Preview port ",
|
|
293
332
|
value: previewPort,
|
|
294
333
|
onChange: setPreviewPort,
|
|
295
|
-
onSubmit:
|
|
296
|
-
|
|
297
|
-
|
|
334
|
+
onSubmit: handlePreviewPortSubmit,
|
|
335
|
+
onConfirm: handleConfirm,
|
|
336
|
+
placeholder: String(DEFAULT_PREVIEW_PORT)
|
|
337
|
+
}
|
|
338
|
+
),
|
|
339
|
+
/* @__PURE__ */ jsx6(
|
|
340
|
+
FieldRow,
|
|
341
|
+
{
|
|
342
|
+
label: "Output directory",
|
|
343
|
+
value: outputDir,
|
|
344
|
+
onChange: setOutputDir,
|
|
345
|
+
onSubmit: handleOutputDirSubmit,
|
|
346
|
+
onConfirm: handleConfirm,
|
|
347
|
+
isLast: true
|
|
298
348
|
}
|
|
299
349
|
)
|
|
300
350
|
] })
|
|
@@ -303,33 +353,33 @@ var PortsPrompt = ({ onSubmit, onBack }) => {
|
|
|
303
353
|
};
|
|
304
354
|
|
|
305
355
|
// src/components/ScaffoldProgress.tsx
|
|
306
|
-
import { Box as
|
|
356
|
+
import { Box as Box7, Text as Text7 } from "ink";
|
|
307
357
|
import Spinner from "ink-spinner";
|
|
308
|
-
import { jsx as
|
|
358
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
309
359
|
var stepIcon = (status) => {
|
|
310
360
|
switch (status) {
|
|
311
361
|
case "running":
|
|
312
|
-
return /* @__PURE__ */
|
|
362
|
+
return /* @__PURE__ */ jsx7(Spinner, { type: "dots" });
|
|
313
363
|
case "done":
|
|
314
|
-
return /* @__PURE__ */
|
|
364
|
+
return /* @__PURE__ */ jsx7(Text7, { color: "green", children: "\u2714" });
|
|
315
365
|
case "error":
|
|
316
|
-
return /* @__PURE__ */
|
|
366
|
+
return /* @__PURE__ */ jsx7(Text7, { color: "red", children: "\u2716" });
|
|
317
367
|
default:
|
|
318
|
-
return /* @__PURE__ */
|
|
368
|
+
return /* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "\u25CB" });
|
|
319
369
|
}
|
|
320
370
|
};
|
|
321
|
-
var ScaffoldProgress = ({ steps }) => /* @__PURE__ */
|
|
322
|
-
/* @__PURE__ */
|
|
323
|
-
/* @__PURE__ */
|
|
371
|
+
var ScaffoldProgress = ({ steps }) => /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", gap: 1, children: [
|
|
372
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, children: "Scaffolding your Extension\u2026" }),
|
|
373
|
+
/* @__PURE__ */ jsx7(Box7, { flexDirection: "column", children: steps.map((step) => /* @__PURE__ */ jsxs7(Box7, { gap: 2, children: [
|
|
324
374
|
stepIcon(step.status),
|
|
325
|
-
/* @__PURE__ */
|
|
375
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: step.status === "pending", color: step.status === "running" ? "cyan" : void 0, children: step.label })
|
|
326
376
|
] }, step.label)) })
|
|
327
377
|
] });
|
|
328
378
|
|
|
329
379
|
// src/components/TargetSelect.tsx
|
|
330
|
-
import { Box as
|
|
331
|
-
import { useState as
|
|
332
|
-
import { jsx as
|
|
380
|
+
import { Box as Box8, Text as Text8, useInput as useInput4 } from "ink";
|
|
381
|
+
import { useState as useState5 } from "react";
|
|
382
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
333
383
|
var TARGET_DESCRIPTIONS = {
|
|
334
384
|
"slot.header": "Renders content in the panel header area",
|
|
335
385
|
"slot.content": "Renders the main panel body (includes store + navigation state)",
|
|
@@ -337,13 +387,13 @@ var TARGET_DESCRIPTIONS = {
|
|
|
337
387
|
"slot.footer-links": "Renders a link row in the global footer"
|
|
338
388
|
};
|
|
339
389
|
var TargetSelect = ({ availableTargets, preSelected, onSubmit, onBack }) => {
|
|
340
|
-
const [cursor, setCursor] =
|
|
341
|
-
const [backFocused, setBackFocused] =
|
|
342
|
-
const [selected, setSelected] =
|
|
390
|
+
const [cursor, setCursor] = useState5(0);
|
|
391
|
+
const [backFocused, setBackFocused] = useState5(false);
|
|
392
|
+
const [selected, setSelected] = useState5(
|
|
343
393
|
new Set(preSelected ?? (availableTargets.includes("slot.content") ? ["slot.content"] : []))
|
|
344
394
|
);
|
|
345
|
-
const [error, setError] =
|
|
346
|
-
|
|
395
|
+
const [error, setError] = useState5();
|
|
396
|
+
useInput4((input, key) => {
|
|
347
397
|
if (key.upArrow) {
|
|
348
398
|
if (cursor === 0 && onBack) {
|
|
349
399
|
setBackFocused(true);
|
|
@@ -387,7 +437,7 @@ var TargetSelect = ({ availableTargets, preSelected, onSubmit, onBack }) => {
|
|
|
387
437
|
onSubmit([...selected]);
|
|
388
438
|
}
|
|
389
439
|
});
|
|
390
|
-
return /* @__PURE__ */
|
|
440
|
+
return /* @__PURE__ */ jsxs8(
|
|
391
441
|
StepShell,
|
|
392
442
|
{
|
|
393
443
|
title: "Select Surface targets/slots",
|
|
@@ -395,41 +445,46 @@ var TargetSelect = ({ availableTargets, preSelected, onSubmit, onBack }) => {
|
|
|
395
445
|
onBack,
|
|
396
446
|
backFocused,
|
|
397
447
|
children: [
|
|
398
|
-
/* @__PURE__ */
|
|
448
|
+
/* @__PURE__ */ jsx8(Box8, { flexDirection: "column", gap: 1, children: availableTargets.map((target, i) => {
|
|
399
449
|
const isSelected = selected.has(target);
|
|
400
450
|
const isCursor = i === cursor && !backFocused;
|
|
401
|
-
return /* @__PURE__ */
|
|
402
|
-
/* @__PURE__ */
|
|
403
|
-
/* @__PURE__ */
|
|
404
|
-
/* @__PURE__ */
|
|
405
|
-
/* @__PURE__ */
|
|
406
|
-
/* @__PURE__ */
|
|
451
|
+
return /* @__PURE__ */ jsxs8(Box8, { gap: 1, children: [
|
|
452
|
+
/* @__PURE__ */ jsx8(Text8, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u276F" : " " }),
|
|
453
|
+
/* @__PURE__ */ jsx8(Text8, { color: isSelected ? "green" : void 0, children: isSelected ? "\u25C9" : "\u25CB" }),
|
|
454
|
+
/* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
|
|
455
|
+
/* @__PURE__ */ jsx8(Text8, { bold: isSelected, children: target }),
|
|
456
|
+
/* @__PURE__ */ jsx8(Text8, { dimColor: true, children: TARGET_DESCRIPTIONS[target] ?? target })
|
|
407
457
|
] })
|
|
408
458
|
] }, target);
|
|
409
459
|
}) }),
|
|
410
|
-
error && /* @__PURE__ */
|
|
460
|
+
error && /* @__PURE__ */ jsx8(Text8, { color: "red", children: error })
|
|
411
461
|
]
|
|
412
462
|
}
|
|
413
463
|
);
|
|
414
464
|
};
|
|
415
465
|
|
|
416
466
|
// src/components/AppSelect.tsx
|
|
417
|
-
import { Box as
|
|
467
|
+
import { Box as Box10, Text as Text10, useInput as useInput5 } from "ink";
|
|
418
468
|
import Spinner2 from "ink-spinner";
|
|
419
|
-
import { useEffect, useState as
|
|
469
|
+
import { useEffect, useState as useState6 } from "react";
|
|
420
470
|
|
|
421
471
|
// src/lib/api.ts
|
|
422
|
-
var DEFAULT_API_URL = "https://api.stackablelabs.io/app-extension/latest";
|
|
423
472
|
var DEFAULT_ADMIN_API_URL = "https://api-use1.stackablelabs.io/admin";
|
|
424
|
-
var getApiBaseUrl = () => process.env.API_BASE_URL ?? DEFAULT_API_URL;
|
|
425
473
|
var getAdminApiBaseUrl = () => process.env.ADMIN_API_BASE_URL ?? DEFAULT_ADMIN_API_URL;
|
|
426
474
|
var fetchApps = async () => {
|
|
427
|
-
const
|
|
428
|
-
const res = await fetch(
|
|
475
|
+
const baseUrl = getAdminApiBaseUrl();
|
|
476
|
+
const res = await fetch(`${baseUrl}/app-extension`);
|
|
429
477
|
if (!res.ok) {
|
|
430
|
-
throw new Error(`Failed to fetch apps: ${res.status} ${res.statusText}`);
|
|
478
|
+
throw new Error(`Failed to fetch apps${baseUrl !== DEFAULT_ADMIN_API_URL ? ` (from ${baseUrl})` : ""}: ${res.status} ${res.statusText}`);
|
|
431
479
|
}
|
|
432
|
-
|
|
480
|
+
const adminApps = await res.json();
|
|
481
|
+
return adminApps.filter((app) => app.enabled).map(({ id, name, targets, iconUrl }) => ({
|
|
482
|
+
id,
|
|
483
|
+
name,
|
|
484
|
+
targets,
|
|
485
|
+
enabled: true,
|
|
486
|
+
iconUrl
|
|
487
|
+
}));
|
|
433
488
|
};
|
|
434
489
|
var createExtensionRemote = async (appId, payload) => {
|
|
435
490
|
const baseUrl = getAdminApiBaseUrl();
|
|
@@ -445,17 +500,29 @@ var createExtensionRemote = async (appId, payload) => {
|
|
|
445
500
|
return res.json();
|
|
446
501
|
};
|
|
447
502
|
var fetchExtensions = async (appId) => {
|
|
448
|
-
const baseUrl =
|
|
449
|
-
const res = await fetch(`${baseUrl}/
|
|
503
|
+
const baseUrl = getAdminApiBaseUrl();
|
|
504
|
+
const res = await fetch(`${baseUrl}/app-extension/${appId}/extensions`);
|
|
450
505
|
if (!res.ok) {
|
|
451
506
|
throw new Error(`Failed to fetch extensions: ${res.status} ${res.statusText}`);
|
|
452
507
|
}
|
|
453
|
-
|
|
508
|
+
const adminExtensions = await res.json();
|
|
509
|
+
return Object.fromEntries(
|
|
510
|
+
adminExtensions.filter((ext) => ext.enabled).map(({ id, manifest, bundleUrl, iconUrl }) => [
|
|
511
|
+
id,
|
|
512
|
+
{
|
|
513
|
+
id,
|
|
514
|
+
manifest,
|
|
515
|
+
bundleUrl,
|
|
516
|
+
enabled: true,
|
|
517
|
+
iconUrl
|
|
518
|
+
}
|
|
519
|
+
])
|
|
520
|
+
);
|
|
454
521
|
};
|
|
455
522
|
|
|
456
523
|
// src/components/Banner.tsx
|
|
457
|
-
import { Box as
|
|
458
|
-
import { jsx as
|
|
524
|
+
import { Box as Box9, Text as Text9 } from "ink";
|
|
525
|
+
import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
459
526
|
var WORDMARK = [
|
|
460
527
|
" _ _ _ _ ",
|
|
461
528
|
" ___| |_ __ _ ___| | ____ _| |__ | | ___",
|
|
@@ -491,23 +558,23 @@ var gradientColor = (row, col, rows, cols) => {
|
|
|
491
558
|
var Banner = () => {
|
|
492
559
|
const termWidth = process.stdout.columns ?? 80;
|
|
493
560
|
const maxLen = Math.max(...WORDMARK.map((l) => l.length));
|
|
494
|
-
return /* @__PURE__ */
|
|
495
|
-
/* @__PURE__ */
|
|
496
|
-
/* @__PURE__ */
|
|
561
|
+
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
|
|
562
|
+
/* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "\u2500".repeat(termWidth) }),
|
|
563
|
+
/* @__PURE__ */ jsx9(Box9, { flexDirection: "column", paddingX: 1, paddingY: 1, children: WORDMARK.map((line, row) => /* @__PURE__ */ jsx9(Box9, { children: line.split("").map((ch, col) => /* @__PURE__ */ jsx9(Text9, { bold: true, color: ch === " " ? void 0 : gradientColor(row, col, WORDMARK.length, maxLen), children: ch }, col)) }, row)) })
|
|
497
564
|
] });
|
|
498
565
|
};
|
|
499
566
|
|
|
500
567
|
// src/components/AppSelect.tsx
|
|
501
|
-
import { jsx as
|
|
568
|
+
import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
502
569
|
var AppSelect = ({ onSubmit }) => {
|
|
503
|
-
const [apps, setApps] =
|
|
504
|
-
const [loading, setLoading] =
|
|
505
|
-
const [error, setError] =
|
|
506
|
-
const [cursor, setCursor] =
|
|
570
|
+
const [apps, setApps] = useState6([]);
|
|
571
|
+
const [loading, setLoading] = useState6(true);
|
|
572
|
+
const [error, setError] = useState6();
|
|
573
|
+
const [cursor, setCursor] = useState6(0);
|
|
507
574
|
useEffect(() => {
|
|
508
575
|
fetchApps().then(setApps).catch((err) => setError(err instanceof Error ? err.message : String(err))).finally(() => setLoading(false));
|
|
509
576
|
}, []);
|
|
510
|
-
|
|
577
|
+
useInput5((_, key) => {
|
|
511
578
|
if (loading || error || apps.length === 0) return;
|
|
512
579
|
if (key.upArrow) {
|
|
513
580
|
setCursor((c) => Math.max(0, c - 1));
|
|
@@ -517,60 +584,59 @@ var AppSelect = ({ onSubmit }) => {
|
|
|
517
584
|
onSubmit(apps[cursor]);
|
|
518
585
|
}
|
|
519
586
|
});
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
/* @__PURE__ */
|
|
523
|
-
|
|
524
|
-
/* @__PURE__ */
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
return /* @__PURE__ */
|
|
537
|
-
}
|
|
538
|
-
return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
|
|
539
|
-
/* @__PURE__ */ jsx11(Banner, {}),
|
|
540
|
-
/* @__PURE__ */ jsx11(StepShell, { title: "Select the App you are building an Extension for:", children: /* @__PURE__ */ jsx11(Box11, { flexDirection: "column", children: apps.map((app, i) => {
|
|
587
|
+
const renderContent = () => {
|
|
588
|
+
if (loading) {
|
|
589
|
+
return /* @__PURE__ */ jsxs10(Box10, { gap: 2, children: [
|
|
590
|
+
/* @__PURE__ */ jsx10(Spinner2, { type: "dots" }),
|
|
591
|
+
/* @__PURE__ */ jsx10(Text10, { children: "Loading available Apps\u2026" })
|
|
592
|
+
] });
|
|
593
|
+
}
|
|
594
|
+
if (error) {
|
|
595
|
+
return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", gap: 1, children: [
|
|
596
|
+
/* @__PURE__ */ jsx10(Text10, { color: "red", bold: true, children: "Failed to load Apps" }),
|
|
597
|
+
/* @__PURE__ */ jsx10(Text10, { color: "red", children: error })
|
|
598
|
+
] });
|
|
599
|
+
}
|
|
600
|
+
if (apps.length === 0) {
|
|
601
|
+
return /* @__PURE__ */ jsx10(Text10, { color: "yellow", children: "No Apps available. Contact your administrator." });
|
|
602
|
+
}
|
|
603
|
+
return /* @__PURE__ */ jsx10(Box10, { flexDirection: "column", children: apps.map((app, i) => {
|
|
541
604
|
const isCursor = i === cursor;
|
|
542
|
-
return /* @__PURE__ */
|
|
543
|
-
/* @__PURE__ */
|
|
544
|
-
/* @__PURE__ */
|
|
545
|
-
/* @__PURE__ */
|
|
605
|
+
return /* @__PURE__ */ jsxs10(Box10, { gap: 1, children: [
|
|
606
|
+
/* @__PURE__ */ jsx10(Text10, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u276F" : " " }),
|
|
607
|
+
/* @__PURE__ */ jsx10(Text10, { bold: isCursor, children: app.name }),
|
|
608
|
+
/* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
|
|
546
609
|
"(",
|
|
547
610
|
app.id,
|
|
548
611
|
")"
|
|
549
612
|
] })
|
|
550
613
|
] }, app.id);
|
|
551
|
-
}) })
|
|
614
|
+
}) });
|
|
615
|
+
};
|
|
616
|
+
return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
|
|
617
|
+
/* @__PURE__ */ jsx10(Banner, {}),
|
|
618
|
+
/* @__PURE__ */ jsx10(StepShell, { title: "Select the App you are building an Extension for:", children: renderContent() })
|
|
552
619
|
] });
|
|
553
620
|
};
|
|
554
621
|
|
|
555
622
|
// src/components/ExtensionSelect.tsx
|
|
556
|
-
import { Box as
|
|
623
|
+
import { Box as Box11, Text as Text11, useInput as useInput6 } from "ink";
|
|
557
624
|
import Spinner3 from "ink-spinner";
|
|
558
|
-
import { useEffect as useEffect2, useState as
|
|
559
|
-
import { jsx as
|
|
625
|
+
import { useEffect as useEffect2, useState as useState7 } from "react";
|
|
626
|
+
import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
560
627
|
var ExtensionSelect = ({ appId, onSubmit, onBack }) => {
|
|
561
|
-
const [extensions, setExtensions] =
|
|
562
|
-
const [loading, setLoading] =
|
|
563
|
-
const [error, setError] =
|
|
564
|
-
const [cursor, setCursor] =
|
|
565
|
-
const [backFocused, setBackFocused] =
|
|
628
|
+
const [extensions, setExtensions] = useState7([]);
|
|
629
|
+
const [loading, setLoading] = useState7(true);
|
|
630
|
+
const [error, setError] = useState7();
|
|
631
|
+
const [cursor, setCursor] = useState7(0);
|
|
632
|
+
const [backFocused, setBackFocused] = useState7(false);
|
|
566
633
|
useEffect2(() => {
|
|
567
634
|
fetchExtensions(appId).then((byId) => setExtensions(Object.values(byId))).catch((err) => setError(err instanceof Error ? err.message : String(err))).finally(() => setLoading(false));
|
|
568
635
|
}, [appId]);
|
|
569
|
-
|
|
570
|
-
if (loading || error || extensions.length === 0) return;
|
|
636
|
+
useInput6((_, key) => {
|
|
571
637
|
if (key.upArrow) {
|
|
572
|
-
if (
|
|
573
|
-
setBackFocused(true);
|
|
638
|
+
if (loading || error || extensions.length === 0 || cursor === 0) {
|
|
639
|
+
if (onBack) setBackFocused(true);
|
|
574
640
|
} else {
|
|
575
641
|
setBackFocused(false);
|
|
576
642
|
setCursor((c) => Math.max(0, c - 1));
|
|
@@ -580,7 +646,7 @@ var ExtensionSelect = ({ appId, onSubmit, onBack }) => {
|
|
|
580
646
|
if (key.downArrow) {
|
|
581
647
|
if (backFocused) {
|
|
582
648
|
setBackFocused(false);
|
|
583
|
-
} else {
|
|
649
|
+
} else if (!loading && !error && extensions.length > 0) {
|
|
584
650
|
setCursor((c) => Math.min(extensions.length - 1, c + 1));
|
|
585
651
|
}
|
|
586
652
|
return;
|
|
@@ -590,36 +656,45 @@ var ExtensionSelect = ({ appId, onSubmit, onBack }) => {
|
|
|
590
656
|
onBack?.();
|
|
591
657
|
return;
|
|
592
658
|
}
|
|
593
|
-
|
|
659
|
+
if (!loading && !error && extensions.length > 0) {
|
|
660
|
+
onSubmit(extensions[cursor]);
|
|
661
|
+
}
|
|
594
662
|
}
|
|
595
663
|
});
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
/* @__PURE__ */
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
/* @__PURE__ */
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
/* @__PURE__ */
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
664
|
+
const renderContent = () => {
|
|
665
|
+
if (loading) {
|
|
666
|
+
return /* @__PURE__ */ jsxs11(Box11, { gap: 2, children: [
|
|
667
|
+
/* @__PURE__ */ jsx11(Spinner3, { type: "dots" }),
|
|
668
|
+
/* @__PURE__ */ jsx11(Text11, { children: "Loading Extensions\u2026" })
|
|
669
|
+
] });
|
|
670
|
+
}
|
|
671
|
+
if (error) {
|
|
672
|
+
return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", gap: 1, children: [
|
|
673
|
+
/* @__PURE__ */ jsx11(Text11, { color: "red", bold: true, children: "Failed to load Extensions" }),
|
|
674
|
+
/* @__PURE__ */ jsx11(Text11, { color: "red", children: error })
|
|
675
|
+
] });
|
|
676
|
+
}
|
|
677
|
+
if (extensions.length === 0) {
|
|
678
|
+
return /* @__PURE__ */ jsx11(Text11, { color: "yellow", children: "No Extensions found for this App." });
|
|
679
|
+
}
|
|
680
|
+
return /* @__PURE__ */ jsx11(Box11, { flexDirection: "column", children: extensions.map((ext, i) => {
|
|
681
|
+
const isCursor = i === cursor && !backFocused;
|
|
682
|
+
return /* @__PURE__ */ jsxs11(Box11, { gap: 1, children: [
|
|
683
|
+
/* @__PURE__ */ jsx11(Text11, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u276F" : " " }),
|
|
684
|
+
/* @__PURE__ */ jsx11(Text11, { bold: isCursor, children: ext.manifest.name }),
|
|
685
|
+
/* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
|
|
686
|
+
"v",
|
|
687
|
+
ext.manifest.version
|
|
688
|
+
] }),
|
|
689
|
+
/* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
|
|
690
|
+
"(",
|
|
691
|
+
ext.id,
|
|
692
|
+
")"
|
|
693
|
+
] })
|
|
694
|
+
] }, ext.id);
|
|
695
|
+
}) });
|
|
696
|
+
};
|
|
697
|
+
return /* @__PURE__ */ jsx11(StepShell, { title: "Select an existing Extension to scaffold:", onBack, backFocused, children: renderContent() });
|
|
623
698
|
};
|
|
624
699
|
|
|
625
700
|
// src/constants.ts
|
|
@@ -658,6 +733,8 @@ var postScaffold = async (options) => {
|
|
|
658
733
|
import { readFile, readdir, rm, writeFile } from "fs/promises";
|
|
659
734
|
import { join } from "path";
|
|
660
735
|
import { downloadTemplate } from "giget";
|
|
736
|
+
var toKebabCase = (value) => value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
737
|
+
var isTextFile = (filePath) => /\.(ts|tsx|js|jsx|json|md|html|yml|yaml|env|gitignore|nvmrc)$/i.test(filePath);
|
|
661
738
|
var normalizeTargets = (targets) => Array.from(new Set(targets));
|
|
662
739
|
var derivePermissions = (targets) => {
|
|
663
740
|
const permissions = /* @__PURE__ */ new Set();
|
|
@@ -673,7 +750,29 @@ var derivePermissions = (targets) => {
|
|
|
673
750
|
}
|
|
674
751
|
return [...permissions];
|
|
675
752
|
};
|
|
676
|
-
var
|
|
753
|
+
var upsertOrRemove = async (filePath, shouldExist, content) => {
|
|
754
|
+
if (shouldExist) {
|
|
755
|
+
await writeFile(filePath, content);
|
|
756
|
+
return;
|
|
757
|
+
}
|
|
758
|
+
await rm(filePath, { force: true });
|
|
759
|
+
};
|
|
760
|
+
var walkFiles = async (rootDir) => {
|
|
761
|
+
const entries = await readdir(rootDir, { withFileTypes: true });
|
|
762
|
+
const files = [];
|
|
763
|
+
for (const entry of entries) {
|
|
764
|
+
if (entry.name === ".git" || entry.name === "node_modules" || entry.name === "dist") {
|
|
765
|
+
continue;
|
|
766
|
+
}
|
|
767
|
+
const fullPath = join(rootDir, entry.name);
|
|
768
|
+
if (entry.isDirectory()) {
|
|
769
|
+
files.push(...await walkFiles(fullPath));
|
|
770
|
+
continue;
|
|
771
|
+
}
|
|
772
|
+
files.push(fullPath);
|
|
773
|
+
}
|
|
774
|
+
return files;
|
|
775
|
+
};
|
|
677
776
|
var replacePlaceholders = async (rootDir, replacements) => {
|
|
678
777
|
const files = await walkFiles(rootDir);
|
|
679
778
|
for (const filePath of files) {
|
|
@@ -902,23 +1001,6 @@ var rewriteTurboJson = async (rootDir) => {
|
|
|
902
1001
|
await writeFile(turboPath, `${JSON.stringify(turbo, null, 2)}
|
|
903
1002
|
`);
|
|
904
1003
|
};
|
|
905
|
-
var walkFiles = async (rootDir) => {
|
|
906
|
-
const entries = await readdir(rootDir, { withFileTypes: true });
|
|
907
|
-
const files = [];
|
|
908
|
-
for (const entry of entries) {
|
|
909
|
-
if (entry.name === ".git" || entry.name === "node_modules" || entry.name === "dist") {
|
|
910
|
-
continue;
|
|
911
|
-
}
|
|
912
|
-
const fullPath = join(rootDir, entry.name);
|
|
913
|
-
if (entry.isDirectory()) {
|
|
914
|
-
files.push(...await walkFiles(fullPath));
|
|
915
|
-
continue;
|
|
916
|
-
}
|
|
917
|
-
files.push(fullPath);
|
|
918
|
-
}
|
|
919
|
-
return files;
|
|
920
|
-
};
|
|
921
|
-
var isTextFile = (filePath) => /\.(ts|tsx|js|jsx|json|md|html|yml|yaml|env|gitignore|nvmrc)$/i.test(filePath);
|
|
922
1004
|
var writeEnvFile = async (dir, extensionPort, previewPort) => {
|
|
923
1005
|
const envPath = join(dir, ".env");
|
|
924
1006
|
const content = `VITE_EXTENSION_PORT=${extensionPort}
|
|
@@ -926,13 +1008,6 @@ VITE_PREVIEW_PORT=${previewPort}
|
|
|
926
1008
|
`;
|
|
927
1009
|
await writeFile(envPath, content);
|
|
928
1010
|
};
|
|
929
|
-
var upsertOrRemove = async (filePath, shouldExist, content) => {
|
|
930
|
-
if (shouldExist) {
|
|
931
|
-
await writeFile(filePath, content);
|
|
932
|
-
return;
|
|
933
|
-
}
|
|
934
|
-
await rm(filePath, { force: true });
|
|
935
|
-
};
|
|
936
1011
|
var scaffold = async (options) => {
|
|
937
1012
|
const { dir } = await downloadTemplate(TEMPLATE_SOURCE, {
|
|
938
1013
|
dir: options.outputDir,
|
|
@@ -956,20 +1031,24 @@ var scaffold = async (options) => {
|
|
|
956
1031
|
};
|
|
957
1032
|
|
|
958
1033
|
// src/App.tsx
|
|
959
|
-
import { jsx as
|
|
960
|
-
var
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
1034
|
+
import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1035
|
+
var STEPS = {
|
|
1036
|
+
["create" /* CREATE */]: ["app", "name", "targets", "settings", "confirm"],
|
|
1037
|
+
["scaffold" /* SCAFFOLD */]: ["app", "extensionSelect", "confirmTargets", "settings", "confirm"]
|
|
1038
|
+
};
|
|
1039
|
+
var PROGRESS_STEPS = {
|
|
1040
|
+
["create" /* CREATE */]: [
|
|
1041
|
+
{ label: "Registering extension", status: "pending" },
|
|
1042
|
+
{ label: "Fetching template", status: "pending" },
|
|
1043
|
+
{ label: "Generating files", status: "pending" },
|
|
1044
|
+
{ label: "Installing dependencies", status: "pending" }
|
|
1045
|
+
],
|
|
1046
|
+
["scaffold" /* SCAFFOLD */]: [
|
|
1047
|
+
{ label: "Fetching template", status: "pending" },
|
|
1048
|
+
{ label: "Generating files", status: "pending" },
|
|
1049
|
+
{ label: "Installing dependencies", status: "pending" }
|
|
1050
|
+
]
|
|
1051
|
+
};
|
|
973
1052
|
var toKebabCase2 = (value) => value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
974
1053
|
var derivePermissions2 = (targets) => {
|
|
975
1054
|
const permissions = /* @__PURE__ */ new Set();
|
|
@@ -988,32 +1067,33 @@ var derivePermissions2 = (targets) => {
|
|
|
988
1067
|
}
|
|
989
1068
|
return [...permissions];
|
|
990
1069
|
};
|
|
991
|
-
var App = ({
|
|
1070
|
+
var App = ({ command, initialName, options }) => {
|
|
992
1071
|
const { exit } = useApp();
|
|
993
|
-
const [step, setStep] =
|
|
994
|
-
const [name, setName] =
|
|
995
|
-
const [extensionId, setExtensionId] =
|
|
996
|
-
const [
|
|
997
|
-
const [
|
|
1072
|
+
const [step, setStep] = useState8("app");
|
|
1073
|
+
const [name, setName] = useState8(initialName ?? "");
|
|
1074
|
+
const [extensionId, setExtensionId] = useState8("");
|
|
1075
|
+
const [extensionVersion, setExtensionVersion] = useState8("");
|
|
1076
|
+
const [selectedApp, setSelectedApp] = useState8(null);
|
|
1077
|
+
const [extensionPort, setExtensionPort] = useState8(
|
|
998
1078
|
options?.extensionPort ? parseInt(options.extensionPort, 10) : 5173
|
|
999
1079
|
);
|
|
1000
|
-
const [previewPort, setPreviewPort] =
|
|
1080
|
+
const [previewPort, setPreviewPort] = useState8(
|
|
1001
1081
|
options?.previewPort ? parseInt(options.previewPort, 10) : 5174
|
|
1002
1082
|
);
|
|
1003
|
-
const [targets, setTargets] =
|
|
1004
|
-
const [outputDir, setOutputDir] =
|
|
1005
|
-
const [progressSteps, setProgressSteps] =
|
|
1006
|
-
const [errorMessage, setErrorMessage] =
|
|
1083
|
+
const [targets, setTargets] = useState8([]);
|
|
1084
|
+
const [outputDir, setOutputDir] = useState8("");
|
|
1085
|
+
const [progressSteps, setProgressSteps] = useState8(PROGRESS_STEPS[command]);
|
|
1086
|
+
const [errorMessage, setErrorMessage] = useState8();
|
|
1007
1087
|
const updateStep = useCallback((index, status) => {
|
|
1008
1088
|
setProgressSteps((prev) => prev.map((s, i) => i === index ? { ...s, status } : s));
|
|
1009
1089
|
}, []);
|
|
1010
1090
|
const activeSteps = useCallback(() => {
|
|
1011
|
-
const base =
|
|
1091
|
+
const base = STEPS[command];
|
|
1012
1092
|
const skipped = /* @__PURE__ */ new Set();
|
|
1013
|
-
if (
|
|
1014
|
-
if (options?.extensionPort || options?.previewPort) skipped.add("
|
|
1093
|
+
if (command === "create" /* CREATE */ && initialName) skipped.add("name");
|
|
1094
|
+
if (options?.extensionPort || options?.previewPort) skipped.add("settings");
|
|
1015
1095
|
return base.filter((s) => !skipped.has(s));
|
|
1016
|
-
}, [
|
|
1096
|
+
}, [command, initialName, options?.extensionPort, options?.previewPort]);
|
|
1017
1097
|
const goBack = useCallback(() => {
|
|
1018
1098
|
setStep((prev) => {
|
|
1019
1099
|
const steps = activeSteps();
|
|
@@ -1023,7 +1103,7 @@ var App = ({ mode, initialName, options }) => {
|
|
|
1023
1103
|
}, [activeSteps]);
|
|
1024
1104
|
const handleAppSelect = (app) => {
|
|
1025
1105
|
setSelectedApp(app);
|
|
1026
|
-
if (
|
|
1106
|
+
if (command === "scaffold" /* SCAFFOLD */) {
|
|
1027
1107
|
setStep("extensionSelect");
|
|
1028
1108
|
return;
|
|
1029
1109
|
}
|
|
@@ -1032,16 +1112,18 @@ var App = ({ mode, initialName, options }) => {
|
|
|
1032
1112
|
const handleExtensionSelect = (ext) => {
|
|
1033
1113
|
setName(ext.manifest.name);
|
|
1034
1114
|
setExtensionId(ext.id);
|
|
1115
|
+
setExtensionVersion(ext.manifest.version);
|
|
1035
1116
|
setTargets(ext.manifest.targets);
|
|
1036
|
-
setStep("confirmName");
|
|
1037
|
-
};
|
|
1038
|
-
const handleConfirmName = (value) => {
|
|
1039
|
-
setName(value);
|
|
1040
1117
|
setStep("confirmTargets");
|
|
1041
1118
|
};
|
|
1042
1119
|
const handleConfirmTargets = (value) => {
|
|
1043
1120
|
setTargets(value);
|
|
1044
|
-
|
|
1121
|
+
if (options?.extensionPort || options?.previewPort) {
|
|
1122
|
+
setOutputDir(join2(process.cwd(), toKebabCase2(extensionId || name)));
|
|
1123
|
+
setStep("confirm");
|
|
1124
|
+
} else {
|
|
1125
|
+
setStep("settings");
|
|
1126
|
+
}
|
|
1045
1127
|
};
|
|
1046
1128
|
const handleName = (value) => {
|
|
1047
1129
|
setName(value);
|
|
@@ -1050,24 +1132,26 @@ var App = ({ mode, initialName, options }) => {
|
|
|
1050
1132
|
};
|
|
1051
1133
|
const handleTargets = (value) => {
|
|
1052
1134
|
setTargets(value);
|
|
1053
|
-
|
|
1135
|
+
if (options?.extensionPort || options?.previewPort) {
|
|
1136
|
+
setOutputDir(join2(process.cwd(), toKebabCase2(extensionId || name)));
|
|
1137
|
+
setStep("confirm");
|
|
1138
|
+
} else {
|
|
1139
|
+
setStep("settings");
|
|
1140
|
+
}
|
|
1054
1141
|
};
|
|
1055
|
-
const
|
|
1142
|
+
const handleSettings = (extPort, prevPort, dir) => {
|
|
1056
1143
|
setExtensionPort(extPort);
|
|
1057
1144
|
setPreviewPort(prevPort);
|
|
1058
|
-
setStep("dir");
|
|
1059
|
-
};
|
|
1060
|
-
const handleDir = (dir) => {
|
|
1061
1145
|
setOutputDir(dir);
|
|
1062
1146
|
setStep("confirm");
|
|
1063
1147
|
};
|
|
1064
1148
|
const handleConfirm = async () => {
|
|
1065
1149
|
setStep("scaffolding");
|
|
1066
|
-
setProgressSteps(
|
|
1150
|
+
setProgressSteps(PROGRESS_STEPS[command]);
|
|
1067
1151
|
try {
|
|
1068
1152
|
let resolvedExtensionId = extensionId || toKebabCase2(name);
|
|
1069
1153
|
let scaffoldStepOffset = 0;
|
|
1070
|
-
if (
|
|
1154
|
+
if (command === "create" /* CREATE */) {
|
|
1071
1155
|
scaffoldStepOffset = 1;
|
|
1072
1156
|
updateStep(0, "running");
|
|
1073
1157
|
const created = await createExtensionRemote(selectedApp.id, {
|
|
@@ -1116,10 +1200,10 @@ var App = ({ mode, initialName, options }) => {
|
|
|
1116
1200
|
};
|
|
1117
1201
|
switch (step) {
|
|
1118
1202
|
case "app": {
|
|
1119
|
-
return /* @__PURE__ */
|
|
1203
|
+
return /* @__PURE__ */ jsx12(AppSelect, { onSubmit: handleAppSelect });
|
|
1120
1204
|
}
|
|
1121
1205
|
case "extensionSelect": {
|
|
1122
|
-
return /* @__PURE__ */
|
|
1206
|
+
return /* @__PURE__ */ jsx12(
|
|
1123
1207
|
ExtensionSelect,
|
|
1124
1208
|
{
|
|
1125
1209
|
appId: selectedApp.id,
|
|
@@ -1128,18 +1212,8 @@ var App = ({ mode, initialName, options }) => {
|
|
|
1128
1212
|
}
|
|
1129
1213
|
);
|
|
1130
1214
|
}
|
|
1131
|
-
case "confirmName": {
|
|
1132
|
-
return /* @__PURE__ */ jsx13(
|
|
1133
|
-
NamePrompt,
|
|
1134
|
-
{
|
|
1135
|
-
initialValue: name,
|
|
1136
|
-
onSubmit: handleConfirmName,
|
|
1137
|
-
onBack: goBack
|
|
1138
|
-
}
|
|
1139
|
-
);
|
|
1140
|
-
}
|
|
1141
1215
|
case "confirmTargets": {
|
|
1142
|
-
return /* @__PURE__ */
|
|
1216
|
+
return /* @__PURE__ */ jsx12(
|
|
1143
1217
|
TargetSelect,
|
|
1144
1218
|
{
|
|
1145
1219
|
availableTargets: selectedApp?.targets ?? [],
|
|
@@ -1150,7 +1224,7 @@ var App = ({ mode, initialName, options }) => {
|
|
|
1150
1224
|
);
|
|
1151
1225
|
}
|
|
1152
1226
|
case "name": {
|
|
1153
|
-
return /* @__PURE__ */
|
|
1227
|
+
return /* @__PURE__ */ jsx12(
|
|
1154
1228
|
NamePrompt,
|
|
1155
1229
|
{
|
|
1156
1230
|
initialValue: name,
|
|
@@ -1160,7 +1234,7 @@ var App = ({ mode, initialName, options }) => {
|
|
|
1160
1234
|
);
|
|
1161
1235
|
}
|
|
1162
1236
|
case "targets": {
|
|
1163
|
-
return /* @__PURE__ */
|
|
1237
|
+
return /* @__PURE__ */ jsx12(
|
|
1164
1238
|
TargetSelect,
|
|
1165
1239
|
{
|
|
1166
1240
|
availableTargets: selectedApp?.targets ?? [],
|
|
@@ -1169,27 +1243,18 @@ var App = ({ mode, initialName, options }) => {
|
|
|
1169
1243
|
}
|
|
1170
1244
|
);
|
|
1171
1245
|
}
|
|
1172
|
-
case "
|
|
1173
|
-
return /* @__PURE__ */
|
|
1174
|
-
|
|
1175
|
-
{
|
|
1176
|
-
onSubmit: handlePorts,
|
|
1177
|
-
onBack: goBack
|
|
1178
|
-
}
|
|
1179
|
-
);
|
|
1180
|
-
}
|
|
1181
|
-
case "dir": {
|
|
1182
|
-
return /* @__PURE__ */ jsx13(
|
|
1183
|
-
DirPrompt,
|
|
1246
|
+
case "settings": {
|
|
1247
|
+
return /* @__PURE__ */ jsx12(
|
|
1248
|
+
SettingsPrompt,
|
|
1184
1249
|
{
|
|
1185
1250
|
defaultDir: join2(process.cwd(), toKebabCase2(extensionId || name)),
|
|
1186
|
-
onSubmit:
|
|
1251
|
+
onSubmit: handleSettings,
|
|
1187
1252
|
onBack: goBack
|
|
1188
1253
|
}
|
|
1189
1254
|
);
|
|
1190
1255
|
}
|
|
1191
1256
|
case "confirm": {
|
|
1192
|
-
return /* @__PURE__ */
|
|
1257
|
+
return /* @__PURE__ */ jsx12(
|
|
1193
1258
|
Confirm,
|
|
1194
1259
|
{
|
|
1195
1260
|
name,
|
|
@@ -1197,6 +1262,7 @@ var App = ({ mode, initialName, options }) => {
|
|
|
1197
1262
|
previewPort,
|
|
1198
1263
|
targets,
|
|
1199
1264
|
outputDir,
|
|
1265
|
+
extensionVersion: command === "scaffold" /* SCAFFOLD */ ? extensionVersion : void 0,
|
|
1200
1266
|
onConfirm: handleConfirm,
|
|
1201
1267
|
onCancel: handleCancel,
|
|
1202
1268
|
onBack: goBack
|
|
@@ -1204,31 +1270,27 @@ var App = ({ mode, initialName, options }) => {
|
|
|
1204
1270
|
);
|
|
1205
1271
|
}
|
|
1206
1272
|
case "scaffolding": {
|
|
1207
|
-
return /* @__PURE__ */
|
|
1273
|
+
return /* @__PURE__ */ jsx12(ScaffoldProgress, { steps: progressSteps });
|
|
1208
1274
|
}
|
|
1209
1275
|
case "done": {
|
|
1210
|
-
return /* @__PURE__ */
|
|
1276
|
+
return /* @__PURE__ */ jsx12(Done, { name, outputDir });
|
|
1211
1277
|
}
|
|
1212
1278
|
default: {
|
|
1213
|
-
return /* @__PURE__ */
|
|
1214
|
-
/* @__PURE__ */
|
|
1215
|
-
errorMessage && /* @__PURE__ */
|
|
1216
|
-
] });
|
|
1279
|
+
return /* @__PURE__ */ jsx12(StepShell, { title: "Scaffold failed", onBack: goBack, backFocused: false, children: /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", gap: 1, children: [
|
|
1280
|
+
/* @__PURE__ */ jsx12(Text12, { color: "red", bold: true, children: "An error occurred" }),
|
|
1281
|
+
errorMessage && /* @__PURE__ */ jsx12(Text12, { color: "red", children: errorMessage })
|
|
1282
|
+
] }) });
|
|
1217
1283
|
}
|
|
1218
1284
|
}
|
|
1219
1285
|
};
|
|
1220
1286
|
|
|
1221
1287
|
// src/index.tsx
|
|
1222
|
-
import { jsx as
|
|
1223
|
-
program.name("stackable-extension").description("Stackable extension developer CLI");
|
|
1224
|
-
program.command("create").description("Create a new
|
|
1225
|
-
render(/* @__PURE__ */
|
|
1288
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
1289
|
+
program.name("stackable-app-extension").description("Stackable app extension developer CLI");
|
|
1290
|
+
program.command("create" /* CREATE */).description("Create a new Extension project").argument("[name]", "Extension project name").option("--extension-port <port>", "Extension dev server port (default: 5173)").option("--preview-port <port>", "Preview host dev server port").option("--skip-install", "Skip package manager install").option("--skip-git", "Skip git initialization").action((name, options) => {
|
|
1291
|
+
render(/* @__PURE__ */ jsx13(App, { command: "create" /* CREATE */, initialName: name, options }));
|
|
1226
1292
|
});
|
|
1227
|
-
program.command("scaffold").description("Scaffold a local project from an existing
|
|
1228
|
-
render(/* @__PURE__ */
|
|
1293
|
+
program.command("scaffold" /* SCAFFOLD */).description("Scaffold a local project from an existing Extension").option("--extension-port <port>", "Extension dev server port (default: 5173)").option("--preview-port <port>", "Preview host dev server port").option("--skip-install", "Skip package manager install").option("--skip-git", "Skip git initialization").action((options) => {
|
|
1294
|
+
render(/* @__PURE__ */ jsx13(App, { command: "scaffold" /* SCAFFOLD */, options }));
|
|
1229
1295
|
});
|
|
1230
|
-
|
|
1231
|
-
program.parse(["node", "stackable-extension", "create", ...process.argv.slice(2).filter((arg) => arg !== "--")]);
|
|
1232
|
-
} else {
|
|
1233
|
-
program.parse(process.argv.filter((arg) => arg !== "--"));
|
|
1234
|
-
}
|
|
1296
|
+
program.parse(process.argv.filter((arg) => arg !== "--"));
|
package/package.json
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stackable-labs/cli-app-extension",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"private": false,
|
|
6
6
|
"bin": {
|
|
7
|
-
"
|
|
8
|
-
"stackable-extension": "./dist/index.js"
|
|
7
|
+
"stackable-app-extension": "./dist/index.js"
|
|
9
8
|
},
|
|
10
9
|
"files": [
|
|
11
10
|
"dist/",
|
|
@@ -16,7 +15,6 @@
|
|
|
16
15
|
"commander": "12.x",
|
|
17
16
|
"giget": "3.x",
|
|
18
17
|
"ink": "5.x",
|
|
19
|
-
"ink-select-input": "6.x",
|
|
20
18
|
"ink-spinner": "5.x",
|
|
21
19
|
"ink-text-input": "6.x",
|
|
22
20
|
"nypm": "0.4.x",
|