@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.
- package/README.md +3 -1
- package/dist/cli.js +121 -78
- 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
|
-
|
|
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
|
-
"
|
|
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, "
|
|
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
|
|
1191
|
-
//
|
|
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"
|
|
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: "
|
|
1228
|
-
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
|
|
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
|
-
|
|
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.
|
|
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;
|