@greatstore/cli 0.0.11-beta.0 → 0.0.11-beta.2

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 +3 -1
  2. package/dist/cli.js +121 -78
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -5,8 +5,10 @@ Author and ship GreatStore custom remote components from the command line.
5
5
  ```
6
6
  npm install -g @greatstore/cli
7
7
  gs login
8
+ gs init --store <slug>
9
+ cd <project> && npm install
8
10
  gs init my-widget
9
- cd my-widget && npm install && npm run build
11
+ gs build
10
12
  gs push
11
13
  gs publish my-widget
12
14
  ```
package/dist/cli.js CHANGED
@@ -989,6 +989,18 @@ function initCommand(args) {
989
989
  const outRel = flagString(args.flags, "out") ?? ".";
990
990
  const root = path6.resolve(outRel);
991
991
  const rootExisted = hasRootScaffold(root);
992
+ if (rootExisted) {
993
+ if (storeFlag !== void 0) {
994
+ throw new Error(
995
+ `Project at ${root} is already pinned to a store via .gsrc. Drop --store; a project folder ships to exactly one store.`
996
+ );
997
+ }
998
+ } else if (storeFlag === void 0) {
999
+ const example = name ? `gs init ${name} --store <slug>` : `gs init --store <slug>`;
1000
+ throw new Error(
1001
+ `--store <slug> is required when scaffolding a new project root. Run \`${example}\`.`
1002
+ );
1003
+ }
992
1004
  ensureRoot(root, rootExisted, force, { store: storeFlag });
993
1005
  if (!name) {
994
1006
  const created = rootExisted ? "Updated" : "Scaffolded";
@@ -1015,14 +1027,14 @@ function initCommand(args) {
1015
1027
  "Next steps:",
1016
1028
  ...rootExisted ? [] : [` cd ${projectLabel}`, " npm install"],
1017
1029
  ` # edit components/${name}/component.tsx and manifest.json`,
1018
- " npm run build",
1030
+ " gs build",
1019
1031
  " gs push",
1020
1032
  ""
1021
1033
  ].join("\n")
1022
1034
  );
1023
1035
  }
1024
1036
  function hasRootScaffold(dir) {
1025
- return fs6.existsSync(path6.join(dir, "package.json")) && fs6.existsSync(path6.join(dir, "build.mjs"));
1037
+ return fs6.existsSync(path6.join(dir, "package.json")) && fs6.existsSync(path6.join(dir, ".gsrc"));
1026
1038
  }
1027
1039
  function ensureRoot(root, rootExisted, force, opts) {
1028
1040
  fs6.mkdirSync(root, { recursive: true });
@@ -1062,9 +1074,11 @@ function ensureComponent(componentDir, name, force) {
1062
1074
  }
1063
1075
  }
1064
1076
  function rootFiles(opts) {
1077
+ if (!opts.store) {
1078
+ throw new Error("internal: rootFiles called without a store slug");
1079
+ }
1065
1080
  return [
1066
1081
  ["package.json", rootPackageJson()],
1067
- ["build.mjs", buildScript()],
1068
1082
  ["vite.config.ts", viteEditorConfig()],
1069
1083
  ["tsconfig.json", rootTsconfig()],
1070
1084
  [".gsrc", gsrc(opts.store)],
@@ -1116,79 +1130,13 @@ export default function ${pascal(name)}(_props: Props): React.ReactElement {
1116
1130
  }
1117
1131
  `;
1118
1132
  }
1119
- function buildScript() {
1120
- return `import { build } from "vite";
1121
- import react from "@vitejs/plugin-react";
1122
- import * as fs from "node:fs";
1123
- import * as path from "node:path";
1124
-
1125
- const COMPONENTS_DIR = path.resolve("components");
1126
-
1127
- function listComponents() {
1128
- if (!fs.existsSync(COMPONENTS_DIR)) return [];
1129
- return fs
1130
- .readdirSync(COMPONENTS_DIR)
1131
- .filter((entry) => {
1132
- const dir = path.join(COMPONENTS_DIR, entry);
1133
- return (
1134
- fs.statSync(dir).isDirectory() &&
1135
- fs.existsSync(path.join(dir, "component.tsx"))
1136
- );
1137
- })
1138
- .sort();
1139
- }
1140
-
1141
- const components = listComponents();
1142
- if (components.length === 0) {
1143
- console.log("(no components in ./components \u2014 run \`gs init <name>\` to add one)");
1144
- process.exit(0);
1145
- }
1146
-
1147
- const target = process.argv[2];
1148
- const queue = target ? components.filter((c) => c === target) : components;
1149
- if (target && queue.length === 0) {
1150
- console.error(\`No component named "\${target}" in ./components\`);
1151
- process.exit(1);
1152
- }
1153
-
1154
- for (const name of queue) {
1155
- const dir = path.join(COMPONENTS_DIR, name);
1156
- await build({
1157
- plugins: [react()],
1158
- logLevel: "warn",
1159
- build: {
1160
- lib: {
1161
- entry: path.join(dir, "component.tsx"),
1162
- formats: ["es"],
1163
- fileName: () => "bundle.js",
1164
- },
1165
- outDir: dir,
1166
- emptyOutDir: false,
1167
- rollupOptions: {
1168
- external: ["react", "react-dom", "react/jsx-runtime"],
1169
- output: {
1170
- entryFileNames: "bundle.js",
1171
- paths: {
1172
- react: "/assets/remote-components/_runtime.js",
1173
- "react-dom": "/assets/remote-components/_runtime.js",
1174
- "react/jsx-runtime": "/assets/remote-components/_runtime.js",
1175
- },
1176
- },
1177
- },
1178
- minify: true,
1179
- sourcemap: false,
1180
- },
1181
- });
1182
- console.log(\`built components/\${name}/bundle.js\`);
1183
- }
1184
- `;
1185
- }
1186
1133
  function viteEditorConfig() {
1187
1134
  return `import { defineConfig } from "vite";
1188
1135
  import react from "@vitejs/plugin-react";
1189
1136
 
1190
- // Real builds happen in build.mjs (one Vite invocation per component).
1191
- // This file exists only so editors / language servers can resolve the
1137
+ // Real builds happen in \`gs build\` (one Vite invocation per
1138
+ // component, externals + runtime shim paths owned by the CLI). This
1139
+ // file exists only so editors / language servers can resolve the
1192
1140
  // React plugin when inspecting components/*/component.tsx.
1193
1141
  export default defineConfig({
1194
1142
  plugins: [react()],
@@ -1210,7 +1158,7 @@ function rootTsconfig() {
1210
1158
  isolatedModules: true,
1211
1159
  noEmit: true
1212
1160
  },
1213
- include: ["components/**/component.tsx", "vite.config.ts", "build.mjs"]
1161
+ include: ["components/**/component.tsx", "vite.config.ts"]
1214
1162
  },
1215
1163
  null,
1216
1164
  2
@@ -1224,8 +1172,8 @@ function rootPackageJson() {
1224
1172
  private: true,
1225
1173
  type: "module",
1226
1174
  scripts: {
1227
- build: "node build.mjs",
1228
- push: "node build.mjs && gs push"
1175
+ build: "gs build",
1176
+ push: "gs build && gs push"
1229
1177
  },
1230
1178
  dependencies: {
1231
1179
  react: "^19.0.0",
@@ -1244,7 +1192,7 @@ function rootPackageJson() {
1244
1192
  ) + "\n";
1245
1193
  }
1246
1194
  function gsrc(store) {
1247
- return JSON.stringify({ store: store ?? "<your-store-slug>" }, null, 2) + "\n";
1195
+ return JSON.stringify({ store }, null, 2) + "\n";
1248
1196
  }
1249
1197
  function gitignore() {
1250
1198
  return [
@@ -1265,7 +1213,7 @@ component lives in its own folder under \`components/\`.
1265
1213
  \`\`\`
1266
1214
  npm install
1267
1215
  gs init <component_name> # add a new component
1268
- npm run build # builds every component/<name>/bundle.js
1216
+ gs build # builds every components/<name>/bundle.js
1269
1217
  gs push # uploads every changed component as a draft
1270
1218
  gs publish <component_name> # promote a specific component to live
1271
1219
  \`\`\`
@@ -1281,8 +1229,99 @@ function pascal(name) {
1281
1229
  return name.split(/[_-]/).filter(Boolean).map((part) => part[0]?.toUpperCase() + part.slice(1)).join("");
1282
1230
  }
1283
1231
 
1232
+ // src/commands/build.ts
1233
+ import * as fs7 from "fs";
1234
+ import * as path7 from "path";
1235
+ import { createRequire } from "module";
1236
+ var COMPONENTS_DIR = "components";
1237
+ async function buildCommand(args) {
1238
+ const root = process.cwd();
1239
+ if (!fs7.existsSync(path7.join(root, "package.json")) || !fs7.existsSync(path7.join(root, COMPONENTS_DIR))) {
1240
+ throw new Error(
1241
+ `\`gs build\` must run from a project root (contains \`package.json\` and \`${COMPONENTS_DIR}/\`). Current dir: ${root}`
1242
+ );
1243
+ }
1244
+ const components = listComponents(root);
1245
+ if (components.length === 0) {
1246
+ process.stdout.write(
1247
+ `(no components in ./${COMPONENTS_DIR} \u2014 run \`gs init <name>\` to add one)
1248
+ `
1249
+ );
1250
+ return;
1251
+ }
1252
+ const target = args.positional[0];
1253
+ const queue = target ? components.filter((c) => c === target) : components;
1254
+ if (target && queue.length === 0) {
1255
+ throw new Error(`No component named "${target}" in ./${COMPONENTS_DIR}`);
1256
+ }
1257
+ const { build, reactPlugin } = await loadVite(root);
1258
+ for (const name of queue) {
1259
+ const dir = path7.join(root, COMPONENTS_DIR, name);
1260
+ await build({
1261
+ plugins: [reactPlugin()],
1262
+ logLevel: "warn",
1263
+ build: {
1264
+ lib: {
1265
+ entry: path7.join(dir, "component.tsx"),
1266
+ formats: ["es"],
1267
+ fileName: () => "bundle.js"
1268
+ },
1269
+ outDir: dir,
1270
+ emptyOutDir: false,
1271
+ rollupOptions: {
1272
+ external: ["react", "react-dom", "react/jsx-runtime"],
1273
+ output: {
1274
+ entryFileNames: "bundle.js",
1275
+ paths: {
1276
+ react: "/assets/remote-components/_runtime.js",
1277
+ "react-dom": "/assets/remote-components/_runtime.js",
1278
+ "react/jsx-runtime": "/assets/remote-components/_runtime.js"
1279
+ }
1280
+ }
1281
+ },
1282
+ minify: true,
1283
+ sourcemap: false
1284
+ }
1285
+ });
1286
+ process.stdout.write(`built ${COMPONENTS_DIR}/${name}/bundle.js
1287
+ `);
1288
+ }
1289
+ }
1290
+ function listComponents(root) {
1291
+ const dir = path7.join(root, COMPONENTS_DIR);
1292
+ return fs7.readdirSync(dir).filter((entry) => {
1293
+ const candidate = path7.join(dir, entry);
1294
+ return fs7.statSync(candidate).isDirectory() && fs7.existsSync(path7.join(candidate, "component.tsx"));
1295
+ }).sort();
1296
+ }
1297
+ async function loadVite(root) {
1298
+ const localRequire = createRequire(path7.join(root, "package.json"));
1299
+ const vitePath = tryResolve(localRequire, "vite");
1300
+ if (!vitePath) {
1301
+ throw new Error(
1302
+ "Cannot find `vite` in this project. Run `npm install` first."
1303
+ );
1304
+ }
1305
+ const reactPath = tryResolve(localRequire, "@vitejs/plugin-react");
1306
+ if (!reactPath) {
1307
+ throw new Error(
1308
+ "Cannot find `@vitejs/plugin-react` in this project. Run `npm install` first."
1309
+ );
1310
+ }
1311
+ const viteMod = await import(vitePath);
1312
+ const reactMod = await import(reactPath);
1313
+ return { build: viteMod.build, reactPlugin: reactMod.default };
1314
+ }
1315
+ function tryResolve(req, specifier) {
1316
+ try {
1317
+ return req.resolve(specifier);
1318
+ } catch {
1319
+ return null;
1320
+ }
1321
+ }
1322
+
1284
1323
  // src/index.ts
1285
- var VERSION = true ? "0.0.11-beta.0" : "0.0.0-dev";
1324
+ var VERSION = true ? "0.0.11-beta.2" : "0.0.0-dev";
1286
1325
  var HELP = `gs \u2014 GreatStore CLI (v${VERSION})
1287
1326
 
1288
1327
  Usage:
@@ -1293,6 +1332,7 @@ Commands:
1293
1332
  logout Wipe ~/.greatstore/credentials.json.
1294
1333
  whoami Print the identity stored locally.
1295
1334
  init [<name>] Scaffold project root; add \`components/<name>/\` if name given.
1335
+ build [<name>] Build component bundle(s) via the project's Vite. No args = all.
1296
1336
  list List components in the current store.
1297
1337
  pull [<name>|*] Download remote component(s) into \`components/<name>/\`. No args = all.
1298
1338
  push [<name>] Upload changed components from \`components/\`. No args = all (skips unchanged).
@@ -1341,6 +1381,9 @@ async function main() {
1341
1381
  case "init":
1342
1382
  initCommand(parsed);
1343
1383
  return 0;
1384
+ case "build":
1385
+ await buildCommand(parsed);
1386
+ return 0;
1344
1387
  case "list":
1345
1388
  await listCommand(parsed);
1346
1389
  return 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@greatstore/cli",
3
- "version": "0.0.11-beta.0",
3
+ "version": "0.0.11-beta.2",
4
4
  "description": "CLI for authoring and shipping GreatStore custom components.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",