@greatstore/cli 0.0.18 → 0.0.20
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 +14 -0
- package/dist/cli.js +134 -44
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,20 @@
|
|
|
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.20 — 2026-05-29
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
- `gs pull`, `gs push`, and `gs publish` now accept several component
|
|
10
|
+
names at once (e.g. `gs publish header footer cart`). Each component
|
|
11
|
+
is reported on its own line and one failure no longer stops the rest.
|
|
12
|
+
|
|
13
|
+
## 0.0.19 — 2026-05-28
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- `gs login` on Windows no longer opens a sign-in URL with parameters
|
|
17
|
+
stripped, which surfaced as a "Missing redirect_uri or state
|
|
18
|
+
parameter" page in the browser.
|
|
19
|
+
|
|
6
20
|
## 0.0.18 — 2026-05-28
|
|
7
21
|
|
|
8
22
|
### Changed
|
package/dist/cli.js
CHANGED
|
@@ -157,8 +157,17 @@ function openInBrowser(url, overrideCmd) {
|
|
|
157
157
|
return;
|
|
158
158
|
}
|
|
159
159
|
try {
|
|
160
|
-
|
|
161
|
-
|
|
160
|
+
let child;
|
|
161
|
+
if (cmd === "start") {
|
|
162
|
+
const command = `start "" "${url}"`;
|
|
163
|
+
child = spawn("cmd.exe", ["/d", "/s", "/c", command], {
|
|
164
|
+
stdio: "ignore",
|
|
165
|
+
detached: true,
|
|
166
|
+
windowsVerbatimArguments: true
|
|
167
|
+
});
|
|
168
|
+
} else {
|
|
169
|
+
child = spawn(cmd, [url], { stdio: "ignore", detached: true });
|
|
170
|
+
}
|
|
162
171
|
child.on("error", () => {
|
|
163
172
|
});
|
|
164
173
|
child.unref();
|
|
@@ -623,21 +632,32 @@ function safeComputeHashes(componentDir) {
|
|
|
623
632
|
async function pullCommand(args) {
|
|
624
633
|
const slug = requireProjectStore();
|
|
625
634
|
const force = flagBool(args.flags, "force");
|
|
626
|
-
const
|
|
635
|
+
const targets = args.positional;
|
|
627
636
|
const root = process.cwd();
|
|
628
|
-
if (
|
|
637
|
+
if (targets.length === 0 || targets.length === 1 && targets[0] === "*") {
|
|
629
638
|
return pullAll({ slug, root, args, force });
|
|
630
639
|
}
|
|
640
|
+
if (targets.length > 1 && flagString(args.flags, "version")) {
|
|
641
|
+
throw new Error(
|
|
642
|
+
"--version is per-component; pass it together with a single `gs pull <name>`."
|
|
643
|
+
);
|
|
644
|
+
}
|
|
631
645
|
ensureComponentsDir(root);
|
|
632
|
-
const
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
646
|
+
const revisionQuery = buildRevisionQuery(args);
|
|
647
|
+
const outcomes = [];
|
|
648
|
+
for (const name of targets) {
|
|
649
|
+
const outcome = await pullOne({
|
|
650
|
+
slug,
|
|
651
|
+
componentDir: path4.join(root, "components", name),
|
|
652
|
+
name,
|
|
653
|
+
revisionQuery,
|
|
654
|
+
force
|
|
655
|
+
});
|
|
656
|
+
outcomes.push(outcome);
|
|
657
|
+
printOutcome(outcome, force);
|
|
658
|
+
}
|
|
659
|
+
if (outcomes.length > 1) printPullSummary(outcomes, slug);
|
|
660
|
+
if (outcomes.some((o) => o.status === "failed")) process.exitCode = 1;
|
|
641
661
|
}
|
|
642
662
|
async function pullAll(opts) {
|
|
643
663
|
const { slug, root, args, force } = opts;
|
|
@@ -668,6 +688,10 @@ async function pullAll(opts) {
|
|
|
668
688
|
outcomes.push(outcome);
|
|
669
689
|
printOutcome(outcome, force);
|
|
670
690
|
}
|
|
691
|
+
printPullSummary(outcomes, slug);
|
|
692
|
+
if (outcomes.some((o) => o.status === "failed")) process.exitCode = 1;
|
|
693
|
+
}
|
|
694
|
+
function printPullSummary(outcomes, slug) {
|
|
671
695
|
const pulled = outcomes.filter((o) => o.status === "pulled").length;
|
|
672
696
|
const skipped = outcomes.filter((o) => o.status === "skipped").length;
|
|
673
697
|
const failed = outcomes.filter((o) => o.status === "failed").length;
|
|
@@ -678,7 +702,6 @@ async function pullAll(opts) {
|
|
|
678
702
|
${summary.join(", ")} (of ${outcomes.length}) \u2190 ${slug}
|
|
679
703
|
`
|
|
680
704
|
);
|
|
681
|
-
if (failed > 0) process.exitCode = 1;
|
|
682
705
|
}
|
|
683
706
|
async function pullOne(opts) {
|
|
684
707
|
const { slug, componentDir, name, revisionQuery, force } = opts;
|
|
@@ -774,25 +797,30 @@ async function pushCommand(args) {
|
|
|
774
797
|
"No components/ directory here. Run `gs init <name>` to scaffold the project root and your first component."
|
|
775
798
|
);
|
|
776
799
|
}
|
|
777
|
-
const named = args.positional
|
|
800
|
+
const named = args.positional;
|
|
778
801
|
const manifestOverride = flagString(args.flags, "manifest");
|
|
779
802
|
const bundleOverride = flagString(args.flags, "bundle");
|
|
780
|
-
if (
|
|
803
|
+
if (named.length !== 1 && (manifestOverride || bundleOverride)) {
|
|
781
804
|
throw new Error(
|
|
782
|
-
"--manifest / --bundle can only be used together with `gs push <name>`."
|
|
805
|
+
"--manifest / --bundle can only be used together with a single `gs push <name>`."
|
|
783
806
|
);
|
|
784
807
|
}
|
|
785
|
-
if (named) {
|
|
786
|
-
const
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
808
|
+
if (named.length > 0) {
|
|
809
|
+
const outcomes2 = [];
|
|
810
|
+
for (const name of named) {
|
|
811
|
+
const outcome = await pushOne({
|
|
812
|
+
slug,
|
|
813
|
+
root,
|
|
814
|
+
name,
|
|
815
|
+
...manifestOverride !== void 0 ? { manifestPath: manifestOverride } : {},
|
|
816
|
+
...bundleOverride !== void 0 ? { bundlePath: bundleOverride } : {},
|
|
817
|
+
force: true
|
|
818
|
+
});
|
|
819
|
+
outcomes2.push(outcome);
|
|
820
|
+
printOutcome2(outcome);
|
|
821
|
+
}
|
|
822
|
+
if (outcomes2.length > 1) printPushSummary(outcomes2, slug);
|
|
823
|
+
if (outcomes2.some((o) => o.status === "failed")) process.exitCode = 1;
|
|
796
824
|
return;
|
|
797
825
|
}
|
|
798
826
|
const names = listLocalComponents(componentsDir);
|
|
@@ -808,6 +836,10 @@ async function pushCommand(args) {
|
|
|
808
836
|
outcomes.push(outcome);
|
|
809
837
|
printOutcome2(outcome);
|
|
810
838
|
}
|
|
839
|
+
printPushSummary(outcomes, slug);
|
|
840
|
+
if (outcomes.some((o) => o.status === "failed")) process.exitCode = 1;
|
|
841
|
+
}
|
|
842
|
+
function printPushSummary(outcomes, slug) {
|
|
811
843
|
const pushed = outcomes.filter((o) => o.status === "pushed").length;
|
|
812
844
|
const unchanged = outcomes.filter((o) => o.status === "unchanged").length;
|
|
813
845
|
const failed = outcomes.filter((o) => o.status === "failed").length;
|
|
@@ -816,7 +848,6 @@ async function pushCommand(args) {
|
|
|
816
848
|
process.stdout.write(`
|
|
817
849
|
${summary.join(", ")} (of ${outcomes.length}) \u2192 ${slug}
|
|
818
850
|
`);
|
|
819
|
-
if (failed > 0) process.exitCode = 1;
|
|
820
851
|
}
|
|
821
852
|
async function pushOne(opts) {
|
|
822
853
|
const { slug, root, name, force } = opts;
|
|
@@ -955,24 +986,83 @@ function printOutcome2(outcome) {
|
|
|
955
986
|
|
|
956
987
|
// src/commands/publish.ts
|
|
957
988
|
async function publishCommand(args) {
|
|
958
|
-
const
|
|
959
|
-
if (
|
|
989
|
+
const names = args.positional;
|
|
990
|
+
if (names.length === 0) {
|
|
991
|
+
throw new Error("Usage: gs publish <name> [<name>...] [--version N]");
|
|
992
|
+
}
|
|
960
993
|
const slug = requireProjectStore();
|
|
961
|
-
const url = `${apiBaseFor(slug)}/api/builder/components/${encodeURIComponent(name)}/publish`;
|
|
962
994
|
const versionFlag = flagString(args.flags, "version");
|
|
963
|
-
let
|
|
995
|
+
let version;
|
|
964
996
|
if (versionFlag !== void 0) {
|
|
997
|
+
if (names.length > 1) {
|
|
998
|
+
throw new Error(
|
|
999
|
+
"--version is per-component; pass it together with a single `gs publish <name>`."
|
|
1000
|
+
);
|
|
1001
|
+
}
|
|
965
1002
|
const n = Number.parseInt(versionFlag, 10);
|
|
966
1003
|
if (!Number.isInteger(n) || n < 1) {
|
|
967
1004
|
throw new Error(`Invalid --version: ${versionFlag}`);
|
|
968
1005
|
}
|
|
969
|
-
|
|
970
|
-
} else {
|
|
971
|
-
body = {};
|
|
1006
|
+
version = n;
|
|
972
1007
|
}
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
1008
|
+
if (names.length === 1) {
|
|
1009
|
+
const name = names[0];
|
|
1010
|
+
const data = await publish(slug, name, version);
|
|
1011
|
+
process.stdout.write(
|
|
1012
|
+
`Published ${name} (v${data.live_version}). ${data.permalink}
|
|
1013
|
+
`
|
|
1014
|
+
);
|
|
1015
|
+
return;
|
|
1016
|
+
}
|
|
1017
|
+
const outcomes = [];
|
|
1018
|
+
for (const name of names) {
|
|
1019
|
+
let outcome;
|
|
1020
|
+
try {
|
|
1021
|
+
const data = await publish(slug, name, version);
|
|
1022
|
+
outcome = {
|
|
1023
|
+
name,
|
|
1024
|
+
status: "published",
|
|
1025
|
+
version: data.live_version,
|
|
1026
|
+
permalink: data.permalink
|
|
1027
|
+
};
|
|
1028
|
+
} catch (err) {
|
|
1029
|
+
outcome = {
|
|
1030
|
+
name,
|
|
1031
|
+
status: "failed",
|
|
1032
|
+
message: err instanceof Error ? err.message : String(err)
|
|
1033
|
+
};
|
|
1034
|
+
}
|
|
1035
|
+
outcomes.push(outcome);
|
|
1036
|
+
printOutcome3(outcome);
|
|
1037
|
+
}
|
|
1038
|
+
const published = outcomes.filter((o) => o.status === "published").length;
|
|
1039
|
+
const failed = outcomes.filter((o) => o.status === "failed").length;
|
|
1040
|
+
const summary = [`${published} published`];
|
|
1041
|
+
if (failed > 0) summary.push(`${failed} failed`);
|
|
1042
|
+
process.stdout.write(
|
|
1043
|
+
`
|
|
1044
|
+
${summary.join(", ")} (of ${outcomes.length}) \u2192 ${slug}
|
|
1045
|
+
`
|
|
1046
|
+
);
|
|
1047
|
+
if (failed > 0) process.exitCode = 1;
|
|
1048
|
+
}
|
|
1049
|
+
async function publish(slug, name, version) {
|
|
1050
|
+
const url = `${apiBaseFor(slug)}/api/builder/components/${encodeURIComponent(name)}/publish`;
|
|
1051
|
+
const body = version !== void 0 ? { version } : {};
|
|
1052
|
+
return request(url, { method: "POST", body });
|
|
1053
|
+
}
|
|
1054
|
+
function printOutcome3(outcome) {
|
|
1055
|
+
if (outcome.status === "published") {
|
|
1056
|
+
process.stdout.write(
|
|
1057
|
+
` published ${outcome.name} v${outcome.version} \u2192 ${outcome.permalink ?? ""}
|
|
1058
|
+
`
|
|
1059
|
+
);
|
|
1060
|
+
return;
|
|
1061
|
+
}
|
|
1062
|
+
process.stdout.write(
|
|
1063
|
+
` failed ${outcome.name}: ${outcome.message ?? "unknown error"}
|
|
1064
|
+
`
|
|
1065
|
+
);
|
|
976
1066
|
}
|
|
977
1067
|
|
|
978
1068
|
// src/commands/unpublish.ts
|
|
@@ -1585,8 +1675,8 @@ function parseVer(v) {
|
|
|
1585
1675
|
}
|
|
1586
1676
|
|
|
1587
1677
|
// src/index.ts
|
|
1588
|
-
var VERSION = true ? "0.0.
|
|
1589
|
-
var CHANGELOG = true ?
|
|
1678
|
+
var VERSION = true ? "0.0.20" : "0.0.0-dev";
|
|
1679
|
+
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.20 \u2014 2026-05-29\n\n### Added\n- `gs pull`, `gs push`, and `gs publish` now accept several component\n names at once (e.g. `gs publish header footer cart`). Each component\n is reported on its own line and one failure no longer stops the rest.\n\n## 0.0.19 \u2014 2026-05-28\n\n### Fixed\n- `gs login` on Windows no longer opens a sign-in URL with parameters\n stripped, which surfaced as a "Missing redirect_uri or state\n parameter" page in the browser.\n\n## 0.0.18 \u2014 2026-05-28\n\n### Changed\n- Push and publish errors now name the specific reason \u2014 including\n every failing field in `manifest.json` \u2014 instead of the previous\n generic message.\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' : "";
|
|
1590
1680
|
var HELP = `gs \u2014 GreatStore CLI (v${VERSION})
|
|
1591
1681
|
|
|
1592
1682
|
Usage:
|
|
@@ -1599,9 +1689,9 @@ Commands:
|
|
|
1599
1689
|
init [<name>] Scaffold project root; add \`components/<name>/\` if name given.
|
|
1600
1690
|
build [<name>] Build component bundle(s) via the project's Vite. No args = all.
|
|
1601
1691
|
list List components in the current store.
|
|
1602
|
-
pull [<name
|
|
1603
|
-
push [<name
|
|
1604
|
-
publish <name
|
|
1692
|
+
pull [<name>...|*] Download remote component(s) into \`components/<name>/\`. No args = all.
|
|
1693
|
+
push [<name>...] Upload changed components from \`components/\`. No args = all (skips unchanged).
|
|
1694
|
+
publish <name>... Promote the draft(s) (or --version N) to live.
|
|
1605
1695
|
unpublish <name> Clear the live pointer.
|
|
1606
1696
|
delete <name> Soft-delete the component.
|
|
1607
1697
|
|