@greatstore/cli 0.0.11-beta.1 → 0.0.11-beta.3
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 +68 -0
- package/README.md +3 -1
- package/dist/cli.js +128 -77
- package/package.json +3 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@greatstore/cli` are recorded here. The format
|
|
4
|
+
follows [Keep a Changelog](https://keepachangelog.com/).
|
|
5
|
+
|
|
6
|
+
## 0.0.11-beta.3 — 2026-05-24
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
- Public `CHANGELOG.md`. `gs --version` now prints the most recent entries.
|
|
10
|
+
|
|
11
|
+
## 0.0.11-beta.2 — 2026-05-24
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- `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.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- `gs init` no longer writes a `build.mjs`. Scaffolded `package.json` scripts run `gs build`.
|
|
18
|
+
|
|
19
|
+
## 0.0.11-beta.1 — 2026-05-24
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
- `gs init` errors on a fresh root without `--store <slug>` (no placeholder slug is written). On an existing root, passing `--store` errors — a project is pinned to one store.
|
|
23
|
+
|
|
24
|
+
## 0.0.11-beta.0 — 2026-05-24
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
- Multi-component projects: scaffold one root, then add N components under `components/<name>/`.
|
|
28
|
+
- `gs init` (no args) writes the project root. `gs init <name>` adds a component (auto-scaffolds the root if missing).
|
|
29
|
+
- `gs push` (no args) hashes each component against `.gssync.json` and uploads only the changed ones.
|
|
30
|
+
- `gs pull` (no args, or `*`) batch-pulls every remote component. Components with uncommitted local edits are skipped with a warning; `--force` overwrites.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
- 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.
|
|
34
|
+
|
|
35
|
+
## 0.0.10 — 2026-05-23
|
|
36
|
+
|
|
37
|
+
### Changed
|
|
38
|
+
- The OAuth callback tab opened by `gs login` auto-closes once credentials are persisted.
|
|
39
|
+
|
|
40
|
+
## 0.0.9 — 2026-05-23
|
|
41
|
+
|
|
42
|
+
### Changed
|
|
43
|
+
- `gs init` scaffold writes a `displayName` into the generated manifest so the admin Builder UI has a friendlier label.
|
|
44
|
+
|
|
45
|
+
## 0.0.8 — 2026-05-23
|
|
46
|
+
|
|
47
|
+
### Changed
|
|
48
|
+
- `gs push` and `gs publish` print a permalink to the component's card in the admin Builder panel.
|
|
49
|
+
|
|
50
|
+
## 0.0.6 — 2026-05-23
|
|
51
|
+
|
|
52
|
+
### Changed
|
|
53
|
+
- `gs --version` reads the version from `cli/package.json` at build time so it can't drift from the published release.
|
|
54
|
+
|
|
55
|
+
## 0.0.4 — 2026-05-23
|
|
56
|
+
|
|
57
|
+
### Changed
|
|
58
|
+
- Scaffolded projects produce browser-ready bundles (React + runtime shim wired up).
|
|
59
|
+
|
|
60
|
+
## 0.0.3 — 2026-05-23
|
|
61
|
+
|
|
62
|
+
### Changed
|
|
63
|
+
- Trimmed public README to the essentials.
|
|
64
|
+
|
|
65
|
+
## 0.0.2 — 2026-05-23
|
|
66
|
+
|
|
67
|
+
### Fixed
|
|
68
|
+
- Read the nav OAuth callback parameter as `code` instead of `token`.
|
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
|
@@ -1027,14 +1027,14 @@ function initCommand(args) {
|
|
|
1027
1027
|
"Next steps:",
|
|
1028
1028
|
...rootExisted ? [] : [` cd ${projectLabel}`, " npm install"],
|
|
1029
1029
|
` # edit components/${name}/component.tsx and manifest.json`,
|
|
1030
|
-
"
|
|
1030
|
+
" gs build",
|
|
1031
1031
|
" gs push",
|
|
1032
1032
|
""
|
|
1033
1033
|
].join("\n")
|
|
1034
1034
|
);
|
|
1035
1035
|
}
|
|
1036
1036
|
function hasRootScaffold(dir) {
|
|
1037
|
-
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"));
|
|
1038
1038
|
}
|
|
1039
1039
|
function ensureRoot(root, rootExisted, force, opts) {
|
|
1040
1040
|
fs6.mkdirSync(root, { recursive: true });
|
|
@@ -1079,7 +1079,6 @@ function rootFiles(opts) {
|
|
|
1079
1079
|
}
|
|
1080
1080
|
return [
|
|
1081
1081
|
["package.json", rootPackageJson()],
|
|
1082
|
-
["build.mjs", buildScript()],
|
|
1083
1082
|
["vite.config.ts", viteEditorConfig()],
|
|
1084
1083
|
["tsconfig.json", rootTsconfig()],
|
|
1085
1084
|
[".gsrc", gsrc(opts.store)],
|
|
@@ -1131,79 +1130,13 @@ export default function ${pascal(name)}(_props: Props): React.ReactElement {
|
|
|
1131
1130
|
}
|
|
1132
1131
|
`;
|
|
1133
1132
|
}
|
|
1134
|
-
function buildScript() {
|
|
1135
|
-
return `import { build } from "vite";
|
|
1136
|
-
import react from "@vitejs/plugin-react";
|
|
1137
|
-
import * as fs from "node:fs";
|
|
1138
|
-
import * as path from "node:path";
|
|
1139
|
-
|
|
1140
|
-
const COMPONENTS_DIR = path.resolve("components");
|
|
1141
|
-
|
|
1142
|
-
function listComponents() {
|
|
1143
|
-
if (!fs.existsSync(COMPONENTS_DIR)) return [];
|
|
1144
|
-
return fs
|
|
1145
|
-
.readdirSync(COMPONENTS_DIR)
|
|
1146
|
-
.filter((entry) => {
|
|
1147
|
-
const dir = path.join(COMPONENTS_DIR, entry);
|
|
1148
|
-
return (
|
|
1149
|
-
fs.statSync(dir).isDirectory() &&
|
|
1150
|
-
fs.existsSync(path.join(dir, "component.tsx"))
|
|
1151
|
-
);
|
|
1152
|
-
})
|
|
1153
|
-
.sort();
|
|
1154
|
-
}
|
|
1155
|
-
|
|
1156
|
-
const components = listComponents();
|
|
1157
|
-
if (components.length === 0) {
|
|
1158
|
-
console.log("(no components in ./components \u2014 run \`gs init <name>\` to add one)");
|
|
1159
|
-
process.exit(0);
|
|
1160
|
-
}
|
|
1161
|
-
|
|
1162
|
-
const target = process.argv[2];
|
|
1163
|
-
const queue = target ? components.filter((c) => c === target) : components;
|
|
1164
|
-
if (target && queue.length === 0) {
|
|
1165
|
-
console.error(\`No component named "\${target}" in ./components\`);
|
|
1166
|
-
process.exit(1);
|
|
1167
|
-
}
|
|
1168
|
-
|
|
1169
|
-
for (const name of queue) {
|
|
1170
|
-
const dir = path.join(COMPONENTS_DIR, name);
|
|
1171
|
-
await build({
|
|
1172
|
-
plugins: [react()],
|
|
1173
|
-
logLevel: "warn",
|
|
1174
|
-
build: {
|
|
1175
|
-
lib: {
|
|
1176
|
-
entry: path.join(dir, "component.tsx"),
|
|
1177
|
-
formats: ["es"],
|
|
1178
|
-
fileName: () => "bundle.js",
|
|
1179
|
-
},
|
|
1180
|
-
outDir: dir,
|
|
1181
|
-
emptyOutDir: false,
|
|
1182
|
-
rollupOptions: {
|
|
1183
|
-
external: ["react", "react-dom", "react/jsx-runtime"],
|
|
1184
|
-
output: {
|
|
1185
|
-
entryFileNames: "bundle.js",
|
|
1186
|
-
paths: {
|
|
1187
|
-
react: "/assets/remote-components/_runtime.js",
|
|
1188
|
-
"react-dom": "/assets/remote-components/_runtime.js",
|
|
1189
|
-
"react/jsx-runtime": "/assets/remote-components/_runtime.js",
|
|
1190
|
-
},
|
|
1191
|
-
},
|
|
1192
|
-
},
|
|
1193
|
-
minify: true,
|
|
1194
|
-
sourcemap: false,
|
|
1195
|
-
},
|
|
1196
|
-
});
|
|
1197
|
-
console.log(\`built components/\${name}/bundle.js\`);
|
|
1198
|
-
}
|
|
1199
|
-
`;
|
|
1200
|
-
}
|
|
1201
1133
|
function viteEditorConfig() {
|
|
1202
1134
|
return `import { defineConfig } from "vite";
|
|
1203
1135
|
import react from "@vitejs/plugin-react";
|
|
1204
1136
|
|
|
1205
|
-
// Real builds happen in build
|
|
1206
|
-
//
|
|
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
|
|
1207
1140
|
// React plugin when inspecting components/*/component.tsx.
|
|
1208
1141
|
export default defineConfig({
|
|
1209
1142
|
plugins: [react()],
|
|
@@ -1225,7 +1158,7 @@ function rootTsconfig() {
|
|
|
1225
1158
|
isolatedModules: true,
|
|
1226
1159
|
noEmit: true
|
|
1227
1160
|
},
|
|
1228
|
-
include: ["components/**/component.tsx", "vite.config.ts"
|
|
1161
|
+
include: ["components/**/component.tsx", "vite.config.ts"]
|
|
1229
1162
|
},
|
|
1230
1163
|
null,
|
|
1231
1164
|
2
|
|
@@ -1239,8 +1172,8 @@ function rootPackageJson() {
|
|
|
1239
1172
|
private: true,
|
|
1240
1173
|
type: "module",
|
|
1241
1174
|
scripts: {
|
|
1242
|
-
build: "
|
|
1243
|
-
push: "
|
|
1175
|
+
build: "gs build",
|
|
1176
|
+
push: "gs build && gs push"
|
|
1244
1177
|
},
|
|
1245
1178
|
dependencies: {
|
|
1246
1179
|
react: "^19.0.0",
|
|
@@ -1280,7 +1213,7 @@ component lives in its own folder under \`components/\`.
|
|
|
1280
1213
|
\`\`\`
|
|
1281
1214
|
npm install
|
|
1282
1215
|
gs init <component_name> # add a new component
|
|
1283
|
-
|
|
1216
|
+
gs build # builds every components/<name>/bundle.js
|
|
1284
1217
|
gs push # uploads every changed component as a draft
|
|
1285
1218
|
gs publish <component_name> # promote a specific component to live
|
|
1286
1219
|
\`\`\`
|
|
@@ -1296,8 +1229,118 @@ function pascal(name) {
|
|
|
1296
1229
|
return name.split(/[_-]/).filter(Boolean).map((part) => part[0]?.toUpperCase() + part.slice(1)).join("");
|
|
1297
1230
|
}
|
|
1298
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
|
+
|
|
1323
|
+
// src/changelog.ts
|
|
1324
|
+
function recentChangelog(text, minItems = 15) {
|
|
1325
|
+
if (!text.trim()) return "";
|
|
1326
|
+
const lines = text.split("\n");
|
|
1327
|
+
const out = [];
|
|
1328
|
+
let bullets = 0;
|
|
1329
|
+
let inSection = false;
|
|
1330
|
+
for (const line of lines) {
|
|
1331
|
+
if (line.startsWith("## ")) {
|
|
1332
|
+
if (inSection && bullets >= minItems) break;
|
|
1333
|
+
inSection = true;
|
|
1334
|
+
}
|
|
1335
|
+
out.push(line);
|
|
1336
|
+
if (inSection && /^\s*[-*+]\s/.test(line)) bullets++;
|
|
1337
|
+
}
|
|
1338
|
+
return out.join("\n").trimEnd();
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1299
1341
|
// src/index.ts
|
|
1300
|
-
var VERSION = true ? "0.0.11-beta.
|
|
1342
|
+
var VERSION = true ? "0.0.11-beta.3" : "0.0.0-dev";
|
|
1343
|
+
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.11-beta.3 \u2014 2026-05-24\n\n### Added\n- Public `CHANGELOG.md`. `gs --version` now prints the most recent entries.\n\n## 0.0.11-beta.2 \u2014 2026-05-24\n\n### Added\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\n### Changed\n- `gs init` no longer writes a `build.mjs`. Scaffolded `package.json` scripts run `gs build`.\n\n## 0.0.11-beta.1 \u2014 2026-05-24\n\n### Changed\n- `gs init` errors on a fresh root without `--store <slug>` (no placeholder slug is written). On an existing root, passing `--store` errors \u2014 a project is pinned to one store.\n\n## 0.0.11-beta.0 \u2014 2026-05-24\n\n### Added\n- Multi-component projects: scaffold one root, then add N components under `components/<name>/`.\n- `gs init` (no args) writes the project root. `gs init <name>` adds a component (auto-scaffolds the root if missing).\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\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\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" : "";
|
|
1301
1344
|
var HELP = `gs \u2014 GreatStore CLI (v${VERSION})
|
|
1302
1345
|
|
|
1303
1346
|
Usage:
|
|
@@ -1308,6 +1351,7 @@ Commands:
|
|
|
1308
1351
|
logout Wipe ~/.greatstore/credentials.json.
|
|
1309
1352
|
whoami Print the identity stored locally.
|
|
1310
1353
|
init [<name>] Scaffold project root; add \`components/<name>/\` if name given.
|
|
1354
|
+
build [<name>] Build component bundle(s) via the project's Vite. No args = all.
|
|
1311
1355
|
list List components in the current store.
|
|
1312
1356
|
pull [<name>|*] Download remote component(s) into \`components/<name>/\`. No args = all.
|
|
1313
1357
|
push [<name>] Upload changed components from \`components/\`. No args = all (skips unchanged).
|
|
@@ -1337,6 +1381,10 @@ async function main() {
|
|
|
1337
1381
|
const parsed = parseArgs(argv);
|
|
1338
1382
|
if (flagBool(parsed.flags, "version")) {
|
|
1339
1383
|
process.stdout.write(`gs v${VERSION}
|
|
1384
|
+
|
|
1385
|
+
`);
|
|
1386
|
+
const changelog = recentChangelog(CHANGELOG);
|
|
1387
|
+
if (changelog) process.stdout.write(`${changelog}
|
|
1340
1388
|
`);
|
|
1341
1389
|
return 0;
|
|
1342
1390
|
}
|
|
@@ -1356,6 +1404,9 @@ async function main() {
|
|
|
1356
1404
|
case "init":
|
|
1357
1405
|
initCommand(parsed);
|
|
1358
1406
|
return 0;
|
|
1407
|
+
case "build":
|
|
1408
|
+
await buildCommand(parsed);
|
|
1409
|
+
return 0;
|
|
1359
1410
|
case "list":
|
|
1360
1411
|
await listCommand(parsed);
|
|
1361
1412
|
return 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@greatstore/cli",
|
|
3
|
-
"version": "0.0.11-beta.
|
|
3
|
+
"version": "0.0.11-beta.3",
|
|
4
4
|
"description": "CLI for authoring and shipping GreatStore custom components.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
11
|
"dist",
|
|
12
|
-
"README.md"
|
|
12
|
+
"README.md",
|
|
13
|
+
"CHANGELOG.md"
|
|
13
14
|
],
|
|
14
15
|
"engines": {
|
|
15
16
|
"node": ">=20"
|