@dforge-core/dforge-cli 0.2.1 → 0.2.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.
Files changed (2) hide show
  1. package/dist/cli.js +180 -128
  2. package/package.json +7 -7
package/dist/cli.js CHANGED
@@ -1050,12 +1050,16 @@ var init_templates = __esm({
1050
1050
 
1051
1051
  // src/init/module.ts
1052
1052
  async function runInitModule(argv2) {
1053
- const rawPath = argv2[0];
1054
- if (!rawPath) {
1055
- console.error("Usage: dforge-cli init module <path>");
1053
+ const args = parseArgs(argv2);
1054
+ if (args.help) {
1055
+ printModuleHelp();
1056
+ return 0;
1057
+ }
1058
+ if (!args.path) {
1059
+ printModuleHelp();
1056
1060
  return 2;
1057
1061
  }
1058
- const absPath = path2.resolve(rawPath);
1062
+ const absPath = path2.resolve(args.path);
1059
1063
  if (fs2.existsSync(absPath)) {
1060
1064
  const stat = fs2.statSync(absPath);
1061
1065
  if (!stat.isDirectory()) {
@@ -1067,29 +1071,180 @@ async function runInitModule(argv2) {
1067
1071
  return 1;
1068
1072
  }
1069
1073
  }
1070
- Ie("dforge-cli init module");
1071
- const opts = await collectOpts(absPath);
1072
- if (opts === null) {
1073
- xe("Aborted.");
1074
- return CANCEL_EXIT;
1075
- }
1076
- const s = Y2();
1077
- s.start("Writing files");
1078
- try {
1079
- writeAll(opts);
1080
- s.stop("Files written.");
1081
- } catch (err) {
1082
- s.stop("Write failed.");
1083
- console.error(err.message);
1084
- return 1;
1074
+ const nonInteractive = args.yes || args.code !== void 0 || !process.stdin.isTTY;
1075
+ let opts;
1076
+ if (nonInteractive) {
1077
+ if (args.code === void 0) {
1078
+ console.error(
1079
+ "dforge-cli init module: no TTY for interactive prompts and no --code given.\nPass --code <code> (plus optional --display-name, --entity, --preset, \u2026) to scaffold\nnon-interactively, or run in a real terminal. See `dforge-cli init module --help`."
1080
+ );
1081
+ return 2;
1082
+ }
1083
+ opts = buildOptsFromArgs(absPath, args);
1084
+ if (opts === null) return 1;
1085
+ try {
1086
+ writeAll(opts);
1087
+ } catch (err) {
1088
+ console.error(err.message);
1089
+ return 1;
1090
+ }
1091
+ console.log(`Created module ${opts.code} at ${opts.path}`);
1092
+ } else {
1093
+ Ie("dforge-cli init module");
1094
+ opts = await collectOpts(absPath);
1095
+ if (opts === null) {
1096
+ xe("Aborted.");
1097
+ return CANCEL_EXIT;
1098
+ }
1099
+ const s = Y2();
1100
+ s.start("Writing files");
1101
+ try {
1102
+ writeAll(opts);
1103
+ s.stop("Files written.");
1104
+ } catch (err) {
1105
+ s.stop("Write failed.");
1106
+ console.error(err.message);
1107
+ return 1;
1108
+ }
1109
+ Se(`Created module ${opts.code} at ${opts.path}`);
1085
1110
  }
1086
- Se(`Created module ${opts.code} at ${opts.path}`);
1087
1111
  console.log("");
1088
1112
  console.log("Next steps:");
1089
1113
  console.log(` cd ${path2.relative(process.cwd(), opts.path) || "."}`);
1090
1114
  console.log(` dforge-cli module install --path . --code <tenant>`);
1091
1115
  return 0;
1092
1116
  }
1117
+ function parseArgs(argv2) {
1118
+ const out = {};
1119
+ const list = (prev, v2) => [
1120
+ ...prev ?? [],
1121
+ ...v2.split(",").map((s) => s.trim()).filter(Boolean)
1122
+ ];
1123
+ for (let i = 0; i < argv2.length; i++) {
1124
+ const tok = argv2[i];
1125
+ if (tok === "--help" || tok === "-h") {
1126
+ out.help = true;
1127
+ continue;
1128
+ }
1129
+ if (tok === "--yes" || tok === "-y") {
1130
+ out.yes = true;
1131
+ continue;
1132
+ }
1133
+ if (!tok.startsWith("-")) {
1134
+ if (out.path === void 0) out.path = tok;
1135
+ continue;
1136
+ }
1137
+ const eq = tok.indexOf("=");
1138
+ const flag = eq === -1 ? tok : tok.slice(0, eq);
1139
+ const inlineVal = eq === -1 ? void 0 : tok.slice(eq + 1);
1140
+ const value = () => inlineVal !== void 0 ? inlineVal : argv2[++i] ?? "";
1141
+ switch (flag) {
1142
+ case "--code":
1143
+ out.code = value();
1144
+ break;
1145
+ case "--display-name":
1146
+ case "--name":
1147
+ out.displayName = value();
1148
+ break;
1149
+ case "--description":
1150
+ out.description = value();
1151
+ break;
1152
+ case "--author":
1153
+ out.author = value();
1154
+ break;
1155
+ case "--license":
1156
+ out.license = value();
1157
+ break;
1158
+ case "--version":
1159
+ out.version = value();
1160
+ break;
1161
+ case "--db-schema-version":
1162
+ out.dbSchemaVersion = value();
1163
+ break;
1164
+ case "--dependencies":
1165
+ out.dependencies = list(out.dependencies, value());
1166
+ break;
1167
+ case "--preset":
1168
+ out.preset = value();
1169
+ break;
1170
+ case "--entity":
1171
+ out.entities = list(out.entities, value());
1172
+ break;
1173
+ case "--traits":
1174
+ out.traits = value();
1175
+ break;
1176
+ default:
1177
+ console.error(`dforge-cli init module: unknown flag "${flag}" (ignored)`);
1178
+ }
1179
+ }
1180
+ return out;
1181
+ }
1182
+ function buildOptsFromArgs(absPath, args) {
1183
+ const fail = (msg) => {
1184
+ console.error(`dforge-cli init module: ${msg}`);
1185
+ return null;
1186
+ };
1187
+ const code = args.code;
1188
+ const codeErr = validateCode(code);
1189
+ if (codeErr) return fail(`--code ${codeErr}`);
1190
+ const version = args.version ?? "0.1.0";
1191
+ const versionErr = validateSemver(version);
1192
+ if (versionErr) return fail(`--version ${versionErr}`);
1193
+ const dbSchemaVersion = args.dbSchemaVersion ?? "0.0.1";
1194
+ const dbErr = validateSemver(dbSchemaVersion);
1195
+ if (dbErr) return fail(`--db-schema-version ${dbErr}`);
1196
+ const preset = args.preset ?? "minimal";
1197
+ if (!PRESETS.has(preset)) {
1198
+ return fail(`--preset must be one of: ${[...PRESETS].join(", ")}.`);
1199
+ }
1200
+ const traits = args.traits ?? "identity+audit";
1201
+ if (!TRAITS_VALUES.has(traits)) {
1202
+ return fail(`--traits must be one of: ${[...TRAITS_VALUES].join(", ")}.`);
1203
+ }
1204
+ const names = args.entities && args.entities.length > 0 ? args.entities : ["item"];
1205
+ const entities = [];
1206
+ for (const name of names) {
1207
+ const nameErr = validateEntityName(name);
1208
+ if (nameErr) return fail(`--entity "${name}": ${nameErr}`);
1209
+ entities.push({ name, label: titlecase(name), traits });
1210
+ }
1211
+ const displayName = args.displayName ?? titlecase(code);
1212
+ if (validateNonEmpty(displayName)) return fail("--display-name cannot be empty.");
1213
+ return {
1214
+ path: absPath,
1215
+ code,
1216
+ displayName,
1217
+ description: args.description ?? "",
1218
+ author: args.author ?? tryGitUserName() ?? "",
1219
+ license: args.license ?? "MIT",
1220
+ version,
1221
+ dbSchemaVersion,
1222
+ dependencies: args.dependencies ?? ["admin", "metadata"],
1223
+ preset,
1224
+ entities
1225
+ };
1226
+ }
1227
+ function printModuleHelp() {
1228
+ console.log("Usage: dforge-cli init module <path> [options]");
1229
+ console.log("");
1230
+ console.log("Scaffold a new dForge module. With a TTY and no flags, runs interactively.");
1231
+ console.log("With --code (or when there's no TTY), runs non-interactively from flags + defaults.");
1232
+ console.log("");
1233
+ console.log("Options:");
1234
+ console.log(" --code <code> Module code (required when non-interactive)");
1235
+ console.log(" --display-name <name> Default: title-cased code");
1236
+ console.log(" --description <text> Default: empty");
1237
+ console.log(" --author <name> Default: git user.name");
1238
+ console.log(" --license <id> Default: MIT");
1239
+ console.log(" --version <semver> Default: 0.1.0");
1240
+ console.log(" --db-schema-version <ver> Default: 0.0.1");
1241
+ console.log(" --dependencies <a,b> Default: admin,metadata");
1242
+ console.log(" --preset <p> minimal | minimal-plus | full (default: minimal)");
1243
+ console.log(" --entity <name[,name\u2026]> Entities to scaffold (default: item). Repeatable.");
1244
+ console.log(" --traits <t> identity+audit | identity (default: identity+audit)");
1245
+ console.log(" -y, --yes Force non-interactive even with a TTY");
1246
+ console.log(" -h, --help Show this help");
1247
+ }
1093
1248
  async function collectOpts(absPath) {
1094
1249
  const gitName = tryGitUserName();
1095
1250
  const meta = await Ce(
@@ -1278,7 +1433,7 @@ function tryGitUserName() {
1278
1433
  return void 0;
1279
1434
  }
1280
1435
  }
1281
- var fs2, path2, import_node_child_process2, import_node_crypto, CANCEL_EXIT;
1436
+ var fs2, path2, import_node_child_process2, import_node_crypto, CANCEL_EXIT, PRESETS, TRAITS_VALUES;
1282
1437
  var init_module = __esm({
1283
1438
  "src/init/module.ts"() {
1284
1439
  "use strict";
@@ -1290,6 +1445,8 @@ var init_module = __esm({
1290
1445
  init_prompts();
1291
1446
  init_templates();
1292
1447
  CANCEL_EXIT = 130;
1448
+ PRESETS = /* @__PURE__ */ new Set(["minimal", "minimal-plus", "full"]);
1449
+ TRAITS_VALUES = /* @__PURE__ */ new Set(["identity+audit", "identity"]);
1293
1450
  }
1294
1451
  });
1295
1452
 
@@ -1318,7 +1475,8 @@ function printHelp() {
1318
1475
  console.log("Usage: dforge-cli init <subcommand>");
1319
1476
  console.log("");
1320
1477
  console.log("Subcommands:");
1321
- console.log(" module <path> Scaffold a new dForge module (interactive)");
1478
+ console.log(" module <path> Scaffold a new dForge module. Interactive with a TTY;");
1479
+ console.log(" non-interactive with --code (see `init module --help`).");
1322
1480
  }
1323
1481
  var init_init = __esm({
1324
1482
  "src/init/index.ts"() {
@@ -1327,110 +1485,6 @@ var init_init = __esm({
1327
1485
  }
1328
1486
  });
1329
1487
 
1330
- // src/pack.ts
1331
- var pack_exports = {};
1332
- __export(pack_exports, {
1333
- runPack: () => runPack
1334
- });
1335
- async function runPack(argv2) {
1336
- const positional = [];
1337
- let outPath;
1338
- for (let i = 0; i < argv2.length; i++) {
1339
- const a = argv2[i];
1340
- if (a === "-o" || a === "--output") {
1341
- outPath = argv2[++i];
1342
- } else if (a === "-h" || a === "--help") {
1343
- printHelp2();
1344
- return 0;
1345
- } else {
1346
- positional.push(a);
1347
- }
1348
- }
1349
- if (positional.length === 0) {
1350
- console.error("Usage: dforge-cli module pack <module-dir> [-o <output>]");
1351
- return 2;
1352
- }
1353
- const moduleDir = path3.resolve(positional[0]);
1354
- const manifestPath = path3.join(moduleDir, "manifest.json");
1355
- if (!fs3.existsSync(manifestPath)) {
1356
- console.error(`No manifest.json at ${manifestPath}`);
1357
- return 1;
1358
- }
1359
- let manifest;
1360
- try {
1361
- manifest = JSON.parse(fs3.readFileSync(manifestPath, "utf8"));
1362
- } catch (e2) {
1363
- console.error(`manifest.json: ${e2.message}`);
1364
- return 1;
1365
- }
1366
- if (!manifest.code || !manifest.version) {
1367
- console.error("manifest.json missing required `code` or `version`");
1368
- return 1;
1369
- }
1370
- const defaultName = `${manifest.code}-${manifest.version}.dforge`;
1371
- let finalOut;
1372
- if (!outPath) {
1373
- finalOut = path3.resolve(process.cwd(), defaultName);
1374
- } else {
1375
- const abs = path3.resolve(outPath);
1376
- if (abs.endsWith(".dforge")) {
1377
- finalOut = abs;
1378
- } else {
1379
- fs3.mkdirSync(abs, { recursive: true });
1380
- finalOut = path3.join(abs, defaultName);
1381
- }
1382
- }
1383
- fs3.mkdirSync(path3.dirname(finalOut), { recursive: true });
1384
- if (fs3.existsSync(finalOut)) fs3.rmSync(finalOut);
1385
- const zip = (0, import_node_child_process3.spawnSync)(
1386
- "zip",
1387
- ["-r", "-q", finalOut, "."],
1388
- {
1389
- cwd: moduleDir,
1390
- stdio: ["ignore", "inherit", "inherit"]
1391
- }
1392
- );
1393
- if (zip.error) {
1394
- console.error(
1395
- `pack: failed to run \`zip\`: ${zip.error.message}. Install zip (brew install zip / apt install zip / git-for-windows ships it).`
1396
- );
1397
- return 1;
1398
- }
1399
- if (zip.status !== 0) {
1400
- console.error(`pack: zip exited ${zip.status}`);
1401
- return zip.status ?? 1;
1402
- }
1403
- const size = fs3.statSync(finalOut).size;
1404
- const kib = (size / 1024).toFixed(1);
1405
- console.log(`\u2713 ${finalOut} (${kib} KB)`);
1406
- void import_promises.pipeline;
1407
- void import_node_zlib.createGzip;
1408
- return 0;
1409
- }
1410
- function printHelp2() {
1411
- console.log("Usage: dforge-cli module pack <module-dir> [-o <output>]");
1412
- console.log("");
1413
- console.log(
1414
- "Packages a module directory into a .dforge archive (zip with .dforge extension)."
1415
- );
1416
- console.log("");
1417
- console.log("Examples:");
1418
- console.log(" dforge-cli module pack ./my-module # \u2192 ./<code>-<version>.dforge");
1419
- console.log(" dforge-cli module pack ./my-module -o ./dist/ # \u2192 ./dist/<code>-<version>.dforge");
1420
- console.log(" dforge-cli module pack ./my-module -o pkg.dforge # \u2192 ./pkg.dforge");
1421
- }
1422
- var fs3, path3, import_node_zlib, import_promises, import_node_child_process3;
1423
- var init_pack = __esm({
1424
- "src/pack.ts"() {
1425
- "use strict";
1426
- fs3 = __toESM(require("fs"));
1427
- path3 = __toESM(require("path"));
1428
- import_node_zlib = require("zlib");
1429
- import_promises = require("stream/promises");
1430
- import_node_child_process3 = require("child_process");
1431
- }
1432
- });
1433
-
1434
1488
  // src/native.ts
1435
1489
  var import_node_child_process = require("child_process");
1436
1490
  var path = __toESM(require("path"));
@@ -1524,8 +1578,6 @@ function jsCommand(loader, rest) {
1524
1578
  }
1525
1579
  if (argv[0] === "init") {
1526
1580
  jsCommand(() => Promise.resolve().then(() => (init_init(), init_exports)).then((m2) => m2.runInit), argv.slice(1));
1527
- } else if (argv[0] === "module" && argv[1] === "pack") {
1528
- jsCommand(() => Promise.resolve().then(() => (init_pack(), pack_exports)).then((m2) => m2.runPack), argv.slice(2));
1529
1581
  } else {
1530
1582
  spawnNative(argv);
1531
1583
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dforge-core/dforge-cli",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "dForge CLI - validate, pack, publish, and install dForge modules. Distributes a single-file native binary per platform via optionalDependencies (esbuild-style).",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/iash44/dForge-core",
@@ -41,11 +41,11 @@
41
41
  "typescript": "^6.0.3"
42
42
  },
43
43
  "optionalDependencies": {
44
- "@dforge-core/dforge-cli-darwin-arm64": "0.2.1",
45
- "@dforge-core/dforge-cli-darwin-x64": "0.2.1",
46
- "@dforge-core/dforge-cli-linux-arm64": "0.2.1",
47
- "@dforge-core/dforge-cli-linux-x64": "0.2.1",
48
- "@dforge-core/dforge-cli-win32-arm64": "0.2.1",
49
- "@dforge-core/dforge-cli-win32-x64": "0.2.1"
44
+ "@dforge-core/dforge-cli-darwin-arm64": "0.2.3",
45
+ "@dforge-core/dforge-cli-darwin-x64": "0.2.3",
46
+ "@dforge-core/dforge-cli-linux-arm64": "0.2.3",
47
+ "@dforge-core/dforge-cli-linux-x64": "0.2.3",
48
+ "@dforge-core/dforge-cli-win32-arm64": "0.2.3",
49
+ "@dforge-core/dforge-cli-win32-x64": "0.2.3"
50
50
  }
51
51
  }