@nanoforge-dev/cli 1.0.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.
@@ -11,7 +11,7 @@ var __decorateClass = (decorators, target, key, kind) => {
11
11
  };
12
12
 
13
13
  // src/command/command.loader.ts
14
- import { red as red6 } from "ansis";
14
+ import { red as red8 } from "ansis";
15
15
 
16
16
  // src/lib/ui/messages.ts
17
17
  import { green } from "ansis";
@@ -41,7 +41,9 @@ var Emojis = {
41
41
  // src/lib/ui/messages.ts
42
42
  var Messages = {
43
43
  BUILD_START: "NanoForge Build",
44
- BUILD_PART_IN_PROGRESS: /* @__PURE__ */ __name((part) => `Building ${part}...`, "BUILD_PART_IN_PROGRESS"),
44
+ BUILD_WATCH_START: "Start watching mode",
45
+ BUILD_PART_IN_PROGRESS: /* @__PURE__ */ __name((part) => `Building ${part}`, "BUILD_PART_IN_PROGRESS"),
46
+ BUILD_PART_WATCH_IN_PROGRESS: /* @__PURE__ */ __name((part) => `${part} updated. Rebuilding`, "BUILD_PART_WATCH_IN_PROGRESS"),
45
47
  BUILD_NOTHING: "Nothing to build, terminated.",
46
48
  BUILD_SUCCESS: `${Emojis.ROCKET} Build succeeded !`,
47
49
  BUILD_PART_FAILED: /* @__PURE__ */ __name((part, commandToRunManually) => `${Emojis.SCREAM} Build of ${part} failed !
@@ -58,8 +60,16 @@ In case you don't see any errors above, consider manually running the failed com
58
60
  NEW_STRICT_QUESTION: "Do you want to use types strict mode ?",
59
61
  NEW_SERVER_QUESTION: "Do you want generate a server to create a multiplayer game ?",
60
62
  NEW_SKIP_INSTALL_QUESTION: "Do you want to skip installation ?",
63
+ GENERATE_START: "NanoForge Generate",
64
+ GENERATE_WATCH_START: "Start watching mode",
65
+ GENERATE_SUCCESS: `${Emojis.ROCKET} Generate succeeded !`,
66
+ GENERATE_FAILED: `${Emojis.SCREAM} Generate failed !`,
67
+ DEV_START: "NanoForge Dev mode",
68
+ DEV_SUCCESS: "Dev mode ended",
69
+ DEV_FAILED: `${Emojis.SCREAM} Dev failed !`,
61
70
  SCHEMATICS_START: "Schematics execution",
62
71
  SCHEMATIC_IN_PROGRESS: /* @__PURE__ */ __name((name) => `Executing schematic ${name}...`, "SCHEMATIC_IN_PROGRESS"),
72
+ SCHEMATIC_WATCH_IN_PROGRESS: /* @__PURE__ */ __name((name) => `Update watched. Executing schematic ${name}...`, "SCHEMATIC_WATCH_IN_PROGRESS"),
63
73
  SCHEMATIC_SUCCESS: /* @__PURE__ */ __name((name) => `${Emojis.ROCKET} Schematic ${name} executed successfully !`, "SCHEMATIC_SUCCESS"),
64
74
  SCHEMATIC_FAILED: /* @__PURE__ */ __name((name) => `${Emojis.SCREAM} Schematic ${name} execution failed. See error below for more details.`, "SCHEMATIC_FAILED"),
65
75
  PACKAGE_MANAGER_INSTALLATION_IN_PROGRESS: `Installation in progress... ${Emojis.COFFEE}`,
@@ -84,7 +94,9 @@ var Prefixes = {
84
94
 
85
95
  // src/action/actions/build.action.ts
86
96
  import * as ansis from "ansis";
87
- import * as process3 from "process";
97
+ import { watch } from "chokidar";
98
+ import * as console2 from "console";
99
+ import { dirname, join as join3 } from "path";
88
100
 
89
101
  // src/lib/input/base-inputs.ts
90
102
  var getStringInput = /* @__PURE__ */ __name((input2, field) => {
@@ -133,6 +145,16 @@ var getConfigInput = /* @__PURE__ */ __name((inputs) => {
133
145
  return getStringInputWithDefault(inputs, "config", ".");
134
146
  }, "getConfigInput");
135
147
 
148
+ // src/lib/input/inputs/watch.input.ts
149
+ var getWatchInput = /* @__PURE__ */ __name((inputs) => {
150
+ return getBooleanInputWithDefault(inputs, "watch", false);
151
+ }, "getWatchInput");
152
+
153
+ // src/lib/input/inputs/dev/generate.input.ts
154
+ var getDevGenerateInput = /* @__PURE__ */ __name((inputs) => {
155
+ return getBooleanInputWithDefault(inputs, "generate", false);
156
+ }, "getDevGenerateInput");
157
+
136
158
  // src/lib/question/questions/confirm.question.ts
137
159
  import { confirm } from "@inquirer/prompts";
138
160
 
@@ -214,6 +236,10 @@ var getInstallNamesInputOrAsk = /* @__PURE__ */ __name((inputs) => {
214
236
  );
215
237
  }, "getInstallNamesInputOrAsk");
216
238
 
239
+ // src/lib/package-manager/package-manager.factory.ts
240
+ import fs2 from "fs";
241
+ import { resolve as resolve2 } from "path";
242
+
217
243
  // src/lib/runner/runner.factory.ts
218
244
  import { yellow } from "ansis";
219
245
 
@@ -236,7 +262,7 @@ var AbstractRunner = class {
236
262
  shell: true,
237
263
  env: { ...process2.env, ...env2 }
238
264
  };
239
- return new Promise((resolve, reject) => {
265
+ return new Promise((resolve3, reject) => {
240
266
  const child = spawn(
241
267
  `${this.binary} ${[...this.args, ...args].join(" ")}`,
242
268
  options
@@ -252,7 +278,7 @@ var AbstractRunner = class {
252
278
  );
253
279
  child.on("close", (code) => {
254
280
  if (code === 0) {
255
- resolve(collect && res.length ? res.join("\n") : null);
281
+ resolve3(collect && res.length ? res.join("\n") : null);
256
282
  } else {
257
283
  if (failSpinner) failSpinner();
258
284
  console.error(
@@ -285,15 +311,59 @@ var BunRunner = class extends AbstractRunner {
285
311
  };
286
312
 
287
313
  // src/lib/utils/path.ts
288
- import { join } from "path";
314
+ import fs from "fs";
315
+ import { join, resolve } from "path";
289
316
  var getCwd = /* @__PURE__ */ __name((directory) => {
290
- return directory.startsWith("/") ? directory : join(process.cwd(), directory);
317
+ return resolve(directory);
291
318
  }, "getCwd");
292
319
  var getModulePath = /* @__PURE__ */ __name((name, removeLast = false) => {
293
320
  const path = import.meta.resolve(name).replace(/^file:\/\//, "");
294
321
  if (removeLast) return path.split("/").slice(0, -1).join("/");
295
322
  return path;
296
323
  }, "getModulePath");
324
+ var resolveCLINodeBinaryPath = /* @__PURE__ */ __name((name) => {
325
+ let base = join(getModulePath(".", true), "..");
326
+ while (base.length >= 1) {
327
+ const path = join(base, "node_modules", ".bin", name);
328
+ try {
329
+ fs.accessSync(path);
330
+ return path;
331
+ } catch {
332
+ base = join(base, "..");
333
+ }
334
+ }
335
+ throw new Error("Could not find module path");
336
+ }, "resolveCLINodeBinaryPath");
337
+
338
+ // src/lib/runner/runners/local-bun.runner.ts
339
+ var LocalBunRunner = class extends AbstractRunner {
340
+ static {
341
+ __name(this, "LocalBunRunner");
342
+ }
343
+ constructor() {
344
+ super(resolveCLINodeBinaryPath("bun"));
345
+ }
346
+ };
347
+
348
+ // src/lib/runner/runners/npm.runner.ts
349
+ var NpmRunner = class extends AbstractRunner {
350
+ static {
351
+ __name(this, "NpmRunner");
352
+ }
353
+ constructor() {
354
+ super("npm");
355
+ }
356
+ };
357
+
358
+ // src/lib/runner/runners/pnpm.runner.ts
359
+ var PnpmRunner = class extends AbstractRunner {
360
+ static {
361
+ __name(this, "PnpmRunner");
362
+ }
363
+ constructor() {
364
+ super("pnpm");
365
+ }
366
+ };
297
367
 
298
368
  // src/lib/runner/runners/schematic.runner.ts
299
369
  var SchematicRunner = class _SchematicRunner extends AbstractRunner {
@@ -316,6 +386,16 @@ var SchematicRunner = class _SchematicRunner extends AbstractRunner {
316
386
  }
317
387
  };
318
388
 
389
+ // src/lib/runner/runners/yarn.runner.ts
390
+ var YarnRunner = class extends AbstractRunner {
391
+ static {
392
+ __name(this, "YarnRunner");
393
+ }
394
+ constructor() {
395
+ super("yarn");
396
+ }
397
+ };
398
+
319
399
  // src/lib/runner/runner.factory.ts
320
400
  var RunnerFactory = class {
321
401
  static {
@@ -325,8 +405,16 @@ var RunnerFactory = class {
325
405
  switch (runner) {
326
406
  case 0 /* BUN */:
327
407
  return new BunRunner();
328
- case 1 /* SCHEMATIC */:
408
+ case 1 /* LOCAL_BUN */:
409
+ return new LocalBunRunner();
410
+ case 2 /* NPM */:
411
+ return new NpmRunner();
412
+ case 3 /* PNPM */:
413
+ return new PnpmRunner();
414
+ case 4 /* SCHEMATIC */:
329
415
  return new SchematicRunner();
416
+ case 5 /* YARN */:
417
+ return new YarnRunner();
330
418
  default:
331
419
  console.info(yellow`[WARN] Unsupported runner: ${runner}`);
332
420
  throw Error(`Unsupported runner: ${runner}`);
@@ -383,9 +471,11 @@ var AbstractPackageManager = class {
383
471
  const command = [this.cli.add, this.cli.saveDevFlag];
384
472
  return this.add(command, directory, dependencies);
385
473
  }
386
- async build(name, directory, entry, output, flags) {
474
+ async build(name, directory, entry, output, flags, watch3) {
387
475
  if (!this.cli.build) throw new Error(`Package manager ${this.name} does not support building`);
388
- const spinner = SPINNER(Messages.BUILD_PART_IN_PROGRESS(name));
476
+ const spinner = SPINNER(
477
+ (watch3 ? Messages.BUILD_PART_WATCH_IN_PROGRESS : Messages.BUILD_PART_IN_PROGRESS)(name)
478
+ );
389
479
  spinner.start();
390
480
  try {
391
481
  const commandArgs = [
@@ -415,7 +505,6 @@ var AbstractPackageManager = class {
415
505
  }
416
506
  }
417
507
  async run(name, directory, file, env2 = {}, flags = [], silent = false) {
418
- if (!this.cli.run) throw new Error(`Package manager ${this.name} does not support running`);
419
508
  try {
420
509
  console.info(Messages.RUN_PART_IN_PROGRESS(name));
421
510
  const commandArgs = [...flags, this.cli.run];
@@ -432,6 +521,15 @@ var AbstractPackageManager = class {
432
521
  return false;
433
522
  }
434
523
  }
524
+ async runDev(directory, command, env2 = {}, flags = [], collect = true) {
525
+ try {
526
+ const commandArgs = [this.cli.exec, command, ...flags];
527
+ await this.runner.run(commandArgs, collect, getCwd(directory), env2);
528
+ return true;
529
+ } catch {
530
+ return false;
531
+ }
532
+ }
435
533
  async add(args, directory, dependencies) {
436
534
  if (!dependencies.length) {
437
535
  console.info();
@@ -503,7 +601,7 @@ var BunPackageManager = class extends AbstractPackageManager {
503
601
  add: "add",
504
602
  update: "update",
505
603
  remove: "remove",
506
- build: "build",
604
+ exec: "exec",
507
605
  run: "run",
508
606
  saveFlag: "--save",
509
607
  saveDevFlag: "--dev",
@@ -512,6 +610,112 @@ var BunPackageManager = class extends AbstractPackageManager {
512
610
  }
513
611
  };
514
612
 
613
+ // src/lib/package-manager/package-managers/local-bun.package-manager.ts
614
+ var LocalBunPackageManager = class extends AbstractPackageManager {
615
+ static {
616
+ __name(this, "LocalBunPackageManager");
617
+ }
618
+ constructor() {
619
+ super(RunnerFactory.create(1 /* LOCAL_BUN */));
620
+ }
621
+ get name() {
622
+ return "local_bun" /* LOCAL_BUN */.toUpperCase();
623
+ }
624
+ get cli() {
625
+ return {
626
+ install: "install",
627
+ add: "add",
628
+ update: "update",
629
+ remove: "remove",
630
+ exec: "exec",
631
+ run: "run",
632
+ build: "build",
633
+ runFile: "run",
634
+ saveFlag: "--save",
635
+ saveDevFlag: "--dev",
636
+ silentFlag: "--silent"
637
+ };
638
+ }
639
+ };
640
+
641
+ // src/lib/package-manager/package-managers/npm.package-manager.ts
642
+ var NpmPackageManager = class extends AbstractPackageManager {
643
+ static {
644
+ __name(this, "NpmPackageManager");
645
+ }
646
+ constructor() {
647
+ super(RunnerFactory.create(2 /* NPM */));
648
+ }
649
+ get name() {
650
+ return "npm" /* NPM */.toUpperCase();
651
+ }
652
+ get cli() {
653
+ return {
654
+ install: "install",
655
+ add: "install",
656
+ update: "update",
657
+ remove: "uninstall",
658
+ exec: "exec",
659
+ run: "run",
660
+ saveFlag: "--save",
661
+ saveDevFlag: "--save-dev",
662
+ silentFlag: "--silent"
663
+ };
664
+ }
665
+ };
666
+
667
+ // src/lib/package-manager/package-managers/pnpm.package-manager.ts
668
+ var PnpmPackageManager = class extends AbstractPackageManager {
669
+ static {
670
+ __name(this, "PnpmPackageManager");
671
+ }
672
+ constructor() {
673
+ super(RunnerFactory.create(3 /* PNPM */));
674
+ }
675
+ get name() {
676
+ return "pnpm" /* PNPM */.toUpperCase();
677
+ }
678
+ get cli() {
679
+ return {
680
+ install: "install",
681
+ add: "add",
682
+ update: "update",
683
+ remove: "remove",
684
+ exec: "exec",
685
+ run: "run",
686
+ saveFlag: "-P",
687
+ saveDevFlag: "-D",
688
+ silentFlag: "--silent"
689
+ };
690
+ }
691
+ };
692
+
693
+ // src/lib/package-manager/package-managers/yarn.package-manager.ts
694
+ var YarnPackageManager = class extends AbstractPackageManager {
695
+ static {
696
+ __name(this, "YarnPackageManager");
697
+ }
698
+ constructor() {
699
+ super(RunnerFactory.create(5 /* YARN */));
700
+ }
701
+ get name() {
702
+ return "yarn" /* YARN */.toUpperCase();
703
+ }
704
+ get cli() {
705
+ return {
706
+ install: "install",
707
+ add: "add",
708
+ update: "update",
709
+ remove: "remove",
710
+ exec: "exec",
711
+ run: "run",
712
+ saveFlag: "",
713
+ saveDevFlag: "-D",
714
+ silentFlag: "--silent"
715
+ };
716
+ }
717
+ };
718
+
515
719
  // src/lib/package-manager/package-manager.factory.ts
516
720
  var PackageManagerFactory = class {
517
721
  static {
@@ -521,10 +725,39 @@ var PackageManagerFactory = class {
521
725
  switch (name) {
522
726
  case "bun" /* BUN */:
523
727
  return new BunPackageManager();
728
+ case "local_bun" /* LOCAL_BUN */:
729
+ return new LocalBunPackageManager();
730
+ case "npm" /* NPM */:
731
+ return new NpmPackageManager();
732
+ case "pnpm" /* PNPM */:
733
+ return new PnpmPackageManager();
734
+ case "yarn" /* YARN */:
735
+ return new YarnPackageManager();
524
736
  default:
525
737
  throw new Error(`Package manager ${name} is not managed.`);
526
738
  }
527
739
  }
740
+ static async find(directory = ".") {
741
+ const DEFAULT_PACKAGE_MANAGER = "npm" /* NPM */;
742
+ try {
743
+ const files = await fs2.promises.readdir(resolve2(directory));
744
+ if (files.includes("bun.lock")) {
745
+ return this.create("bun" /* BUN */);
746
+ }
747
+ if (files.includes("package-lock.json")) {
748
+ return this.create("npm" /* NPM */);
749
+ }
750
+ if (files.includes("pnpm-lock.yaml")) {
751
+ return this.create("pnpm" /* PNPM */);
752
+ }
753
+ if (files.includes("yarn.lock")) {
754
+ return this.create("yarn" /* YARN */);
755
+ }
756
+ return this.create(DEFAULT_PACKAGE_MANAGER);
757
+ } catch {
758
+ return this.create(DEFAULT_PACKAGE_MANAGER);
759
+ }
760
+ }
528
761
  };
529
762
 
530
763
  // src/lib/config/config.type.ts
@@ -754,32 +987,41 @@ var BuildAction = class extends AbstractAction {
754
987
  __name(this, "BuildAction");
755
988
  }
756
989
  async handle(_args, options) {
757
- console.info(Messages.BUILD_START);
758
- console.info();
990
+ console2.info(Messages.BUILD_START);
991
+ console2.info();
759
992
  try {
760
993
  const directory = getDirectoryInput(options);
761
994
  const config2 = await getConfig(options, directory);
995
+ const watch3 = getWatchInput(options);
762
996
  const client = getPart(
763
997
  config2.client.build,
764
998
  options.get("clientDirectory")?.value,
765
999
  "client"
766
1000
  );
767
- let res = await buildPart("Client", client, directory);
1001
+ let res = await buildPart("Client", client, directory, { watch: watch3 });
768
1002
  if (config2.server.enable) {
769
1003
  const server = getPart(
770
1004
  config2.server.build,
771
1005
  options.get("serverDirectory")?.value,
772
1006
  "server"
773
1007
  );
774
- res = await buildPart("Server", server, directory) ? res : false;
1008
+ res = await buildPart("Server", server, directory, { watch: watch3 }) ? res : false;
775
1009
  }
776
- console.info();
777
- if (!res) console.info(Messages.BUILD_FAILED);
778
- else console.info(Messages.BUILD_SUCCESS);
779
- process3.exit(0);
1010
+ console2.info();
1011
+ if (watch3) {
1012
+ console2.info(Messages.BUILD_WATCH_START);
1013
+ console2.info();
1014
+ return;
1015
+ }
1016
+ if (!res) {
1017
+ console2.info(Messages.BUILD_FAILED);
1018
+ process.exit(1);
1019
+ }
1020
+ console2.info(Messages.BUILD_SUCCESS);
1021
+ process.exit(0);
780
1022
  } catch (e) {
781
- console.error(e);
782
- process3.exit(1);
1023
+ console2.error(e);
1024
+ process.exit(1);
783
1025
  }
784
1026
  }
785
1027
  };
@@ -790,26 +1032,76 @@ var getPart = /* @__PURE__ */ __name((config2, directoryOption, target) => {
790
1032
  target
791
1033
  };
792
1034
  }, "getPart");
793
- var buildPart = /* @__PURE__ */ __name(async (name, part, directory) => {
794
- const packageManagerName = "bun" /* BUN */;
1035
+ var buildPart = /* @__PURE__ */ __name(async (name, part, directory, options) => {
1036
+ const packageManagerName = "local_bun" /* LOCAL_BUN */;
1037
+ const packageManager = PackageManagerFactory.create(packageManagerName);
1038
+ const build = /* @__PURE__ */ __name(async (watch3 = false) => {
1039
+ try {
1040
+ return await packageManager.build(
1041
+ name,
1042
+ directory,
1043
+ part.entry,
1044
+ part.output,
1045
+ [
1046
+ "--asset-naming",
1047
+ "[name].[ext]",
1048
+ "--target",
1049
+ part.target === "client" ? "browser" : "node"
1050
+ ],
1051
+ watch3
1052
+ );
1053
+ } catch (error4) {
1054
+ if (error4 && error4.message) {
1055
+ console2.error(ansis.red(error4.message));
1056
+ }
1057
+ return false;
1058
+ }
1059
+ }, "build");
1060
+ if (options?.watch)
1061
+ watch(dirname(join3(getCwd(directory), part.entry))).on("change", () => build(true));
1062
+ return await build();
1063
+ }, "buildPart");
1064
+
1065
+ // src/action/actions/dev.action.ts
1066
+ import * as ansis2 from "ansis";
1067
+ var DevAction = class extends AbstractAction {
1068
+ static {
1069
+ __name(this, "DevAction");
1070
+ }
1071
+ async handle(_args, options) {
1072
+ console.info(Messages.DEV_START);
1073
+ console.info();
1074
+ try {
1075
+ const directory = getDirectoryInput(options);
1076
+ const generate = getDevGenerateInput(options);
1077
+ await Promise.all([
1078
+ generate ? runAction("generate", [], directory, false) : void 0,
1079
+ runAction("build", [], directory, false),
1080
+ runAction("start", [], directory, true)
1081
+ ]);
1082
+ console.info(Messages.DEV_SUCCESS);
1083
+ process.exit(0);
1084
+ } catch (e) {
1085
+ console.error(Messages.DEV_FAILED);
1086
+ console.error(e);
1087
+ process.exit(1);
1088
+ }
1089
+ }
1090
+ };
1091
+ var runAction = /* @__PURE__ */ __name(async (command, params, directory, stdout = false) => {
795
1092
  try {
796
- const packageManager = PackageManagerFactory.create(packageManagerName);
797
- return await packageManager.build(name, directory, part.entry, part.output, [
798
- "--asset-naming",
799
- "[name].[ext]",
800
- "--target",
801
- part.target === "client" ? "browser" : "node"
802
- ]);
803
- } catch (error3) {
804
- if (error3 && error3.message) {
805
- console.error(ansis.red(error3.message));
1093
+ const packageManager = await PackageManagerFactory.find(directory);
1094
+ await packageManager.runDev(directory, "nf", {}, [command, ...params, "--watch"], !stdout);
1095
+ } catch (error4) {
1096
+ if (error4 && error4.message) {
1097
+ console.error(ansis2.red(error4.message));
806
1098
  }
807
- return false;
808
1099
  }
809
- }, "buildPart");
1100
+ }, "runAction");
810
1101
 
811
1102
  // src/action/actions/generate.action.ts
812
- import * as console2 from "console";
1103
+ import * as console3 from "console";
1104
+ import { join as join4 } from "path";
813
1105
 
814
1106
  // src/lib/schematics/abstract.collection.ts
815
1107
  var AbstractCollection = class {
@@ -899,7 +1191,7 @@ var CollectionFactory = class {
899
1191
  __name(this, "CollectionFactory");
900
1192
  }
901
1193
  static create(collection, directory) {
902
- const schematicRunner = RunnerFactory.create(1 /* SCHEMATIC */);
1194
+ const schematicRunner = RunnerFactory.create(4 /* SCHEMATIC */);
903
1195
  if (collection === "@nanoforge-dev/schematics" /* NANOFORGE */) {
904
1196
  return new NanoforgeCollection(schematicRunner, directory);
905
1197
  } else {
@@ -937,7 +1229,7 @@ var SchematicOption = class {
937
1229
  }
938
1230
  } else if (typeof this.value === "boolean") {
939
1231
  const str = normalizedName;
940
- return this.value ? [`--${str}`] : [`--no-${str}`];
1232
+ return this.value ? [`--${str}=true`] : [`--${str}=false`];
941
1233
  } else if (Array.isArray(this.value)) {
942
1234
  return this.value.reduce(
943
1235
  (old, option) => [
@@ -960,6 +1252,9 @@ var SchematicOption = class {
960
1252
  }
961
1253
  };
962
1254
 
1255
+ // src/action/common/schematics.ts
1256
+ import { watch as watch2 } from "chokidar";
1257
+
963
1258
  // src/action/common/spinner.ts
964
1259
  import ora2 from "ora";
965
1260
  var getSpinner = /* @__PURE__ */ __name((message) => ora2({
@@ -967,16 +1262,22 @@ var getSpinner = /* @__PURE__ */ __name((message) => ora2({
967
1262
  }), "getSpinner");
968
1263
 
969
1264
  // src/action/common/schematics.ts
970
- var executeSchematic = /* @__PURE__ */ __name(async (name, collection, schematicName, options) => {
971
- const spinner = getSpinner(Messages.SCHEMATIC_IN_PROGRESS(name));
972
- spinner.start();
973
- await collection.execute(
974
- schematicName,
975
- mapSchematicOptions(options),
976
- void 0,
977
- () => spinner.fail(Messages.SCHEMATIC_FAILED(name))
978
- );
979
- spinner.succeed(Messages.SCHEMATIC_SUCCESS(name));
1265
+ var executeSchematic = /* @__PURE__ */ __name(async (name, collection, schematicName, options, fileToWatch) => {
1266
+ const execute = /* @__PURE__ */ __name(async (watch3 = false) => {
1267
+ const spinner = getSpinner(
1268
+ (watch3 ? Messages.SCHEMATIC_WATCH_IN_PROGRESS : Messages.SCHEMATIC_IN_PROGRESS)(name)
1269
+ );
1270
+ spinner.start();
1271
+ await collection.execute(
1272
+ schematicName,
1273
+ mapSchematicOptions(options),
1274
+ void 0,
1275
+ () => spinner.fail(Messages.SCHEMATIC_FAILED(name))
1276
+ );
1277
+ spinner.succeed(Messages.SCHEMATIC_SUCCESS(name));
1278
+ }, "execute");
1279
+ if (fileToWatch) watch2(fileToWatch).on("change", () => execute(true));
1280
+ return await execute();
980
1281
  }, "executeSchematic");
981
1282
  var mapSchematicOptions = /* @__PURE__ */ __name((inputs) => {
982
1283
  return Object.entries(inputs).reduce((old, [key, value]) => {
@@ -994,18 +1295,25 @@ var GenerateAction = class extends AbstractAction {
994
1295
  __name(this, "GenerateAction");
995
1296
  }
996
1297
  async handle(_args, options) {
997
- console2.info(Messages.NEW_START);
1298
+ console3.info(Messages.GENERATE_START);
1299
+ console3.info();
998
1300
  try {
999
1301
  const directory = getDirectoryInput(options);
1000
1302
  const config2 = await getConfig(options, directory);
1303
+ const watch3 = getWatchInput(options);
1001
1304
  const values = await getSchemaValues(config2);
1002
- await generateFiles(values, directory);
1003
- console2.info();
1004
- console2.info(Messages.NEW_SUCCESS);
1305
+ await generateFiles(values, directory, watch3);
1306
+ console3.info();
1307
+ if (watch3) {
1308
+ console3.info(Messages.GENERATE_WATCH_START);
1309
+ console3.info();
1310
+ return;
1311
+ }
1312
+ console3.info(Messages.GENERATE_SUCCESS);
1005
1313
  process.exit(0);
1006
1314
  } catch (e) {
1007
- console2.error(Messages.NEW_FAILED);
1008
- console2.error(e);
1315
+ console3.error(Messages.GENERATE_FAILED);
1316
+ console3.error(e);
1009
1317
  process.exit(1);
1010
1318
  }
1011
1319
  }
@@ -1019,33 +1327,43 @@ var getSchemaValues = /* @__PURE__ */ __name(async (config2) => {
1019
1327
  initFunctions: config2.initFunctions
1020
1328
  };
1021
1329
  }, "getSchemaValues");
1022
- var generateFiles = /* @__PURE__ */ __name(async (values, directory) => {
1023
- console2.info();
1330
+ var generateFiles = /* @__PURE__ */ __name(async (values, directory, watch3) => {
1024
1331
  const collection = CollectionFactory.create("@nanoforge-dev/schematics" /* NANOFORGE */, directory);
1025
- console2.info();
1026
- console2.info(Messages.SCHEMATICS_START);
1027
- console2.info();
1028
- await executeSchematic("Client main file", collection, "part-main", {
1029
- name: values.name,
1030
- part: "client",
1031
- directory: values.directory,
1032
- language: values.language,
1033
- initFunctions: values.initFunctions
1034
- });
1035
- if (values.server) {
1036
- await executeSchematic("Server main file", collection, "part-main", {
1332
+ console3.info(Messages.SCHEMATICS_START);
1333
+ console3.info();
1334
+ await executeSchematic(
1335
+ "Client main file",
1336
+ collection,
1337
+ "part-main",
1338
+ {
1037
1339
  name: values.name,
1038
- part: "server",
1340
+ part: "client",
1039
1341
  directory: values.directory,
1040
1342
  language: values.language,
1041
1343
  initFunctions: values.initFunctions
1042
- });
1344
+ },
1345
+ watch3 ? join4(getCwd(directory), values.directory, ".nanoforge", "client.save.json") : void 0
1346
+ );
1347
+ if (values.server) {
1348
+ await executeSchematic(
1349
+ "Server main file",
1350
+ collection,
1351
+ "part-main",
1352
+ {
1353
+ name: values.name,
1354
+ part: "server",
1355
+ directory: values.directory,
1356
+ language: values.language,
1357
+ initFunctions: values.initFunctions
1358
+ },
1359
+ join4(getCwd(directory), values.directory, ".nanoforge", "server.save.json")
1360
+ );
1043
1361
  }
1044
1362
  }, "generateFiles");
1045
1363
 
1046
1364
  // src/action/actions/install.action.ts
1047
- import * as ansis2 from "ansis";
1048
- import * as process4 from "process";
1365
+ import * as ansis3 from "ansis";
1366
+ import * as process3 from "process";
1049
1367
  var InstallAction = class extends AbstractAction {
1050
1368
  static {
1051
1369
  __name(this, "InstallAction");
@@ -1057,25 +1375,31 @@ var InstallAction = class extends AbstractAction {
1057
1375
  const names = await getInstallNamesInputOrAsk(args);
1058
1376
  const directory = getDirectoryInput(options);
1059
1377
  await installPackages(names, directory);
1060
- process4.exit(0);
1378
+ process3.exit(0);
1061
1379
  } catch (e) {
1062
1380
  console.error(e);
1063
- process4.exit(1);
1381
+ process3.exit(1);
1064
1382
  }
1065
1383
  }
1066
1384
  };
1067
1385
  var installPackages = /* @__PURE__ */ __name(async (names, directory) => {
1068
- const packageManagerName = "bun" /* BUN */;
1069
1386
  try {
1070
- const packageManager = PackageManagerFactory.create(packageManagerName);
1071
- await packageManager.addProduction(directory, names);
1072
- } catch (error3) {
1073
- if (error3 && error3.message) {
1074
- console.error(ansis2.red(error3.message));
1387
+ const packageManager = await PackageManagerFactory.find(directory);
1388
+ const res = await packageManager.addProduction(directory, names);
1389
+ if (!res) process3.exit(1);
1390
+ } catch (error4) {
1391
+ if (error4 && error4.message) {
1392
+ console.error(ansis3.red(error4.message));
1075
1393
  }
1394
+ process3.exit(1);
1076
1395
  }
1077
1396
  }, "installPackages");
1078
1397
 
1398
+ // src/action/actions/new.action.ts
1399
+ import * as ansis4 from "ansis";
1400
+ import console4 from "console";
1401
+ import * as process4 from "process";
1402
+
1079
1403
  // src/lib/input/inputs/new/init-functions.input.ts
1080
1404
  var getNewInitFunctionsWithDefault = /* @__PURE__ */ __name((inputs) => {
1081
1405
  return getBooleanInputWithDefault(inputs, "initFunctions", false);
@@ -1169,17 +1493,18 @@ var NewAction = class extends AbstractAction {
1169
1493
  __name(this, "NewAction");
1170
1494
  }
1171
1495
  async handle(_args, options) {
1172
- console.info(Messages.NEW_START);
1496
+ console4.info(Messages.NEW_START);
1173
1497
  try {
1174
1498
  const directory = getDirectoryInput(options);
1175
1499
  const values = await getSchemaValues2(options);
1176
1500
  await generateApplicationFiles(values, directory);
1177
- console.info();
1178
- console.info(Messages.NEW_SUCCESS);
1179
- process.exit(0);
1501
+ if (!values.skipInstall) await runInstall(directory, values.packageManager);
1502
+ console4.info();
1503
+ console4.info(Messages.NEW_SUCCESS);
1504
+ process4.exit(0);
1180
1505
  } catch {
1181
- console.error(Messages.NEW_FAILED);
1182
- process.exit(1);
1506
+ console4.error(Messages.NEW_FAILED);
1507
+ process4.exit(1);
1183
1508
  }
1184
1509
  }
1185
1510
  };
@@ -1196,11 +1521,11 @@ var getSchemaValues2 = /* @__PURE__ */ __name(async (inputs) => {
1196
1521
  };
1197
1522
  }, "getSchemaValues");
1198
1523
  var generateApplicationFiles = /* @__PURE__ */ __name(async (values, directory) => {
1199
- console.info();
1524
+ console4.info();
1200
1525
  const collection = CollectionFactory.create("@nanoforge-dev/schematics" /* NANOFORGE */, directory);
1201
- console.info();
1202
- console.info(Messages.SCHEMATICS_START);
1203
- console.info();
1526
+ console4.info();
1527
+ console4.info(Messages.SCHEMATICS_START);
1528
+ console4.info();
1204
1529
  await executeSchematic("Application", collection, "application", {
1205
1530
  name: values.name,
1206
1531
  directory: values.directory,
@@ -1245,56 +1570,91 @@ var generateApplicationFiles = /* @__PURE__ */ __name(async (values, directory)
1245
1570
  });
1246
1571
  }
1247
1572
  }, "generateApplicationFiles");
1573
+ var runInstall = /* @__PURE__ */ __name(async (directory, pkgManagerName) => {
1574
+ try {
1575
+ const packageManager = PackageManagerFactory.create(pkgManagerName);
1576
+ await packageManager.install(directory);
1577
+ } catch (error4) {
1578
+ if (error4 && error4.message) {
1579
+ console4.error(ansis4.red(error4.message));
1580
+ }
1581
+ process4.exit(1);
1582
+ }
1583
+ }, "runInstall");
1248
1584
 
1249
1585
  // src/action/actions/start.action.ts
1250
- import * as ansis3 from "ansis";
1251
- import * as console3 from "console";
1252
- import { join as join3 } from "path";
1586
+ import * as ansis5 from "ansis";
1587
+ import * as console5 from "console";
1588
+ import * as process5 from "process";
1589
+ import { join as join5 } from "path";
1253
1590
  var StartAction = class extends AbstractAction {
1254
1591
  static {
1255
1592
  __name(this, "StartAction");
1256
1593
  }
1257
1594
  async handle(_args, options) {
1258
- console3.info(Messages.RUN_START);
1259
- console3.info();
1595
+ console5.info(Messages.RUN_START);
1596
+ console5.info();
1260
1597
  try {
1261
1598
  const directory = getDirectoryInput(options);
1262
1599
  const config2 = await getConfig(options, directory);
1263
1600
  const clientDir = config2.client.runtime.dir;
1264
1601
  const serverDir = config2.server.runtime.dir;
1265
1602
  const clientPort = getStringInputWithDefault(options, "clientPort", config2.client.port);
1603
+ const cert = getStringInput(options, "cert");
1604
+ const key = getStringInput(options, "key");
1605
+ const watch3 = getWatchInput(options);
1266
1606
  await Promise.all([
1267
- config2.server.enable ? this.startServer(directory, serverDir) : void 0,
1268
- this.startClient(clientPort, directory, clientDir)
1607
+ config2.server.enable ? this.startServer(directory, serverDir, watch3) : void 0,
1608
+ this.startClient(
1609
+ clientPort,
1610
+ directory,
1611
+ clientDir,
1612
+ {
1613
+ watch: watch3,
1614
+ serverGameDir: config2.server.enable ? serverDir : void 0
1615
+ },
1616
+ cert,
1617
+ key
1618
+ )
1269
1619
  ]);
1270
- process.exit(0);
1620
+ process5.exit(0);
1271
1621
  } catch (e) {
1272
- console3.error(e);
1273
- process.exit(1);
1622
+ console5.error(e);
1623
+ process5.exit(1);
1274
1624
  }
1275
1625
  }
1276
- async startClient(port, directory, gameDir) {
1626
+ async startClient(port, directory, gameDir, options, cert, key) {
1277
1627
  const path = getModulePath("@nanoforge-dev/loader-client/package.json", true);
1278
- return runPart("Client", path, {
1628
+ const params = {
1279
1629
  PORT: port,
1280
- GAME_DIR: getCwd(join3(directory, gameDir))
1281
- });
1630
+ GAME_DIR: getCwd(join5(directory, gameDir)),
1631
+ CERT: cert ? join5(getCwd(directory), cert) : void 0,
1632
+ KEY: key ? join5(getCwd(directory), key) : void 0
1633
+ };
1634
+ if (options?.watch) {
1635
+ params["WATCH"] = "true";
1636
+ if (options?.serverGameDir) {
1637
+ params["WATCH_SERVER_GAME_DIR"] = getCwd(join5(directory, options.serverGameDir));
1638
+ }
1639
+ }
1640
+ return runPart("Client", path, params);
1282
1641
  }
1283
- startServer(directory, gameDir) {
1642
+ startServer(directory, gameDir, watch3) {
1284
1643
  const path = getModulePath("@nanoforge-dev/loader-server/package.json", true);
1285
- return runPart("Server", path, {
1286
- GAME_DIR: getCwd(join3(directory, gameDir))
1287
- });
1644
+ const params = {
1645
+ GAME_DIR: getCwd(join5(directory, gameDir))
1646
+ };
1647
+ if (watch3) params["WATCH"] = "true";
1648
+ return runPart("Server", path, params);
1288
1649
  }
1289
1650
  };
1290
1651
  var runPart = /* @__PURE__ */ __name(async (part, directory, env2, flags) => {
1291
- const packageManagerName = "bun" /* BUN */;
1292
1652
  try {
1293
- const packageManager = PackageManagerFactory.create(packageManagerName);
1653
+ const packageManager = await PackageManagerFactory.find(directory);
1294
1654
  await packageManager.run(part, directory, "start", env2, flags, true);
1295
- } catch (error3) {
1296
- if (error3 && error3.message) {
1297
- console3.error(ansis3.red(error3.message));
1655
+ } catch (error4) {
1656
+ if (error4 && error4.message) {
1657
+ console5.error(ansis5.red(error4.message));
1298
1658
  }
1299
1659
  }
1300
1660
  }, "runPart");
@@ -1315,12 +1675,30 @@ var BuildCommand = class extends AbstractCommand {
1315
1675
  __name(this, "BuildCommand");
1316
1676
  }
1317
1677
  load(program) {
1318
- program.command("build").description("build 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("--client-outDir [clientDirectory]", "specify the output directory of the client").option("--server-outDir [serverDirectory]", "specify the output directory of the server").action(async (rawOptions) => {
1678
+ program.command("build").description("build 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("--client-outDir [clientDirectory]", "specify the output directory of the client").option("--server-outDir [serverDirectory]", "specify the output directory of the server").option("--watch", "build app in watching mode", false).action(async (rawOptions) => {
1319
1679
  const options = /* @__PURE__ */ new Map();
1320
1680
  options.set("directory", { value: rawOptions.directory });
1321
1681
  options.set("config", { value: rawOptions.config });
1322
1682
  options.set("clientDirectory", { value: rawOptions.clientOutDir });
1323
1683
  options.set("serverDirectory", { value: rawOptions.serverOutDir });
1684
+ options.set("watch", { value: rawOptions.watch });
1685
+ const args = /* @__PURE__ */ new Map();
1686
+ await this.action.handle(args, options);
1687
+ });
1688
+ }
1689
+ };
1690
+
1691
+ // src/command/commands/dev.command.ts
1692
+ var DevCommand = class extends AbstractCommand {
1693
+ static {
1694
+ __name(this, "DevCommand");
1695
+ }
1696
+ load(program) {
1697
+ program.command("dev").description("run your game in dev mode").option("-d, --directory [directory]", "specify the directory of your project").option("--generate", "generate app from config", false).action(async (rawOptions) => {
1698
+ const options = /* @__PURE__ */ new Map();
1699
+ options.set("directory", { value: rawOptions.directory });
1700
+ options.set("config", { value: rawOptions.config });
1701
+ options.set("generate", { value: rawOptions.generate });
1324
1702
  const args = /* @__PURE__ */ new Map();
1325
1703
  await this.action.handle(args, options);
1326
1704
  });
@@ -1333,10 +1711,11 @@ var GenerateCommand = class extends AbstractCommand {
1333
1711
  __name(this, "GenerateCommand");
1334
1712
  }
1335
1713
  load(program) {
1336
- program.command("generate").description("generate nanoforge files from config").option("-d, --directory [directory]", "specify the directory of your project").option("-c, --config [config]", "path to the config file", "nanoforge.config.json").action(async (rawOptions) => {
1714
+ program.command("generate").description("generate nanoforge files from config").option("-d, --directory [directory]", "specify the directory of your project").option("-c, --config [config]", "path to the config file", "nanoforge.config.json").option("--watch", "generate app in watching mode", false).action(async (rawOptions) => {
1337
1715
  const options = /* @__PURE__ */ new Map();
1338
1716
  options.set("directory", { value: rawOptions.directory });
1339
1717
  options.set("config", { value: rawOptions.config });
1718
+ options.set("watch", { value: rawOptions.watch });
1340
1719
  const args = /* @__PURE__ */ new Map();
1341
1720
  await this.action.handle(args, options);
1342
1721
  });
@@ -1391,7 +1770,7 @@ var StartCommand = class extends AbstractCommand {
1391
1770
  program.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(
1392
1771
  "-p, --client-port [clientPort]",
1393
1772
  "specify the port of the loader (the website to load the game)"
1394
- ).option("--game-exposure-port [gameExposurePort]", "specify the port of the game exposure").option("--server-port [serverPort]", "specify the port of the server").action(async (rawOptions) => {
1773
+ ).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) => {
1395
1774
  const options = /* @__PURE__ */ new Map();
1396
1775
  options.set("directory", { value: rawOptions.directory });
1397
1776
  options.set("config", { value: rawOptions.config });
@@ -1400,6 +1779,9 @@ var StartCommand = class extends AbstractCommand {
1400
1779
  value: rawOptions.gameExposurePort
1401
1780
  });
1402
1781
  options.set("serverPort", { value: rawOptions.serverPort });
1782
+ options.set("watch", { value: rawOptions.watch });
1783
+ options.set("cert", { value: rawOptions.cert });
1784
+ options.set("key", { value: rawOptions.key });
1403
1785
  const args = /* @__PURE__ */ new Map();
1404
1786
  await this.action.handle(args, options);
1405
1787
  });
@@ -1413,6 +1795,7 @@ var CommandLoader = class {
1413
1795
  }
1414
1796
  static async load(program) {
1415
1797
  new BuildCommand(new BuildAction()).load(program);
1798
+ new DevCommand(new DevAction()).load(program);
1416
1799
  new GenerateCommand(new GenerateAction()).load(program);
1417
1800
  new InstallCommand(new InstallAction()).load(program);
1418
1801
  new NewCommand(new NewAction()).load(program);
@@ -1422,8 +1805,8 @@ var CommandLoader = class {
1422
1805
  static handleInvalidCommand(program) {
1423
1806
  program.on("command:*", () => {
1424
1807
  console.error(`
1425
- ${Prefixes.ERROR} Invalid command: ${red6`%s`}`, program.args.join(" "));
1426
- console.log(`See ${red6`--help`} for a list of available commands.
1808
+ ${Prefixes.ERROR} Invalid command: ${red8`%s`}`, program.args.join(" "));
1809
+ console.log(`See ${red8`--help`} for a list of available commands.
1427
1810
  `);
1428
1811
  process.exit(1);
1429
1812
  });