@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.
- package/README.md +39 -2
- package/dist/index.js +16 -11
- 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: `
|
|
29
|
-
| 5 | **Preview Port** | Dev server port for the Preview host (default: `
|
|
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 =
|
|
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:
|
|
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 || "
|
|
1070
|
-
const previewPort = parseInt(devLocalEnv.VITE_PREVIEW_PORT || env.VITE_PREVIEW_PORT || "
|
|
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 || '
|
|
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) :
|
|
1519
|
+
options?.extensionPort ? parseInt(options.extensionPort, 10) : 6543
|
|
1517
1520
|
);
|
|
1518
1521
|
const [previewPort, setPreviewPort] = useState8(
|
|
1519
|
-
options?.previewPort ? parseInt(options.previewPort, 10) :
|
|
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:
|
|
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:
|
|
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) => {
|