@greatstore/cli 0.0.15 → 0.0.17

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 CHANGED
@@ -3,64 +3,85 @@
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.17 — 2026-05-28
7
+
8
+ ### Added
9
+ - Each command now prints a one-line upgrade notice when a newer
10
+ `@greatstore/cli` is available on npm.
11
+
12
+ ## 0.0.16 — 2026-05-28
13
+
14
+ ### Changed
15
+ - Simplified error messages.
16
+
6
17
  ## 0.0.15 — 2026-05-24
7
18
 
8
19
  ### Added
9
- - `gs init <name>` scaffold now declares the four GreatStore-injected lifecycle props (`onSendMessage`, `onCallTool`, `onClose`, and the new `onError(message)`) on the `Props` interface with inline comments. `onError` lets a component surface in-flight failures (failed fetch, host-page action rejected, invalid host state) back to the in-store AI so it can apologize or self-correct on its next turn. Render-time crashes are reported automatically by the GreatStore error boundary — `onError` is for *expected* failures the boundary can't catch.
20
+ - Scaffolded `component.tsx` now declares the four injected lifecycle
21
+ props (`onSendMessage`, `onCallTool`, `onClose`, `onError`) on
22
+ `Props`. Use `onError(message)` to report expected failures (failed
23
+ fetch, host action rejected, invalid host state) so the AI can
24
+ recover on its next turn. Render-time crashes are reported for you.
10
25
 
11
26
  ## 0.0.14 — 2026-05-24
12
27
 
13
28
  ### Changed
14
- - `gs build` output is now whitespace-minified. Vite's lib mode in `es` format only minifies identifiers / syntax and preserves all whitespace + `/* @__PURE__ */` annotations for downstream tree-shaking. Since the bundles are loaded directly by the browser at runtime (no downstream bundler), the CLI now post-processes each `bundle.js` with `esbuild.transform` to collapse whitespace and strip legal comments — typically ~50% smaller files, cheaper to host and faster to ship.
29
+ - `gs build` output is now whitespace-minified — typically ~50% smaller.
15
30
 
16
31
  ## 0.0.13 — 2026-05-24
17
32
 
18
33
  ### Changed
19
- - `gs build` now prints a closing hint naming the next steps (`gs push`, then `gs publish <name>`) so AI assistants driving the CLI don't stop at "built" and leave the change unshipped.
34
+ - `gs build` prints the next-step hint (`gs push`, then `gs publish`).
20
35
 
21
36
  ## 0.0.12 — 2026-05-24
22
37
 
23
38
  ### Fixed
24
- - `gs build` failed with `Error: build is not a function` because `require.resolve("vite")` lands on Vite 5's deprecated CJS entry. The CLI now walks `vite/package.json#exports.import` to load the ESM build, and falls back to the CJS-default shape if a host package ships only CJS.
39
+ - `gs build` failing to load Vite in some setups.
25
40
 
26
41
  ## 0.0.11 — 2026-05-24
27
42
 
28
43
  ### Added
29
- - Multi-component projects: scaffold one root, then add N components under `components/<name>/`. `gs init` (no args) writes the project root; `gs init <name>` adds a component (auto-scaffolds the root if missing).
30
- - `gs build [<name>]` compiles every `components/<name>/bundle.js` via the project's local Vite. Externals + runtime shim paths now live in the CLI, so future versions can adjust them without a re-scaffold.
31
- - `gs push` (no args) hashes each component against `.gssync.json` and uploads only the changed ones.
32
- - `gs pull` (no args, or `*`) batch-pulls every remote component. Components with uncommitted local edits are skipped with a warning; `--force` overwrites.
33
- - Public `CHANGELOG.md`. `gs --version` now prints the most recent entries.
44
+ - Multi-component projects. `gs init` (no args) scaffolds the project
45
+ root; `gs init <name>` adds a component under `components/<name>/`.
46
+ - `gs build [<name>]` compiles every `components/<name>/bundle.js`.
47
+ - `gs push` (no args) uploads only the components that changed.
48
+ - `gs pull` (no args, or `*`) downloads every component. Locally
49
+ edited components are skipped; pass `--force` to overwrite.
50
+ - Public `CHANGELOG.md`; `gs --version` prints recent entries.
34
51
 
35
52
  ### Changed
36
- - A project folder ships to exactly one store. Only `gs init` accepts `--store`; every other command reads the slug from `.gsrc`. The legacy single-component layout is rejected with a migration hint.
37
- - `gs init` errors on a fresh root without `--store <slug>` (no placeholder slug is written). On an existing root, passing `--store` errors.
38
- - `gs init` no longer writes `build.mjs`. Scaffolded `package.json` scripts run `gs build`.
53
+ - A project folder ships to exactly one store. Only `gs init` accepts
54
+ `--store`; every other command reads the slug from `.gsrc`. The old
55
+ single-component layout is rejected with a migration hint.
56
+ - `gs init` requires `--store <slug>` for a fresh root, and rejects
57
+ `--store` on an existing root.
58
+ - `gs init` no longer writes `build.mjs` — scripts call `gs build`.
39
59
 
40
60
  ## 0.0.10 — 2026-05-23
41
61
 
42
62
  ### Changed
43
- - The OAuth callback tab opened by `gs login` auto-closes once credentials are persisted.
63
+ - The sign-in browser tab auto-closes once `gs login` finishes.
44
64
 
45
65
  ## 0.0.9 — 2026-05-23
46
66
 
47
67
  ### Changed
48
- - `gs init` scaffold writes a `displayName` into the generated manifest so the admin Builder UI has a friendlier label.
68
+ - Scaffolded manifests include a `displayName` so the admin UI has a
69
+ friendlier label.
49
70
 
50
71
  ## 0.0.8 — 2026-05-23
51
72
 
52
73
  ### Changed
53
- - `gs push` and `gs publish` print a permalink to the component's card in the admin Builder panel.
74
+ - `gs push` and `gs publish` print a link to view the component.
54
75
 
55
76
  ## 0.0.6 — 2026-05-23
56
77
 
57
78
  ### Changed
58
- - `gs --version` reads the version from `cli/package.json` at build time so it can't drift from the published release.
79
+ - `gs --version` reads from the published package version.
59
80
 
60
81
  ## 0.0.4 — 2026-05-23
61
82
 
62
83
  ### Changed
63
- - Scaffolded projects produce browser-ready bundles (React + runtime shim wired up).
84
+ - Scaffolded projects produce browser-ready bundles out of the box.
64
85
 
65
86
  ## 0.0.3 — 2026-05-23
66
87
 
@@ -70,4 +91,4 @@ follows [Keep a Changelog](https://keepachangelog.com/).
70
91
  ## 0.0.2 — 2026-05-23
71
92
 
72
93
  ### Fixed
73
- - Read the nav OAuth callback parameter as `code` instead of `token`.
94
+ - 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 manifest + bundle to disk. |
33
- | `gs push [<name>] [--manifest path] [--bundle path]` | Upload a new draft revision. |
34
- | `gs publish <name> [--version N]` | Promote a draft (or roll back to a historical version) to live.|
35
- | `gs unpublish <name>` | Clear the live pointer; draft + history stay. |
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("Timed out waiting for sign-in. Re-run `gs login`.")));
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("State mismatch on OAuth callback \u2014 possible CSRF, login aborted.")));
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(`Sign-in failed: ${error}`)));
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, detail) {
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 = "Not logged in. Run `gs login`.") {
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
- const message = parsed.error?.trim() || parsed.detail?.trim() || text.trim() || `HTTP ${res.status}`;
386
- throw new HttpError(res.status, message, parsed.code, parsed.detail);
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("Access token expired \u2014 re-running sign-in.\n");
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
- `Published ${name} (live = v${data.live_version}). View: ${data.permalink}
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}. The draft and version history are retained.
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}. (R2 objects retained; history preserved.)
965
+ process.stdout.write(`Deleted ${name}.
966
966
  `);
967
967
  }
968
968
  function prompt(question) {
@@ -1132,10 +1132,10 @@ interface Props {
1132
1132
  // Tell the in-store AI something went wrong so it can apologize or
1133
1133
  // self-correct on its next turn. Use for *expected* failures inside
1134
1134
  // async handlers (failed fetch, host-page action rejected, invalid
1135
- // host state). Render-time crashes are reported automatically by
1136
- // the GreatStore error boundary \u2014 you don't need a try/catch just
1137
- // to forward exceptions. The message is read by the AI, not the
1138
- // shopper, so write it like a short engineering note.
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
1139
  onError: (message: string) => void;
1140
1140
  }
1141
1141
 
@@ -1320,7 +1320,7 @@ async function buildCommand(args) {
1320
1320
  }
1321
1321
  process.stdout.write(
1322
1322
  `
1323
- Built locally \u2014 nothing uploaded yet. Next step is \`gs push\` to upload the draft, then \`gs publish <name>\` to make it live. 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).
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).
1324
1324
  `
1325
1325
  );
1326
1326
  }
@@ -1448,9 +1448,104 @@ function recentChangelog(text, minItems = 15) {
1448
1448
  return out.join("\n").trimEnd();
1449
1449
  }
1450
1450
 
1451
+ // src/version-check.ts
1452
+ import * as fs8 from "fs";
1453
+ import * as os2 from "os";
1454
+ import * as path8 from "path";
1455
+ var NOTICE = "GreatStore CLI is still in early beta and we constantly pushing new features and security update. It is advised to update to the latest version whenever possible.";
1456
+ var PKG = "@greatstore/cli";
1457
+ var REGISTRY_URL = `https://registry.npmjs.org/${PKG}/latest`;
1458
+ var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
1459
+ var FETCH_TIMEOUT_MS = 1e3;
1460
+ async function maybePrintUpgradeNotice(current, opts = {}) {
1461
+ if (!/^\d+\.\d+\.\d+/.test(current)) return;
1462
+ if (/-dev\b/.test(current)) return;
1463
+ const home = opts.home ?? os2.homedir();
1464
+ const now = opts.now ?? Date.now;
1465
+ const write2 = opts.write ?? ((line) => process.stderr.write(line));
1466
+ const latest = await resolveLatest({
1467
+ home,
1468
+ now: now(),
1469
+ ...opts.fetcher ? { fetcher: opts.fetcher } : {}
1470
+ });
1471
+ if (!latest) return;
1472
+ if (compareSemver(latest, current) <= 0) return;
1473
+ write2(`${NOTICE} (installed: v${current}, latest: v${latest})
1474
+
1475
+ `);
1476
+ }
1477
+ async function resolveLatest(opts) {
1478
+ const cached = readCache(opts.home);
1479
+ if (cached && opts.now - cached.checkedAt < CACHE_TTL_MS) {
1480
+ return cached.latest;
1481
+ }
1482
+ const fetcher = opts.fetcher ?? fetchLatest;
1483
+ const fresh = await fetcher();
1484
+ if (fresh) {
1485
+ writeCache(opts.home, { latest: fresh, checkedAt: opts.now });
1486
+ return fresh;
1487
+ }
1488
+ return cached?.latest ?? null;
1489
+ }
1490
+ async function fetchLatest() {
1491
+ const ctrl = new AbortController();
1492
+ const timer = setTimeout(() => ctrl.abort(), FETCH_TIMEOUT_MS);
1493
+ try {
1494
+ const res = await fetch(REGISTRY_URL, {
1495
+ signal: ctrl.signal,
1496
+ headers: { accept: "application/json" }
1497
+ });
1498
+ if (!res.ok) return null;
1499
+ const json = await res.json();
1500
+ return typeof json.version === "string" ? json.version : null;
1501
+ } catch {
1502
+ return null;
1503
+ } finally {
1504
+ clearTimeout(timer);
1505
+ }
1506
+ }
1507
+ function cachePath(home) {
1508
+ return path8.join(home, ".greatstore", "version-check.json");
1509
+ }
1510
+ function readCache(home) {
1511
+ try {
1512
+ const raw = fs8.readFileSync(cachePath(home), "utf8");
1513
+ const parsed = JSON.parse(raw);
1514
+ if (typeof parsed.latest === "string" && typeof parsed.checkedAt === "number") {
1515
+ return { latest: parsed.latest, checkedAt: parsed.checkedAt };
1516
+ }
1517
+ } catch {
1518
+ }
1519
+ return null;
1520
+ }
1521
+ function writeCache(home, cache) {
1522
+ try {
1523
+ const file = cachePath(home);
1524
+ fs8.mkdirSync(path8.dirname(file), { recursive: true });
1525
+ fs8.writeFileSync(file, JSON.stringify(cache));
1526
+ } catch {
1527
+ }
1528
+ }
1529
+ function compareSemver(a, b) {
1530
+ const pa = parseVer(a);
1531
+ const pb = parseVer(b);
1532
+ if (!pa || !pb) return 0;
1533
+ for (let i = 0; i < 3; i++) {
1534
+ const av = pa[i];
1535
+ const bv = pb[i];
1536
+ if (av !== bv) return av - bv;
1537
+ }
1538
+ return 0;
1539
+ }
1540
+ function parseVer(v) {
1541
+ const m = v.match(/^(\d+)\.(\d+)\.(\d+)/);
1542
+ if (!m) return null;
1543
+ return [Number(m[1]), Number(m[2]), Number(m[3])];
1544
+ }
1545
+
1451
1546
  // src/index.ts
1452
- var VERSION = true ? "0.0.15" : "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.15 \u2014 2026-05-24\n\n### Added\n- `gs init <name>` scaffold now declares the four GreatStore-injected lifecycle props (`onSendMessage`, `onCallTool`, `onClose`, and the new `onError(message)`) on the `Props` interface with inline comments. `onError` lets a component surface in-flight failures (failed fetch, host-page action rejected, invalid host state) back to the in-store AI so it can apologize or self-correct on its next turn. Render-time crashes are reported automatically by the GreatStore error boundary \u2014 `onError` is for *expected* failures the boundary can't catch.\n\n## 0.0.14 \u2014 2026-05-24\n\n### Changed\n- `gs build` output is now whitespace-minified. Vite's lib mode in `es` format only minifies identifiers / syntax and preserves all whitespace + `/* @__PURE__ */` annotations for downstream tree-shaking. Since the bundles are loaded directly by the browser at runtime (no downstream bundler), the CLI now post-processes each `bundle.js` with `esbuild.transform` to collapse whitespace and strip legal comments \u2014 typically ~50% smaller files, cheaper to host and faster to ship.\n\n## 0.0.13 \u2014 2026-05-24\n\n### Changed\n- `gs build` now prints a closing hint naming the next steps (`gs push`, then `gs publish <name>`) so AI assistants driving the CLI don't stop at \"built\" and leave the change unshipped.\n\n## 0.0.12 \u2014 2026-05-24\n\n### Fixed\n- `gs build` failed with `Error: build is not a function` because `require.resolve(\"vite\")` lands on Vite 5's deprecated CJS entry. The CLI now walks `vite/package.json#exports.import` to load the ESM build, and falls back to the CJS-default shape if a host package ships only CJS.\n\n## 0.0.11 \u2014 2026-05-24\n\n### Added\n- Multi-component projects: scaffold one root, then add N components under `components/<name>/`. `gs init` (no args) writes the project root; `gs init <name>` adds a component (auto-scaffolds the root if missing).\n- `gs build [<name>]` \u2014 compiles every `components/<name>/bundle.js` via the project's local Vite. Externals + runtime shim paths now live in the CLI, so future versions can adjust them without a re-scaffold.\n- `gs push` (no args) hashes each component against `.gssync.json` and uploads only the changed ones.\n- `gs pull` (no args, or `*`) batch-pulls every remote component. Components with uncommitted local edits are skipped with a warning; `--force` overwrites.\n- Public `CHANGELOG.md`. `gs --version` now prints the most recent entries.\n\n### Changed\n- A project folder ships to exactly one store. Only `gs init` accepts `--store`; every other command reads the slug from `.gsrc`. The legacy single-component layout is rejected with a migration hint.\n- `gs init` errors on a fresh root without `--store <slug>` (no placeholder slug is written). On an existing root, passing `--store` errors.\n- `gs init` no longer writes `build.mjs`. Scaffolded `package.json` scripts run `gs build`.\n\n## 0.0.10 \u2014 2026-05-23\n\n### Changed\n- The OAuth callback tab opened by `gs login` auto-closes once credentials are persisted.\n\n## 0.0.9 \u2014 2026-05-23\n\n### Changed\n- `gs init` scaffold writes a `displayName` into the generated manifest so the admin Builder UI has a friendlier label.\n\n## 0.0.8 \u2014 2026-05-23\n\n### Changed\n- `gs push` and `gs publish` print a permalink to the component's card in the admin Builder panel.\n\n## 0.0.6 \u2014 2026-05-23\n\n### Changed\n- `gs --version` reads the version from `cli/package.json` at build time so it can't drift from the published release.\n\n## 0.0.4 \u2014 2026-05-23\n\n### Changed\n- Scaffolded projects produce browser-ready bundles (React + runtime shim wired up).\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- Read the nav OAuth callback parameter as `code` instead of `token`.\n" : "";
1547
+ var VERSION = true ? "0.0.17" : "0.0.0-dev";
1548
+ 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.17 \u2014 2026-05-28\n\n### Added\n- Each command now prints a one-line upgrade notice when a newer\n `@greatstore/cli` is available on npm.\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" : "";
1454
1549
  var HELP = `gs \u2014 GreatStore CLI (v${VERSION})
1455
1550
 
1456
1551
  Usage:
@@ -1489,6 +1584,7 @@ Environment:
1489
1584
  async function main() {
1490
1585
  const argv = process.argv.slice(2);
1491
1586
  const parsed = parseArgs(argv);
1587
+ await maybePrintUpgradeNotice(VERSION);
1492
1588
  if (flagBool(parsed.flags, "version")) {
1493
1589
  process.stdout.write(`gs v${VERSION}
1494
1590
 
@@ -1547,12 +1643,8 @@ main().then((code) => process.exit(code)).catch((err) => {
1547
1643
  process.stderr.write(`${err.message}
1548
1644
  `);
1549
1645
  } else if (err instanceof HttpError) {
1550
- process.stderr.write(`Error (HTTP ${err.status}): ${err.message}
1551
- `);
1552
- if (err.detail && err.detail !== err.message) {
1553
- process.stderr.write(` ${err.detail}
1646
+ process.stderr.write(`Error: ${err.message}
1554
1647
  `);
1555
- }
1556
1648
  } else if (err instanceof StoreResolutionError || err instanceof LoopbackError) {
1557
1649
  process.stderr.write(`Error: ${err.message}
1558
1650
  `);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@greatstore/cli",
3
- "version": "0.0.15",
3
+ "version": "0.0.17",
4
4
  "description": "CLI for authoring and shipping GreatStore custom components.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",