@stackable-labs/cli-app-extension 1.25.3 → 1.26.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 +7 -5
  2. package/dist/index.js +444 -289
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -7,14 +7,48 @@ import { render } from "ink";
7
7
 
8
8
  // src/App.tsx
9
9
  import { join as join3 } from "path";
10
- import { Box as Box13, Text as Text13, useApp } from "ink";
11
- import { useCallback, useState as useState8 } from "react";
10
+ import { Box as Box14, Text as Text14, useApp } from "ink";
11
+ import { useCallback, useState as useState9 } from "react";
12
12
 
13
13
  // src/components/Confirm.tsx
14
14
  import { Box as Box2, Text as Text2, useFocus, useFocusManager, useInput as useInput2 } from "ink";
15
15
  import TextInput from "ink-text-input";
16
16
  import { useEffect, useState } from "react";
17
17
 
18
+ // src/constants.ts
19
+ var TEMPLATE_SOURCES = {
20
+ minimal: "github:stackable-labs/templates/app-extension-minimal",
21
+ starter: "github:stackable-labs/templates/app-extension",
22
+ "kitchen-sink": "github:stackable-labs/templates/app-extension-kitchen-sink"
23
+ };
24
+ var DEFAULT_PERMISSIONS = ["context:read"];
25
+ var TEMPLATE_FLAVOR_META = {
26
+ minimal: {
27
+ label: "Minimal",
28
+ description: "Bare minimum \u2014 single surface, hello-world component",
29
+ defaultTargets: ["slot.content"],
30
+ skipTargetStep: true
31
+ },
32
+ starter: {
33
+ label: "Starter",
34
+ description: "Common patterns \u2014 store, api helpers, menu (current default)",
35
+ defaultTargets: null,
36
+ skipTargetStep: false
37
+ },
38
+ "kitchen-sink": {
39
+ label: "Kitchen Sink",
40
+ description: "Everything including the kitchen sink \u2014 every component, capability, surface, and hook we could fit",
41
+ defaultTargets: ["slot.header", "slot.content", "slot.footer", "slot.footer-links"],
42
+ skipTargetStep: true
43
+ }
44
+ };
45
+ var TARGET_PERMISSION_MAP = {
46
+ "slot.header": ["context:read"],
47
+ "slot.content": ["context:read", "data:query", "actions:toast", "actions:invoke"],
48
+ "slot.footer": [],
49
+ "slot.footer-links": []
50
+ };
51
+
18
52
  // src/components/StepShell.tsx
19
53
  import { Box, Text, useInput } from "ink";
20
54
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -101,6 +135,7 @@ var VersionRow = ({ currentVersion, value, onChange, onFocusChange, onConfirm, o
101
135
  var Confirm = ({
102
136
  command,
103
137
  name,
138
+ templateFlavor,
104
139
  extensionVersion,
105
140
  extensionPort,
106
141
  previewPort,
@@ -158,6 +193,10 @@ var Confirm = ({
158
193
  /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Name " }),
159
194
  /* @__PURE__ */ jsx2(Text2, { dimColor: !!extensionVersion, children: name })
160
195
  ] }),
196
+ templateFlavor && /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
197
+ /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Template " }),
198
+ /* @__PURE__ */ jsx2(Text2, { children: TEMPLATE_FLAVOR_META[templateFlavor].label })
199
+ ] }),
161
200
  extensionVersion && command === "update" /* UPDATE */ && newVersion && onVersionOverride && /* @__PURE__ */ jsx2(
162
201
  VersionRow,
163
202
  {
@@ -212,7 +251,12 @@ var Confirm = ({
212
251
  // src/components/Done.tsx
213
252
  import { Box as Box3, Text as Text3 } from "ink";
214
253
  import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
215
- var Done = ({ name, outputDir }) => /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", gap: 1, children: [
254
+ var FLAVOR_HINTS = {
255
+ minimal: "A clean slate \u2014 add surfaces and capabilities as you need them.",
256
+ starter: "Common patterns included \u2014 customize and build from here.",
257
+ "kitchen-sink": "We threw in everything \u2014 including the kitchen sink. Poke around, steal patterns, then delete what you don't need."
258
+ };
259
+ var Done = ({ name, outputDir, templateFlavor }) => /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", gap: 1, children: [
216
260
  /* @__PURE__ */ jsxs3(Box3, { gap: 1, children: [
217
261
  /* @__PURE__ */ jsx3(Text3, { color: "green", bold: true, children: "\u2714" }),
218
262
  /* @__PURE__ */ jsx3(Text3, { bold: true, children: "Extension scaffolded successfully!" })
@@ -222,11 +266,16 @@ var Done = ({ name, outputDir }) => /* @__PURE__ */ jsxs3(Box3, { flexDirection:
222
266
  "Created: ",
223
267
  /* @__PURE__ */ jsx3(Text3, { color: "cyan", children: name })
224
268
  ] }),
269
+ templateFlavor && /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
270
+ "Template: ",
271
+ /* @__PURE__ */ jsx3(Text3, { color: "cyan", children: TEMPLATE_FLAVOR_META[templateFlavor].label })
272
+ ] }),
225
273
  /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
226
274
  "Location: ",
227
275
  /* @__PURE__ */ jsx3(Text3, { color: "cyan", children: outputDir })
228
276
  ] })
229
277
  ] }),
278
+ templateFlavor && /* @__PURE__ */ jsx3(Box3, { marginLeft: 2, children: /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: FLAVOR_HINTS[templateFlavor] }) }),
230
279
  /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginTop: 1, borderStyle: "round", borderColor: "green", paddingX: 2, paddingY: 1, children: [
231
280
  /* @__PURE__ */ jsx3(Text3, { bold: true, children: "Next steps:" }),
232
281
  /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginTop: 1, gap: 1, children: [
@@ -744,10 +793,52 @@ var TargetSelect = ({ availableTargets, preSelected, onSubmit, onBack }) => {
744
793
  );
745
794
  };
746
795
 
796
+ // src/components/TemplateSelect.tsx
797
+ import { Box as Box10, Text as Text10, useInput as useInput6 } from "ink";
798
+ import { useState as useState6 } from "react";
799
+ import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
800
+ var FLAVORS = ["minimal", "starter", "kitchen-sink"];
801
+ var TemplateSelect = ({ onSubmit, onBack }) => {
802
+ const [cursor, setCursor] = useState6(1);
803
+ useInput6((_input, key) => {
804
+ if (key.upArrow) {
805
+ setCursor((c) => Math.max(0, c - 1));
806
+ return;
807
+ }
808
+ if (key.downArrow) {
809
+ setCursor((c) => Math.min(FLAVORS.length - 1, c + 1));
810
+ return;
811
+ }
812
+ if (key.return) {
813
+ onSubmit(FLAVORS[cursor]);
814
+ }
815
+ });
816
+ return /* @__PURE__ */ jsx10(
817
+ StepShell,
818
+ {
819
+ title: "Choose a template",
820
+ hint: "\u2191\u2193 to navigate, Enter to select",
821
+ onBack,
822
+ children: /* @__PURE__ */ jsx10(Box10, { flexDirection: "column", gap: 1, children: FLAVORS.map((flavor, i) => {
823
+ const meta = TEMPLATE_FLAVOR_META[flavor];
824
+ const isCursor = i === cursor;
825
+ return /* @__PURE__ */ jsxs10(Box10, { gap: 1, children: [
826
+ /* @__PURE__ */ jsx10(Text10, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u276F" : " " }),
827
+ /* @__PURE__ */ jsx10(Text10, { color: isCursor ? "green" : void 0, children: isCursor ? "\u25C9" : "\u25CB" }),
828
+ /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
829
+ /* @__PURE__ */ jsx10(Text10, { bold: isCursor, children: meta.label }),
830
+ /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: meta.description })
831
+ ] })
832
+ ] }, flavor);
833
+ }) })
834
+ }
835
+ );
836
+ };
837
+
747
838
  // src/components/AppSelect.tsx
748
- import { Box as Box11, Text as Text11, useInput as useInput6 } from "ink";
839
+ import { Box as Box12, Text as Text12, useInput as useInput7 } from "ink";
749
840
  import Spinner2 from "ink-spinner";
750
- import { useEffect as useEffect2, useState as useState6 } from "react";
841
+ import { useEffect as useEffect2, useState as useState7 } from "react";
751
842
 
752
843
  // src/lib/api.ts
753
844
  var DEFAULT_ADMIN_API_URL = "https://api-use1.stackablelabs.io/admin";
@@ -775,7 +866,7 @@ var fetchApps = async (token) => {
775
866
  iconUrl
776
867
  }));
777
868
  };
778
- var createExtensionRemote = async (appId, token, payload) => {
869
+ var createExtensionRemote = async (token, appId, payload) => {
779
870
  const baseUrl = getAdminApiBaseUrl();
780
871
  const res = await fetch(`${baseUrl}/app-extension/${appId}/extensions`, {
781
872
  method: "POST",
@@ -788,7 +879,7 @@ var createExtensionRemote = async (appId, token, payload) => {
788
879
  }
789
880
  return res.json();
790
881
  };
791
- var fetchExtensions = async (appId, token) => {
882
+ var fetchExtensions = async (token, appId) => {
792
883
  const baseUrl = getAdminApiBaseUrl();
793
884
  const res = await fetch(`${baseUrl}/app-extension/${appId}/extensions`, {
794
885
  headers: authHeaders(token)
@@ -810,7 +901,7 @@ var fetchExtensions = async (appId, token) => {
810
901
  ])
811
902
  );
812
903
  };
813
- var updateExtension = async (appId, extensionId, payload, token) => {
904
+ var updateExtension = async (token, appId, extensionId, payload) => {
814
905
  const baseUrl = getAdminApiBaseUrl();
815
906
  const res = await fetch(`${baseUrl}/app-extension/${appId}/extensions/${extensionId}`, {
816
907
  method: "PUT",
@@ -824,8 +915,8 @@ var updateExtension = async (appId, extensionId, payload, token) => {
824
915
  };
825
916
 
826
917
  // src/components/Banner.tsx
827
- import { Box as Box10, Text as Text10 } from "ink";
828
- import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
918
+ import { Box as Box11, Text as Text11 } from "ink";
919
+ import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
829
920
  var WORDMARK = [
830
921
  " _ _ _ _ ",
831
922
  " ___| |_ __ _ ___| | ____ _| |__ | | ___",
@@ -861,18 +952,18 @@ var gradientColor = (row, col, rows, cols) => {
861
952
  var Banner = ({ userId, orgId } = {}) => {
862
953
  const termWidth = process.stdout.columns ?? 80;
863
954
  const maxLen = Math.max(...WORDMARK.map((l) => l.length));
864
- return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
865
- /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: "\u2500".repeat(termWidth) }),
866
- /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", paddingX: 1, paddingY: 1, children: [
867
- WORDMARK.map((line, row) => /* @__PURE__ */ jsx10(Box10, { children: line.split("").map((ch, col) => /* @__PURE__ */ jsx10(Text10, { bold: true, color: ch === " " ? void 0 : gradientColor(row, col, WORDMARK.length, maxLen), children: ch }, col)) }, row)),
868
- userId && orgId && /* @__PURE__ */ jsxs10(Box10, { gap: 2, marginTop: 1, children: [
869
- /* @__PURE__ */ jsxs10(Box10, { gap: 1, children: [
870
- /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: "User:" }),
871
- /* @__PURE__ */ jsx10(Text10, { color: "cyan", children: userId })
955
+ return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
956
+ /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "\u2500".repeat(termWidth) }),
957
+ /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", paddingX: 1, paddingY: 1, children: [
958
+ WORDMARK.map((line, row) => /* @__PURE__ */ jsx11(Box11, { children: line.split("").map((ch, col) => /* @__PURE__ */ jsx11(Text11, { bold: true, color: ch === " " ? void 0 : gradientColor(row, col, WORDMARK.length, maxLen), children: ch }, col)) }, row)),
959
+ userId && orgId && /* @__PURE__ */ jsxs11(Box11, { gap: 2, marginTop: 1, children: [
960
+ /* @__PURE__ */ jsxs11(Box11, { gap: 1, children: [
961
+ /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "User:" }),
962
+ /* @__PURE__ */ jsx11(Text11, { color: "cyan", children: userId })
872
963
  ] }),
873
- /* @__PURE__ */ jsxs10(Box10, { gap: 1, children: [
874
- /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: "Org:" }),
875
- /* @__PURE__ */ jsx10(Text10, { color: "cyan", children: orgId })
964
+ /* @__PURE__ */ jsxs11(Box11, { gap: 1, children: [
965
+ /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "Org:" }),
966
+ /* @__PURE__ */ jsx11(Text11, { color: "cyan", children: orgId })
876
967
  ] })
877
968
  ] })
878
969
  ] })
@@ -880,16 +971,16 @@ var Banner = ({ userId, orgId } = {}) => {
880
971
  };
881
972
 
882
973
  // src/components/AppSelect.tsx
883
- import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
974
+ import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
884
975
  var AppSelect = ({ token, userId, orgId, onSubmit }) => {
885
- const [apps, setApps] = useState6([]);
886
- const [loading, setLoading] = useState6(true);
887
- const [error, setError] = useState6();
888
- const [cursor, setCursor] = useState6(0);
976
+ const [apps, setApps] = useState7([]);
977
+ const [loading, setLoading] = useState7(true);
978
+ const [error, setError] = useState7();
979
+ const [cursor, setCursor] = useState7(0);
889
980
  useEffect2(() => {
890
981
  fetchApps(token).then(setApps).catch((err) => setError(err instanceof Error ? err.message : String(err))).finally(() => setLoading(false));
891
982
  }, [token]);
892
- useInput6((_, key) => {
983
+ useInput7((_, key) => {
893
984
  if (loading || error || apps.length === 0) return;
894
985
  if (key.upArrow) {
895
986
  setCursor((c) => Math.max(0, c - 1));
@@ -901,26 +992,26 @@ var AppSelect = ({ token, userId, orgId, onSubmit }) => {
901
992
  });
902
993
  const renderContent = () => {
903
994
  if (loading) {
904
- return /* @__PURE__ */ jsxs11(Box11, { gap: 2, children: [
905
- /* @__PURE__ */ jsx11(Spinner2, { type: "dots" }),
906
- /* @__PURE__ */ jsx11(Text11, { children: "Loading available Apps\u2026" })
995
+ return /* @__PURE__ */ jsxs12(Box12, { gap: 2, children: [
996
+ /* @__PURE__ */ jsx12(Spinner2, { type: "dots" }),
997
+ /* @__PURE__ */ jsx12(Text12, { children: "Loading available Apps\u2026" })
907
998
  ] });
908
999
  }
909
1000
  if (error) {
910
- return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", gap: 1, children: [
911
- /* @__PURE__ */ jsx11(Text11, { color: "red", bold: true, children: "Failed to load Apps" }),
912
- /* @__PURE__ */ jsx11(Text11, { color: "red", children: error })
1001
+ return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", gap: 1, children: [
1002
+ /* @__PURE__ */ jsx12(Text12, { color: "red", bold: true, children: "Failed to load Apps" }),
1003
+ /* @__PURE__ */ jsx12(Text12, { color: "red", children: error })
913
1004
  ] });
914
1005
  }
915
1006
  if (apps.length === 0) {
916
- return /* @__PURE__ */ jsx11(Text11, { color: "yellow", children: "No Apps available. Contact your administrator." });
1007
+ return /* @__PURE__ */ jsx12(Text12, { color: "yellow", children: "No Apps available. Contact your administrator." });
917
1008
  }
918
- return /* @__PURE__ */ jsx11(Box11, { flexDirection: "column", children: apps.map((app, i) => {
1009
+ return /* @__PURE__ */ jsx12(Box12, { flexDirection: "column", children: apps.map((app, i) => {
919
1010
  const isCursor = i === cursor;
920
- return /* @__PURE__ */ jsxs11(Box11, { gap: 1, children: [
921
- /* @__PURE__ */ jsx11(Text11, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u276F" : " " }),
922
- /* @__PURE__ */ jsx11(Text11, { bold: isCursor, children: app.name }),
923
- /* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
1011
+ return /* @__PURE__ */ jsxs12(Box12, { gap: 1, children: [
1012
+ /* @__PURE__ */ jsx12(Text12, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u276F" : " " }),
1013
+ /* @__PURE__ */ jsx12(Text12, { bold: isCursor, children: app.name }),
1014
+ /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
924
1015
  "(",
925
1016
  app.id,
926
1017
  ")"
@@ -928,26 +1019,26 @@ var AppSelect = ({ token, userId, orgId, onSubmit }) => {
928
1019
  ] }, app.id);
929
1020
  }) });
930
1021
  };
931
- return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
932
- /* @__PURE__ */ jsx11(Banner, { userId, orgId }),
933
- /* @__PURE__ */ jsx11(StepShell, { title: "Select the App you are building an Extension for:", children: renderContent() })
1022
+ return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", children: [
1023
+ /* @__PURE__ */ jsx12(Banner, { userId, orgId }),
1024
+ /* @__PURE__ */ jsx12(StepShell, { title: "Select the App you are building an Extension for:", children: renderContent() })
934
1025
  ] });
935
1026
  };
936
1027
 
937
1028
  // src/components/ExtensionSelect.tsx
938
- import { Box as Box12, Text as Text12, useInput as useInput7 } from "ink";
1029
+ import { Box as Box13, Text as Text13, useInput as useInput8 } from "ink";
939
1030
  import Spinner3 from "ink-spinner";
940
- import { useEffect as useEffect3, useState as useState7 } from "react";
941
- import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
1031
+ import { useEffect as useEffect3, useState as useState8 } from "react";
1032
+ import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
942
1033
  var ExtensionSelect = ({ appId, token, command, onSubmit, onBack }) => {
943
- const [extensions, setExtensions] = useState7([]);
944
- const [loading, setLoading] = useState7(true);
945
- const [error, setError] = useState7();
946
- const [cursor, setCursor] = useState7(0);
1034
+ const [extensions, setExtensions] = useState8([]);
1035
+ const [loading, setLoading] = useState8(true);
1036
+ const [error, setError] = useState8();
1037
+ const [cursor, setCursor] = useState8(0);
947
1038
  useEffect3(() => {
948
- fetchExtensions(appId, token).then((byId) => setExtensions(Object.values(byId))).catch((err) => setError(err instanceof Error ? err.message : String(err))).finally(() => setLoading(false));
1039
+ fetchExtensions(token, appId).then((byId) => setExtensions(Object.values(byId))).catch((err) => setError(err instanceof Error ? err.message : String(err))).finally(() => setLoading(false));
949
1040
  }, [appId, token]);
950
- useInput7((_, key) => {
1041
+ useInput8((_, key) => {
951
1042
  if (key.upArrow) {
952
1043
  if (!loading && !error && extensions.length > 0) {
953
1044
  setCursor((c) => Math.max(0, c - 1));
@@ -968,30 +1059,30 @@ var ExtensionSelect = ({ appId, token, command, onSubmit, onBack }) => {
968
1059
  });
969
1060
  const renderContent = () => {
970
1061
  if (loading) {
971
- return /* @__PURE__ */ jsxs12(Box12, { gap: 2, children: [
972
- /* @__PURE__ */ jsx12(Spinner3, { type: "dots" }),
973
- /* @__PURE__ */ jsx12(Text12, { children: "Loading Extensions\u2026" })
1062
+ return /* @__PURE__ */ jsxs13(Box13, { gap: 2, children: [
1063
+ /* @__PURE__ */ jsx13(Spinner3, { type: "dots" }),
1064
+ /* @__PURE__ */ jsx13(Text13, { children: "Loading Extensions\u2026" })
974
1065
  ] });
975
1066
  }
976
1067
  if (error) {
977
- return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", gap: 1, children: [
978
- /* @__PURE__ */ jsx12(Text12, { color: "red", bold: true, children: "Failed to load Extensions" }),
979
- /* @__PURE__ */ jsx12(Text12, { color: "red", children: error })
1068
+ return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", gap: 1, children: [
1069
+ /* @__PURE__ */ jsx13(Text13, { color: "red", bold: true, children: "Failed to load Extensions" }),
1070
+ /* @__PURE__ */ jsx13(Text13, { color: "red", children: error })
980
1071
  ] });
981
1072
  }
982
1073
  if (extensions.length === 0) {
983
- return /* @__PURE__ */ jsx12(Text12, { color: "yellow", children: "No Extensions found for this App." });
1074
+ return /* @__PURE__ */ jsx13(Text13, { color: "yellow", children: "No Extensions found for this App." });
984
1075
  }
985
- return /* @__PURE__ */ jsx12(Box12, { flexDirection: "column", children: extensions.map((ext, i) => {
1076
+ return /* @__PURE__ */ jsx13(Box13, { flexDirection: "column", children: extensions.map((ext, i) => {
986
1077
  const isCursor = i === cursor;
987
- return /* @__PURE__ */ jsxs12(Box12, { gap: 1, children: [
988
- /* @__PURE__ */ jsx12(Text12, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u276F" : " " }),
989
- /* @__PURE__ */ jsx12(Text12, { bold: isCursor, children: ext.manifest.name }),
990
- /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
1078
+ return /* @__PURE__ */ jsxs13(Box13, { gap: 1, children: [
1079
+ /* @__PURE__ */ jsx13(Text13, { color: isCursor ? "cyan" : void 0, children: isCursor ? "\u276F" : " " }),
1080
+ /* @__PURE__ */ jsx13(Text13, { bold: isCursor, children: ext.manifest.name }),
1081
+ /* @__PURE__ */ jsxs13(Text13, { dimColor: true, children: [
991
1082
  "v",
992
1083
  ext.manifest.version
993
1084
  ] }),
994
- /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
1085
+ /* @__PURE__ */ jsxs13(Text13, { dimColor: true, children: [
995
1086
  "(",
996
1087
  ext.id,
997
1088
  ")"
@@ -999,7 +1090,7 @@ var ExtensionSelect = ({ appId, token, command, onSubmit, onBack }) => {
999
1090
  ] }, ext.id);
1000
1091
  }) });
1001
1092
  };
1002
- return /* @__PURE__ */ jsx12(
1093
+ return /* @__PURE__ */ jsx13(
1003
1094
  StepShell,
1004
1095
  {
1005
1096
  title: command === "update" /* UPDATE */ ? "Select an Extension to update:" : "Select an existing Extension to scaffold:",
@@ -1009,16 +1100,6 @@ var ExtensionSelect = ({ appId, token, command, onSubmit, onBack }) => {
1009
1100
  );
1010
1101
  };
1011
1102
 
1012
- // src/constants.ts
1013
- var TEMPLATE_SOURCE = "github:stackable-labs/templates/app-extension";
1014
- var DEFAULT_PERMISSIONS = ["context:read"];
1015
- var TARGET_PERMISSION_MAP = {
1016
- "slot.header": ["context:read"],
1017
- "slot.content": ["context:read", "data:query", "actions:toast", "actions:invoke"],
1018
- "slot.footer": [],
1019
- "slot.footer-links": []
1020
- };
1021
-
1022
1103
  // src/lib/postScaffold.ts
1023
1104
  import { execFile } from "child_process";
1024
1105
  import { promisify } from "util";
@@ -1444,28 +1525,33 @@ var updateGitignore = async (dir) => {
1444
1525
  }
1445
1526
  };
1446
1527
  var scaffold = async (options) => {
1447
- const { dir } = await downloadTemplate(TEMPLATE_SOURCE, {
1528
+ const flavor = options.templateFlavor ?? "starter";
1529
+ const templateSource = TEMPLATE_SOURCES[flavor];
1530
+ const { dir } = await downloadTemplate(templateSource, {
1448
1531
  dir: options.outputDir,
1449
1532
  force: true
1450
1533
  });
1451
- const selectedTargets = normalizeTargets(options.targets);
1452
- const derivedPermissions = derivePermissions(selectedTargets);
1453
1534
  await replacePlaceholders(dir, {
1454
1535
  "__EXTENSION_ID__": toKebabCase(options.extensionId || options.name),
1455
1536
  "__EXTENSION_DISPLAY_NAME__": options.name,
1456
1537
  "replace-with-extension-name": toKebabCase(options.name),
1457
1538
  "replace-with-extension-package-name": `@agnostack/extensions-${toKebabCase(options.extensionId || options.name)}`
1458
1539
  });
1459
- await generateManifest(dir, options.name, selectedTargets, derivedPermissions);
1460
- await generateSurfaceFiles(dir, selectedTargets);
1461
- await rewriteExtensionIndex(dir, options.extensionId || options.name, selectedTargets);
1462
- await rewritePreviewApp(dir, selectedTargets, derivedPermissions);
1540
+ if (flavor === "starter") {
1541
+ const selectedTargets = normalizeTargets(options.targets);
1542
+ const derivedPermissions = derivePermissions(selectedTargets);
1543
+ await generateManifest(dir, options.name, selectedTargets, derivedPermissions);
1544
+ await generateSurfaceFiles(dir, selectedTargets);
1545
+ await rewriteExtensionIndex(dir, options.extensionId || options.name, selectedTargets);
1546
+ await rewritePreviewApp(dir, selectedTargets, derivedPermissions);
1547
+ }
1463
1548
  await rewriteTurboJson(dir);
1464
1549
  await patchViteAllowedHosts(dir);
1465
1550
  await writeEnvFile2(dir, options.extensionPort, options.previewPort);
1466
1551
  await updateGitignore(dir);
1467
1552
  await writeDevContext(dir, {
1468
1553
  projectRoot: dir,
1554
+ orgId: null,
1469
1555
  appId: options.appId,
1470
1556
  extensionId: toKebabCase(options.extensionId || options.name),
1471
1557
  appName: options.appName || null,
@@ -1477,9 +1563,9 @@ var scaffold = async (options) => {
1477
1563
  };
1478
1564
 
1479
1565
  // src/App.tsx
1480
- import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
1566
+ import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
1481
1567
  var STEPS = {
1482
- ["create" /* CREATE */]: ["app", "name", "targets", "settings", "confirm"],
1568
+ ["create" /* CREATE */]: ["app", "name", "template", "targets", "settings", "confirm"],
1483
1569
  ["scaffold" /* SCAFFOLD */]: ["app", "extensionSelect", "confirmTargets", "settings", "confirm"],
1484
1570
  ["update" /* UPDATE */]: ["app", "extensionSelect", "updateSettings", "confirm"],
1485
1571
  ["dev" /* DEV */]: []
@@ -1523,30 +1609,33 @@ var derivePermissions2 = (targets) => {
1523
1609
  };
1524
1610
  var App = ({ command, token, userId, orgId, initialName, initialExtensionId, options }) => {
1525
1611
  const { exit } = useApp();
1526
- const [step, setStep] = useState8("app");
1527
- const [name, setName] = useState8(initialName ?? options?.name ?? "");
1528
- const [extensionId, setExtensionId] = useState8(initialExtensionId ?? "");
1529
- const [extensionVersion, setExtensionVersion] = useState8("");
1530
- const [bundleUrl, setBundleUrl] = useState8(options?.bundleUrl ?? "");
1531
- const [enabled, setEnabled] = useState8(
1612
+ const [step, setStep] = useState9("app");
1613
+ const [name, setName] = useState9(initialName ?? options?.name ?? "");
1614
+ const [extensionId, setExtensionId] = useState9(initialExtensionId ?? "");
1615
+ const [extensionVersion, setExtensionVersion] = useState9("");
1616
+ const [bundleUrl, setBundleUrl] = useState9(options?.bundleUrl ?? "");
1617
+ const [enabled, setEnabled] = useState9(
1532
1618
  options?.enabled !== void 0 ? options.enabled !== "false" : true
1533
1619
  );
1534
- const [versionOverride, setVersionOverride] = useState8(void 0);
1535
- const [forceMajor, setForceMajor] = useState8(false);
1536
- const [initialExtension, setInitialExtension] = useState8(null);
1537
- const [targets, setTargets] = useState8(
1620
+ const [versionOverride, setVersionOverride] = useState9(void 0);
1621
+ const [forceMajor, setForceMajor] = useState9(false);
1622
+ const [initialExtension, setInitialExtension] = useState9(null);
1623
+ const [templateFlavor, setTemplateFlavor] = useState9(
1624
+ options?.template ?? "starter"
1625
+ );
1626
+ const [targets, setTargets] = useState9(
1538
1627
  options?.targets ? options.targets.split(",").map((t) => t.trim()) : []
1539
1628
  );
1540
- const [selectedApp, setSelectedApp] = useState8(null);
1541
- const [extensionPort, setExtensionPort] = useState8(
1629
+ const [selectedApp, setSelectedApp] = useState9(null);
1630
+ const [extensionPort, setExtensionPort] = useState9(
1542
1631
  options?.extensionPort ? parseInt(options.extensionPort, 10) : 6543
1543
1632
  );
1544
- const [previewPort, setPreviewPort] = useState8(
1633
+ const [previewPort, setPreviewPort] = useState9(
1545
1634
  options?.previewPort ? parseInt(options.previewPort, 10) : 6544
1546
1635
  );
1547
- const [outputDir, setOutputDir] = useState8("");
1548
- const [progressSteps, setProgressSteps] = useState8(PROGRESS_STEPS[command]);
1549
- const [errorMessage, setErrorMessage] = useState8();
1636
+ const [outputDir, setOutputDir] = useState9("");
1637
+ const [progressSteps, setProgressSteps] = useState9(PROGRESS_STEPS[command]);
1638
+ const [errorMessage, setErrorMessage] = useState9();
1550
1639
  const updateStep = useCallback((index, status) => {
1551
1640
  setProgressSteps((prev) => prev.map((s, i) => i === index ? { ...s, status } : s));
1552
1641
  }, []);
@@ -1554,6 +1643,10 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
1554
1643
  const base = STEPS[command];
1555
1644
  const skipped = /* @__PURE__ */ new Set();
1556
1645
  if (command === "create" /* CREATE */ && initialName) skipped.add("name");
1646
+ if (command === "create" /* CREATE */ && options?.template) skipped.add("template");
1647
+ if (command === "create" /* CREATE */ && TEMPLATE_FLAVOR_META[templateFlavor].skipTargetStep) {
1648
+ skipped.add("targets");
1649
+ }
1557
1650
  if (options?.extensionPort || options?.previewPort) skipped.add("settings");
1558
1651
  if (command === "update" /* UPDATE */) {
1559
1652
  if (options?.appId) skipped.add("app");
@@ -1564,6 +1657,8 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
1564
1657
  command,
1565
1658
  initialName,
1566
1659
  initialExtensionId,
1660
+ templateFlavor,
1661
+ options?.template,
1567
1662
  options?.extensionPort,
1568
1663
  options?.previewPort,
1569
1664
  options?.appId
@@ -1581,7 +1676,26 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
1581
1676
  setStep("extensionSelect");
1582
1677
  return;
1583
1678
  }
1584
- setStep(initialName ? "targets" : "name");
1679
+ if (initialName) {
1680
+ if (options?.template) {
1681
+ const meta = TEMPLATE_FLAVOR_META[templateFlavor];
1682
+ if (meta.skipTargetStep && meta.defaultTargets) {
1683
+ setTargets(meta.defaultTargets);
1684
+ if (options?.extensionPort || options?.previewPort) {
1685
+ setOutputDir(join3(process.cwd(), toKebabCase2(initialName)));
1686
+ setStep("confirm");
1687
+ } else {
1688
+ setStep("settings");
1689
+ }
1690
+ return;
1691
+ }
1692
+ setStep("targets");
1693
+ } else {
1694
+ setStep("template");
1695
+ }
1696
+ } else {
1697
+ setStep("name");
1698
+ }
1585
1699
  };
1586
1700
  const handleExtensionSelect = (ext) => {
1587
1701
  setName(ext.manifest.name);
@@ -1613,6 +1727,36 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
1613
1727
  const handleName = (value) => {
1614
1728
  setName(value);
1615
1729
  setExtensionId(toKebabCase2(value));
1730
+ if (options?.template) {
1731
+ const meta = TEMPLATE_FLAVOR_META[templateFlavor];
1732
+ if (meta.skipTargetStep && meta.defaultTargets) {
1733
+ setTargets(meta.defaultTargets);
1734
+ if (options?.extensionPort || options?.previewPort) {
1735
+ setOutputDir(join3(process.cwd(), toKebabCase2(value)));
1736
+ setStep("confirm");
1737
+ } else {
1738
+ setStep("settings");
1739
+ }
1740
+ return;
1741
+ }
1742
+ setStep("targets");
1743
+ } else {
1744
+ setStep("template");
1745
+ }
1746
+ };
1747
+ const handleTemplateSelect = (flavor) => {
1748
+ setTemplateFlavor(flavor);
1749
+ const meta = TEMPLATE_FLAVOR_META[flavor];
1750
+ if (meta.skipTargetStep && meta.defaultTargets) {
1751
+ setTargets(meta.defaultTargets);
1752
+ if (options?.extensionPort || options?.previewPort) {
1753
+ setOutputDir(join3(process.cwd(), toKebabCase2(extensionId || name)));
1754
+ setStep("confirm");
1755
+ } else {
1756
+ setStep("settings");
1757
+ }
1758
+ return;
1759
+ }
1616
1760
  setStep("targets");
1617
1761
  };
1618
1762
  const handleTargets = (value) => {
@@ -1649,7 +1793,7 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
1649
1793
  try {
1650
1794
  updateStep(0, "running");
1651
1795
  const resolvedVersion = options?.setVersion ?? versionOverride ?? computeVersionBump(extensionVersion, name, targets, bundleUrl, forceMajor);
1652
- await updateExtension(selectedApp.id, extensionId, {
1796
+ await updateExtension(token, selectedApp.id, extensionId, {
1653
1797
  manifest: {
1654
1798
  name,
1655
1799
  version: resolvedVersion,
@@ -1659,7 +1803,7 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
1659
1803
  },
1660
1804
  bundleUrl: bundleUrl || void 0,
1661
1805
  enabled
1662
- }, token);
1806
+ });
1663
1807
  updateStep(0, "done");
1664
1808
  setExtensionVersion(resolvedVersion);
1665
1809
  setStep("updateDone");
@@ -1678,7 +1822,7 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
1678
1822
  if (command === "create" /* CREATE */) {
1679
1823
  scaffoldStepOffset = 1;
1680
1824
  updateStep(0, "running");
1681
- const created = await createExtensionRemote(selectedApp.id, {
1825
+ const created = await createExtensionRemote(token, selectedApp.id, {
1682
1826
  manifest: {
1683
1827
  name,
1684
1828
  version: "0.0.0",
@@ -1687,7 +1831,7 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
1687
1831
  allowedDomains: []
1688
1832
  },
1689
1833
  bundleUrl: `http://localhost:${extensionPort}`
1690
- }, token);
1834
+ });
1691
1835
  resolvedExtensionId = created.id;
1692
1836
  setExtensionId(created.id);
1693
1837
  updateStep(0, "done");
@@ -1699,6 +1843,7 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
1699
1843
  name,
1700
1844
  extensionId: resolvedExtensionId,
1701
1845
  targets,
1846
+ templateFlavor: command === "create" /* CREATE */ ? templateFlavor : void 0,
1702
1847
  outputDir,
1703
1848
  extensionPort,
1704
1849
  previewPort
@@ -1726,7 +1871,7 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
1726
1871
  };
1727
1872
  switch (step) {
1728
1873
  case "app": {
1729
- return /* @__PURE__ */ jsx13(
1874
+ return /* @__PURE__ */ jsx14(
1730
1875
  AppSelect,
1731
1876
  {
1732
1877
  token,
@@ -1737,7 +1882,7 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
1737
1882
  );
1738
1883
  }
1739
1884
  case "extensionSelect": {
1740
- return /* @__PURE__ */ jsx13(
1885
+ return /* @__PURE__ */ jsx14(
1741
1886
  ExtensionSelect,
1742
1887
  {
1743
1888
  appId: selectedApp.id,
@@ -1749,7 +1894,7 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
1749
1894
  );
1750
1895
  }
1751
1896
  case "confirmTargets": {
1752
- return /* @__PURE__ */ jsx13(
1897
+ return /* @__PURE__ */ jsx14(
1753
1898
  TargetSelect,
1754
1899
  {
1755
1900
  availableTargets: selectedApp?.targets ?? [],
@@ -1760,7 +1905,7 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
1760
1905
  );
1761
1906
  }
1762
1907
  case "name": {
1763
- return /* @__PURE__ */ jsx13(
1908
+ return /* @__PURE__ */ jsx14(
1764
1909
  NamePrompt,
1765
1910
  {
1766
1911
  initialValue: name,
@@ -1769,8 +1914,17 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
1769
1914
  }
1770
1915
  );
1771
1916
  }
1917
+ case "template": {
1918
+ return /* @__PURE__ */ jsx14(
1919
+ TemplateSelect,
1920
+ {
1921
+ onSubmit: handleTemplateSelect,
1922
+ onBack: goBack
1923
+ }
1924
+ );
1925
+ }
1772
1926
  case "targets": {
1773
- return /* @__PURE__ */ jsx13(
1927
+ return /* @__PURE__ */ jsx14(
1774
1928
  TargetSelect,
1775
1929
  {
1776
1930
  availableTargets: selectedApp?.targets ?? [],
@@ -1780,7 +1934,7 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
1780
1934
  );
1781
1935
  }
1782
1936
  case "settings": {
1783
- return /* @__PURE__ */ jsx13(
1937
+ return /* @__PURE__ */ jsx14(
1784
1938
  SettingsPrompt,
1785
1939
  {
1786
1940
  defaultDir: join3(process.cwd(), toKebabCase2(extensionId || name)),
@@ -1790,11 +1944,12 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
1790
1944
  );
1791
1945
  }
1792
1946
  case "confirm": {
1793
- return /* @__PURE__ */ jsx13(
1947
+ return /* @__PURE__ */ jsx14(
1794
1948
  Confirm,
1795
1949
  {
1796
1950
  command,
1797
1951
  name,
1952
+ templateFlavor: command === "create" /* CREATE */ ? templateFlavor : void 0,
1798
1953
  targets,
1799
1954
  outputDir,
1800
1955
  previewPort,
@@ -1811,10 +1966,10 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
1811
1966
  );
1812
1967
  }
1813
1968
  case "scaffolding": {
1814
- return /* @__PURE__ */ jsx13(ScaffoldProgress, { steps: progressSteps });
1969
+ return /* @__PURE__ */ jsx14(ScaffoldProgress, { steps: progressSteps });
1815
1970
  }
1816
1971
  case "updateSettings": {
1817
- return /* @__PURE__ */ jsx13(
1972
+ return /* @__PURE__ */ jsx14(
1818
1973
  UpdateSettingsPrompt,
1819
1974
  {
1820
1975
  name,
@@ -1836,46 +1991,46 @@ var App = ({ command, token, userId, orgId, initialName, initialExtensionId, opt
1836
1991
  );
1837
1992
  }
1838
1993
  case "updating": {
1839
- return /* @__PURE__ */ jsx13(ScaffoldProgress, { steps: progressSteps });
1994
+ return /* @__PURE__ */ jsx14(ScaffoldProgress, { steps: progressSteps });
1840
1995
  }
1841
1996
  case "updateDone": {
1842
- return /* @__PURE__ */ jsx13(StepShell, { title: "Extension updated", onBack: goBack, children: /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", gap: 1, children: [
1843
- /* @__PURE__ */ jsx13(Text13, { color: "green", bold: true, children: "Extension updated successfully!" }),
1844
- /* @__PURE__ */ jsxs13(Text13, { dimColor: true, children: [
1997
+ return /* @__PURE__ */ jsx14(StepShell, { title: "Extension updated", onBack: goBack, children: /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", gap: 1, children: [
1998
+ /* @__PURE__ */ jsx14(Text14, { color: "green", bold: true, children: "Extension updated successfully!" }),
1999
+ /* @__PURE__ */ jsxs14(Text14, { dimColor: true, children: [
1845
2000
  "Name: ",
1846
2001
  name
1847
2002
  ] }),
1848
- /* @__PURE__ */ jsxs13(Text13, { dimColor: true, children: [
2003
+ /* @__PURE__ */ jsxs14(Text14, { dimColor: true, children: [
1849
2004
  "ID: ",
1850
2005
  extensionId
1851
2006
  ] }),
1852
- /* @__PURE__ */ jsxs13(Text13, { dimColor: true, children: [
2007
+ /* @__PURE__ */ jsxs14(Text14, { dimColor: true, children: [
1853
2008
  "Version: ",
1854
2009
  extensionVersion
1855
2010
  ] })
1856
2011
  ] }) });
1857
2012
  }
1858
2013
  case "done": {
1859
- return /* @__PURE__ */ jsx13(Done, { name, outputDir });
2014
+ return /* @__PURE__ */ jsx14(Done, { name, outputDir, templateFlavor: command === "create" /* CREATE */ ? templateFlavor : void 0 });
1860
2015
  }
1861
2016
  case "error": {
1862
- return /* @__PURE__ */ jsx13(StepShell, { title: "Operation failed", onBack: goBack, children: /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", gap: 1, children: [
1863
- /* @__PURE__ */ jsx13(Text13, { color: "red", bold: true, children: "An error occurred" }),
1864
- errorMessage && /* @__PURE__ */ jsx13(Text13, { color: "red", children: errorMessage })
2017
+ return /* @__PURE__ */ jsx14(StepShell, { title: "Operation failed", onBack: goBack, children: /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", gap: 1, children: [
2018
+ /* @__PURE__ */ jsx14(Text14, { color: "red", bold: true, children: "An error occurred" }),
2019
+ errorMessage && /* @__PURE__ */ jsx14(Text14, { color: "red", children: errorMessage })
1865
2020
  ] }) });
1866
2021
  }
1867
2022
  default: {
1868
- return /* @__PURE__ */ jsx13(StepShell, { title: "Scaffold failed", onBack: goBack, children: /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", gap: 1, children: [
1869
- /* @__PURE__ */ jsx13(Text13, { color: "red", bold: true, children: "An error occurred" }),
1870
- errorMessage && /* @__PURE__ */ jsx13(Text13, { color: "red", children: errorMessage })
2023
+ return /* @__PURE__ */ jsx14(StepShell, { title: "Scaffold failed", onBack: goBack, children: /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", gap: 1, children: [
2024
+ /* @__PURE__ */ jsx14(Text14, { color: "red", bold: true, children: "An error occurred" }),
2025
+ errorMessage && /* @__PURE__ */ jsx14(Text14, { color: "red", children: errorMessage })
1871
2026
  ] }) });
1872
2027
  }
1873
2028
  }
1874
2029
  };
1875
2030
 
1876
2031
  // src/components/DevApp.tsx
1877
- import { useRef, useState as useState10, useEffect as useEffect6, useCallback as useCallback2 } from "react";
1878
- import { useInput as useInput9, Box as Box16, Text as Text16 } from "ink";
2032
+ import { useRef, useState as useState11, useEffect as useEffect6, useCallback as useCallback2 } from "react";
2033
+ import { useInput as useInput10, Box as Box17, Text as Text17 } from "ink";
1879
2034
 
1880
2035
  // src/lib/tunnel.ts
1881
2036
  import { Tunnel } from "cloudflared";
@@ -1909,12 +2064,12 @@ var startDevServer = (projectRoot) => {
1909
2064
  };
1910
2065
 
1911
2066
  // src/components/DevSetup.tsx
1912
- import { Box as Box14, Text as Text14 } from "ink";
1913
- import { useState as useState9, useEffect as useEffect4 } from "react";
1914
- import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
2067
+ import { Box as Box15, Text as Text15 } from "ink";
2068
+ import { useState as useState10, useEffect as useEffect4 } from "react";
2069
+ import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
1915
2070
  var DevSetup = ({ initialContext, token, onReady }) => {
1916
- const [step, setStep] = useState9("app");
1917
- const [selectedApp, setSelectedApp] = useState9(null);
2071
+ const [step, setStep] = useState10("app");
2072
+ const [selectedApp, setSelectedApp] = useState10(null);
1918
2073
  useEffect4(() => {
1919
2074
  if (initialContext.appId) {
1920
2075
  setStep("extension");
@@ -1932,9 +2087,9 @@ var DevSetup = ({ initialContext, token, onReady }) => {
1932
2087
  });
1933
2088
  };
1934
2089
  if (step === "app") {
1935
- return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
1936
- /* @__PURE__ */ jsx14(Box14, { marginBottom: 1, children: /* @__PURE__ */ jsx14(Text14, { children: "Select the App for your extension:" }) }),
1937
- /* @__PURE__ */ jsx14(
2090
+ return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", children: [
2091
+ /* @__PURE__ */ jsx15(Box15, { marginBottom: 1, children: /* @__PURE__ */ jsx15(Text15, { children: "Select the App for your extension:" }) }),
2092
+ /* @__PURE__ */ jsx15(
1938
2093
  AppSelect,
1939
2094
  {
1940
2095
  token,
@@ -1943,9 +2098,9 @@ var DevSetup = ({ initialContext, token, onReady }) => {
1943
2098
  )
1944
2099
  ] });
1945
2100
  }
1946
- return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
1947
- /* @__PURE__ */ jsx14(Box14, { marginBottom: 1, children: /* @__PURE__ */ jsx14(Text14, { children: "Select the Extension to develop:" }) }),
1948
- /* @__PURE__ */ jsx14(
2101
+ return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", children: [
2102
+ /* @__PURE__ */ jsx15(Box15, { marginBottom: 1, children: /* @__PURE__ */ jsx15(Text15, { children: "Select the Extension to develop:" }) }),
2103
+ /* @__PURE__ */ jsx15(
1949
2104
  ExtensionSelect,
1950
2105
  {
1951
2106
  token,
@@ -1957,9 +2112,9 @@ var DevSetup = ({ initialContext, token, onReady }) => {
1957
2112
  };
1958
2113
 
1959
2114
  // src/components/DevDashboard.tsx
1960
- import { Box as Box15, Text as Text15, useInput as useInput8 } from "ink";
2115
+ import { Box as Box16, Text as Text16, useInput as useInput9 } from "ink";
1961
2116
  import { useEffect as useEffect5 } from "react";
1962
- import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
2117
+ import { jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
1963
2118
  var DevDashboard = ({
1964
2119
  previewTunnelUrl,
1965
2120
  tunnelUrl,
@@ -1982,68 +2137,68 @@ var DevDashboard = ({
1982
2137
  process.off("SIGINT", handler);
1983
2138
  };
1984
2139
  }, [onQuit]);
1985
- useInput8((input, key) => {
2140
+ useInput9((input, key) => {
1986
2141
  if (input === "q" || key.ctrl && input === "c") {
1987
2142
  onQuit();
1988
2143
  }
1989
2144
  });
1990
- return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", children: [
1991
- /* @__PURE__ */ jsx15(Banner, { userId, orgId }),
1992
- /* @__PURE__ */ jsxs15(
2145
+ return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
2146
+ /* @__PURE__ */ jsx16(Banner, { userId, orgId }),
2147
+ /* @__PURE__ */ jsxs16(
1993
2148
  StepShell,
1994
2149
  {
1995
2150
  title: "dev",
1996
2151
  hint: `Live development ${tunnelUrl ? "with" : "w/o"} Tunnel`,
1997
- footer: /* @__PURE__ */ jsx15(Box15, { flexDirection: "column", gap: 1, children: /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "Press q or Ctrl-C to quit" }) }),
2152
+ footer: /* @__PURE__ */ jsx16(Box16, { flexDirection: "column", gap: 1, children: /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: "Press q or Ctrl-C to quit" }) }),
1998
2153
  children: [
1999
- /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", children: [
2000
- /* @__PURE__ */ jsxs15(Box15, { gap: 2, children: [
2001
- /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "Extension:" }),
2002
- /* @__PURE__ */ jsxs15(Text15, { children: [
2154
+ /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
2155
+ /* @__PURE__ */ jsxs16(Box16, { gap: 2, children: [
2156
+ /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: "Extension:" }),
2157
+ /* @__PURE__ */ jsxs16(Text16, { children: [
2003
2158
  extensionName,
2004
2159
  " (",
2005
2160
  extensionId,
2006
2161
  ")"
2007
2162
  ] })
2008
2163
  ] }),
2009
- /* @__PURE__ */ jsxs15(Box15, { gap: 2, children: [
2010
- /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "App:" }),
2011
- /* @__PURE__ */ jsx15(Text15, { children: `${appName ? `${appName} ` : ""}(${appId})` })
2164
+ /* @__PURE__ */ jsxs16(Box16, { gap: 2, children: [
2165
+ /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: "App:" }),
2166
+ /* @__PURE__ */ jsx16(Text16, { children: `${appName ? `${appName} ` : ""}(${appId})` })
2012
2167
  ] }),
2013
- /* @__PURE__ */ jsxs15(Box15, { gap: 2, children: [
2014
- /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "Bundle URL:" }),
2015
- /* @__PURE__ */ jsx15(Text15, { children: tunnelUrl || `http://localhost:${extensionPort}` })
2168
+ /* @__PURE__ */ jsxs16(Box16, { gap: 2, children: [
2169
+ /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: "Bundle URL:" }),
2170
+ /* @__PURE__ */ jsx16(Text16, { children: tunnelUrl || `http://localhost:${extensionPort}` })
2016
2171
  ] })
2017
2172
  ] }),
2018
- /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", children: [
2019
- previewTunnelUrl && /* @__PURE__ */ jsxs15(Box15, { gap: 2, children: [
2020
- /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "Tunnel Dev - Preview:" }),
2021
- /* @__PURE__ */ jsx15(Text15, { children: previewTunnelUrl })
2173
+ /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
2174
+ previewTunnelUrl && /* @__PURE__ */ jsxs16(Box16, { gap: 2, children: [
2175
+ /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: "Tunnel Dev - Preview:" }),
2176
+ /* @__PURE__ */ jsx16(Text16, { children: previewTunnelUrl })
2022
2177
  ] }),
2023
- /* @__PURE__ */ jsxs15(Box15, { gap: 2, children: [
2024
- /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "Local Dev - Preview:" }),
2025
- /* @__PURE__ */ jsxs15(Text15, { children: [
2178
+ /* @__PURE__ */ jsxs16(Box16, { gap: 2, children: [
2179
+ /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: "Local Dev - Preview:" }),
2180
+ /* @__PURE__ */ jsxs16(Text16, { children: [
2026
2181
  "http://localhost:",
2027
2182
  previewPort
2028
2183
  ] })
2029
2184
  ] })
2030
2185
  ] }),
2031
- /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", children: [
2032
- tunnelUrl && /* @__PURE__ */ jsxs15(Box15, { gap: 2, children: [
2033
- /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "Tunnel Dev - Extension:" }),
2034
- /* @__PURE__ */ jsx15(Text15, { children: tunnelUrl })
2186
+ /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", children: [
2187
+ tunnelUrl && /* @__PURE__ */ jsxs16(Box16, { gap: 2, children: [
2188
+ /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: "Tunnel Dev - Extension:" }),
2189
+ /* @__PURE__ */ jsx16(Text16, { children: tunnelUrl })
2035
2190
  ] }),
2036
- /* @__PURE__ */ jsxs15(Box15, { gap: 2, children: [
2037
- /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "Local Dev - Extension:" }),
2038
- /* @__PURE__ */ jsxs15(Text15, { children: [
2191
+ /* @__PURE__ */ jsxs16(Box16, { gap: 2, children: [
2192
+ /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: "Local Dev - Extension:" }),
2193
+ /* @__PURE__ */ jsxs16(Text16, { children: [
2039
2194
  "http://localhost:",
2040
2195
  extensionPort
2041
2196
  ] })
2042
2197
  ] })
2043
2198
  ] }),
2044
- /* @__PURE__ */ jsx15(Box15, { flexDirection: "column", children: tunnelUrl && /* @__PURE__ */ jsxs15(Box15, { gap: 2, children: [
2045
- /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "Host Dev - Query Param:" }),
2046
- /* @__PURE__ */ jsxs15(Text15, { children: [
2199
+ /* @__PURE__ */ jsx16(Box16, { flexDirection: "column", children: tunnelUrl && /* @__PURE__ */ jsxs16(Box16, { gap: 2, children: [
2200
+ /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: "Host Dev - Query Param:" }),
2201
+ /* @__PURE__ */ jsxs16(Text16, { children: [
2047
2202
  "?_stackable_dev=",
2048
2203
  encodeURIComponent(`${extensionId}:${tunnelUrl}`)
2049
2204
  ] })
@@ -2055,16 +2210,16 @@ var DevDashboard = ({
2055
2210
  };
2056
2211
 
2057
2212
  // src/components/DevApp.tsx
2058
- import { jsx as jsx16 } from "react/jsx-runtime";
2213
+ import { jsx as jsx17 } from "react/jsx-runtime";
2059
2214
  var DevApp = ({ token, userId, orgId, options = {} }) => {
2060
- const [state, setState] = useState10("setup");
2061
- const [devContext, setDevContext] = useState10(null);
2062
- const [resolvedContext, setResolvedContext] = useState10(null);
2063
- const [tunnelUrl, setTunnelUrl] = useState10(null);
2064
- const [previewTunnelUrl, setPreviewTunnelUrl] = useState10(null);
2065
- const [tunnelHandle, setTunnelHandle] = useState10(null);
2066
- const [previewTunnelHandle, setPreviewTunnelHandle] = useState10(null);
2067
- const [devServerHandle, setDevServerHandle] = useState10(null);
2215
+ const [state, setState] = useState11("setup");
2216
+ const [devContext, setDevContext] = useState11(null);
2217
+ const [resolvedContext, setResolvedContext] = useState11(null);
2218
+ const [tunnelUrl, setTunnelUrl] = useState11(null);
2219
+ const [previewTunnelUrl, setPreviewTunnelUrl] = useState11(null);
2220
+ const [tunnelHandle, setTunnelHandle] = useState11(null);
2221
+ const [previewTunnelHandle, setPreviewTunnelHandle] = useState11(null);
2222
+ const [devServerHandle, setDevServerHandle] = useState11(null);
2068
2223
  const shuttingDown = useRef(false);
2069
2224
  const useTunnel = options.tunnel !== false;
2070
2225
  useEffect6(() => {
@@ -2149,7 +2304,7 @@ var DevApp = ({ token, userId, orgId, options = {} }) => {
2149
2304
  console.log("[dev] Done");
2150
2305
  process.exit(0);
2151
2306
  };
2152
- useInput9((input, key) => {
2307
+ useInput10((input, key) => {
2153
2308
  if (input === "c" && key.ctrl) {
2154
2309
  if (state === "running") {
2155
2310
  handleQuit();
@@ -2160,7 +2315,7 @@ var DevApp = ({ token, userId, orgId, options = {} }) => {
2160
2315
  });
2161
2316
  if (state === "setup" && devContext) {
2162
2317
  if (!devContext.appId || !devContext.extensionId) {
2163
- return /* @__PURE__ */ jsx16(
2318
+ return /* @__PURE__ */ jsx17(
2164
2319
  DevSetup,
2165
2320
  {
2166
2321
  token,
@@ -2172,7 +2327,7 @@ var DevApp = ({ token, userId, orgId, options = {} }) => {
2172
2327
  return null;
2173
2328
  }
2174
2329
  if (state === "running" && devContext && resolvedContext) {
2175
- return /* @__PURE__ */ jsx16(
2330
+ return /* @__PURE__ */ jsx17(
2176
2331
  DevDashboard,
2177
2332
  {
2178
2333
  previewTunnelUrl,
@@ -2192,13 +2347,13 @@ var DevApp = ({ token, userId, orgId, options = {} }) => {
2192
2347
  if (state === "stopping") {
2193
2348
  return null;
2194
2349
  }
2195
- return /* @__PURE__ */ jsx16(Box16, { children: /* @__PURE__ */ jsx16(Text16, { children: "Loading..." }) });
2350
+ return /* @__PURE__ */ jsx17(Box17, { children: /* @__PURE__ */ jsx17(Text17, { children: "Loading..." }) });
2196
2351
  };
2197
2352
 
2198
2353
  // src/components/AIScaffold.tsx
2199
- import { Box as Box17, Text as Text17, useApp as useApp2 } from "ink";
2354
+ import { Box as Box18, Text as Text18, useApp as useApp2 } from "ink";
2200
2355
  import Spinner4 from "ink-spinner";
2201
- import { useState as useState11, useEffect as useEffect7 } from "react";
2356
+ import { useState as useState12, useEffect as useEffect7 } from "react";
2202
2357
 
2203
2358
  // src/lib/aiDocs.ts
2204
2359
  import { existsSync, readFileSync } from "fs";
@@ -2251,12 +2406,12 @@ var downloadAndExtractAiDocs = async (targetDir, version2) => {
2251
2406
  };
2252
2407
 
2253
2408
  // src/components/AIScaffold.tsx
2254
- import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
2409
+ import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
2255
2410
  var AIScaffold = ({ version: version2 }) => {
2256
2411
  const { exit } = useApp2();
2257
- const [state, setState] = useState11("validating");
2258
- const [files, setFiles] = useState11([]);
2259
- const [errorMessage, setErrorMessage] = useState11("");
2412
+ const [state, setState] = useState12("validating");
2413
+ const [files, setFiles] = useState12([]);
2414
+ const [errorMessage, setErrorMessage] = useState12("");
2260
2415
  useEffect7(() => {
2261
2416
  const run = async () => {
2262
2417
  const projectDir = process.cwd();
@@ -2280,35 +2435,35 @@ var AIScaffold = ({ version: version2 }) => {
2280
2435
  };
2281
2436
  run();
2282
2437
  }, []);
2283
- return /* @__PURE__ */ jsxs16(Box17, { flexDirection: "column", children: [
2284
- /* @__PURE__ */ jsx17(Banner, {}),
2285
- /* @__PURE__ */ jsxs16(StepShell, { title: "AI Editor Config", children: [
2286
- state === "validating" && /* @__PURE__ */ jsxs16(Box17, { gap: 1, children: [
2287
- /* @__PURE__ */ jsx17(Text17, { color: "cyan", children: /* @__PURE__ */ jsx17(Spinner4, { type: "dots" }) }),
2288
- /* @__PURE__ */ jsx17(Text17, { children: "Checking project..." })
2438
+ return /* @__PURE__ */ jsxs17(Box18, { flexDirection: "column", children: [
2439
+ /* @__PURE__ */ jsx18(Banner, {}),
2440
+ /* @__PURE__ */ jsxs17(StepShell, { title: "AI Editor Config", children: [
2441
+ state === "validating" && /* @__PURE__ */ jsxs17(Box18, { gap: 1, children: [
2442
+ /* @__PURE__ */ jsx18(Text18, { color: "cyan", children: /* @__PURE__ */ jsx18(Spinner4, { type: "dots" }) }),
2443
+ /* @__PURE__ */ jsx18(Text18, { children: "Checking project..." })
2289
2444
  ] }),
2290
- state === "downloading" && /* @__PURE__ */ jsxs16(Box17, { gap: 1, children: [
2291
- /* @__PURE__ */ jsx17(Text17, { color: "cyan", children: /* @__PURE__ */ jsx17(Spinner4, { type: "dots" }) }),
2292
- /* @__PURE__ */ jsxs16(Text17, { children: [
2445
+ state === "downloading" && /* @__PURE__ */ jsxs17(Box18, { gap: 1, children: [
2446
+ /* @__PURE__ */ jsx18(Text18, { color: "cyan", children: /* @__PURE__ */ jsx18(Spinner4, { type: "dots" }) }),
2447
+ /* @__PURE__ */ jsxs17(Text18, { children: [
2293
2448
  "Downloading AI editor configs (",
2294
2449
  version2,
2295
2450
  ")..."
2296
2451
  ] })
2297
2452
  ] }),
2298
- state === "done" && /* @__PURE__ */ jsxs16(Box17, { flexDirection: "column", gap: 1, children: [
2299
- /* @__PURE__ */ jsxs16(Box17, { gap: 1, children: [
2300
- /* @__PURE__ */ jsx17(Text17, { color: "green", bold: true, children: "\u2714" }),
2301
- /* @__PURE__ */ jsxs16(Text17, { bold: true, children: [
2453
+ state === "done" && /* @__PURE__ */ jsxs17(Box18, { flexDirection: "column", gap: 1, children: [
2454
+ /* @__PURE__ */ jsxs17(Box18, { gap: 1, children: [
2455
+ /* @__PURE__ */ jsx18(Text18, { color: "green", bold: true, children: "\u2714" }),
2456
+ /* @__PURE__ */ jsxs17(Text18, { bold: true, children: [
2302
2457
  "AI editor configs installed (",
2303
2458
  files.length,
2304
2459
  " files)"
2305
2460
  ] })
2306
2461
  ] }),
2307
- /* @__PURE__ */ jsx17(Box17, { flexDirection: "column", marginLeft: 2, children: files.map((f) => /* @__PURE__ */ jsx17(Text17, { dimColor: true, children: f }, f)) })
2462
+ /* @__PURE__ */ jsx18(Box18, { flexDirection: "column", marginLeft: 2, children: files.map((f) => /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: f }, f)) })
2308
2463
  ] }),
2309
- state === "error" && /* @__PURE__ */ jsxs16(Box17, { gap: 1, children: [
2310
- /* @__PURE__ */ jsx17(Text17, { color: "red", children: "\u2716" }),
2311
- /* @__PURE__ */ jsx17(Text17, { children: errorMessage })
2464
+ state === "error" && /* @__PURE__ */ jsxs17(Box18, { gap: 1, children: [
2465
+ /* @__PURE__ */ jsx18(Text18, { color: "red", children: "\u2716" }),
2466
+ /* @__PURE__ */ jsx18(Text18, { children: errorMessage })
2312
2467
  ] })
2313
2468
  ] })
2314
2469
  ] });
@@ -2316,10 +2471,10 @@ var AIScaffold = ({ version: version2 }) => {
2316
2471
 
2317
2472
  // src/components/AuthLogin.tsx
2318
2473
  import { createServer } from "http";
2319
- import { Box as Box18, Text as Text18, useApp as useApp3 } from "ink";
2474
+ import { Box as Box19, Text as Text19, useApp as useApp3 } from "ink";
2320
2475
  import Spinner5 from "ink-spinner";
2321
2476
  import open from "open";
2322
- import { useState as useState12, useEffect as useEffect8 } from "react";
2477
+ import { useState as useState13, useEffect as useEffect8 } from "react";
2323
2478
 
2324
2479
  // src/lib/auth.ts
2325
2480
  import { readFile as readFile3, writeFile as writeFile4, mkdir as mkdir2, unlink } from "fs/promises";
@@ -2372,7 +2527,7 @@ var getToken = async () => {
2372
2527
  };
2373
2528
 
2374
2529
  // src/components/AuthLogin.tsx
2375
- import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
2530
+ import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
2376
2531
  var LOGIN_TIMEOUT_MS = 5 * 60 * 1e3;
2377
2532
  var callbackPage = (heading, sub, redirectUrl) => `<!DOCTYPE html>
2378
2533
  <html><head><meta charset="utf-8"><title>Stackable CLI</title>
@@ -2383,11 +2538,11 @@ ${redirectUrl ? `<script>(function(){var s=3,el=document.getElementById('h');fun
2383
2538
  </body></html>`;
2384
2539
  var AuthLogin = ({ dashboardUrl }) => {
2385
2540
  const { exit } = useApp3();
2386
- const [state, setState] = useState12("waiting");
2387
- const [loginUrl, setLoginUrl] = useState12("");
2388
- const [userIdLabel, setUserIdLabel] = useState12("");
2389
- const [orgIdLabel, setOrgIdLabel] = useState12("");
2390
- const [errorMessage, setErrorMessage] = useState12("");
2541
+ const [state, setState] = useState13("waiting");
2542
+ const [loginUrl, setLoginUrl] = useState13("");
2543
+ const [userIdLabel, setUserIdLabel] = useState13("");
2544
+ const [orgIdLabel, setOrgIdLabel] = useState13("");
2545
+ const [errorMessage, setErrorMessage] = useState13("");
2391
2546
  useEffect8(() => {
2392
2547
  let server;
2393
2548
  let timeout;
@@ -2463,38 +2618,38 @@ var AuthLogin = ({ dashboardUrl }) => {
2463
2618
  server?.close();
2464
2619
  };
2465
2620
  }, []);
2466
- return /* @__PURE__ */ jsxs17(Box18, { flexDirection: "column", children: [
2467
- /* @__PURE__ */ jsx18(Banner, {}),
2468
- /* @__PURE__ */ jsxs17(StepShell, { title: "Authenticate with Stackable", children: [
2469
- state === "waiting" && /* @__PURE__ */ jsxs17(Box18, { flexDirection: "column", gap: 1, children: [
2470
- /* @__PURE__ */ jsxs17(Box18, { gap: 1, children: [
2471
- /* @__PURE__ */ jsx18(Text18, { color: "cyan", children: /* @__PURE__ */ jsx18(Spinner5, { type: "dots" }) }),
2472
- /* @__PURE__ */ jsx18(Text18, { children: "Waiting for browser authentication..." })
2621
+ return /* @__PURE__ */ jsxs18(Box19, { flexDirection: "column", children: [
2622
+ /* @__PURE__ */ jsx19(Banner, {}),
2623
+ /* @__PURE__ */ jsxs18(StepShell, { title: "Authenticate with Stackable", children: [
2624
+ state === "waiting" && /* @__PURE__ */ jsxs18(Box19, { flexDirection: "column", gap: 1, children: [
2625
+ /* @__PURE__ */ jsxs18(Box19, { gap: 1, children: [
2626
+ /* @__PURE__ */ jsx19(Text19, { color: "cyan", children: /* @__PURE__ */ jsx19(Spinner5, { type: "dots" }) }),
2627
+ /* @__PURE__ */ jsx19(Text19, { children: "Waiting for browser authentication..." })
2473
2628
  ] }),
2474
- loginUrl && /* @__PURE__ */ jsxs17(Text18, { dimColor: true, children: [
2629
+ loginUrl && /* @__PURE__ */ jsxs18(Text19, { dimColor: true, children: [
2475
2630
  " ",
2476
2631
  loginUrl
2477
2632
  ] })
2478
2633
  ] }),
2479
- state === "success" && /* @__PURE__ */ jsxs17(Box18, { flexDirection: "column", gap: 1, children: [
2480
- /* @__PURE__ */ jsxs17(Box18, { flexDirection: "column", children: [
2481
- /* @__PURE__ */ jsxs17(Box18, { gap: 2, children: [
2482
- /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: "User:" }),
2483
- /* @__PURE__ */ jsx18(Text18, { color: "cyan", children: userIdLabel })
2634
+ state === "success" && /* @__PURE__ */ jsxs18(Box19, { flexDirection: "column", gap: 1, children: [
2635
+ /* @__PURE__ */ jsxs18(Box19, { flexDirection: "column", children: [
2636
+ /* @__PURE__ */ jsxs18(Box19, { gap: 2, children: [
2637
+ /* @__PURE__ */ jsx19(Text19, { dimColor: true, children: "User:" }),
2638
+ /* @__PURE__ */ jsx19(Text19, { color: "cyan", children: userIdLabel })
2484
2639
  ] }),
2485
- /* @__PURE__ */ jsxs17(Box18, { gap: 2, children: [
2486
- /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: "Org: " }),
2487
- /* @__PURE__ */ jsx18(Text18, { color: "cyan", children: orgIdLabel })
2640
+ /* @__PURE__ */ jsxs18(Box19, { gap: 2, children: [
2641
+ /* @__PURE__ */ jsx19(Text19, { dimColor: true, children: "Org: " }),
2642
+ /* @__PURE__ */ jsx19(Text19, { color: "cyan", children: orgIdLabel })
2488
2643
  ] })
2489
2644
  ] }),
2490
- /* @__PURE__ */ jsxs17(Box18, { gap: 1, children: [
2491
- /* @__PURE__ */ jsx18(Text18, { color: "green", bold: true, children: "\u2714" }),
2492
- /* @__PURE__ */ jsx18(Text18, { bold: true, children: "Authenticated" })
2645
+ /* @__PURE__ */ jsxs18(Box19, { gap: 1, children: [
2646
+ /* @__PURE__ */ jsx19(Text19, { color: "green", bold: true, children: "\u2714" }),
2647
+ /* @__PURE__ */ jsx19(Text19, { bold: true, children: "Authenticated" })
2493
2648
  ] })
2494
2649
  ] }),
2495
- state === "error" && /* @__PURE__ */ jsxs17(Box18, { gap: 1, children: [
2496
- /* @__PURE__ */ jsx18(Text18, { color: "red", children: "\u2716" }),
2497
- /* @__PURE__ */ jsx18(Text18, { children: errorMessage })
2650
+ state === "error" && /* @__PURE__ */ jsxs18(Box19, { gap: 1, children: [
2651
+ /* @__PURE__ */ jsx19(Text19, { color: "red", children: "\u2716" }),
2652
+ /* @__PURE__ */ jsx19(Text19, { children: errorMessage })
2498
2653
  ] })
2499
2654
  ] })
2500
2655
  ] });
@@ -2502,70 +2657,70 @@ var AuthLogin = ({ dashboardUrl }) => {
2502
2657
 
2503
2658
  // src/components/AuthLogout.tsx
2504
2659
  import { useEffect as useEffect9 } from "react";
2505
- import { Box as Box19, Text as Text19, useApp as useApp4 } from "ink";
2506
- import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
2660
+ import { Box as Box20, Text as Text20, useApp as useApp4 } from "ink";
2661
+ import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
2507
2662
  var AuthLogout = () => {
2508
2663
  const { exit } = useApp4();
2509
2664
  useEffect9(() => {
2510
2665
  exit();
2511
2666
  }, [exit]);
2512
- return /* @__PURE__ */ jsxs18(Box19, { flexDirection: "column", children: [
2513
- /* @__PURE__ */ jsx19(Banner, {}),
2514
- /* @__PURE__ */ jsx19(StepShell, { title: "Authenticate with Stackable", children: /* @__PURE__ */ jsxs18(Box19, { gap: 1, children: [
2515
- /* @__PURE__ */ jsx19(Text19, { color: "green", bold: true, children: "\u2714" }),
2516
- /* @__PURE__ */ jsx19(Text19, { bold: true, children: "Logged out" })
2667
+ return /* @__PURE__ */ jsxs19(Box20, { flexDirection: "column", children: [
2668
+ /* @__PURE__ */ jsx20(Banner, {}),
2669
+ /* @__PURE__ */ jsx20(StepShell, { title: "Authenticate with Stackable", children: /* @__PURE__ */ jsxs19(Box20, { gap: 1, children: [
2670
+ /* @__PURE__ */ jsx20(Text20, { color: "green", bold: true, children: "\u2714" }),
2671
+ /* @__PURE__ */ jsx20(Text20, { bold: true, children: "Logged out" })
2517
2672
  ] }) })
2518
2673
  ] });
2519
2674
  };
2520
2675
 
2521
2676
  // src/components/AuthStatus.tsx
2522
2677
  import { useEffect as useEffect10 } from "react";
2523
- import { useApp as useApp5, Box as Box20, Text as Text20 } from "ink";
2524
- import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
2678
+ import { useApp as useApp5, Box as Box21, Text as Text21 } from "ink";
2679
+ import { jsx as jsx21, jsxs as jsxs20 } from "react/jsx-runtime";
2525
2680
  var AuthStatus = ({ state, userId, orgId, expiry }) => {
2526
2681
  const { exit } = useApp5();
2527
2682
  useEffect10(() => {
2528
2683
  exit();
2529
2684
  }, [exit]);
2530
- return /* @__PURE__ */ jsxs19(Box20, { flexDirection: "column", children: [
2531
- /* @__PURE__ */ jsx20(Banner, {}),
2532
- /* @__PURE__ */ jsxs19(StepShell, { title: "Authenticate with Stackable", children: [
2533
- state === "authenticated" && /* @__PURE__ */ jsxs19(Box20, { flexDirection: "column", gap: 1, children: [
2534
- /* @__PURE__ */ jsxs19(Box20, { flexDirection: "column", children: [
2535
- /* @__PURE__ */ jsxs19(Box20, { gap: 2, children: [
2536
- /* @__PURE__ */ jsx20(Text20, { dimColor: true, children: "User:" }),
2537
- /* @__PURE__ */ jsx20(Text20, { color: "cyan", children: userId })
2685
+ return /* @__PURE__ */ jsxs20(Box21, { flexDirection: "column", children: [
2686
+ /* @__PURE__ */ jsx21(Banner, {}),
2687
+ /* @__PURE__ */ jsxs20(StepShell, { title: "Authenticate with Stackable", children: [
2688
+ state === "authenticated" && /* @__PURE__ */ jsxs20(Box21, { flexDirection: "column", gap: 1, children: [
2689
+ /* @__PURE__ */ jsxs20(Box21, { flexDirection: "column", children: [
2690
+ /* @__PURE__ */ jsxs20(Box21, { gap: 2, children: [
2691
+ /* @__PURE__ */ jsx21(Text21, { dimColor: true, children: "User:" }),
2692
+ /* @__PURE__ */ jsx21(Text21, { color: "cyan", children: userId })
2538
2693
  ] }),
2539
- /* @__PURE__ */ jsxs19(Box20, { gap: 2, children: [
2540
- /* @__PURE__ */ jsx20(Text20, { dimColor: true, children: "Org: " }),
2541
- /* @__PURE__ */ jsx20(Text20, { color: "cyan", children: orgId })
2694
+ /* @__PURE__ */ jsxs20(Box21, { gap: 2, children: [
2695
+ /* @__PURE__ */ jsx21(Text21, { dimColor: true, children: "Org: " }),
2696
+ /* @__PURE__ */ jsx21(Text21, { color: "cyan", children: orgId })
2542
2697
  ] }),
2543
- expiry && /* @__PURE__ */ jsxs19(Box20, { gap: 2, children: [
2544
- /* @__PURE__ */ jsx20(Text20, { dimColor: true, children: "Exp: " }),
2545
- /* @__PURE__ */ jsx20(Text20, { color: "cyan", children: expiry.toLocaleDateString() })
2698
+ expiry && /* @__PURE__ */ jsxs20(Box21, { gap: 2, children: [
2699
+ /* @__PURE__ */ jsx21(Text21, { dimColor: true, children: "Exp: " }),
2700
+ /* @__PURE__ */ jsx21(Text21, { color: "cyan", children: expiry.toLocaleDateString() })
2546
2701
  ] })
2547
2702
  ] }),
2548
- /* @__PURE__ */ jsxs19(Box20, { gap: 1, children: [
2549
- /* @__PURE__ */ jsx20(Text20, { color: "green", bold: true, children: "\u2714" }),
2550
- /* @__PURE__ */ jsx20(Text20, { bold: true, children: "Authenticated" })
2703
+ /* @__PURE__ */ jsxs20(Box21, { gap: 1, children: [
2704
+ /* @__PURE__ */ jsx21(Text21, { color: "green", bold: true, children: "\u2714" }),
2705
+ /* @__PURE__ */ jsx21(Text21, { bold: true, children: "Authenticated" })
2551
2706
  ] })
2552
2707
  ] }),
2553
- state === "expired" && /* @__PURE__ */ jsxs19(Box20, { flexDirection: "column", gap: 1, children: [
2554
- /* @__PURE__ */ jsxs19(Box20, { gap: 1, children: [
2555
- /* @__PURE__ */ jsx20(Text20, { color: "red", children: "\u2716" }),
2556
- /* @__PURE__ */ jsxs19(Text20, { children: [
2708
+ state === "expired" && /* @__PURE__ */ jsxs20(Box21, { flexDirection: "column", gap: 1, children: [
2709
+ /* @__PURE__ */ jsxs20(Box21, { gap: 1, children: [
2710
+ /* @__PURE__ */ jsx21(Text21, { color: "red", children: "\u2716" }),
2711
+ /* @__PURE__ */ jsxs20(Text21, { children: [
2557
2712
  "Session expired",
2558
2713
  expiry ? ` (${expiry.toLocaleDateString()})` : ""
2559
2714
  ] })
2560
2715
  ] }),
2561
- /* @__PURE__ */ jsx20(Text20, { dimColor: true, children: "Run `stackable-app-extension auth login` to re-authenticate." })
2716
+ /* @__PURE__ */ jsx21(Text21, { dimColor: true, children: "Run `stackable-app-extension auth login` to re-authenticate." })
2562
2717
  ] }),
2563
- state === "not-logged-in" && /* @__PURE__ */ jsxs19(Box20, { flexDirection: "column", gap: 1, children: [
2564
- /* @__PURE__ */ jsxs19(Box20, { gap: 1, children: [
2565
- /* @__PURE__ */ jsx20(Text20, { color: "red", children: "\u2716" }),
2566
- /* @__PURE__ */ jsx20(Text20, { children: "Not logged in" })
2718
+ state === "not-logged-in" && /* @__PURE__ */ jsxs20(Box21, { flexDirection: "column", gap: 1, children: [
2719
+ /* @__PURE__ */ jsxs20(Box21, { gap: 1, children: [
2720
+ /* @__PURE__ */ jsx21(Text21, { color: "red", children: "\u2716" }),
2721
+ /* @__PURE__ */ jsx21(Text21, { children: "Not logged in" })
2567
2722
  ] }),
2568
- /* @__PURE__ */ jsx20(Text20, { dimColor: true, children: "Run `stackable-app-extension auth login`" })
2723
+ /* @__PURE__ */ jsx21(Text21, { dimColor: true, children: "Run `stackable-app-extension auth login`" })
2569
2724
  ] })
2570
2725
  ] })
2571
2726
  ] });
@@ -2619,7 +2774,7 @@ var checkForUpdate = (currentVersion) => {
2619
2774
  };
2620
2775
 
2621
2776
  // src/index.tsx
2622
- import { jsx as jsx21 } from "react/jsx-runtime";
2777
+ import { jsx as jsx22 } from "react/jsx-runtime";
2623
2778
  var require2 = createRequire(import.meta.url);
2624
2779
  var { version } = require2("../package.json");
2625
2780
  checkForUpdate(version);
@@ -2632,20 +2787,20 @@ var ensureToken = async () => {
2632
2787
  const message = err instanceof Error ? err.message : String(err);
2633
2788
  const isExpired = message.toLowerCase().includes("expired");
2634
2789
  render(
2635
- /* @__PURE__ */ jsx21(AuthStatus, { state: isExpired ? "expired" : "not-logged-in" })
2790
+ /* @__PURE__ */ jsx22(AuthStatus, { state: isExpired ? "expired" : "not-logged-in" })
2636
2791
  );
2637
2792
  return null;
2638
2793
  }
2639
2794
  };
2640
2795
  program.name("stackable-app-extension").description("Stackable Labs - App Extension developer CLI").version(version);
2641
- program.command("create" /* CREATE */).description("Create a new Extension project").argument("[name]", "Extension project name").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) => {
2796
+ program.command("create" /* CREATE */).description("Create a new Extension project").argument("[name]", "Extension project name").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) => {
2642
2797
  const auth2 = await ensureToken();
2643
2798
  if (!auth2) {
2644
2799
  return;
2645
2800
  }
2646
2801
  const { token, userId, orgId } = auth2;
2647
2802
  render(
2648
- /* @__PURE__ */ jsx21(
2803
+ /* @__PURE__ */ jsx22(
2649
2804
  App,
2650
2805
  {
2651
2806
  command: "create" /* CREATE */,
@@ -2665,7 +2820,7 @@ program.command("scaffold" /* SCAFFOLD */).description("Scaffold a local project
2665
2820
  }
2666
2821
  const { token, userId, orgId } = auth2;
2667
2822
  render(
2668
- /* @__PURE__ */ jsx21(
2823
+ /* @__PURE__ */ jsx22(
2669
2824
  App,
2670
2825
  {
2671
2826
  command: "scaffold" /* SCAFFOLD */,
@@ -2684,7 +2839,7 @@ program.command("update" /* UPDATE */).description("Update an existing Extension
2684
2839
  }
2685
2840
  const { token, userId, orgId } = auth2;
2686
2841
  render(
2687
- /* @__PURE__ */ jsx21(
2842
+ /* @__PURE__ */ jsx22(
2688
2843
  App,
2689
2844
  {
2690
2845
  command: "update" /* UPDATE */,
@@ -2704,7 +2859,7 @@ program.command("dev" /* DEV */).description("Start dev servers with a public tu
2704
2859
  }
2705
2860
  const { token, userId, orgId } = auth2;
2706
2861
  render(
2707
- /* @__PURE__ */ jsx21(
2862
+ /* @__PURE__ */ jsx22(
2708
2863
  DevApp,
2709
2864
  {
2710
2865
  options,
@@ -2719,17 +2874,17 @@ program.command("dev" /* DEV */).description("Start dev servers with a public tu
2719
2874
  var DASHBOARD_URL = process.env.ADMIN_DASHBOARD_URL ?? "https://admin.stackablelabs.io";
2720
2875
  var auth = program.command("auth").description("Manage CLI authentication");
2721
2876
  auth.command("login").description("Authenticate with Stackable via browser").action(async () => {
2722
- render(/* @__PURE__ */ jsx21(AuthLogin, { dashboardUrl: DASHBOARD_URL }));
2877
+ render(/* @__PURE__ */ jsx22(AuthLogin, { dashboardUrl: DASHBOARD_URL }));
2723
2878
  });
2724
2879
  auth.command("logout").description("Clear stored CLI credentials").action(async () => {
2725
2880
  await clearAuthState();
2726
- render(/* @__PURE__ */ jsx21(AuthLogout, {}));
2881
+ render(/* @__PURE__ */ jsx22(AuthLogout, {}));
2727
2882
  });
2728
2883
  auth.command("status").description("Show current authentication status").action(async () => {
2729
2884
  const state = await readAuthState();
2730
2885
  if (!state) {
2731
2886
  render(
2732
- /* @__PURE__ */ jsx21(AuthStatus, { state: "not-logged-in" })
2887
+ /* @__PURE__ */ jsx22(AuthStatus, { state: "not-logged-in" })
2733
2888
  );
2734
2889
  return;
2735
2890
  }
@@ -2737,11 +2892,11 @@ auth.command("status").description("Show current authentication status").action(
2737
2892
  const payload = JSON.parse(Buffer.from(payloadB64, "base64url").toString());
2738
2893
  const expiry = payload.exp ? new Date(payload.exp * 1e3) : null;
2739
2894
  if (expiry && Date.now() >= expiry.getTime()) {
2740
- render(/* @__PURE__ */ jsx21(AuthStatus, { state: "expired", expiry }));
2895
+ render(/* @__PURE__ */ jsx22(AuthStatus, { state: "expired", expiry }));
2741
2896
  return;
2742
2897
  }
2743
2898
  render(
2744
- /* @__PURE__ */ jsx21(
2899
+ /* @__PURE__ */ jsx22(
2745
2900
  AuthStatus,
2746
2901
  {
2747
2902
  state: "authenticated",
@@ -2754,6 +2909,6 @@ auth.command("status").description("Show current authentication status").action(
2754
2909
  });
2755
2910
  var ai = program.command("ai").description("AI editor configuration tools");
2756
2911
  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) => {
2757
- render(/* @__PURE__ */ jsx21(AIScaffold, { version: options.version }));
2912
+ render(/* @__PURE__ */ jsx22(AIScaffold, { version: options.version }));
2758
2913
  });
2759
2914
  program.parse(process.argv.filter((arg) => arg !== "--"));