@stackable-labs/cli-app-extension 1.10.3 → 1.12.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 +39 -2
  2. package/dist/index.js +16 -11
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -25,8 +25,8 @@ When run without all required flags, the CLI guides you through a step-by-step p
25
25
  | 1 | **App** | Select the App you are building an Extension for (fetched live from the API) |
26
26
  | 2 | **Name** | Display name for your Extension (e.g. `My Commerce Extension`) |
27
27
  | 3 | **Targets** | Multiselect from the Surface targets/slots exposed by the selected app |
28
- | 4 | **Extension Port** | Dev server port for the Extension (default: `5173`) |
29
- | 5 | **Preview Port** | Dev server port for the Preview host (default: `5174`) |
28
+ | 4 | **Extension Port** | Dev server port for the Extension (default: `6543`) |
29
+ | 5 | **Preview Port** | Dev server port for the Preview host (default: `6544`) |
30
30
  | 6 | **Directory** | Output directory path (default: kebab-case of name) |
31
31
  | 7 | **Confirm** | Review all selections before scaffolding |
32
32
 
@@ -76,6 +76,43 @@ my-extension/
76
76
  └── package.json
77
77
  ```
78
78
 
79
+ ## `dev` Command
80
+
81
+ Start local dev servers with a public Cloudflare tunnel for testing:
82
+
83
+ ```bash
84
+ pnpm preview
85
+ ```
86
+
87
+ ```
88
+ Usage: stackable-app-extension dev [options]
89
+
90
+ Options:
91
+ --dir <path> Project root (default: cwd)
92
+ --extension-port <port> Override Extension port
93
+ --preview-port <port> Override Preview port
94
+ --no-tunnel Skip tunnel, just run vite dev
95
+ -h, --help Display help
96
+ ```
97
+
98
+ The `dev` command:
99
+ 1. Reads `.env.stackable` for cached App/Extension context (prompts if missing)
100
+ 2. Starts Cloudflare tunnels for both extension and preview servers
101
+ 3. Starts Vite dev servers with hot-reload
102
+ 4. Displays a **Host App Query Param** you can append to your host app URL to test against the real deployed host
103
+
104
+ ### Host App Override
105
+
106
+ The dashboard displays a query param like:
107
+
108
+ ```
109
+ ?_stackable_dev=ext-123%3Ahttps%3A%2F%2Fabc.trycloudflare.com
110
+ ```
111
+
112
+ Append this to your deployed host app URL to override the extension's `bundleUrl` in your browser session only. The `@stackable-labs/embeddables` SDK detects this param and loads from your tunnel instead of the production bundle. No DB changes, no shared state — each developer gets isolated overrides.
113
+
114
+ > **Note:** The `dev` command never updates the `bundleUrl` in the database. It is purely local.
115
+
79
116
  ## Development Workflow
80
117
 
81
118
  ```bash
package/dist/index.js CHANGED
@@ -287,7 +287,7 @@ import { Box as Box6, Text as Text6, useFocus as useFocus2, useFocusManager as u
287
287
  import TextInput3 from "ink-text-input";
288
288
  import { useState as useState3 } from "react";
289
289
  import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
290
- var DEFAULT_EXTENSION_PORT = 5173;
290
+ var DEFAULT_EXTENSION_PORT = 6543;
291
291
  var DEFAULT_PREVIEW_PORT = DEFAULT_EXTENSION_PORT + 1;
292
292
  var FieldRow = ({ label, value, onChange, onSubmit, onConfirm, placeholder, autoFocus, isFirst, isLast }) => {
293
293
  const { isFocused } = useFocus2({ autoFocus });
@@ -622,7 +622,7 @@ var UpdateSettingsPrompt = ({
622
622
  label: "Bundle URL",
623
623
  value: bundleUrlValue,
624
624
  onChange: setBundleUrlValue,
625
- placeholder: "http://localhost:5173",
625
+ placeholder: "http://localhost:6543",
626
626
  onSubmitAll: handleSubmitAll
627
627
  }
628
628
  ),
@@ -1066,8 +1066,8 @@ var readDevContext = async (projectRoot) => {
1066
1066
  } catch {
1067
1067
  }
1068
1068
  const devLocalEnv = await readEnvFile(join(projectRoot, ".env.development.local"));
1069
- const extensionPort = parseInt(devLocalEnv.VITE_EXTENSION_PORT || env.VITE_EXTENSION_PORT || "5173", 10);
1070
- const previewPort = parseInt(devLocalEnv.VITE_PREVIEW_PORT || env.VITE_PREVIEW_PORT || "5174", 10);
1069
+ const extensionPort = parseInt(devLocalEnv.VITE_EXTENSION_PORT || env.VITE_EXTENSION_PORT || "6543", 10);
1070
+ const previewPort = parseInt(devLocalEnv.VITE_PREVIEW_PORT || env.VITE_PREVIEW_PORT || "6544", 10);
1071
1071
  return {
1072
1072
  projectRoot,
1073
1073
  extensionName,
@@ -1297,9 +1297,12 @@ var rewritePreviewApp = async (rootDir, targets, permissions) => {
1297
1297
  "Permission",
1298
1298
  includeInvoke ? "ActionInvokePayload" : "",
1299
1299
  includeDataQuery ? "ApiRequest" : "",
1300
+ "FetchRequest",
1301
+ "FetchResponse",
1300
1302
  includeToast ? "ToastPayload" : ""
1301
1303
  ].filter(Boolean);
1302
1304
  const handlers = [];
1305
+ handlers.push(" 'data.fetch': async (_extensionId: string, payload: FetchRequest): Promise<FetchResponse> => {\n const response = await fetch(payload.url, {\n method: payload.method ?? 'GET',\n headers: payload.headers,\n ...(payload.body !== undefined ? { body: JSON.stringify(payload.body) } : {}),\n })\n const text = await response.text()\n let data: unknown = null\n try {\n data = text ? JSON.parse(text) : null\n } catch {\n data = text\n }\n\n return {\n status: response.status,\n ok: response.ok,\n data,\n }\n },");
1303
1306
  if (includeDataQuery) {
1304
1307
  handlers.push(" 'data.query': async (_payload: ApiRequest) => {\n return mockData\n },");
1305
1308
  }
@@ -1330,7 +1333,7 @@ const extensions: ExtensionRegistryEntry[] = [
1330
1333
  {
1331
1334
  id: manifest.name.toLowerCase().replace(/\\s+/g, '-'),
1332
1335
  manifest,
1333
- bundleUrl: import.meta.env.VITE_EXTENSION_BUNDLE_URL || \`http://localhost:\${import.meta.env.VITE_EXTENSION_PORT || '5173'}\`,
1336
+ bundleUrl: import.meta.env.VITE_EXTENSION_BUNDLE_URL || \`http://localhost:\${import.meta.env.VITE_EXTENSION_PORT || '6543'}\`,
1334
1337
  enabled: true,
1335
1338
  },
1336
1339
  ]
@@ -1513,10 +1516,10 @@ var App = ({ command, initialName, initialExtensionId, options }) => {
1513
1516
  );
1514
1517
  const [selectedApp, setSelectedApp] = useState8(null);
1515
1518
  const [extensionPort, setExtensionPort] = useState8(
1516
- options?.extensionPort ? parseInt(options.extensionPort, 10) : 5173
1519
+ options?.extensionPort ? parseInt(options.extensionPort, 10) : 6543
1517
1520
  );
1518
1521
  const [previewPort, setPreviewPort] = useState8(
1519
- options?.previewPort ? parseInt(options.previewPort, 10) : 5174
1522
+ options?.previewPort ? parseInt(options.previewPort, 10) : 6544
1520
1523
  );
1521
1524
  const [outputDir, setOutputDir] = useState8("");
1522
1525
  const [progressSteps, setProgressSteps] = useState8(PROGRESS_STEPS[command]);
@@ -1628,7 +1631,8 @@ var App = ({ command, initialName, initialExtensionId, options }) => {
1628
1631
  name,
1629
1632
  version: resolvedVersion,
1630
1633
  targets,
1631
- permissions: derivePermissions2(targets)
1634
+ permissions: derivePermissions2(targets),
1635
+ allowedDomains: []
1632
1636
  },
1633
1637
  bundleUrl: bundleUrl || void 0,
1634
1638
  enabled
@@ -1656,7 +1660,8 @@ var App = ({ command, initialName, initialExtensionId, options }) => {
1656
1660
  name,
1657
1661
  version: "0.0.0",
1658
1662
  targets,
1659
- permissions: derivePermissions2(targets)
1663
+ permissions: derivePermissions2(targets),
1664
+ allowedDomains: []
1660
1665
  },
1661
1666
  bundleUrl: `http://localhost:${extensionPort}`
1662
1667
  });
@@ -2190,10 +2195,10 @@ var require2 = createRequire(import.meta.url);
2190
2195
  var { version } = require2("../package.json");
2191
2196
  checkForUpdate(version);
2192
2197
  program.name("stackable-app-extension").description("Stackable Labs - App Extension developer CLI").version(version);
2193
- 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 dev server port").option("--skip-install", "Skip package manager install").option("--skip-git", "Skip git initialization").action((name, options) => {
2198
+ 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((name, options) => {
2194
2199
  render(/* @__PURE__ */ jsx17(App, { command: "create" /* CREATE */, initialName: name, options }));
2195
2200
  });
2196
- 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 dev server port").option("--skip-install", "Skip package manager install").option("--skip-git", "Skip git initialization").action((options) => {
2201
+ program.command("scaffold" /* SCAFFOLD */).description("Scaffold a local project from an existing Extension").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((options) => {
2197
2202
  render(/* @__PURE__ */ jsx17(App, { command: "scaffold" /* SCAFFOLD */, options }));
2198
2203
  });
2199
2204
  program.command("update" /* UPDATE */).description("Update an existing Extension").argument("[extensionId]", "Extension ID to update").option("--app-id <id>", "Skip App selection").option("--name <name>", "New Extension name").option("--targets <targets>", "Comma-separated target slots (validated against app)").option("--bundle-url <url>", "New bundle URL").option("--enabled <bool>", "Enable/disable Extension").option("--set-version <version>", "Explicit version (skips auto-compute)").action((extensionId, options) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackable-labs/cli-app-extension",
3
- "version": "1.10.3",
3
+ "version": "1.12.0",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "bin": {