@nanoforge-dev/cli 1.1.0 → 1.1.1

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/dist/nf.js CHANGED
@@ -40,7 +40,7 @@ var require_package = __commonJS({
40
40
  module2.exports = {
41
41
  $schema: "https://json.schemastore.org/package.json",
42
42
  name: "@nanoforge-dev/cli",
43
- version: "1.1.0",
43
+ version: "1.1.1",
44
44
  description: "NanoForge CLI",
45
45
  keywords: [
46
46
  "nanoforge",
@@ -79,6 +79,12 @@ var require_package = __commonJS({
79
79
  prepack: "pnpm run build && pnpm run lint",
80
80
  changelog: "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r . --include-path '.'",
81
81
  release: "cliff-jumper",
82
+ test: "pnpm run test:unit && pnpm run test:e2e",
83
+ "test:unit": "vitest run -c vitest.config.ts",
84
+ "test:unit:watch": "vitest -c vitest.config.ts",
85
+ "test:e2e": "vitest run -c vitest.config.e2e.ts",
86
+ "test:e2e:watch": "vitest -c vitest.config.e2e.ts",
87
+ "test:coverage": "pnpm run test:unit --coverage && pnpm run test:e2e",
82
88
  prepare: "husky"
83
89
  },
84
90
  dependencies: {
@@ -108,12 +114,14 @@ var require_package = __commonJS({
108
114
  "@trivago/prettier-plugin-sort-imports": "catalog:lint",
109
115
  "@types/inquirer": "catalog:cli",
110
116
  "@types/node": "catalog:core",
117
+ "@vitest/coverage-v8": "catalog:tests",
111
118
  eslint: "catalog:lint",
112
119
  husky: "catalog:ci",
113
120
  "lint-staged": "catalog:ci",
114
121
  prettier: "catalog:lint",
115
122
  tsup: "catalog:build",
116
- typescript: "catalog:build"
123
+ typescript: "catalog:build",
124
+ vitest: "catalog:tests"
117
125
  },
118
126
  packageManager: "pnpm@10.28.1",
119
127
  engines: {
@@ -236,7 +244,7 @@ var Prefixes = {
236
244
  import * as ansis from "ansis";
237
245
  import { watch } from "chokidar";
238
246
  import * as console2 from "console";
239
- import { dirname, join as join3 } from "path";
247
+ import { dirname, join as join4 } from "path";
240
248
 
241
249
  // src/lib/input/base-inputs.ts
242
250
  var getStringInput = /* @__PURE__ */ __name((input2, field) => {
@@ -377,7 +385,7 @@ var getInstallNamesInputOrAsk = /* @__PURE__ */ __name((inputs) => {
377
385
  }, "getInstallNamesInputOrAsk");
378
386
 
379
387
  // src/lib/package-manager/package-manager.factory.ts
380
- import fs from "fs";
388
+ import fs2 from "fs";
381
389
  import { resolve as resolve2 } from "path";
382
390
 
383
391
  // src/lib/runner/runner.factory.ts
@@ -451,7 +459,8 @@ var BunRunner = class extends AbstractRunner {
451
459
  };
452
460
 
453
461
  // src/lib/utils/path.ts
454
- import { resolve } from "path";
462
+ import fs from "fs";
463
+ import { join as join2, resolve } from "path";
455
464
  var getCwd = /* @__PURE__ */ __name((directory) => {
456
465
  return resolve(directory);
457
466
  }, "getCwd");
@@ -460,9 +469,19 @@ var getModulePath = /* @__PURE__ */ __name((name, removeLast = false) => {
460
469
  if (removeLast) return path.split("/").slice(0, -1).join("/");
461
470
  return path;
462
471
  }, "getModulePath");
463
- var getNodeBinaryPath = /* @__PURE__ */ __name((name) => {
464
- return resolve("node_modules", ".bin", name);
465
- }, "getNodeBinaryPath");
472
+ var resolveCLINodeBinaryPath = /* @__PURE__ */ __name((name) => {
473
+ let base = join2(getModulePath(".", true), "..");
474
+ while (base.length >= 1) {
475
+ const path = join2(base, "node_modules", ".bin", name);
476
+ try {
477
+ fs.accessSync(path);
478
+ return path;
479
+ } catch {
480
+ base = join2(base, "..");
481
+ }
482
+ }
483
+ throw new Error("Could not find module path");
484
+ }, "resolveCLINodeBinaryPath");
466
485
 
467
486
  // src/lib/runner/runners/local-bun.runner.ts
468
487
  var LocalBunRunner = class extends AbstractRunner {
@@ -470,7 +489,7 @@ var LocalBunRunner = class extends AbstractRunner {
470
489
  __name(this, "LocalBunRunner");
471
490
  }
472
491
  constructor() {
473
- super(getNodeBinaryPath("bun"));
492
+ super(resolveCLINodeBinaryPath("bun"));
474
493
  }
475
494
  };
476
495
 
@@ -652,7 +671,7 @@ var AbstractPackageManager = class {
652
671
  }
653
672
  async runDev(directory, command, env2 = {}, flags = [], collect = true) {
654
673
  try {
655
- const commandArgs = [this.cli.run, command, ...flags];
674
+ const commandArgs = [this.cli.exec, command, ...flags];
656
675
  await this.runner.run(commandArgs, collect, getCwd(directory), env2);
657
676
  return true;
658
677
  } catch {
@@ -730,6 +749,7 @@ var BunPackageManager = class extends AbstractPackageManager {
730
749
  add: "add",
731
750
  update: "update",
732
751
  remove: "remove",
752
+ exec: "exec",
733
753
  run: "run",
734
754
  saveFlag: "--save",
735
755
  saveDevFlag: "--dev",
@@ -755,6 +775,7 @@ var LocalBunPackageManager = class extends AbstractPackageManager {
755
775
  add: "add",
756
776
  update: "update",
757
777
  remove: "remove",
778
+ exec: "exec",
758
779
  run: "run",
759
780
  build: "build",
760
781
  runFile: "run",
@@ -782,6 +803,7 @@ var NpmPackageManager = class extends AbstractPackageManager {
782
803
  add: "install",
783
804
  update: "update",
784
805
  remove: "uninstall",
806
+ exec: "exec",
785
807
  run: "run",
786
808
  saveFlag: "--save",
787
809
  saveDevFlag: "--save-dev",
@@ -807,6 +829,7 @@ var PnpmPackageManager = class extends AbstractPackageManager {
807
829
  add: "add",
808
830
  update: "update",
809
831
  remove: "remove",
832
+ exec: "exec",
810
833
  run: "run",
811
834
  saveFlag: "-P",
812
835
  saveDevFlag: "-D",
@@ -832,6 +855,7 @@ var YarnPackageManager = class extends AbstractPackageManager {
832
855
  add: "add",
833
856
  update: "update",
834
857
  remove: "remove",
858
+ exec: "exec",
835
859
  run: "run",
836
860
  saveFlag: "",
837
861
  saveDevFlag: "-D",
@@ -864,7 +888,7 @@ var PackageManagerFactory = class {
864
888
  static async find(directory = ".") {
865
889
  const DEFAULT_PACKAGE_MANAGER = "npm" /* NPM */;
866
890
  try {
867
- const files = await fs.promises.readdir(resolve2(directory));
891
+ const files = await fs2.promises.readdir(resolve2(directory));
868
892
  if (files.includes("bun.lock")) {
869
893
  return this.create("bun" /* BUN */);
870
894
  }
@@ -1007,7 +1031,7 @@ __decorateClass([
1007
1031
  import { plainToInstance } from "class-transformer";
1008
1032
  import { validate } from "class-validator";
1009
1033
  import { existsSync as existsSync2, readFileSync } from "fs";
1010
- import { join as join2 } from "path";
1034
+ import { join as join3 } from "path";
1011
1035
 
1012
1036
  // src/lib/utils/object.ts
1013
1037
  var isObject = /* @__PURE__ */ __name((item) => {
@@ -1062,10 +1086,10 @@ var CONFIG_DEFAULTS = {
1062
1086
  var config;
1063
1087
  var getConfigPath = /* @__PURE__ */ __name((directory, name) => {
1064
1088
  if (name) {
1065
- return join2(directory, name);
1089
+ return join3(directory, name);
1066
1090
  } else {
1067
1091
  for (const n of ["nanoforge.config.json"]) {
1068
- const path = join2(directory, n);
1092
+ const path = join3(directory, n);
1069
1093
  if (existsSync2(path)) return path;
1070
1094
  }
1071
1095
  throw new Error(`Unsupported config: ${name}`);
@@ -1137,8 +1161,11 @@ var BuildAction = class extends AbstractAction {
1137
1161
  console2.info();
1138
1162
  return;
1139
1163
  }
1140
- if (!res) console2.info(Messages.BUILD_FAILED);
1141
- else console2.info(Messages.BUILD_SUCCESS);
1164
+ if (!res) {
1165
+ console2.info(Messages.BUILD_FAILED);
1166
+ process.exit(1);
1167
+ }
1168
+ console2.info(Messages.BUILD_SUCCESS);
1142
1169
  process.exit(0);
1143
1170
  } catch (e) {
1144
1171
  console2.error(e);
@@ -1179,7 +1206,7 @@ var buildPart = /* @__PURE__ */ __name(async (name, part, directory, options) =>
1179
1206
  }
1180
1207
  }, "build");
1181
1208
  if (options?.watch)
1182
- watch(dirname(join3(getCwd(directory), part.entry))).on("change", () => build(true));
1209
+ watch(dirname(join4(getCwd(directory), part.entry))).on("change", () => build(true));
1183
1210
  return await build();
1184
1211
  }, "buildPart");
1185
1212
 
@@ -1222,7 +1249,7 @@ var runAction = /* @__PURE__ */ __name(async (command, params, directory, stdout
1222
1249
 
1223
1250
  // src/action/actions/generate.action.ts
1224
1251
  import * as console3 from "console";
1225
- import { join as join4 } from "path";
1252
+ import { join as join5 } from "path";
1226
1253
 
1227
1254
  // src/lib/schematics/abstract.collection.ts
1228
1255
  var AbstractCollection = class {
@@ -1350,7 +1377,7 @@ var SchematicOption = class {
1350
1377
  }
1351
1378
  } else if (typeof this.value === "boolean") {
1352
1379
  const str = normalizedName;
1353
- return this.value ? [`--${str}`] : [`--no-${str}`];
1380
+ return this.value ? [`--${str}=true`] : [`--${str}=false`];
1354
1381
  } else if (Array.isArray(this.value)) {
1355
1382
  return this.value.reduce(
1356
1383
  (old, option) => [
@@ -1463,7 +1490,7 @@ var generateFiles = /* @__PURE__ */ __name(async (values, directory, watch3) =>
1463
1490
  language: values.language,
1464
1491
  initFunctions: values.initFunctions
1465
1492
  },
1466
- watch3 ? join4(getCwd(directory), values.directory, ".nanoforge", "client.save.json") : void 0
1493
+ watch3 ? join5(getCwd(directory), values.directory, ".nanoforge", "client.save.json") : void 0
1467
1494
  );
1468
1495
  if (values.server) {
1469
1496
  await executeSchematic(
@@ -1477,7 +1504,7 @@ var generateFiles = /* @__PURE__ */ __name(async (values, directory, watch3) =>
1477
1504
  language: values.language,
1478
1505
  initFunctions: values.initFunctions
1479
1506
  },
1480
- join4(getCwd(directory), values.directory, ".nanoforge", "server.save.json")
1507
+ join5(getCwd(directory), values.directory, ".nanoforge", "server.save.json")
1481
1508
  );
1482
1509
  }
1483
1510
  }, "generateFiles");
@@ -1506,17 +1533,20 @@ var InstallAction = class extends AbstractAction {
1506
1533
  var installPackages = /* @__PURE__ */ __name(async (names, directory) => {
1507
1534
  try {
1508
1535
  const packageManager = await PackageManagerFactory.find(directory);
1509
- await packageManager.addProduction(directory, names);
1536
+ const res = await packageManager.addProduction(directory, names);
1537
+ if (!res) process3.exit(1);
1510
1538
  } catch (error4) {
1511
1539
  if (error4 && error4.message) {
1512
1540
  console.error(ansis3.red(error4.message));
1513
1541
  }
1542
+ process3.exit(1);
1514
1543
  }
1515
1544
  }, "installPackages");
1516
1545
 
1517
1546
  // src/action/actions/new.action.ts
1518
1547
  import * as ansis4 from "ansis";
1519
1548
  import console4 from "console";
1549
+ import * as process4 from "process";
1520
1550
 
1521
1551
  // src/lib/input/inputs/new/init-functions.input.ts
1522
1552
  var getNewInitFunctionsWithDefault = /* @__PURE__ */ __name((inputs) => {
@@ -1619,10 +1649,10 @@ var NewAction = class extends AbstractAction {
1619
1649
  if (!values.skipInstall) await runInstall(directory, values.packageManager);
1620
1650
  console4.info();
1621
1651
  console4.info(Messages.NEW_SUCCESS);
1622
- process.exit(0);
1652
+ process4.exit(0);
1623
1653
  } catch {
1624
1654
  console4.error(Messages.NEW_FAILED);
1625
- process.exit(1);
1655
+ process4.exit(1);
1626
1656
  }
1627
1657
  }
1628
1658
  };
@@ -1696,13 +1726,15 @@ var runInstall = /* @__PURE__ */ __name(async (directory, pkgManagerName) => {
1696
1726
  if (error4 && error4.message) {
1697
1727
  console4.error(ansis4.red(error4.message));
1698
1728
  }
1729
+ process4.exit(1);
1699
1730
  }
1700
1731
  }, "runInstall");
1701
1732
 
1702
1733
  // src/action/actions/start.action.ts
1703
1734
  import * as ansis5 from "ansis";
1704
1735
  import * as console5 from "console";
1705
- import { join as join5 } from "path";
1736
+ import * as process5 from "process";
1737
+ import { join as join6 } from "path";
1706
1738
  var StartAction = class extends AbstractAction {
1707
1739
  static {
1708
1740
  __name(this, "StartAction");
@@ -1716,30 +1748,41 @@ var StartAction = class extends AbstractAction {
1716
1748
  const clientDir = config2.client.runtime.dir;
1717
1749
  const serverDir = config2.server.runtime.dir;
1718
1750
  const clientPort = getStringInputWithDefault(options, "clientPort", config2.client.port);
1751
+ const cert = getStringInput(options, "cert");
1752
+ const key = getStringInput(options, "key");
1719
1753
  const watch3 = getWatchInput(options);
1720
1754
  await Promise.all([
1721
1755
  config2.server.enable ? this.startServer(directory, serverDir, watch3) : void 0,
1722
- this.startClient(clientPort, directory, clientDir, {
1723
- watch: watch3,
1724
- serverGameDir: config2.server.enable ? serverDir : void 0
1725
- })
1756
+ this.startClient(
1757
+ clientPort,
1758
+ directory,
1759
+ clientDir,
1760
+ {
1761
+ watch: watch3,
1762
+ serverGameDir: config2.server.enable ? serverDir : void 0
1763
+ },
1764
+ cert,
1765
+ key
1766
+ )
1726
1767
  ]);
1727
- process.exit(0);
1768
+ process5.exit(0);
1728
1769
  } catch (e) {
1729
1770
  console5.error(e);
1730
- process.exit(1);
1771
+ process5.exit(1);
1731
1772
  }
1732
1773
  }
1733
- async startClient(port, directory, gameDir, options) {
1774
+ async startClient(port, directory, gameDir, options, cert, key) {
1734
1775
  const path = getModulePath("@nanoforge-dev/loader-client/package.json", true);
1735
1776
  const params = {
1736
1777
  PORT: port,
1737
- GAME_DIR: getCwd(join5(directory, gameDir))
1778
+ GAME_DIR: getCwd(join6(directory, gameDir)),
1779
+ CERT: cert ? join6(getCwd(directory), cert) : void 0,
1780
+ KEY: key ? join6(getCwd(directory), key) : void 0
1738
1781
  };
1739
1782
  if (options?.watch) {
1740
1783
  params["WATCH"] = "true";
1741
1784
  if (options?.serverGameDir) {
1742
- params["WATCH_SERVER_GAME_DIR"] = getCwd(join5(directory, options.serverGameDir));
1785
+ params["WATCH_SERVER_GAME_DIR"] = getCwd(join6(directory, options.serverGameDir));
1743
1786
  }
1744
1787
  }
1745
1788
  return runPart("Client", path, params);
@@ -1747,7 +1790,7 @@ var StartAction = class extends AbstractAction {
1747
1790
  startServer(directory, gameDir, watch3) {
1748
1791
  const path = getModulePath("@nanoforge-dev/loader-server/package.json", true);
1749
1792
  const params = {
1750
- GAME_DIR: getCwd(join5(directory, gameDir))
1793
+ GAME_DIR: getCwd(join6(directory, gameDir))
1751
1794
  };
1752
1795
  if (watch3) params["WATCH"] = "true";
1753
1796
  return runPart("Server", path, params);
@@ -1875,7 +1918,7 @@ var StartCommand = class extends AbstractCommand {
1875
1918
  program2.command("start").description("start your game").option("-d, --directory [directory]", "specify the directory of your project").option("-c, --config [config]", "path to the config file", "nanoforge.config.json").option(
1876
1919
  "-p, --client-port [clientPort]",
1877
1920
  "specify the port of the loader (the website to load the game)"
1878
- ).option("--game-exposure-port [gameExposurePort]", "specify the port of the game exposure").option("--server-port [serverPort]", "specify the port of the server").option("--watch", "run app in watching mode", false).action(async (rawOptions) => {
1921
+ ).option("--game-exposure-port [gameExposurePort]", "specify the port of the game exposure").option("--server-port [serverPort]", "specify the port of the server").option("--watch", "run app in watching mode", false).option("--cert [cert]", "path to the SSL certificate for HTTPS").option("--key [key]", "path to the SSL key for HTTPS").action(async (rawOptions) => {
1879
1922
  const options = /* @__PURE__ */ new Map();
1880
1923
  options.set("directory", { value: rawOptions.directory });
1881
1924
  options.set("config", { value: rawOptions.config });
@@ -1885,6 +1928,8 @@ var StartCommand = class extends AbstractCommand {
1885
1928
  });
1886
1929
  options.set("serverPort", { value: rawOptions.serverPort });
1887
1930
  options.set("watch", { value: rawOptions.watch });
1931
+ options.set("cert", { value: rawOptions.cert });
1932
+ options.set("key", { value: rawOptions.key });
1888
1933
  const args = /* @__PURE__ */ new Map();
1889
1934
  await this.action.handle(args, options);
1890
1935
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "@nanoforge-dev/cli",
4
- "version": "1.1.0",
4
+ "version": "1.1.1",
5
5
  "description": "NanoForge CLI",
6
6
  "keywords": [
7
7
  "nanoforge",
@@ -33,38 +33,40 @@
33
33
  },
34
34
  "funding": "",
35
35
  "dependencies": {
36
- "@angular-devkit/schematics": "^21.1.0",
37
- "@angular-devkit/schematics-cli": "^21.1.0",
38
- "@inquirer/prompts": "^8.2.0",
39
- "@nanoforge-dev/loader-client": "^1.1.0",
36
+ "@angular-devkit/schematics": "^21.1.4",
37
+ "@angular-devkit/schematics-cli": "^21.1.4",
38
+ "@inquirer/prompts": "^8.2.1",
39
+ "@nanoforge-dev/loader-client": "^1.2.0",
40
40
  "@nanoforge-dev/loader-server": "^1.1.0",
41
41
  "@nanoforge-dev/schematics": "^1.0.2",
42
42
  "ansis": "^4.2.0",
43
- "bun": "^1.3.6",
43
+ "bun": "^1.3.9",
44
44
  "chokidar": "^5.0.0",
45
45
  "class-transformer": "^0.5.1",
46
46
  "class-validator": "^0.14.3",
47
- "commander": "^14.0.2",
47
+ "commander": "^14.0.3",
48
48
  "node-emoji": "^2.2.0",
49
- "ora": "^9.0.0",
49
+ "ora": "^9.3.0",
50
50
  "reflect-metadata": "^0.2.2"
51
51
  },
52
52
  "devDependencies": {
53
- "@commitlint/cli": "^20.3.1",
54
- "@commitlint/config-conventional": "^20.3.1",
53
+ "@commitlint/cli": "^20.4.1",
54
+ "@commitlint/config-conventional": "^20.4.1",
55
55
  "@favware/cliff-jumper": "^6.0.0",
56
56
  "@nanoforge-dev/actions": "^1.1.0",
57
- "@nanoforge-dev/utils-eslint-config": "^1.0.1",
58
- "@nanoforge-dev/utils-prettier-config": "^1.0.1",
57
+ "@nanoforge-dev/utils-eslint-config": "^1.0.2",
58
+ "@nanoforge-dev/utils-prettier-config": "^1.0.2",
59
59
  "@trivago/prettier-plugin-sort-imports": "^6.0.2",
60
60
  "@types/inquirer": "^9.0.9",
61
- "@types/node": "^25.0.9",
62
- "eslint": "^9.39.2",
61
+ "@types/node": "^25.2.3",
62
+ "@vitest/coverage-v8": "^4.0.18",
63
+ "eslint": "^10.0.0",
63
64
  "husky": "^9.1.7",
64
65
  "lint-staged": "^16.2.7",
65
- "prettier": "^3.8.0",
66
+ "prettier": "^3.8.1",
66
67
  "tsup": "^8.5.1",
67
- "typescript": "^5.9.3"
68
+ "typescript": "^5.9.3",
69
+ "vitest": "^4.0.18"
68
70
  },
69
71
  "engines": {
70
72
  "node": "25"
@@ -86,6 +88,12 @@
86
88
  "lint": "prettier --check . && eslint --format=pretty src",
87
89
  "format": "prettier --write . && eslint --fix --format=pretty src",
88
90
  "changelog": "git cliff --prepend ./CHANGELOG.md -u -c ./cliff.toml -r . --include-path '.'",
89
- "release": "cliff-jumper"
91
+ "release": "cliff-jumper",
92
+ "test": "pnpm run test:unit && pnpm run test:e2e",
93
+ "test:unit": "vitest run -c vitest.config.ts",
94
+ "test:unit:watch": "vitest -c vitest.config.ts",
95
+ "test:e2e": "vitest run -c vitest.config.e2e.ts",
96
+ "test:e2e:watch": "vitest -c vitest.config.e2e.ts",
97
+ "test:coverage": "pnpm run test:unit --coverage && pnpm run test:e2e"
90
98
  }
91
99
  }