@greatstore/cli 0.0.14 → 0.0.16
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/CHANGELOG.md +37 -17
- package/README.md +4 -11
- package/dist/cli.js +45 -31
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,59 +3,79 @@
|
|
|
3
3
|
All notable changes to `@greatstore/cli` are recorded here. The format
|
|
4
4
|
follows [Keep a Changelog](https://keepachangelog.com/).
|
|
5
5
|
|
|
6
|
+
## 0.0.16 — 2026-05-28
|
|
7
|
+
|
|
8
|
+
### Changed
|
|
9
|
+
- Simplified error messages.
|
|
10
|
+
|
|
11
|
+
## 0.0.15 — 2026-05-24
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- Scaffolded `component.tsx` now declares the four injected lifecycle
|
|
15
|
+
props (`onSendMessage`, `onCallTool`, `onClose`, `onError`) on
|
|
16
|
+
`Props`. Use `onError(message)` to report expected failures (failed
|
|
17
|
+
fetch, host action rejected, invalid host state) so the AI can
|
|
18
|
+
recover on its next turn. Render-time crashes are reported for you.
|
|
19
|
+
|
|
6
20
|
## 0.0.14 — 2026-05-24
|
|
7
21
|
|
|
8
22
|
### Changed
|
|
9
|
-
- `gs build` output is now whitespace-minified
|
|
23
|
+
- `gs build` output is now whitespace-minified — typically ~50% smaller.
|
|
10
24
|
|
|
11
25
|
## 0.0.13 — 2026-05-24
|
|
12
26
|
|
|
13
27
|
### Changed
|
|
14
|
-
- `gs build`
|
|
28
|
+
- `gs build` prints the next-step hint (`gs push`, then `gs publish`).
|
|
15
29
|
|
|
16
30
|
## 0.0.12 — 2026-05-24
|
|
17
31
|
|
|
18
32
|
### Fixed
|
|
19
|
-
- `gs build`
|
|
33
|
+
- `gs build` failing to load Vite in some setups.
|
|
20
34
|
|
|
21
35
|
## 0.0.11 — 2026-05-24
|
|
22
36
|
|
|
23
37
|
### Added
|
|
24
|
-
- Multi-component projects
|
|
25
|
-
|
|
26
|
-
- `gs
|
|
27
|
-
- `gs
|
|
28
|
-
-
|
|
38
|
+
- Multi-component projects. `gs init` (no args) scaffolds the project
|
|
39
|
+
root; `gs init <name>` adds a component under `components/<name>/`.
|
|
40
|
+
- `gs build [<name>]` — compiles every `components/<name>/bundle.js`.
|
|
41
|
+
- `gs push` (no args) uploads only the components that changed.
|
|
42
|
+
- `gs pull` (no args, or `*`) downloads every component. Locally
|
|
43
|
+
edited components are skipped; pass `--force` to overwrite.
|
|
44
|
+
- Public `CHANGELOG.md`; `gs --version` prints recent entries.
|
|
29
45
|
|
|
30
46
|
### Changed
|
|
31
|
-
- A project folder ships to exactly one store. Only `gs init` accepts
|
|
32
|
-
|
|
33
|
-
-
|
|
47
|
+
- A project folder ships to exactly one store. Only `gs init` accepts
|
|
48
|
+
`--store`; every other command reads the slug from `.gsrc`. The old
|
|
49
|
+
single-component layout is rejected with a migration hint.
|
|
50
|
+
- `gs init` requires `--store <slug>` for a fresh root, and rejects
|
|
51
|
+
`--store` on an existing root.
|
|
52
|
+
- `gs init` no longer writes `build.mjs` — scripts call `gs build`.
|
|
34
53
|
|
|
35
54
|
## 0.0.10 — 2026-05-23
|
|
36
55
|
|
|
37
56
|
### Changed
|
|
38
|
-
- The
|
|
57
|
+
- The sign-in browser tab auto-closes once `gs login` finishes.
|
|
39
58
|
|
|
40
59
|
## 0.0.9 — 2026-05-23
|
|
41
60
|
|
|
42
61
|
### Changed
|
|
43
|
-
-
|
|
62
|
+
- Scaffolded manifests include a `displayName` so the admin UI has a
|
|
63
|
+
friendlier label.
|
|
44
64
|
|
|
45
65
|
## 0.0.8 — 2026-05-23
|
|
46
66
|
|
|
47
67
|
### Changed
|
|
48
|
-
- `gs push` and `gs publish` print a
|
|
68
|
+
- `gs push` and `gs publish` print a link to view the component.
|
|
49
69
|
|
|
50
70
|
## 0.0.6 — 2026-05-23
|
|
51
71
|
|
|
52
72
|
### Changed
|
|
53
|
-
- `gs --version` reads
|
|
73
|
+
- `gs --version` reads from the published package version.
|
|
54
74
|
|
|
55
75
|
## 0.0.4 — 2026-05-23
|
|
56
76
|
|
|
57
77
|
### Changed
|
|
58
|
-
- Scaffolded projects produce browser-ready bundles
|
|
78
|
+
- Scaffolded projects produce browser-ready bundles out of the box.
|
|
59
79
|
|
|
60
80
|
## 0.0.3 — 2026-05-23
|
|
61
81
|
|
|
@@ -65,4 +85,4 @@ follows [Keep a Changelog](https://keepachangelog.com/).
|
|
|
65
85
|
## 0.0.2 — 2026-05-23
|
|
66
86
|
|
|
67
87
|
### Fixed
|
|
68
|
-
-
|
|
88
|
+
- Sign-in callback parameter handling.
|
package/README.md
CHANGED
|
@@ -13,13 +13,6 @@ gs push
|
|
|
13
13
|
gs publish my-widget
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
## Release channels
|
|
17
|
-
|
|
18
|
-
- `npm install -g @greatstore/cli` — the stable production release (`@latest`).
|
|
19
|
-
- `npm install -g @greatstore/cli@beta` — the prerelease channel for testing in-flight changes before they cut over to `@latest`.
|
|
20
|
-
|
|
21
|
-
Cut a beta by bumping `cli/package.json` to `<x.y.z>-beta.<n>` (e.g. `0.0.12-beta.0`), then push tag `cli-v0.0.12-beta.0`. The publish workflow extracts the prerelease identifier from the version and publishes under that dist-tag, so `@latest` is unaffected. Drop the `-beta.<n>` suffix and tag again to promote to `@latest`.
|
|
22
|
-
|
|
23
16
|
## Commands
|
|
24
17
|
|
|
25
18
|
| Command | What it does |
|
|
@@ -29,10 +22,10 @@ Cut a beta by bumping `cli/package.json` to `<x.y.z>-beta.<n>` (e.g. `0.0.12-bet
|
|
|
29
22
|
| `gs whoami` | Print the identity you're signed in as. |
|
|
30
23
|
| `gs init <name> [--out <dir>] [--store <s>]` | Scaffold a working component project. |
|
|
31
24
|
| `gs list [--json]` | List components in the current store. |
|
|
32
|
-
| `gs pull <name> [--draft\|--live\|--version N] [-o <dir>]` | Download
|
|
33
|
-
| `gs push [<name>] [--manifest path] [--bundle path]` | Upload
|
|
34
|
-
| `gs publish <name> [--version N]` |
|
|
35
|
-
| `gs unpublish <name>` |
|
|
25
|
+
| `gs pull <name> [--draft\|--live\|--version N] [-o <dir>]` | Download a component to disk. |
|
|
26
|
+
| `gs push [<name>] [--manifest path] [--bundle path]` | Upload local changes. |
|
|
27
|
+
| `gs publish <name> [--version N]` | Ship a component (optionally a previous version). |
|
|
28
|
+
| `gs unpublish <name>` | Hide a published component. |
|
|
36
29
|
| `gs delete <name> [--yes]` | Remove the component. |
|
|
37
30
|
|
|
38
31
|
## Store selection
|
package/dist/cli.js
CHANGED
|
@@ -112,7 +112,7 @@ function waitForCallback(server, expectedState, timeoutMs) {
|
|
|
112
112
|
fn();
|
|
113
113
|
};
|
|
114
114
|
const timer = setTimeout(() => {
|
|
115
|
-
settle(() => reject(new LoopbackError("
|
|
115
|
+
settle(() => reject(new LoopbackError("Sign-in timed out. Re-run `gs login`.")));
|
|
116
116
|
}, timeoutMs);
|
|
117
117
|
if (typeof timer.unref === "function") timer.unref();
|
|
118
118
|
server.on("request", (req, res) => {
|
|
@@ -130,21 +130,14 @@ function waitForCallback(server, expectedState, timeoutMs) {
|
|
|
130
130
|
res.writeHead(400, { "content-type": "text/html" });
|
|
131
131
|
res.end(FAILURE_HTML);
|
|
132
132
|
clearTimeout(timer);
|
|
133
|
-
settle(() => reject(new LoopbackError("
|
|
133
|
+
settle(() => reject(new LoopbackError("Sign-in didn't complete. Please try again.")));
|
|
134
134
|
return;
|
|
135
135
|
}
|
|
136
|
-
if (error) {
|
|
136
|
+
if (error || !token) {
|
|
137
137
|
res.writeHead(400, { "content-type": "text/html" });
|
|
138
138
|
res.end(FAILURE_HTML);
|
|
139
139
|
clearTimeout(timer);
|
|
140
|
-
settle(() => reject(new LoopbackError(
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
if (!token) {
|
|
144
|
-
res.writeHead(400, { "content-type": "text/html" });
|
|
145
|
-
res.end(FAILURE_HTML);
|
|
146
|
-
clearTimeout(timer);
|
|
147
|
-
settle(() => reject(new LoopbackError("Callback missing `code` query parameter.")));
|
|
140
|
+
settle(() => reject(new LoopbackError("Sign-in failed. Please try again.")));
|
|
148
141
|
return;
|
|
149
142
|
}
|
|
150
143
|
res.writeHead(200, { "content-type": "text/html" });
|
|
@@ -317,16 +310,15 @@ function stripTrailingSlash(s) {
|
|
|
317
310
|
|
|
318
311
|
// src/http.ts
|
|
319
312
|
var HttpError = class extends Error {
|
|
320
|
-
constructor(status, message, code
|
|
313
|
+
constructor(status, message, code) {
|
|
321
314
|
super(message);
|
|
322
315
|
this.status = status;
|
|
323
316
|
this.code = code;
|
|
324
|
-
this.detail = detail;
|
|
325
317
|
this.name = "HttpError";
|
|
326
318
|
}
|
|
327
319
|
};
|
|
328
320
|
var AuthRequiredError = class extends Error {
|
|
329
|
-
constructor(message = "
|
|
321
|
+
constructor(message = "Sign in first. Run `gs login`.") {
|
|
330
322
|
super(message);
|
|
331
323
|
this.name = "AuthRequiredError";
|
|
332
324
|
}
|
|
@@ -382,11 +374,21 @@ async function sendOnce(url, options, accessToken) {
|
|
|
382
374
|
parsed = JSON.parse(text);
|
|
383
375
|
} catch {
|
|
384
376
|
}
|
|
385
|
-
|
|
386
|
-
|
|
377
|
+
throw new HttpError(res.status, genericMessage(res.status), parsed.code);
|
|
378
|
+
}
|
|
379
|
+
function genericMessage(status) {
|
|
380
|
+
if (status === 401) return "Sign-in needed. Run `gs login`.";
|
|
381
|
+
if (status === 403) return "Not authorized for this component or store.";
|
|
382
|
+
if (status === 404) return "Not found.";
|
|
383
|
+
if (status === 409) return "Conflict \u2014 refresh and try again.";
|
|
384
|
+
if (status === 413) return "Upload too large.";
|
|
385
|
+
if (status === 429) return "Too many requests \u2014 wait a moment and retry.";
|
|
386
|
+
if (status >= 500) return "Server error \u2014 try again shortly.";
|
|
387
|
+
if (status >= 400) return "Request rejected.";
|
|
388
|
+
return "Unexpected response.";
|
|
387
389
|
}
|
|
388
390
|
async function reauthenticate() {
|
|
389
|
-
process.stderr.write("
|
|
391
|
+
process.stderr.write("Sign-in expired \u2014 opening browser.\n");
|
|
390
392
|
try {
|
|
391
393
|
const { token } = await captureLoopbackToken({ navBaseUrl: navBase() });
|
|
392
394
|
const next = buildCredentials(token);
|
|
@@ -928,10 +930,8 @@ async function publishCommand(args) {
|
|
|
928
930
|
body = {};
|
|
929
931
|
}
|
|
930
932
|
const data = await request(url, { method: "POST", body });
|
|
931
|
-
process.stdout.write(
|
|
932
|
-
|
|
933
|
-
`
|
|
934
|
-
);
|
|
933
|
+
process.stdout.write(`Published ${name} (v${data.live_version}). ${data.permalink}
|
|
934
|
+
`);
|
|
935
935
|
}
|
|
936
936
|
|
|
937
937
|
// src/commands/unpublish.ts
|
|
@@ -941,7 +941,7 @@ async function unpublishCommand(args) {
|
|
|
941
941
|
const slug = requireProjectStore();
|
|
942
942
|
const url = `${apiBaseFor(slug)}/api/builder/components/${encodeURIComponent(name)}/unpublish`;
|
|
943
943
|
await request(url, { method: "POST", body: {} });
|
|
944
|
-
process.stdout.write(`Unpublished ${name}.
|
|
944
|
+
process.stdout.write(`Unpublished ${name}.
|
|
945
945
|
`);
|
|
946
946
|
}
|
|
947
947
|
|
|
@@ -962,7 +962,7 @@ async function deleteCommand(args) {
|
|
|
962
962
|
}
|
|
963
963
|
const url = `${apiBaseFor(slug)}/api/builder/components/${encodeURIComponent(name)}`;
|
|
964
964
|
await request(url, { method: "DELETE" });
|
|
965
|
-
process.stdout.write(`Deleted ${name}.
|
|
965
|
+
process.stdout.write(`Deleted ${name}.
|
|
966
966
|
`);
|
|
967
967
|
}
|
|
968
968
|
function prompt(question) {
|
|
@@ -1118,7 +1118,25 @@ function component(name) {
|
|
|
1118
1118
|
return `import React from "react";
|
|
1119
1119
|
|
|
1120
1120
|
interface Props {
|
|
1121
|
+
// ---- Your tool args ----
|
|
1121
1122
|
// Add fields here matching manifest.json#inputSchema.properties.
|
|
1123
|
+
|
|
1124
|
+
// ---- GreatStore-injected lifecycle props (always present) ----
|
|
1125
|
+
// Send text into the chat as if the shopper typed it.
|
|
1126
|
+
onSendMessage: (text: string) => void;
|
|
1127
|
+
// Chain into another remote-component tool by name.
|
|
1128
|
+
onCallTool: (name: string, args: Record<string, unknown>) => void;
|
|
1129
|
+
// Dismiss the host slot (over-input clears the overlay, fullscreen
|
|
1130
|
+
// reverts the pane, inline is a no-op).
|
|
1131
|
+
onClose: () => void;
|
|
1132
|
+
// Tell the in-store AI something went wrong so it can apologize or
|
|
1133
|
+
// self-correct on its next turn. Use for *expected* failures inside
|
|
1134
|
+
// async handlers (failed fetch, host-page action rejected, invalid
|
|
1135
|
+
// host state). Render-time crashes are caught and reported for you
|
|
1136
|
+
// \u2014 you don't need a try/catch just to forward exceptions. The
|
|
1137
|
+
// message is read by the AI, not the shopper, so write it like a
|
|
1138
|
+
// short engineering note.
|
|
1139
|
+
onError: (message: string) => void;
|
|
1122
1140
|
}
|
|
1123
1141
|
|
|
1124
1142
|
export default function ${pascal(name)}(_props: Props): React.ReactElement {
|
|
@@ -1302,7 +1320,7 @@ async function buildCommand(args) {
|
|
|
1302
1320
|
}
|
|
1303
1321
|
process.stdout.write(
|
|
1304
1322
|
`
|
|
1305
|
-
Built locally \u2014 nothing uploaded yet. Next
|
|
1323
|
+
Built locally \u2014 nothing uploaded yet. Next: \`gs push\` to upload, then \`gs publish <name>\` to ship. If you're an AI assistant: confirm with the user before running these (or just run them if they already asked you to ship end-to-end).
|
|
1306
1324
|
`
|
|
1307
1325
|
);
|
|
1308
1326
|
}
|
|
@@ -1431,8 +1449,8 @@ function recentChangelog(text, minItems = 15) {
|
|
|
1431
1449
|
}
|
|
1432
1450
|
|
|
1433
1451
|
// src/index.ts
|
|
1434
|
-
var VERSION = true ? "0.0.
|
|
1435
|
-
var CHANGELOG = true ? "# Changelog\n\nAll notable changes to `@greatstore/cli` are recorded here. The format\nfollows [Keep a Changelog](https://keepachangelog.com/).\n\n## 0.0.
|
|
1452
|
+
var VERSION = true ? "0.0.16" : "0.0.0-dev";
|
|
1453
|
+
var CHANGELOG = true ? "# Changelog\n\nAll notable changes to `@greatstore/cli` are recorded here. The format\nfollows [Keep a Changelog](https://keepachangelog.com/).\n\n## 0.0.16 \u2014 2026-05-28\n\n### Changed\n- Simplified error messages.\n\n## 0.0.15 \u2014 2026-05-24\n\n### Added\n- Scaffolded `component.tsx` now declares the four injected lifecycle\n props (`onSendMessage`, `onCallTool`, `onClose`, `onError`) on\n `Props`. Use `onError(message)` to report expected failures (failed\n fetch, host action rejected, invalid host state) so the AI can\n recover on its next turn. Render-time crashes are reported for you.\n\n## 0.0.14 \u2014 2026-05-24\n\n### Changed\n- `gs build` output is now whitespace-minified \u2014 typically ~50% smaller.\n\n## 0.0.13 \u2014 2026-05-24\n\n### Changed\n- `gs build` prints the next-step hint (`gs push`, then `gs publish`).\n\n## 0.0.12 \u2014 2026-05-24\n\n### Fixed\n- `gs build` failing to load Vite in some setups.\n\n## 0.0.11 \u2014 2026-05-24\n\n### Added\n- Multi-component projects. `gs init` (no args) scaffolds the project\n root; `gs init <name>` adds a component under `components/<name>/`.\n- `gs build [<name>]` \u2014 compiles every `components/<name>/bundle.js`.\n- `gs push` (no args) uploads only the components that changed.\n- `gs pull` (no args, or `*`) downloads every component. Locally\n edited components are skipped; pass `--force` to overwrite.\n- Public `CHANGELOG.md`; `gs --version` prints recent entries.\n\n### Changed\n- A project folder ships to exactly one store. Only `gs init` accepts\n `--store`; every other command reads the slug from `.gsrc`. The old\n single-component layout is rejected with a migration hint.\n- `gs init` requires `--store <slug>` for a fresh root, and rejects\n `--store` on an existing root.\n- `gs init` no longer writes `build.mjs` \u2014 scripts call `gs build`.\n\n## 0.0.10 \u2014 2026-05-23\n\n### Changed\n- The sign-in browser tab auto-closes once `gs login` finishes.\n\n## 0.0.9 \u2014 2026-05-23\n\n### Changed\n- Scaffolded manifests include a `displayName` so the admin UI has a\n friendlier label.\n\n## 0.0.8 \u2014 2026-05-23\n\n### Changed\n- `gs push` and `gs publish` print a link to view the component.\n\n## 0.0.6 \u2014 2026-05-23\n\n### Changed\n- `gs --version` reads from the published package version.\n\n## 0.0.4 \u2014 2026-05-23\n\n### Changed\n- Scaffolded projects produce browser-ready bundles out of the box.\n\n## 0.0.3 \u2014 2026-05-23\n\n### Changed\n- Trimmed public README to the essentials.\n\n## 0.0.2 \u2014 2026-05-23\n\n### Fixed\n- Sign-in callback parameter handling.\n" : "";
|
|
1436
1454
|
var HELP = `gs \u2014 GreatStore CLI (v${VERSION})
|
|
1437
1455
|
|
|
1438
1456
|
Usage:
|
|
@@ -1529,12 +1547,8 @@ main().then((code) => process.exit(code)).catch((err) => {
|
|
|
1529
1547
|
process.stderr.write(`${err.message}
|
|
1530
1548
|
`);
|
|
1531
1549
|
} else if (err instanceof HttpError) {
|
|
1532
|
-
process.stderr.write(`Error
|
|
1533
|
-
`);
|
|
1534
|
-
if (err.detail && err.detail !== err.message) {
|
|
1535
|
-
process.stderr.write(` ${err.detail}
|
|
1550
|
+
process.stderr.write(`Error: ${err.message}
|
|
1536
1551
|
`);
|
|
1537
|
-
}
|
|
1538
1552
|
} else if (err instanceof StoreResolutionError || err instanceof LoopbackError) {
|
|
1539
1553
|
process.stderr.write(`Error: ${err.message}
|
|
1540
1554
|
`);
|