@nanoforge-dev/cli 1.2.0 → 1.4.0

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.
@@ -56,6 +56,16 @@ Try running manually: ${command}`), "BUILD_PART_FAILED"),
56
56
  INSTALL_SUCCESS: success("Installation completed!"),
57
57
  INSTALL_FAILED: failure("Installation failed!"),
58
58
  INSTALL_NAMES_QUESTION: "Which libraries do you want to install?",
59
+ INSTALL_PACKAGES_IN_PROGRESS: "Install Nanoforge Packages",
60
+ // --- Login ---
61
+ LOGIN_START: "NanoForge Login",
62
+ LOGIN_SUCCESS: success("Login completed!"),
63
+ LOGIN_FAILED: failure("Login failed!"),
64
+ LOGIN_API_KEY_QUESTION: "What is your registry api key?",
65
+ // --- Logout ---
66
+ LOGOUT_START: "NanoForge Logout",
67
+ LOGOUT_SUCCESS: success("Logout completed!"),
68
+ LOGOUT_FAILED: failure("Logout failed!"),
59
69
  // --- New Project ---
60
70
  NEW_START: "NanoForge Project Creation",
61
71
  NEW_SUCCESS: success("Project successfully created!"),
@@ -67,6 +77,11 @@ Try running manually: ${command}`), "BUILD_PART_FAILED"),
67
77
  NEW_SERVER_QUESTION: "Do you want to generate a server for multiplayer?",
68
78
  NEW_SKIP_INSTALL_QUESTION: "Do you want to skip dependency installation?",
69
79
  NEW_DOCKER_QUESTION: "Do you want to add a Dockerfile for containerization?",
80
+ // --- Create ---
81
+ CREATE_START: "NanoForge Component/System Creation",
82
+ CREATE_SUCCESS: success("Element successfully created!"),
83
+ CREATE_FAILED: failure("Creation failed!"),
84
+ CREATE_NAME_QUESTION: "What is the name of your component/system?",
70
85
  // --- Generate ---
71
86
  GENERATE_START: "NanoForge Generate",
72
87
  GENERATE_SUCCESS: success("Generation succeeded!"),
@@ -83,6 +98,16 @@ Try running manually: ${command}`), "BUILD_PART_FAILED"),
83
98
  START_PART_IN_PROGRESS: /* @__PURE__ */ __name((part) => `Starting ${part}...`, "START_PART_IN_PROGRESS"),
84
99
  START_PART_SUCCESS: /* @__PURE__ */ __name((part) => success(`${part} terminated.`), "START_PART_SUCCESS"),
85
100
  START_PART_FAILED: /* @__PURE__ */ __name((part) => failure(`${part} failed!`), "START_PART_FAILED"),
101
+ // --- Publish ---
102
+ PUBLISH_START: "NanoForge Publish",
103
+ PUBLISH_SUCCESS: success("Publish completed!"),
104
+ PUBLISH_FAILED: failure("Publish failed!"),
105
+ PUBLISH_IN_PROGRESS: /* @__PURE__ */ __name((name) => `Publishing ${name}...`, "PUBLISH_IN_PROGRESS"),
106
+ // --- Unpublish ---
107
+ UNPUBLISH_START: "NanoForge Unpublish",
108
+ UNPUBLISH_SUCCESS: success("Unpublish completed!"),
109
+ UNPUBLISH_FAILED: failure("Unpublish failed!"),
110
+ UNPUBLISH_IN_PROGRESS: /* @__PURE__ */ __name((name) => `Unpublishing ${name}...`, "UNPUBLISH_IN_PROGRESS"),
86
111
  // --- Schematics ---
87
112
  SCHEMATICS_START: "Running schematics",
88
113
  SCHEMATIC_IN_PROGRESS: /* @__PURE__ */ __name((name) => `Generating ${name}...`, "SCHEMATIC_IN_PROGRESS"),
@@ -113,7 +138,7 @@ var getSpinner = /* @__PURE__ */ __name((message) => ora({ text: message }), "ge
113
138
 
114
139
  // src/action/actions/build.action.ts
115
140
  import { watch } from "chokidar";
116
- import { dirname, join as join3 } from "path";
141
+ import { dirname, join as join4 } from "path";
117
142
 
118
143
  // src/lib/input/base-inputs.ts
119
144
  var getStringInput = /* @__PURE__ */ __name((input2, field) => {
@@ -162,15 +187,10 @@ var getConfigInput = /* @__PURE__ */ __name((inputs) => {
162
187
  return getStringInputWithDefault(inputs, "config", ".");
163
188
  }, "getConfigInput");
164
189
 
165
- // src/lib/input/inputs/watch.input.ts
166
- var getWatchInput = /* @__PURE__ */ __name((inputs) => {
167
- return getBooleanInputWithDefault(inputs, "watch", false);
168
- }, "getWatchInput");
169
-
170
- // src/lib/input/inputs/dev/generate.input.ts
171
- var getDevGenerateInput = /* @__PURE__ */ __name((inputs) => {
172
- return getBooleanInputWithDefault(inputs, "generate", false);
173
- }, "getDevGenerateInput");
190
+ // src/lib/input/inputs/editor.input.ts
191
+ var getEditorInput = /* @__PURE__ */ __name((inputs) => {
192
+ return getBooleanInputWithDefault(inputs, "editor", false);
193
+ }, "getEditorInput");
174
194
 
175
195
  // src/lib/question/questions/confirm.question.ts
176
196
  import { confirm } from "@inquirer/prompts";
@@ -178,10 +198,16 @@ import { confirm } from "@inquirer/prompts";
178
198
  // src/lib/utils/errors.ts
179
199
  import { red } from "ansis";
180
200
  var getErrorMessage = /* @__PURE__ */ __name((error) => {
181
- if (error instanceof Error) return error.message;
201
+ if (error instanceof Error) return getErrorString(error);
182
202
  if (typeof error === "string") return error;
183
203
  return void 0;
184
204
  }, "getErrorMessage");
205
+ var getErrorString = /* @__PURE__ */ __name((error) => {
206
+ const stack = error.stack ? error.stack : error.message;
207
+ const cause = error.cause && typeof error.cause === "object" ? JSON.stringify(error.cause, null, 2) : error.cause;
208
+ return `${stack}${cause ? `
209
+ ${cause}` : ""}`;
210
+ }, "getErrorString");
185
211
  var handleActionError = /* @__PURE__ */ __name((context, error) => {
186
212
  console.error();
187
213
  console.error(red(context));
@@ -254,6 +280,66 @@ var askSelect = /* @__PURE__ */ __name(async (question, choices, baseOptions) =>
254
280
  }).catch(promptError);
255
281
  }, "askSelect");
256
282
 
283
+ // src/lib/input/inputs/name.input.ts
284
+ var getNameInput = /* @__PURE__ */ __name((inputs) => {
285
+ return getStringInput(inputs, "name");
286
+ }, "getNameInput");
287
+ var getNewNameInputOrAsk = /* @__PURE__ */ __name((inputs) => {
288
+ return getInputOrAsk(
289
+ getNameInput(inputs),
290
+ () => askInput(Messages.NEW_NAME_QUESTION, {
291
+ required: true,
292
+ default: "nanoforge-app"
293
+ })
294
+ );
295
+ }, "getNewNameInputOrAsk");
296
+ var getCreateNameInputOrAsk = /* @__PURE__ */ __name((inputs) => {
297
+ return getInputOrAsk(
298
+ getNameInput(inputs),
299
+ () => askInput(Messages.CREATE_NAME_QUESTION, {
300
+ required: true,
301
+ default: "example"
302
+ })
303
+ );
304
+ }, "getCreateNameInputOrAsk");
305
+
306
+ // src/lib/input/inputs/path.input.ts
307
+ var getPathInput = /* @__PURE__ */ __name((inputs) => {
308
+ return getStringInput(inputs, "path");
309
+ }, "getPathInput");
310
+ var getPathInputWithDefault = /* @__PURE__ */ __name((inputs, defaultValue) => {
311
+ return getStringInputWithDefault(inputs, "path", defaultValue);
312
+ }, "getPathInputWithDefault");
313
+
314
+ // src/lib/input/inputs/server.input.ts
315
+ function getServerInput(inputs) {
316
+ return getBooleanInputWithDefault(inputs, "server", false);
317
+ }
318
+ __name(getServerInput, "getServerInput");
319
+
320
+ // src/lib/input/inputs/watch.input.ts
321
+ var getWatchInput = /* @__PURE__ */ __name((inputs) => {
322
+ return getBooleanInputWithDefault(inputs, "watch", false);
323
+ }, "getWatchInput");
324
+
325
+ // src/lib/input/inputs/create/type.input.ts
326
+ var getCreateTypeInput = /* @__PURE__ */ __name((inputs) => {
327
+ const res = getStringInput(inputs, "type");
328
+ if (res && ["component", "system"].includes(res)) return res;
329
+ throw new Error("Invalid type. Please enter 'component' or 'system'.");
330
+ }, "getCreateTypeInput");
331
+
332
+ // src/lib/input/inputs/dev/generate.input.ts
333
+ var getDevGenerateInput = /* @__PURE__ */ __name((inputs) => {
334
+ return getBooleanInputWithDefault(inputs, "generate", false);
335
+ }, "getDevGenerateInput");
336
+
337
+ // src/lib/input/inputs/install/lib.input.ts
338
+ function getInstallLibInput(inputs) {
339
+ return getBooleanInputWithDefault(inputs, "lib", false);
340
+ }
341
+ __name(getInstallLibInput, "getInstallLibInput");
342
+
257
343
  // src/lib/input/inputs/install/names.input.ts
258
344
  var getNamesInput = /* @__PURE__ */ __name((inputs) => {
259
345
  return getArrayInput(inputs, "names");
@@ -265,6 +351,109 @@ var getInstallNamesInputOrAsk = /* @__PURE__ */ __name((inputs) => {
265
351
  );
266
352
  }, "getInstallNamesInputOrAsk");
267
353
 
354
+ // src/lib/input/inputs/login-out/api-key.input.ts
355
+ var getApiKeyInput = /* @__PURE__ */ __name((inputs) => {
356
+ return getStringInput(inputs, "apiKey");
357
+ }, "getApiKeyInput");
358
+ var getLoginApiKeyInputOrAsk = /* @__PURE__ */ __name((inputs) => {
359
+ return getInputOrAsk(
360
+ getApiKeyInput(inputs),
361
+ () => askInput(Messages.LOGIN_API_KEY_QUESTION, {
362
+ required: true
363
+ })
364
+ );
365
+ }, "getLoginApiKeyInputOrAsk");
366
+
367
+ // src/lib/input/inputs/login-out/local.input.ts
368
+ function getLocalInput(inputs) {
369
+ return getBooleanInputWithDefault(inputs, "local", false);
370
+ }
371
+ __name(getLocalInput, "getLocalInput");
372
+
373
+ // src/lib/input/inputs/new/docker.input.ts
374
+ var getNewDockerInput = /* @__PURE__ */ __name((inputs) => {
375
+ return getBooleanInput(inputs, "docker");
376
+ }, "getNewDockerInput");
377
+ var getNewDockerOrAsk = /* @__PURE__ */ __name((inputs) => {
378
+ return getInputOrAsk(
379
+ getNewDockerInput(inputs),
380
+ () => askConfirm(Messages.NEW_DOCKER_QUESTION, { default: true })
381
+ );
382
+ }, "getNewDockerOrAsk");
383
+
384
+ // src/lib/input/inputs/new/init-functions.input.ts
385
+ var getNewInitFunctionsWithDefault = /* @__PURE__ */ __name((inputs) => {
386
+ return getBooleanInputWithDefault(inputs, "initFunctions", false);
387
+ }, "getNewInitFunctionsWithDefault");
388
+
389
+ // src/lib/input/inputs/new/language.input.ts
390
+ var getLanguageInput = /* @__PURE__ */ __name((inputs) => {
391
+ return getStringInput(inputs, "language");
392
+ }, "getLanguageInput");
393
+ var getNewLanguageInputOrAsk = /* @__PURE__ */ __name((inputs) => {
394
+ return getInputOrAsk(
395
+ getLanguageInput(inputs),
396
+ () => askSelect(Messages.NEW_LANGUAGE_QUESTION, [{ value: "ts" }, { value: "js" }], {
397
+ default: "ts"
398
+ })
399
+ );
400
+ }, "getNewLanguageInputOrAsk");
401
+
402
+ // src/lib/input/inputs/new/lint.input.ts
403
+ var getNewLintInput = /* @__PURE__ */ __name((inputs) => {
404
+ return getBooleanInputWithDefault(inputs, "lint", true);
405
+ }, "getNewLintInput");
406
+
407
+ // src/lib/input/inputs/new/package-manager.input.ts
408
+ var getPackageManagerInput = /* @__PURE__ */ __name((inputs) => {
409
+ return getStringInput(inputs, "packageManager");
410
+ }, "getPackageManagerInput");
411
+ var getNewPackageManagerInputOrAsk = /* @__PURE__ */ __name((inputs) => {
412
+ return getInputOrAsk(
413
+ getPackageManagerInput(inputs),
414
+ () => askSelect(
415
+ Messages.NEW_PACKAGE_MANAGER_QUESTION,
416
+ [{ value: "npm" }, { value: "yarn" }, { value: "pnpm" }, { value: "bun" }],
417
+ {
418
+ default: "npm"
419
+ }
420
+ )
421
+ );
422
+ }, "getNewPackageManagerInputOrAsk");
423
+
424
+ // src/lib/input/inputs/new/server.input.ts
425
+ var getNewServerInput = /* @__PURE__ */ __name((inputs) => {
426
+ return getBooleanInput(inputs, "server");
427
+ }, "getNewServerInput");
428
+ var getNewServerOrAsk = /* @__PURE__ */ __name((inputs) => {
429
+ return getInputOrAsk(
430
+ getNewServerInput(inputs),
431
+ () => askConfirm(Messages.NEW_SERVER_QUESTION, { default: false })
432
+ );
433
+ }, "getNewServerOrAsk");
434
+
435
+ // src/lib/input/inputs/new/skip-install.input.ts
436
+ var getNewSkipInstallInput = /* @__PURE__ */ __name((inputs) => {
437
+ return getBooleanInput(inputs, "skipInstall");
438
+ }, "getNewSkipInstallInput");
439
+ var getNewSkipInstallOrAsk = /* @__PURE__ */ __name((inputs) => {
440
+ return getInputOrAsk(
441
+ getNewSkipInstallInput(inputs),
442
+ () => askConfirm(Messages.NEW_SKIP_INSTALL_QUESTION, { default: false })
443
+ );
444
+ }, "getNewSkipInstallOrAsk");
445
+
446
+ // src/lib/input/inputs/new/strict.input.ts
447
+ var getNewStrictInput = /* @__PURE__ */ __name((inputs) => {
448
+ return getBooleanInput(inputs, "strict");
449
+ }, "getNewStrictInput");
450
+ var getNewStrictOrAsk = /* @__PURE__ */ __name((inputs) => {
451
+ return getInputOrAsk(
452
+ getNewStrictInput(inputs),
453
+ () => askConfirm(Messages.NEW_STRICT_QUESTION, { default: true })
454
+ );
455
+ }, "getNewStrictOrAsk");
456
+
268
457
  // src/lib/package-manager/package-manager.ts
269
458
  import { bold, red as red3 } from "ansis";
270
459
 
@@ -312,6 +501,21 @@ var resolveCLINodeBinaryPath = /* @__PURE__ */ __name((name) => {
312
501
  throw new Error("Could not find module path");
313
502
  }, "resolveCLINodeBinaryPath");
314
503
 
504
+ // src/lib/utils/spinner.ts
505
+ var withSpinner = /* @__PURE__ */ __name(async (message, task, onError) => {
506
+ const spinner = getSpinner(message);
507
+ spinner.start();
508
+ try {
509
+ const value = await task(spinner);
510
+ spinner.succeed();
511
+ return { success: true, value };
512
+ } catch (error) {
513
+ spinner.fail();
514
+ if (onError) onError();
515
+ return { success: false, error };
516
+ }
517
+ }, "withSpinner");
518
+
315
519
  // src/lib/package-manager/package-manager.ts
316
520
  var PackageManager = class {
317
521
  constructor(name, commands, runner) {
@@ -319,12 +523,15 @@ var PackageManager = class {
319
523
  this.commands = commands;
320
524
  this.runner = runner;
321
525
  }
526
+ name;
527
+ commands;
528
+ runner;
322
529
  static {
323
530
  __name(this, "PackageManager");
324
531
  }
325
532
  async install(directory) {
326
533
  const args = [this.commands.install, this.commands.silentFlag];
327
- const result = await this.withSpinner(
534
+ const result = await withSpinner(
328
535
  Messages.PACKAGE_MANAGER_INSTALLATION_IN_PROGRESS,
329
536
  async (spinner) => {
330
537
  await this.exec(args, directory, { onFail: /* @__PURE__ */ __name(() => spinner.fail(), "onFail") });
@@ -352,7 +559,7 @@ var PackageManager = class {
352
559
  output,
353
560
  ...flags
354
561
  ];
355
- const result = await this.withSpinner(
562
+ const result = await withSpinner(
356
563
  message,
357
564
  async (spinner) => {
358
565
  await this.exec(args, directory, { onFail: /* @__PURE__ */ __name(() => spinner.fail(), "onFail") });
@@ -361,10 +568,10 @@ var PackageManager = class {
361
568
  );
362
569
  return result.success;
363
570
  }
364
- async run(name, directory, script, env2 = {}, flags = [], silent = false) {
571
+ async run(name, directory, script, params, env2 = {}, flags = [], silent = false) {
365
572
  console.info(Messages.START_PART_IN_PROGRESS(name));
366
573
  try {
367
- const args = this.buildRunArgs(script, flags, silent);
574
+ const args = this.buildRunArgs(script, params, flags, silent);
368
575
  await this.exec(args, directory, {
369
576
  env: env2,
370
577
  listeners: {
@@ -381,32 +588,21 @@ var PackageManager = class {
381
588
  }
382
589
  async runDev(directory, command, env2 = {}, flags = [], collect = true) {
383
590
  try {
384
- await this.exec([this.commands.run, command, ...flags], directory, { collect, env: env2 });
591
+ const base = [this.commands.exec, command];
592
+ if (this.commands.runArgsFlag) base.push(this.commands.runArgsFlag);
593
+ await this.exec([...base, ...flags], directory, { collect, env: env2 });
385
594
  return true;
386
595
  } catch {
387
596
  return false;
388
597
  }
389
598
  }
390
- async withSpinner(message, task, onError) {
391
- const spinner = getSpinner(message);
392
- spinner.start();
393
- try {
394
- const value = await task(spinner);
395
- spinner.succeed();
396
- return { success: true, value };
397
- } catch {
398
- spinner.fail();
399
- if (onError) onError();
400
- return { success: false };
401
- }
402
- }
403
599
  async addDependencies(saveFlag, directory, dependencies) {
404
600
  if (!dependencies.length) {
405
601
  this.logEmpty(Messages.PACKAGE_MANAGER_INSTALLATION_NOTHING);
406
602
  return true;
407
603
  }
408
604
  const args = [this.commands.add, saveFlag, ...dependencies];
409
- const result = await this.withSpinner(
605
+ const result = await withSpinner(
410
606
  Messages.PACKAGE_MANAGER_INSTALLATION_IN_PROGRESS,
411
607
  async (spinner) => {
412
608
  await this.exec(args, directory, { onFail: /* @__PURE__ */ __name(() => spinner.fail(), "onFail") });
@@ -421,11 +617,13 @@ var PackageManager = class {
421
617
  throw new Error(`Package manager "${this.name}" does not support "${feature}"`);
422
618
  }
423
619
  }
424
- buildRunArgs(script, flags, silent) {
620
+ buildRunArgs(script, params, flags, silent) {
425
621
  const args = [...flags, this.commands.run];
426
622
  if (silent) args.push(this.commands.silentFlag);
427
623
  args.push(script);
428
- return args;
624
+ if (params.length === 0) return args;
625
+ if (this.commands.runArgsFlag) args.push(this.commands.runArgsFlag);
626
+ return args.concat(params);
429
627
  }
430
628
  exec(args, directory, options = {}) {
431
629
  return this.runner.run(args, {
@@ -471,6 +669,8 @@ var Runner = class {
471
669
  this.binary = binary;
472
670
  this.baseArgs = baseArgs;
473
671
  }
672
+ binary;
673
+ baseArgs;
474
674
  static {
475
675
  __name(this, "Runner");
476
676
  }
@@ -478,12 +678,12 @@ var Runner = class {
478
678
  const { collect = false, cwd: cwd2 = process2.cwd(), env: env2, listeners, onFail } = options;
479
679
  const spawnOpts = this.buildSpawnOptions(collect, cwd2, env2);
480
680
  const fullArgs = [...this.baseArgs, ...args];
481
- return new Promise((resolve3, reject) => {
681
+ return new Promise((resolve4, reject) => {
482
682
  const child = spawn(`${this.binary} ${fullArgs.join(" ")}`, spawnOpts);
483
683
  const output = this.attachOutputHandlers(child, listeners);
484
684
  child.on("close", (code) => {
485
685
  if (code === 0) {
486
- resolve3(this.formatOutput(output, collect));
686
+ resolve4(this.formatOutput(output, collect));
487
687
  } else {
488
688
  this.handleFailure(output, fullArgs, onFail);
489
689
  reject(this.createError(fullArgs, code));
@@ -598,6 +798,7 @@ var PM_CONFIGS = {
598
798
  remove: "uninstall",
599
799
  exec: "exec",
600
800
  run: "run",
801
+ runArgsFlag: "--",
601
802
  saveFlag: "--save",
602
803
  saveDevFlag: "--save-dev",
603
804
  silentFlag: "--silent"
@@ -674,6 +875,21 @@ var PackageManagerFactory = class {
674
875
  }
675
876
  };
676
877
 
878
+ // src/lib/utils/files.ts
879
+ import fs3 from "fs";
880
+ import { join as join2 } from "path";
881
+ var copyFiles = /* @__PURE__ */ __name((from, to) => {
882
+ if (!fs3.existsSync(from)) return;
883
+ if (!fs3.existsSync(to)) throw new Error(`Directory ${to} does not exist`);
884
+ fs3.readdirSync(from, { recursive: true }).forEach((file) => {
885
+ fs3.copyFileSync(join2(from, file.toString()), join2(to, file.toString()));
886
+ });
887
+ }, "copyFiles");
888
+ var resetFolder = /* @__PURE__ */ __name((folder) => {
889
+ if (fs3.existsSync(folder)) fs3.rmSync(folder, { recursive: true, force: true });
890
+ fs3.mkdirSync(folder);
891
+ }, "resetFolder");
892
+
677
893
  // src/lib/utils/run-safe.ts
678
894
  import { red as red5 } from "ansis";
679
895
  var runSafe = /* @__PURE__ */ __name(async (fn, fallback) => {
@@ -693,47 +909,77 @@ var BuildConfig = class {
693
909
  static {
694
910
  __name(this, "BuildConfig");
695
911
  }
696
- entryFile;
697
- outDir;
912
+ entry;
913
+ staticDir;
914
+ };
915
+ __decorateClass([
916
+ Expose(),
917
+ IsString(),
918
+ IsNotEmpty()
919
+ ], BuildConfig.prototype, "entry", 2);
920
+ __decorateClass([
921
+ Expose(),
922
+ IsString(),
923
+ IsNotEmpty()
924
+ ], BuildConfig.prototype, "staticDir", 2);
925
+ var EditorConfig = class {
926
+ static {
927
+ __name(this, "EditorConfig");
928
+ }
929
+ entry;
930
+ save;
698
931
  };
699
932
  __decorateClass([
700
933
  Expose(),
701
934
  IsString(),
702
935
  IsNotEmpty()
703
- ], BuildConfig.prototype, "entryFile", 2);
936
+ ], EditorConfig.prototype, "entry", 2);
704
937
  __decorateClass([
705
938
  Expose(),
706
939
  IsString(),
707
940
  IsNotEmpty()
708
- ], BuildConfig.prototype, "outDir", 2);
709
- var RunConfig = class {
941
+ ], EditorConfig.prototype, "save", 2);
942
+ var DirsConfig = class {
710
943
  static {
711
- __name(this, "RunConfig");
944
+ __name(this, "DirsConfig");
712
945
  }
713
- dir;
946
+ components;
947
+ systems;
714
948
  };
715
949
  __decorateClass([
716
950
  Expose(),
717
951
  IsString(),
718
952
  IsNotEmpty()
719
- ], RunConfig.prototype, "dir", 2);
953
+ ], DirsConfig.prototype, "components", 2);
954
+ __decorateClass([
955
+ Expose(),
956
+ IsString(),
957
+ IsNotEmpty()
958
+ ], DirsConfig.prototype, "systems", 2);
720
959
  var ClientConfig = class {
721
960
  static {
722
961
  __name(this, "ClientConfig");
723
962
  }
963
+ enable;
724
964
  port;
725
- gameExposurePort;
965
+ outDir;
726
966
  build;
727
- runtime;
967
+ editor;
968
+ dirs;
728
969
  };
970
+ __decorateClass([
971
+ Expose(),
972
+ IsBoolean()
973
+ ], ClientConfig.prototype, "enable", 2);
729
974
  __decorateClass([
730
975
  Expose(),
731
976
  IsPort()
732
977
  ], ClientConfig.prototype, "port", 2);
733
978
  __decorateClass([
734
979
  Expose(),
735
- IsPort()
736
- ], ClientConfig.prototype, "gameExposurePort", 2);
980
+ IsString(),
981
+ IsNotEmpty()
982
+ ], ClientConfig.prototype, "outDir", 2);
737
983
  __decorateClass([
738
984
  Expose(),
739
985
  Type(() => BuildConfig),
@@ -741,17 +987,23 @@ __decorateClass([
741
987
  ], ClientConfig.prototype, "build", 2);
742
988
  __decorateClass([
743
989
  Expose(),
744
- Type(() => RunConfig),
990
+ Type(() => EditorConfig),
991
+ ValidateNested()
992
+ ], ClientConfig.prototype, "editor", 2);
993
+ __decorateClass([
994
+ Expose(),
995
+ Type(() => DirsConfig),
745
996
  ValidateNested()
746
- ], ClientConfig.prototype, "runtime", 2);
997
+ ], ClientConfig.prototype, "dirs", 2);
747
998
  var ServerConfig = class {
748
999
  static {
749
1000
  __name(this, "ServerConfig");
750
1001
  }
751
1002
  enable;
752
- port;
1003
+ outDir;
753
1004
  build;
754
- runtime;
1005
+ editor;
1006
+ dirs;
755
1007
  };
756
1008
  __decorateClass([
757
1009
  Expose(),
@@ -759,8 +1011,9 @@ __decorateClass([
759
1011
  ], ServerConfig.prototype, "enable", 2);
760
1012
  __decorateClass([
761
1013
  Expose(),
762
- IsPort()
763
- ], ServerConfig.prototype, "port", 2);
1014
+ IsString(),
1015
+ IsNotEmpty()
1016
+ ], ServerConfig.prototype, "outDir", 2);
764
1017
  __decorateClass([
765
1018
  Expose(),
766
1019
  Type(() => BuildConfig),
@@ -768,9 +1021,14 @@ __decorateClass([
768
1021
  ], ServerConfig.prototype, "build", 2);
769
1022
  __decorateClass([
770
1023
  Expose(),
771
- Type(() => RunConfig),
1024
+ Type(() => EditorConfig),
1025
+ ValidateNested()
1026
+ ], ServerConfig.prototype, "editor", 2);
1027
+ __decorateClass([
1028
+ Expose(),
1029
+ Type(() => DirsConfig),
772
1030
  ValidateNested()
773
- ], ServerConfig.prototype, "runtime", 2);
1031
+ ], ServerConfig.prototype, "dirs", 2);
774
1032
  var Config = class {
775
1033
  static {
776
1034
  __name(this, "Config");
@@ -809,11 +1067,13 @@ __decorateClass([
809
1067
  import { plainToInstance } from "class-transformer";
810
1068
  import { validate } from "class-validator";
811
1069
  import { existsSync, readFileSync } from "fs";
812
- import { join as join2 } from "path";
1070
+ import { join as join3 } from "path";
813
1071
 
814
1072
  // src/lib/constants.ts
815
1073
  var CONFIG_FILE_NAME = "nanoforge.config.json";
816
- var NANOFORGE_DIR = ".nanoforge";
1074
+ var MANIFEST_FILE_NAME = "nanoforge.manifest.json";
1075
+ var GLOBAL_CONFIG_FILE_NAME = ".nanoforgerc";
1076
+ var REGISTRY_URL = "https://api.nanoforge.dev";
817
1077
 
818
1078
  // src/lib/utils/object.ts
819
1079
  var isObject = /* @__PURE__ */ __name((item) => {
@@ -834,6 +1094,7 @@ var deepMerge = /* @__PURE__ */ __name((target, ...sources) => {
834
1094
  }
835
1095
  return deepMerge(target, ...sources);
836
1096
  }, "deepMerge");
1097
+ var isEmpty = /* @__PURE__ */ __name((target) => Object.keys(target).length === 0, "isEmpty");
837
1098
 
838
1099
  // src/lib/config/config-defaults.ts
839
1100
  var CONFIG_DEFAULTS = {
@@ -841,25 +1102,36 @@ var CONFIG_DEFAULTS = {
841
1102
  language: "ts",
842
1103
  initFunctions: true,
843
1104
  client: {
1105
+ enable: true,
844
1106
  port: "3000",
845
- gameExposurePort: "3001",
1107
+ outDir: ".nanoforge/client",
846
1108
  build: {
847
- entryFile: "client/main.ts",
848
- outDir: ".nanoforge/client"
1109
+ entry: "client/main.ts",
1110
+ staticDir: "client/static"
849
1111
  },
850
- runtime: {
851
- dir: ".nanoforge/client"
1112
+ editor: {
1113
+ entry: ".nanoforge/editor/client/main.ts",
1114
+ save: ".nanoforge/client.save.json"
1115
+ },
1116
+ dirs: {
1117
+ components: "client/components",
1118
+ systems: "client/systems"
852
1119
  }
853
1120
  },
854
1121
  server: {
855
1122
  enable: false,
856
- port: "3002",
1123
+ outDir: ".nanoforge/server",
857
1124
  build: {
858
- entryFile: "server/main.ts",
859
- outDir: ".nanoforge/server"
1125
+ entry: "server/main.ts",
1126
+ staticDir: "server/static"
1127
+ },
1128
+ editor: {
1129
+ entry: ".nanoforge/editor/server/main.ts",
1130
+ save: ".nanoforge/server.save.json"
860
1131
  },
861
- runtime: {
862
- dir: ".nanoforge/server"
1132
+ dirs: {
1133
+ components: "server/components",
1134
+ systems: "server/systems"
863
1135
  }
864
1136
  }
865
1137
  };
@@ -868,23 +1140,23 @@ var CONFIG_DEFAULTS = {
868
1140
  var config;
869
1141
  var getConfigPath = /* @__PURE__ */ __name((directory, name) => {
870
1142
  if (name) {
871
- return join2(directory, name);
1143
+ return join3(directory, name);
872
1144
  } else {
873
1145
  for (const n of [CONFIG_FILE_NAME]) {
874
- const path = join2(directory, n);
1146
+ const path = join3(directory, n);
875
1147
  if (existsSync(path)) return path;
876
1148
  }
877
1149
  throw new Error(`No config file found in directory: ${directory}`);
878
1150
  }
879
1151
  }, "getConfigPath");
880
- var loadConfig = /* @__PURE__ */ __name(async (directory, name) => {
1152
+ var loadConfig = /* @__PURE__ */ __name(async (directory, name, noThrow = false) => {
881
1153
  if (config) return config;
882
1154
  let rawData;
883
1155
  const path = getConfigPath(directory, name);
884
1156
  try {
885
1157
  rawData = deepMerge(CONFIG_DEFAULTS, JSON.parse(readFileSync(path, "utf-8")));
886
1158
  } catch {
887
- rawData = null;
1159
+ rawData = noThrow ? CONFIG_DEFAULTS : null;
888
1160
  }
889
1161
  if (!rawData) throw new Error(`Not able to read config file : ${path}`);
890
1162
  const data = plainToInstance(Config, rawData, {
@@ -899,8 +1171,8 @@ ${errors.toString().replace(/,/g, "\n")}`);
899
1171
  }, "loadConfig");
900
1172
 
901
1173
  // src/action/common/config.ts
902
- var getConfig = /* @__PURE__ */ __name((inputs, dir) => {
903
- return loadConfig(dir, getConfigInput(inputs));
1174
+ var getConfig = /* @__PURE__ */ __name((inputs, dir, noThrow) => {
1175
+ return loadConfig(dir, getConfigInput(inputs), noThrow);
904
1176
  }, "getConfig");
905
1177
 
906
1178
  // src/action/abstract.action.ts
@@ -928,7 +1200,7 @@ var AbstractAction = class {
928
1200
  if (keepAlive) return;
929
1201
  console.info();
930
1202
  if (!success2) {
931
- if (this.failureMessage) console.error(this.failureMessage);
1203
+ handleActionError(this.failureMessage, result.error);
932
1204
  process.exit(1);
933
1205
  }
934
1206
  if (this.successMessage) console.info(this.successMessage);
@@ -947,40 +1219,53 @@ var BuildAction = class extends AbstractAction {
947
1219
  async handle(_args, options) {
948
1220
  const directory = getDirectoryInput(options);
949
1221
  const config2 = await getConfig(options, directory);
1222
+ const isEditor = getEditorInput(options);
950
1223
  const isWatch = getWatchInput(options);
951
- const targets = this.resolveTargets(config2, options);
1224
+ const targets = this.resolveTargets(config2, options, isEditor);
952
1225
  const results = await this.buildAll(targets, directory, isWatch);
953
1226
  if (isWatch) {
954
1227
  return this.enterWatchMode();
955
1228
  }
956
1229
  return { success: results.every(Boolean) };
957
1230
  }
958
- resolveTargets(config2, options) {
959
- const targets = [
960
- this.createTarget(
961
- "Client",
962
- config2.client.build,
963
- "browser",
964
- getStringInput(options, "clientDirectory")
965
- )
966
- ];
967
- if (config2.server.enable) {
1231
+ resolveTargets(config2, options, isEditor) {
1232
+ const targets = [];
1233
+ if (config2.client.enable)
1234
+ targets.push(
1235
+ this.createTarget(
1236
+ "Client",
1237
+ "browser",
1238
+ getStringInputWithDefault(
1239
+ options,
1240
+ "clientEntry",
1241
+ !isEditor ? config2.client.build.entry : config2.client.editor.entry
1242
+ ),
1243
+ getStringInputWithDefault(options, "clientStaticDir", config2.client.build.staticDir),
1244
+ getStringInputWithDefault(options, "clientOutDir", config2.client.outDir)
1245
+ )
1246
+ );
1247
+ if (config2.server.enable)
968
1248
  targets.push(
969
1249
  this.createTarget(
970
1250
  "Server",
971
- config2.server.build,
972
1251
  "node",
973
- getStringInput(options, "serverDirectory")
1252
+ getStringInputWithDefault(
1253
+ options,
1254
+ "serverEntry",
1255
+ !isEditor ? config2.server.build.entry : config2.server.editor.entry
1256
+ ),
1257
+ getStringInputWithDefault(options, "serverStaticDir", config2.server.build.staticDir),
1258
+ getStringInputWithDefault(options, "serverOutDir", config2.server.outDir)
974
1259
  )
975
1260
  );
976
- }
977
1261
  return targets;
978
1262
  }
979
- createTarget(name, config2, platform, outDirOverride) {
1263
+ createTarget(name, platform, entryFile, staticDir, outDir) {
980
1264
  return {
981
1265
  name,
982
- entry: config2.entryFile,
983
- output: outDirOverride || config2.outDir,
1266
+ entry: entryFile,
1267
+ static: staticDir,
1268
+ output: outDir,
984
1269
  platform
985
1270
  };
986
1271
  }
@@ -994,17 +1279,18 @@ var BuildAction = class extends AbstractAction {
994
1279
  }
995
1280
  async buildTarget(target, directory, isWatch) {
996
1281
  const packageManager = PackageManagerFactory.create("local_bun" /* LOCAL_BUN */);
997
- const executeBuild = /* @__PURE__ */ __name((rebuild = false) => runSafe(
998
- () => packageManager.build(
1282
+ const executeBuild = /* @__PURE__ */ __name((rebuild = false) => runSafe(() => {
1283
+ this.resetOut(target.output, directory);
1284
+ this.copyFiles(target, directory);
1285
+ return packageManager.build(
999
1286
  target.name,
1000
1287
  directory,
1001
1288
  target.entry,
1002
1289
  target.output,
1003
1290
  ["--asset-naming", "[name].[ext]", "--target", target.platform],
1004
1291
  rebuild
1005
- ),
1006
- false
1007
- ), "executeBuild");
1292
+ );
1293
+ }, false), "executeBuild");
1008
1294
  if (isWatch) {
1009
1295
  this.watchDirectory(directory, target.entry, () => executeBuild(true));
1010
1296
  }
@@ -1012,7 +1298,7 @@ var BuildAction = class extends AbstractAction {
1012
1298
  return result !== false;
1013
1299
  }
1014
1300
  watchDirectory(directory, entry, onChange) {
1015
- const watchPath = dirname(join3(getCwd(directory), entry));
1301
+ const watchPath = dirname(join4(getCwd(directory), entry));
1016
1302
  watch(watchPath).on("change", onChange);
1017
1303
  }
1018
1304
  enterWatchMode() {
@@ -1021,43 +1307,16 @@ var BuildAction = class extends AbstractAction {
1021
1307
  console.info();
1022
1308
  return { keepAlive: true };
1023
1309
  }
1024
- };
1025
-
1026
- // src/action/actions/dev.action.ts
1027
- var DevAction = class extends AbstractAction {
1028
- static {
1029
- __name(this, "DevAction");
1030
- }
1031
- startMessage = Messages.DEV_START;
1032
- successMessage = Messages.DEV_SUCCESS;
1033
- failureMessage = Messages.DEV_FAILED;
1034
- async handle(_args, options) {
1035
- const directory = getDirectoryInput(options);
1036
- const generate = getDevGenerateInput(options);
1037
- const tasks = this.buildTaskList(directory, generate);
1038
- await Promise.all(tasks);
1039
- return { keepAlive: true };
1040
- }
1041
- buildTaskList(directory, generate) {
1042
- const tasks = [];
1043
- if (generate) {
1044
- tasks.push(this.runSubCommand("generate", directory, { silent: true }));
1045
- }
1046
- tasks.push(this.runSubCommand("build", directory, { silent: true }));
1047
- tasks.push(this.runSubCommand("start", directory, { silent: false }));
1048
- return tasks;
1310
+ resetOut(outDir, directory) {
1311
+ resetFolder(getCwd(join4(directory, outDir)));
1049
1312
  }
1050
- async runSubCommand(command, directory, options) {
1051
- await runSafe(async () => {
1052
- const packageManager = await PackageManagerFactory.find(directory);
1053
- await packageManager.runDev(directory, "nf", {}, [command, "--watch"], options.silent);
1054
- });
1313
+ copyFiles(target, directory) {
1314
+ const from = getCwd(join4(directory, target.static));
1315
+ const to = getCwd(join4(directory, target.output));
1316
+ copyFiles(from, to);
1055
1317
  }
1056
1318
  };
1057
1319
 
1058
- // src/action/actions/generate.action.ts
1059
- import { join as join4 } from "path";
1060
-
1061
1320
  // src/lib/schematics/abstract.collection.ts
1062
1321
  var AbstractCollection = class {
1063
1322
  constructor(collection, runner, cwd2) {
@@ -1065,6 +1324,9 @@ var AbstractCollection = class {
1065
1324
  this.runner = runner;
1066
1325
  this.cwd = cwd2;
1067
1326
  }
1327
+ collection;
1328
+ runner;
1329
+ cwd;
1068
1330
  static {
1069
1331
  __name(this, "AbstractCollection");
1070
1332
  }
@@ -1114,6 +1376,16 @@ var NanoforgeCollection = class _NanoforgeCollection extends AbstractCollection
1114
1376
  name: "docker",
1115
1377
  alias: "docker",
1116
1378
  description: "Generate a Dockerfile for the application"
1379
+ },
1380
+ {
1381
+ name: "component",
1382
+ alias: "component",
1383
+ description: "Generate a Component for an application"
1384
+ },
1385
+ {
1386
+ name: "system",
1387
+ alias: "system",
1388
+ description: "Generate a System for an application"
1117
1389
  }
1118
1390
  ];
1119
1391
  constructor(runner, cwd2) {
@@ -1157,6 +1429,7 @@ var CollectionFactory = class {
1157
1429
  var toKebabCase = /* @__PURE__ */ __name((str) => {
1158
1430
  return str.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
1159
1431
  }, "toKebabCase");
1432
+ var capitalize = /* @__PURE__ */ __name((str) => str.charAt(0).toUpperCase() + str.slice(1), "capitalize");
1160
1433
 
1161
1434
  // src/lib/schematics/schematic.option.ts
1162
1435
  var SchematicOption = class {
@@ -1164,6 +1437,8 @@ var SchematicOption = class {
1164
1437
  this.name = name;
1165
1438
  this.value = value;
1166
1439
  }
1440
+ name;
1441
+ value;
1167
1442
  static {
1168
1443
  __name(this, "SchematicOption");
1169
1444
  }
@@ -1234,64 +1509,131 @@ var mapSchematicOptions = /* @__PURE__ */ __name((inputs) => {
1234
1509
  }, []);
1235
1510
  }, "mapSchematicOptions");
1236
1511
 
1237
- // src/action/actions/generate.action.ts
1238
- var GenerateAction = class extends AbstractAction {
1512
+ // src/action/actions/create.action.ts
1513
+ var CreateAction = class extends AbstractAction {
1239
1514
  static {
1240
- __name(this, "GenerateAction");
1515
+ __name(this, "CreateAction");
1241
1516
  }
1242
- startMessage = Messages.GENERATE_START;
1243
- successMessage = Messages.GENERATE_SUCCESS;
1244
- failureMessage = Messages.GENERATE_FAILED;
1245
- async handle(_args, options) {
1517
+ startMessage = Messages.CREATE_START;
1518
+ successMessage = Messages.CREATE_SUCCESS;
1519
+ failureMessage = Messages.CREATE_FAILED;
1520
+ async handle(args, options) {
1246
1521
  const directory = getDirectoryInput(options);
1247
- const config2 = await getConfig(options, directory);
1248
- const isWatch = getWatchInput(options);
1249
- const values = this.extractValues(config2);
1250
- await this.generateParts(values, directory, isWatch);
1251
- if (isWatch) {
1252
- return this.enterWatchMode();
1253
- }
1522
+ const config2 = await getConfig(options, directory, true);
1523
+ const type = getCreateTypeInput(args);
1524
+ const name = await getCreateNameInputOrAsk(options);
1525
+ const isServer = getServerInput(options);
1526
+ const path = getPathInputWithDefault(
1527
+ options,
1528
+ config2[isServer ? "server" : "client"].dirs[type === "component" ? "components" : "systems"]
1529
+ );
1530
+ await this.generateElement(directory, type, {
1531
+ name,
1532
+ directory: path,
1533
+ part: isServer ? "server" : "client",
1534
+ language: config2.language
1535
+ });
1254
1536
  return {};
1255
1537
  }
1256
- extractValues(config2) {
1257
- return {
1258
- name: config2.name,
1259
- directory: ".",
1260
- language: config2.language,
1261
- server: config2.server.enable,
1262
- initFunctions: config2.initFunctions
1263
- };
1264
- }
1265
- async generateParts(values, directory, watch3) {
1538
+ async generateElement(directory, type, values) {
1266
1539
  const collection = CollectionFactory.create("@nanoforge-dev/schematics" /* NANOFORGE */, directory);
1267
- const baseOptions = this.baseSchematicOptions(values);
1268
- await executeSchematic(
1269
- "Client main file",
1270
- collection,
1271
- "part-main",
1272
- { ...baseOptions, part: "client" },
1273
- watch3 ? this.watchPath(directory, values.directory, "client") : void 0
1274
- );
1275
- if (values.server) {
1276
- await executeSchematic(
1277
- "Server main file",
1278
- collection,
1279
- "part-main",
1280
- { ...baseOptions, part: "server" },
1281
- this.watchPath(directory, values.directory, "server")
1282
- );
1283
- }
1540
+ await executeSchematic(capitalize(type), collection, type, values);
1284
1541
  }
1285
- baseSchematicOptions(values) {
1542
+ };
1543
+
1544
+ // src/action/actions/dev.action.ts
1545
+ var DevAction = class extends AbstractAction {
1546
+ static {
1547
+ __name(this, "DevAction");
1548
+ }
1549
+ startMessage = Messages.DEV_START;
1550
+ successMessage = Messages.DEV_SUCCESS;
1551
+ failureMessage = Messages.DEV_FAILED;
1552
+ async handle(_args, options) {
1553
+ const directory = getDirectoryInput(options);
1554
+ const generate = getDevGenerateInput(options);
1555
+ const tasks = this.buildTaskList(directory, generate);
1556
+ await Promise.all(tasks);
1557
+ return { keepAlive: true };
1558
+ }
1559
+ buildTaskList(directory, generate) {
1560
+ const tasks = [];
1561
+ if (generate) {
1562
+ tasks.push(this.runSubCommand("generate", directory, { silent: true }));
1563
+ }
1564
+ tasks.push(this.runSubCommand("build", directory, { silent: true }));
1565
+ tasks.push(this.runSubCommand("start", directory, { silent: false }));
1566
+ return tasks;
1567
+ }
1568
+ async runSubCommand(command, directory, options) {
1569
+ await runSafe(async () => {
1570
+ const packageManager = await PackageManagerFactory.find(directory);
1571
+ await packageManager.runDev(directory, "nf", {}, [command, "--watch"], options.silent);
1572
+ });
1573
+ }
1574
+ };
1575
+
1576
+ // src/action/actions/generate.action.ts
1577
+ import { join as join5 } from "path";
1578
+ var GenerateAction = class extends AbstractAction {
1579
+ static {
1580
+ __name(this, "GenerateAction");
1581
+ }
1582
+ startMessage = Messages.GENERATE_START;
1583
+ successMessage = Messages.GENERATE_SUCCESS;
1584
+ failureMessage = Messages.GENERATE_FAILED;
1585
+ async handle(_args, options) {
1586
+ const directory = getDirectoryInput(options);
1587
+ const config2 = await getConfig(options, directory);
1588
+ const isEditor = getEditorInput(options);
1589
+ const isWatch = getWatchInput(options);
1590
+ await this.generateParts(config2, directory, isEditor, isWatch);
1591
+ if (isWatch) {
1592
+ return this.enterWatchMode();
1593
+ }
1594
+ return {};
1595
+ }
1596
+ extractValues(config2) {
1286
1597
  return {
1287
- name: values.name,
1288
- directory: values.directory,
1289
- language: values.language,
1290
- initFunctions: values.initFunctions
1598
+ directory: ".",
1599
+ language: config2.language,
1600
+ initFunctions: config2.initFunctions
1291
1601
  };
1292
1602
  }
1293
- watchPath(directory, subDir, part) {
1294
- return join4(getCwd(directory), subDir, NANOFORGE_DIR, `${part}.save.json`);
1603
+ async generateParts(config2, directory, isEditor, watch3) {
1604
+ const collection = CollectionFactory.create("@nanoforge-dev/schematics" /* NANOFORGE */, directory);
1605
+ const values = this.extractValues(config2);
1606
+ if (config2.client.enable)
1607
+ await executeSchematic(
1608
+ "Client main file",
1609
+ collection,
1610
+ "part-main",
1611
+ {
1612
+ ...values,
1613
+ part: "client",
1614
+ outFile: !isEditor ? config2.client.build.entry : config2.client.editor.entry,
1615
+ saveFile: config2.client.editor.save,
1616
+ editor: isEditor
1617
+ },
1618
+ watch3 ? this.watchPath(directory, values.directory, config2.client.editor.save) : void 0
1619
+ );
1620
+ if (config2.server.enable)
1621
+ await executeSchematic(
1622
+ "Server main file",
1623
+ collection,
1624
+ "part-main",
1625
+ {
1626
+ ...values,
1627
+ part: "server",
1628
+ outFile: !isEditor ? config2.server.build.entry : config2.server.editor.entry,
1629
+ saveFile: config2.server.editor.save,
1630
+ editor: isEditor
1631
+ },
1632
+ this.watchPath(directory, values.directory, config2.server.editor.save)
1633
+ );
1634
+ }
1635
+ watchPath(directory, subDir, saveFile) {
1636
+ return join5(getCwd(directory), subDir, saveFile);
1295
1637
  }
1296
1638
  enterWatchMode() {
1297
1639
  console.info();
@@ -1301,6 +1643,310 @@ var GenerateAction = class extends AbstractAction {
1301
1643
  }
1302
1644
  };
1303
1645
 
1646
+ // src/action/actions/install.action.ts
1647
+ import { join as join7 } from "path";
1648
+
1649
+ // src/lib/global-config/global-config-handler.ts
1650
+ import { read, readUser, write, writeUser } from "rc9";
1651
+
1652
+ // src/lib/global-config/global-config-defaults.ts
1653
+ var GLOBAL_CONFIG_DEFAULTS = {};
1654
+
1655
+ // src/lib/global-config/global-config-handler.ts
1656
+ var GlobalConfigHandler = class {
1657
+ static {
1658
+ __name(this, "GlobalConfigHandler");
1659
+ }
1660
+ static read(dir) {
1661
+ const localConfig = this._readConfig(read, false, dir);
1662
+ if (localConfig) return localConfig;
1663
+ return this._readConfig(readUser, true);
1664
+ }
1665
+ static write(config2, local = false, dir) {
1666
+ const options = {
1667
+ name: GLOBAL_CONFIG_FILE_NAME,
1668
+ dir
1669
+ };
1670
+ if (local) write(config2, options);
1671
+ else writeUser(config2, options);
1672
+ }
1673
+ static _readConfig(func, force, dir) {
1674
+ const res = func({
1675
+ name: GLOBAL_CONFIG_FILE_NAME,
1676
+ dir
1677
+ });
1678
+ if (!force) {
1679
+ if (isEmpty(res)) return null;
1680
+ }
1681
+ return deepMerge(GLOBAL_CONFIG_DEFAULTS, res);
1682
+ }
1683
+ };
1684
+
1685
+ // src/lib/http/http-client.ts
1686
+ var HttpClient = class {
1687
+ static {
1688
+ __name(this, "HttpClient");
1689
+ }
1690
+ _baseUrl;
1691
+ _baseOptions;
1692
+ _middlewares;
1693
+ constructor(baseUrl, options) {
1694
+ this._baseUrl = baseUrl;
1695
+ this._baseOptions = options ?? {
1696
+ headers: {
1697
+ "Content-Type": "application/json"
1698
+ }
1699
+ };
1700
+ this._middlewares = [];
1701
+ }
1702
+ get(path, options) {
1703
+ return this._applyMiddlewares(path, options, (newPath, newOptions) => {
1704
+ return this._request(newPath, {
1705
+ ...newOptions,
1706
+ method: "GET"
1707
+ });
1708
+ });
1709
+ }
1710
+ post(path, body, options) {
1711
+ return this._applyMiddlewares(path, options, (newPath, newOptions) => {
1712
+ return this._request(newPath, {
1713
+ ...newOptions,
1714
+ method: "POST",
1715
+ body
1716
+ });
1717
+ });
1718
+ }
1719
+ put(path, body, options) {
1720
+ return this._applyMiddlewares(path, options, (newPath, newOptions) => {
1721
+ return this._request(newPath, {
1722
+ ...newOptions,
1723
+ method: "PUT",
1724
+ body
1725
+ });
1726
+ });
1727
+ }
1728
+ patch(path, body, options) {
1729
+ return this._applyMiddlewares(path, options, async (newPath, newOptions) => {
1730
+ return this._request(newPath, {
1731
+ ...newOptions,
1732
+ method: "PATCH",
1733
+ body
1734
+ });
1735
+ });
1736
+ }
1737
+ delete(path, options) {
1738
+ return this._applyMiddlewares(path, options, (newPath, newOptions) => {
1739
+ return this._request(newPath, {
1740
+ ...newOptions,
1741
+ method: "DELETE",
1742
+ body: "{}"
1743
+ });
1744
+ });
1745
+ }
1746
+ useMiddlewares(...middlewares) {
1747
+ for (const middleware of middlewares) this._middlewares.push(middleware);
1748
+ return this;
1749
+ }
1750
+ async _request(path, request) {
1751
+ const res = await fetch(path, request);
1752
+ res.content = null;
1753
+ return res;
1754
+ }
1755
+ _applyMiddlewares(path, options, callback) {
1756
+ const baseParams = {
1757
+ path,
1758
+ fullPath: this._getUrl(path),
1759
+ options: {
1760
+ ...this._baseOptions,
1761
+ ...options,
1762
+ headers: {
1763
+ ...this._baseOptions.headers,
1764
+ ...options?.headers
1765
+ }
1766
+ }
1767
+ };
1768
+ const middlewares = this._middlewares.slice();
1769
+ let response;
1770
+ const execution = /* @__PURE__ */ __name(async (params) => {
1771
+ if (!params) params = baseParams;
1772
+ const middleware = middlewares.shift();
1773
+ if (!middleware) response = await callback(params.fullPath, params.options);
1774
+ else response = await middleware(params, execution) ?? response;
1775
+ return response;
1776
+ }, "execution");
1777
+ return execution(baseParams);
1778
+ }
1779
+ _getUrl(path) {
1780
+ return `${this._baseUrl}${path}`;
1781
+ }
1782
+ };
1783
+
1784
+ // src/lib/http/repository.ts
1785
+ var Repository = class {
1786
+ static {
1787
+ __name(this, "Repository");
1788
+ }
1789
+ _client;
1790
+ constructor(client2) {
1791
+ this._client = client2;
1792
+ }
1793
+ get(path, options) {
1794
+ return this.runRequest("get", path, options);
1795
+ }
1796
+ getFile(path, options) {
1797
+ return this.runFileRequest("get", path, options);
1798
+ }
1799
+ post(path, body, options) {
1800
+ return this.runRequestBody("post", path, body ?? {}, options);
1801
+ }
1802
+ put(path, body, options) {
1803
+ return this.runRequestBody("put", path, body ?? {}, options);
1804
+ }
1805
+ patch(path, body, options) {
1806
+ return this.runRequestBody("patch", path, body ?? {}, options);
1807
+ }
1808
+ delete(path, options) {
1809
+ return this.runRequest("delete", path, options);
1810
+ }
1811
+ async runRequest(request, path, options) {
1812
+ const res = await this._client[request](path, options);
1813
+ const data = await res.json();
1814
+ if (!res.ok)
1815
+ throw new Error(`Request failed with status code ${res.status}`, {
1816
+ cause: data["error"]
1817
+ });
1818
+ return data;
1819
+ }
1820
+ async runFileRequest(request, path, options) {
1821
+ const res = await this._client[request](path, options);
1822
+ if (!res.ok)
1823
+ throw new Error(`Request failed with status code ${res.status}`, {
1824
+ cause: (await res.json())["error"]
1825
+ });
1826
+ return await res.blob();
1827
+ }
1828
+ async runRequestBody(request, path, body, options) {
1829
+ const res = await this._client[request](
1830
+ path,
1831
+ body === void 0 ? void 0 : body instanceof FormData ? body : JSON.stringify(body),
1832
+ options
1833
+ );
1834
+ const data = await res.json();
1835
+ if (!res.ok)
1836
+ throw new Error(`Request failed with status code ${res.status}`, {
1837
+ cause: data["error"]
1838
+ });
1839
+ return data;
1840
+ }
1841
+ };
1842
+
1843
+ // src/lib/http/client.ts
1844
+ var client = new HttpClient(REGISTRY_URL ?? "");
1845
+ var api = new Repository(client);
1846
+ var withAuth = /* @__PURE__ */ __name((apiKey, force = false, headers = {
1847
+ "Content-Type": "application/json"
1848
+ }) => {
1849
+ if (!apiKey && force) {
1850
+ console.error("No registry key found. Please use `nf login` to login");
1851
+ throw new Error("No apikey found. Please use `nf login` to login");
1852
+ }
1853
+ return new Repository(
1854
+ new HttpClient(REGISTRY_URL ?? "", {
1855
+ headers: {
1856
+ Authorization: apiKey,
1857
+ ...headers
1858
+ }
1859
+ })
1860
+ );
1861
+ }, "withAuth");
1862
+
1863
+ // src/lib/manifest/manifest-resolver.ts
1864
+ var resolveManifestDependencies = /* @__PURE__ */ __name(async (names, dir) => {
1865
+ const client2 = withAuth(GlobalConfigHandler.read(dir).apiKey, false);
1866
+ return concatDeps(await Promise.all(names.map(async (d) => resolveDeps(d, client2))));
1867
+ }, "resolveManifestDependencies");
1868
+ var resolveManifest = /* @__PURE__ */ __name(async (name, client2) => {
1869
+ return await client2.get(`/registry/${name}`);
1870
+ }, "resolveManifest");
1871
+ var resolveDeps = /* @__PURE__ */ __name(async (name, client2) => {
1872
+ const manifest = await resolveManifest(name, client2);
1873
+ const baseDeps = manifest.dependencies ?? [];
1874
+ const deps = await Promise.all(baseDeps.map(async (d) => resolveDeps(d, client2)));
1875
+ return concatDeps(
1876
+ [{ nf: { [manifest.name]: manifest }, npm: getNpmDeps(manifest) }].concat(deps)
1877
+ );
1878
+ }, "resolveDeps");
1879
+ var getNpmDeps = /* @__PURE__ */ __name((manifest) => {
1880
+ return Object.entries(manifest.npmDependencies ?? {});
1881
+ }, "getNpmDeps");
1882
+ var concatDeps = /* @__PURE__ */ __name((deps) => {
1883
+ return {
1884
+ npm: deps.map(({ npm }) => npm).flat(),
1885
+ nf: Object.fromEntries(deps.map(({ nf }) => Object.entries(nf)).flat())
1886
+ };
1887
+ }, "concatDeps");
1888
+
1889
+ // src/lib/registry/registry.ts
1890
+ import fs4 from "fs";
1891
+ import { join as join6 } from "path";
1892
+ var Registry = class {
1893
+ static {
1894
+ __name(this, "Registry");
1895
+ }
1896
+ static async publish(manifest, dir) {
1897
+ const client2 = this._getClient(dir, true, false);
1898
+ const filename = manifest.publish?.paths?.package ?? "index.ts";
1899
+ const file = await this._getPackageFile(filename, dir);
1900
+ const data = new FormData();
1901
+ for (const key of Object.keys(manifest)) {
1902
+ const value = manifest[key];
1903
+ if (!value) continue;
1904
+ data.append(key, typeof value === "string" ? value : JSON.stringify(value));
1905
+ }
1906
+ data.append("_packageFile", file, filename);
1907
+ await client2.put(`/registry/${manifest.name}`, data);
1908
+ }
1909
+ static async unpublish(manifest, dir) {
1910
+ const client2 = this._getClient(dir, true);
1911
+ await client2.delete(`/registry/${manifest.name}`);
1912
+ }
1913
+ static async install(manifests, dir) {
1914
+ const cwd2 = getCwd(dir);
1915
+ const client2 = this._getClient(dir, false);
1916
+ for (const manifest of manifests) {
1917
+ await this.installPackage(client2, manifest, cwd2);
1918
+ }
1919
+ }
1920
+ static async installPackage(client2, manifest, dir) {
1921
+ const file = await client2.getFile(`/registry/${manifest.name}/-/${manifest._file}`);
1922
+ const path = join6(dir, this.getTypeSubFolder(manifest.type));
1923
+ fs4.mkdirSync(path, { recursive: true });
1924
+ fs4.writeFileSync(join6(path, manifest._file), await file.bytes());
1925
+ }
1926
+ static getTypeSubFolder(type) {
1927
+ if (type === "component") return "components";
1928
+ if (type === "system") return "systems";
1929
+ return ".";
1930
+ }
1931
+ static _getClient(dir, force, headers = true) {
1932
+ const config2 = GlobalConfigHandler.read(dir);
1933
+ return withAuth(config2.apiKey, force, !headers ? {} : void 0);
1934
+ }
1935
+ static _getPackageFile(filename, dir) {
1936
+ const path = join6(getCwd(dir ?? "."), filename);
1937
+ if (!fs4.existsSync(path))
1938
+ throw new Error(
1939
+ "Package not found, please specify path in the nanoforge.manifest.json : `publish.paths.package`!"
1940
+ );
1941
+ try {
1942
+ fs4.accessSync(path, fs4.constants.R_OK);
1943
+ return fs4.openAsBlob(path);
1944
+ } catch {
1945
+ throw new Error("Cannot read package file, please verify your file permissions!");
1946
+ }
1947
+ }
1948
+ };
1949
+
1304
1950
  // src/action/actions/install.action.ts
1305
1951
  var InstallAction = class extends AbstractAction {
1306
1952
  static {
@@ -1312,114 +1958,78 @@ var InstallAction = class extends AbstractAction {
1312
1958
  async handle(args, options) {
1313
1959
  const names = await getInstallNamesInputOrAsk(args);
1314
1960
  const directory = getDirectoryInput(options);
1961
+ const isLib = getInstallLibInput(options);
1962
+ const isServer = getServerInput(options);
1963
+ return isLib ? this._installLibs(directory, names) : this._installNfPackages(directory, names, isServer);
1964
+ }
1965
+ async _installLibs(directory, names) {
1315
1966
  const packageManager = await PackageManagerFactory.find(directory);
1316
- const success2 = await packageManager.addProduction(directory, names);
1317
- return { success: success2 };
1967
+ return { success: await packageManager.addDevelopment(directory, names) };
1968
+ }
1969
+ async _installNfPackages(directory, names, isServer) {
1970
+ const deps = await resolveManifestDependencies(names, directory);
1971
+ const libSuccess = await this._installLibs(
1972
+ directory,
1973
+ deps.npm.map(([name, version]) => `${name}@${version}`)
1974
+ );
1975
+ if (!libSuccess) return { success: false };
1976
+ return withSpinner(Messages.INSTALL_PACKAGES_IN_PROGRESS, async () => {
1977
+ await Registry.install(
1978
+ Object.values(deps.nf),
1979
+ join7(directory, isServer ? "server" : "client")
1980
+ );
1981
+ });
1318
1982
  }
1319
1983
  };
1320
1984
 
1321
- // src/action/actions/new.action.ts
1322
- import { join as join5 } from "path";
1323
-
1324
- // src/lib/input/inputs/new/docker.input.ts
1325
- var getDockerInput = /* @__PURE__ */ __name((inputs) => {
1326
- return getBooleanInput(inputs, "docker");
1327
- }, "getDockerInput");
1328
- var getDockerOrAsk = /* @__PURE__ */ __name((inputs) => {
1329
- return getInputOrAsk(
1330
- getDockerInput(inputs),
1331
- () => askConfirm(Messages.NEW_DOCKER_QUESTION, { default: true })
1332
- );
1333
- }, "getDockerOrAsk");
1334
-
1335
- // src/lib/input/inputs/new/init-functions.input.ts
1336
- var getNewInitFunctionsWithDefault = /* @__PURE__ */ __name((inputs) => {
1337
- return getBooleanInputWithDefault(inputs, "initFunctions", false);
1338
- }, "getNewInitFunctionsWithDefault");
1339
-
1340
- // src/lib/input/inputs/new/language.input.ts
1341
- var getLanguageInput = /* @__PURE__ */ __name((inputs) => {
1342
- return getStringInput(inputs, "language");
1343
- }, "getLanguageInput");
1344
- var getNewLanguageInputOrAsk = /* @__PURE__ */ __name((inputs) => {
1345
- return getInputOrAsk(
1346
- getLanguageInput(inputs),
1347
- () => askSelect(Messages.NEW_LANGUAGE_QUESTION, [{ value: "ts" }, { value: "js" }], {
1348
- default: "ts"
1349
- })
1350
- );
1351
- }, "getNewLanguageInputOrAsk");
1352
-
1353
- // src/lib/input/inputs/new/name.input.ts
1354
- var getNameInput = /* @__PURE__ */ __name((inputs) => {
1355
- return getStringInput(inputs, "name");
1356
- }, "getNameInput");
1357
- var getNewNameInputOrAsk = /* @__PURE__ */ __name((inputs) => {
1358
- return getInputOrAsk(
1359
- getNameInput(inputs),
1360
- () => askInput(Messages.NEW_NAME_QUESTION, {
1361
- required: true,
1362
- default: "nanoforge-app"
1363
- })
1364
- );
1365
- }, "getNewNameInputOrAsk");
1366
-
1367
- // src/lib/input/inputs/new/package-manager.input.ts
1368
- var getPackageManagerInput = /* @__PURE__ */ __name((inputs) => {
1369
- return getStringInput(inputs, "packageManager");
1370
- }, "getPackageManagerInput");
1371
- var getNewPackageManagerInputOrAsk = /* @__PURE__ */ __name((inputs) => {
1372
- return getInputOrAsk(
1373
- getPackageManagerInput(inputs),
1374
- () => askSelect(
1375
- Messages.NEW_PACKAGE_MANAGER_QUESTION,
1376
- [{ value: "npm" }, { value: "yarn" }, { value: "pnpm" }, { value: "bun" }],
1985
+ // src/action/actions/login.action.ts
1986
+ var LoginAction = class extends AbstractAction {
1987
+ static {
1988
+ __name(this, "LoginAction");
1989
+ }
1990
+ startMessage = Messages.LOGIN_START;
1991
+ successMessage = Messages.LOGIN_SUCCESS;
1992
+ failureMessage = Messages.LOGIN_FAILED;
1993
+ async handle(_args, options) {
1994
+ const directory = getDirectoryInput(options);
1995
+ const isLocal = getLocalInput(options);
1996
+ const apiKey = await getLoginApiKeyInputOrAsk(options);
1997
+ await withAuth(apiKey, true).post("/registry-key/verify");
1998
+ GlobalConfigHandler.write(
1377
1999
  {
1378
- default: "npm"
1379
- }
1380
- )
1381
- );
1382
- }, "getNewPackageManagerInputOrAsk");
1383
-
1384
- // src/lib/input/inputs/new/path.input.ts
1385
- var getNewPathInput = /* @__PURE__ */ __name((inputs) => {
1386
- return getStringInput(inputs, "path");
1387
- }, "getNewPathInput");
1388
-
1389
- // src/lib/input/inputs/new/server.input.ts
1390
- var getNewServerInput = /* @__PURE__ */ __name((inputs) => {
1391
- return getBooleanInput(inputs, "server");
1392
- }, "getNewServerInput");
1393
- var getNewServerOrAsk = /* @__PURE__ */ __name((inputs) => {
1394
- return getInputOrAsk(
1395
- getNewServerInput(inputs),
1396
- () => askConfirm(Messages.NEW_SERVER_QUESTION, { default: false })
1397
- );
1398
- }, "getNewServerOrAsk");
1399
-
1400
- // src/lib/input/inputs/new/skip-install.input.ts
1401
- var getNewSkipInstallInput = /* @__PURE__ */ __name((inputs) => {
1402
- return getBooleanInput(inputs, "skipInstall");
1403
- }, "getNewSkipInstallInput");
1404
- var getNewSkipInstallOrAsk = /* @__PURE__ */ __name((inputs) => {
1405
- return getInputOrAsk(
1406
- getNewSkipInstallInput(inputs),
1407
- () => askConfirm(Messages.NEW_SKIP_INSTALL_QUESTION, { default: false })
1408
- );
1409
- }, "getNewSkipInstallOrAsk");
2000
+ apiKey
2001
+ },
2002
+ isLocal,
2003
+ directory
2004
+ );
2005
+ return { success: true };
2006
+ }
2007
+ };
1410
2008
 
1411
- // src/lib/input/inputs/new/strict.input.ts
1412
- var getNewStrictInput = /* @__PURE__ */ __name((inputs) => {
1413
- return getBooleanInput(inputs, "strict");
1414
- }, "getNewStrictInput");
1415
- var getNewStrictOrAsk = /* @__PURE__ */ __name((inputs) => {
1416
- return getInputOrAsk(
1417
- getNewStrictInput(inputs),
1418
- () => askConfirm(Messages.NEW_STRICT_QUESTION, { default: true })
1419
- );
1420
- }, "getNewStrictOrAsk");
2009
+ // src/action/actions/logout.action.ts
2010
+ var LogoutAction = class extends AbstractAction {
2011
+ static {
2012
+ __name(this, "LogoutAction");
2013
+ }
2014
+ startMessage = Messages.LOGOUT_START;
2015
+ successMessage = Messages.LOGOUT_SUCCESS;
2016
+ failureMessage = Messages.LOGOUT_FAILED;
2017
+ async handle(_args, options) {
2018
+ const directory = getDirectoryInput(options);
2019
+ const isLocal = getLocalInput(options);
2020
+ GlobalConfigHandler.write(
2021
+ {
2022
+ apiKey: void 0
2023
+ },
2024
+ isLocal,
2025
+ directory
2026
+ );
2027
+ return { success: true };
2028
+ }
2029
+ };
1421
2030
 
1422
2031
  // src/action/actions/new.action.ts
2032
+ import { join as join8 } from "path";
1423
2033
  var NewAction = class extends AbstractAction {
1424
2034
  static {
1425
2035
  __name(this, "NewAction");
@@ -1428,26 +2038,31 @@ var NewAction = class extends AbstractAction {
1428
2038
  successMessage = Messages.NEW_SUCCESS;
1429
2039
  failureMessage = Messages.NEW_FAILED;
1430
2040
  async handle(_args, options) {
1431
- const directory = getDirectoryInput(options);
2041
+ const cwdDirectory = getDirectoryInput(options);
1432
2042
  const values = await this.collectValues(options);
1433
- await this.scaffold(values, directory);
2043
+ await this.scaffold(values, cwdDirectory);
1434
2044
  let res = true;
1435
2045
  if (!values.skipInstall) {
1436
- res = await this.installDependencies(values.packageManager, join5(directory, values.name));
2046
+ res = await this.installDependencies(
2047
+ values.packageManager,
2048
+ join8(cwdDirectory, values.directory ?? values.name)
2049
+ );
1437
2050
  }
1438
2051
  return { success: res };
1439
2052
  }
1440
2053
  async collectValues(inputs) {
1441
2054
  return {
1442
2055
  name: await getNewNameInputOrAsk(inputs),
1443
- directory: getNewPathInput(inputs),
2056
+ directory: getPathInput(inputs),
1444
2057
  packageManager: await getNewPackageManagerInputOrAsk(inputs),
1445
2058
  language: await getNewLanguageInputOrAsk(inputs),
1446
2059
  strict: await getNewStrictOrAsk(inputs),
1447
2060
  server: await getNewServerOrAsk(inputs),
1448
2061
  initFunctions: getNewInitFunctionsWithDefault(inputs),
1449
2062
  skipInstall: await getNewSkipInstallOrAsk(inputs),
1450
- docker: await getDockerOrAsk(inputs)
2063
+ docker: await getNewDockerOrAsk(inputs),
2064
+ lint: getNewLintInput(inputs),
2065
+ editor: getEditorInput(inputs)
1451
2066
  };
1452
2067
  }
1453
2068
  async scaffold(values, directory) {
@@ -1469,14 +2084,18 @@ var NewAction = class extends AbstractAction {
1469
2084
  packageManager: values.packageManager,
1470
2085
  language: values.language,
1471
2086
  strict: values.strict,
1472
- server: values.server
2087
+ server: values.server,
2088
+ lint: values.lint,
2089
+ editor: values.editor
1473
2090
  });
1474
2091
  }
1475
2092
  generateConfiguration(collection, values) {
1476
2093
  return executeSchematic("Configuration", collection, "configuration", {
1477
2094
  name: values.name,
1478
- directory: values.directory,
1479
- server: values.server
2095
+ directory: values.directory ?? values.name,
2096
+ server: values.server,
2097
+ language: values.language,
2098
+ initFunctions: values.initFunctions
1480
2099
  });
1481
2100
  }
1482
2101
  async generateClientParts(collection, values) {
@@ -1485,7 +2104,9 @@ var NewAction = class extends AbstractAction {
1485
2104
  ...partOptions,
1486
2105
  server: values.server
1487
2106
  });
1488
- await executeSchematic("Client main file", collection, "part-main", partOptions);
2107
+ await executeSchematic("Client main file", collection, "part-main", {
2108
+ ...partOptions
2109
+ });
1489
2110
  }
1490
2111
  async generateServerParts(collection, values) {
1491
2112
  const partOptions = this.partOptions(values, "server");
@@ -1493,20 +2114,20 @@ var NewAction = class extends AbstractAction {
1493
2114
  ...partOptions,
1494
2115
  server: values.server
1495
2116
  });
1496
- await executeSchematic("Server main file", collection, "part-main", partOptions);
2117
+ await executeSchematic("Server main file", collection, "part-main", {
2118
+ ...partOptions
2119
+ });
1497
2120
  }
1498
2121
  async generateDocker(collection, values) {
1499
2122
  await executeSchematic("Docker", collection, "docker", {
1500
- name: values.name,
1501
- directory: values.directory,
2123
+ directory: values.directory ?? values.name,
1502
2124
  packageManager: values.packageManager
1503
2125
  });
1504
2126
  }
1505
2127
  partOptions(values, part) {
1506
2128
  return {
1507
- name: values.name,
1508
2129
  part,
1509
- directory: values.directory,
2130
+ directory: values.directory ?? values.name,
1510
2131
  language: values.language,
1511
2132
  initFunctions: values.initFunctions
1512
2133
  };
@@ -1517,8 +2138,149 @@ var NewAction = class extends AbstractAction {
1517
2138
  }
1518
2139
  };
1519
2140
 
2141
+ // src/lib/manifest/manifest.type.ts
2142
+ import { Expose as Expose2, Type as Type2 } from "class-transformer";
2143
+ import {
2144
+ IsEnum as IsEnum2,
2145
+ IsNotEmpty as IsNotEmpty2,
2146
+ IsObject,
2147
+ IsOptional,
2148
+ IsString as IsString2,
2149
+ Matches,
2150
+ ValidateNested as ValidateNested2
2151
+ } from "class-validator";
2152
+ var ManifestPackageTypeEnum = /* @__PURE__ */ ((ManifestPackageTypeEnum2) => {
2153
+ ManifestPackageTypeEnum2["COMPONENT"] = "component";
2154
+ ManifestPackageTypeEnum2["SYSTEM"] = "system";
2155
+ return ManifestPackageTypeEnum2;
2156
+ })(ManifestPackageTypeEnum || {});
2157
+ var PathsPublishManifest = class {
2158
+ static {
2159
+ __name(this, "PathsPublishManifest");
2160
+ }
2161
+ package;
2162
+ };
2163
+ __decorateClass([
2164
+ Expose2(),
2165
+ IsString2(),
2166
+ IsNotEmpty2(),
2167
+ IsOptional()
2168
+ ], PathsPublishManifest.prototype, "package", 2);
2169
+ var PublishManifest = class {
2170
+ static {
2171
+ __name(this, "PublishManifest");
2172
+ }
2173
+ paths;
2174
+ };
2175
+ __decorateClass([
2176
+ Expose2(),
2177
+ IsOptional(),
2178
+ ValidateNested2(),
2179
+ Type2(() => PathsPublishManifest)
2180
+ ], PublishManifest.prototype, "paths", 2);
2181
+ var Manifest = class {
2182
+ static {
2183
+ __name(this, "Manifest");
2184
+ }
2185
+ name;
2186
+ type;
2187
+ description;
2188
+ tags;
2189
+ dependencies;
2190
+ publish;
2191
+ npmDependencies;
2192
+ };
2193
+ __decorateClass([
2194
+ Expose2(),
2195
+ IsString2(),
2196
+ Matches(/^[A-Za-z0-9-]+\/[A-Za-z0-9-]+$/),
2197
+ IsNotEmpty2()
2198
+ ], Manifest.prototype, "name", 2);
2199
+ __decorateClass([
2200
+ Expose2(),
2201
+ IsString2(),
2202
+ IsEnum2(ManifestPackageTypeEnum),
2203
+ IsNotEmpty2()
2204
+ ], Manifest.prototype, "type", 2);
2205
+ __decorateClass([
2206
+ Expose2(),
2207
+ IsString2(),
2208
+ IsOptional()
2209
+ ], Manifest.prototype, "description", 2);
2210
+ __decorateClass([
2211
+ Expose2(),
2212
+ IsString2({ each: true }),
2213
+ IsOptional()
2214
+ ], Manifest.prototype, "tags", 2);
2215
+ __decorateClass([
2216
+ Expose2(),
2217
+ IsString2({ each: true }),
2218
+ IsNotEmpty2({ each: true }),
2219
+ IsOptional()
2220
+ ], Manifest.prototype, "dependencies", 2);
2221
+ __decorateClass([
2222
+ Expose2(),
2223
+ IsOptional(),
2224
+ ValidateNested2(),
2225
+ Type2(() => PublishManifest)
2226
+ ], Manifest.prototype, "publish", 2);
2227
+ __decorateClass([
2228
+ Expose2(),
2229
+ IsObject(),
2230
+ IsOptional()
2231
+ ], Manifest.prototype, "npmDependencies", 2);
2232
+
2233
+ // src/lib/manifest/manifest-loader.ts
2234
+ import { plainToInstance as plainToInstance2 } from "class-transformer";
2235
+ import { validate as validate2 } from "class-validator";
2236
+ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
2237
+ import { join as join9 } from "path";
2238
+ var getManifestPath = /* @__PURE__ */ __name((directory) => {
2239
+ for (const n of [MANIFEST_FILE_NAME]) {
2240
+ const path = join9(directory, n);
2241
+ if (existsSync2(path)) return path;
2242
+ }
2243
+ throw new Error(`No manifest file found in directory: ${directory}`);
2244
+ }, "getManifestPath");
2245
+ var loadManifest = /* @__PURE__ */ __name(async (directory) => {
2246
+ let rawData;
2247
+ const path = getManifestPath(directory);
2248
+ try {
2249
+ rawData = deepMerge({}, JSON.parse(readFileSync2(path, "utf-8")));
2250
+ } catch {
2251
+ rawData = null;
2252
+ }
2253
+ if (!rawData) throw new Error(`Not able to read manifest file : ${path}`);
2254
+ const data = plainToInstance2(Manifest, rawData, {
2255
+ excludeExtraneousValues: true
2256
+ });
2257
+ const errors = await validate2(data);
2258
+ if (errors.length > 0)
2259
+ throw new Error(`Invalid manifest
2260
+ ${errors.toString().replace(/,/g, "\n")}`);
2261
+ return data;
2262
+ }, "loadManifest");
2263
+
2264
+ // src/action/actions/publish.action.ts
2265
+ var PublishAction = class extends AbstractAction {
2266
+ static {
2267
+ __name(this, "PublishAction");
2268
+ }
2269
+ startMessage = Messages.PUBLISH_START;
2270
+ successMessage = Messages.PUBLISH_SUCCESS;
2271
+ failureMessage = Messages.PUBLISH_FAILED;
2272
+ async handle(_args, options) {
2273
+ const directory = getDirectoryInput(options);
2274
+ const manifest = await loadManifest(directory);
2275
+ return withSpinner(Messages.PUBLISH_IN_PROGRESS(manifest.name), async () => {
2276
+ await Registry.publish(manifest, directory);
2277
+ });
2278
+ }
2279
+ };
2280
+
1520
2281
  // src/action/actions/start.action.ts
1521
- import { join as join6 } from "path";
2282
+ import dotenv from "dotenv";
2283
+ import { join as join10, resolve as resolve3 } from "path";
1522
2284
  var StartAction = class extends AbstractAction {
1523
2285
  static {
1524
2286
  __name(this, "StartAction");
@@ -1529,20 +2291,21 @@ var StartAction = class extends AbstractAction {
1529
2291
  async handle(_args, options) {
1530
2292
  const directory = getDirectoryInput(options);
1531
2293
  const config2 = await getConfig(options, directory);
2294
+ const clientDir = getStringInputWithDefault(options, "clientDir", config2.client.outDir);
2295
+ const serverDir = getStringInputWithDefault(options, "serverDir", config2.server.outDir);
1532
2296
  const watch3 = getWatchInput(options);
1533
- const ports = this.resolvePorts(options, config2);
2297
+ const port = getStringInputWithDefault(options, "port", config2.client.port);
1534
2298
  const ssl = this.resolveSSL(options);
1535
- const tasks = this.buildStartTasks(config2, directory, watch3, ports, ssl);
2299
+ const tasks = this.buildStartTasks(config2, directory, {
2300
+ clientDir,
2301
+ serverDir,
2302
+ watch: watch3,
2303
+ port,
2304
+ ssl
2305
+ });
1536
2306
  await Promise.all(tasks);
1537
2307
  return { keepAlive: true };
1538
2308
  }
1539
- resolvePorts(options, config2) {
1540
- return {
1541
- clientPort: getStringInputWithDefault(options, "clientPort", config2.client.port),
1542
- gameExposurePort: getStringInput(options, "gameExposurePort"),
1543
- serverPort: getStringInput(options, "serverPort")
1544
- };
1545
- }
1546
2309
  resolveSSL(options) {
1547
2310
  const cert = getStringInput(options, "cert");
1548
2311
  const key = getStringInput(options, "key");
@@ -1554,53 +2317,100 @@ var StartAction = class extends AbstractAction {
1554
2317
  key
1555
2318
  };
1556
2319
  }
1557
- buildStartTasks(config2, directory, watch3, ports, ssl) {
2320
+ buildStartTasks(config2, directory, options) {
2321
+ const env2 = this.parseEnv(directory);
1558
2322
  const tasks = [];
1559
- if (config2.server.enable) {
1560
- tasks.push(this.startServer(directory, config2.server.runtime.dir, watch3, ports.serverPort));
1561
- }
1562
- tasks.push(this.startClient(directory, config2, watch3, ports, ssl));
2323
+ const { clientDir, serverDir, watch: watch3, port, ssl } = options;
2324
+ if (config2.server.enable)
2325
+ tasks.push(this.startServer(directory, config2, { serverDir, watch: watch3 }, env2));
2326
+ if (config2.client.enable)
2327
+ tasks.push(
2328
+ this.startClient(directory, config2, { clientDir, serverDir, watch: watch3, port, ssl }, env2)
2329
+ );
1563
2330
  return tasks;
1564
2331
  }
1565
- async startClient(directory, config2, watch3, ports, ssl) {
2332
+ async startClient(directory, config2, options, env2) {
1566
2333
  const loaderPath = getModulePath("@nanoforge-dev/loader-client/package.json", true);
1567
- const gameDir = config2.client.runtime.dir;
1568
- const env2 = this.buildClientEnv(directory, gameDir, watch3, config2, ports, ssl);
1569
- await this.runLoader("Client", loaderPath, env2);
1570
- }
1571
- buildClientEnv(directory, gameDir, watch3, config2, ports, ssl) {
1572
- const env2 = {
1573
- PORT: ports.clientPort,
1574
- GAME_DIR: getCwd(join6(directory, gameDir))
2334
+ const params = this.buildClientParams(directory, config2, options);
2335
+ await this.runLoader("Client", loaderPath, params, env2.client);
2336
+ }
2337
+ async startServer(directory, config2, options, env2) {
2338
+ const loaderPath = getModulePath("@nanoforge-dev/loader-server/package.json", true);
2339
+ const params = this.buildServerParams(directory, config2, options);
2340
+ await this.runLoader("Server", loaderPath, params, env2.server);
2341
+ }
2342
+ buildClientParams(directory, config2, options) {
2343
+ const params = {
2344
+ "-d": getCwd(join10(directory, options.clientDir)),
2345
+ "-p": options.port
1575
2346
  };
1576
- if (ports.gameExposurePort) {
1577
- env2["GAME_EXPOSURE_PORT"] = ports.gameExposurePort;
1578
- }
1579
- if (watch3) {
1580
- env2["WATCH"] = "true";
2347
+ if (options.watch) params["--watch"] = true;
2348
+ if (options.watch) {
2349
+ params["--watch"] = true;
1581
2350
  if (config2.server.enable) {
1582
- env2["WATCH_SERVER_GAME_DIR"] = getCwd(join6(directory, config2.server.runtime.dir));
2351
+ params["--watch-server-dir"] = getCwd(join10(directory, options.serverDir));
1583
2352
  }
1584
2353
  }
1585
- if (ssl) {
1586
- env2["CERT"] = ssl.cert;
1587
- env2["KEY"] = ssl.key;
2354
+ if (options.ssl) {
2355
+ params["--cert"] = options.ssl.cert;
2356
+ params["--key"] = options.ssl.key;
1588
2357
  }
1589
- return env2;
2358
+ return this.buildParams(params);
1590
2359
  }
1591
- async startServer(directory, gameDir, watch3, port) {
1592
- const loaderPath = getModulePath("@nanoforge-dev/loader-server/package.json", true);
1593
- const env2 = {
1594
- GAME_DIR: getCwd(join6(directory, gameDir))
2360
+ buildServerParams(directory, _config, options) {
2361
+ const params = {
2362
+ "-d": getCwd(join10(directory, options.serverDir))
2363
+ };
2364
+ if (options.watch) params["--watch"] = true;
2365
+ return this.buildParams(params);
2366
+ }
2367
+ buildParams(params) {
2368
+ return Object.entries(params).map(([key, value]) => typeof value === "string" ? [key, value] : [key]).flat();
2369
+ }
2370
+ parseEnv(dir) {
2371
+ const prefix = "NANOFORGE_";
2372
+ const clientPrefix = `${prefix}CLIENT_`;
2373
+ const serverPrefix = `${prefix}SERVER_`;
2374
+ const rawEnv = {
2375
+ ...process.env
2376
+ };
2377
+ dotenv.config({
2378
+ path: resolve3(getCwd(join10(dir, ".env"))),
2379
+ processEnv: rawEnv
2380
+ });
2381
+ const baseEnv = Object.entries(rawEnv).filter(
2382
+ ([key, value]) => key.startsWith(prefix) && !!value
2383
+ );
2384
+ return {
2385
+ client: Object.fromEntries(
2386
+ baseEnv.filter(([key]) => !key.startsWith(serverPrefix)).map(([key, value]) => [key.replace(clientPrefix, prefix), value])
2387
+ ),
2388
+ server: Object.fromEntries(
2389
+ baseEnv.filter(([key]) => !key.startsWith(clientPrefix)).map(([key, value]) => [key.replace(serverPrefix, prefix), value])
2390
+ )
1595
2391
  };
1596
- if (port) env2["PORT"] = port;
1597
- if (watch3) env2["WATCH"] = "true";
1598
- await this.runLoader("Server", loaderPath, env2);
1599
2392
  }
1600
- async runLoader(name, directory, env2) {
2393
+ async runLoader(name, directory, params, env2) {
1601
2394
  await runSafe(async () => {
1602
2395
  const packageManager = await PackageManagerFactory.find(directory);
1603
- await packageManager.run(name, directory, "start", env2, [], true);
2396
+ await packageManager.run(name, directory, "start", params, env2, [], true);
2397
+ });
2398
+ }
2399
+ };
2400
+
2401
+ // src/action/actions/unpublish.action.ts
2402
+ var UnpublishAction = class extends AbstractAction {
2403
+ static {
2404
+ __name(this, "UnpublishAction");
2405
+ }
2406
+ startMessage = Messages.UNPUBLISH_START;
2407
+ successMessage = Messages.UNPUBLISH_SUCCESS;
2408
+ failureMessage = Messages.UNPUBLISH_FAILED;
2409
+ async handle(_args, options) {
2410
+ const directory = getDirectoryInput(options);
2411
+ const manifest = await loadManifest(directory);
2412
+ return withSpinner(Messages.UNPUBLISH_IN_PROGRESS(manifest.name), async () => {
2413
+ await Registry.unpublish(manifest, directory);
1604
2414
  });
1605
2415
  }
1606
2416
  };
@@ -1610,6 +2420,7 @@ var AbstractCommand = class {
1610
2420
  constructor(action) {
1611
2421
  this.action = action;
1612
2422
  }
2423
+ action;
1613
2424
  static {
1614
2425
  __name(this, "AbstractCommand");
1615
2426
  }
@@ -1628,12 +2439,17 @@ var BuildCommand = class extends AbstractCommand {
1628
2439
  __name(this, "BuildCommand");
1629
2440
  }
1630
2441
  load(program) {
1631
- 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", CONFIG_FILE_NAME).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) => {
2442
+ program.command("build").description("build your game").option("-d, --directory [directory]", "specify the working directory of the command").option("-c, --config [config]", "path to the config file", CONFIG_FILE_NAME).option("--client-entry [clientEntry]", "specify the entry file of the client").option("--server-entry [serverEntry]", "specify the entry file of the server").option("--client-static-dir [clientStaticDir]", "specify the static directory of the client").option("--server-static-dir [serverStaticDir]", "specify the static directory of the server").option("--client-out-dir [clientOutDir]", "specify the output directory of the client").option("--server-out-dir [serverOutDir]", "specify the output directory of the server").option("--editor", "specify if the project must build with editor config").option("--watch", "build app in watching mode", false).action(async (rawOptions) => {
1632
2443
  const options = AbstractCommand.mapToInput({
1633
2444
  directory: rawOptions.directory,
1634
2445
  config: rawOptions.config,
1635
- clientDirectory: rawOptions.clientOutDir,
1636
- serverDirectory: rawOptions.serverOutDir,
2446
+ clientEntry: rawOptions.clientEntry,
2447
+ serverEntry: rawOptions.serverEntry,
2448
+ clientStaticDir: rawOptions.clientStaticDir,
2449
+ serverStaticDir: rawOptions.serverStaticDir,
2450
+ clientOutDir: rawOptions.clientOutDir,
2451
+ serverOutDir: rawOptions.serverOutDir,
2452
+ editor: rawOptions.editor,
1637
2453
  watch: rawOptions.watch
1638
2454
  });
1639
2455
  await this.action.run(/* @__PURE__ */ new Map(), options);
@@ -1641,13 +2457,42 @@ var BuildCommand = class extends AbstractCommand {
1641
2457
  }
1642
2458
  };
1643
2459
 
2460
+ // src/command/commands/create.command.ts
2461
+ var CreateCommand = class extends AbstractCommand {
2462
+ static {
2463
+ __name(this, "CreateCommand");
2464
+ }
2465
+ load(program) {
2466
+ program.command("create [type]").description("create nanoforge components or systems").option("-d, --directory [directory]", "specify the working directory of the command").option("-c, --config [config]", "path to the config file", CONFIG_FILE_NAME).option("-n, --name [name]", "name of the component/system").option(
2467
+ "-s, --server",
2468
+ "install components/systems on server (default install on client)",
2469
+ false
2470
+ ).option(
2471
+ "-p, --path [path]",
2472
+ "path to the component/system folder (default: [part]/<components|systems>)"
2473
+ ).action(async (type, rawOptions) => {
2474
+ const args = AbstractCommand.mapToInput({
2475
+ type
2476
+ });
2477
+ const options = AbstractCommand.mapToInput({
2478
+ directory: rawOptions.directory,
2479
+ config: rawOptions.config,
2480
+ name: rawOptions.name,
2481
+ server: rawOptions.server,
2482
+ path: rawOptions.path
2483
+ });
2484
+ await this.action.run(args, options);
2485
+ });
2486
+ }
2487
+ };
2488
+
1644
2489
  // src/command/commands/dev.command.ts
1645
2490
  var DevCommand = class extends AbstractCommand {
1646
2491
  static {
1647
2492
  __name(this, "DevCommand");
1648
2493
  }
1649
2494
  load(program) {
1650
- program.command("dev").description("run your game in dev mode").option("-d, --directory [directory]", "specify the directory of your project").option("-c, --config [config]", "path to the config file", CONFIG_FILE_NAME).option("--generate", "generate app from config", false).action(async (rawOptions) => {
2495
+ program.command("dev").description("run your game in dev mode").option("-d, --directory [directory]", "specify the working directory of the command").option("-c, --config [config]", "path to the config file", CONFIG_FILE_NAME).option("--generate", "generate app from config", false).action(async (rawOptions) => {
1651
2496
  const options = AbstractCommand.mapToInput({
1652
2497
  directory: rawOptions.directory,
1653
2498
  config: rawOptions.config,
@@ -1664,10 +2509,11 @@ var GenerateCommand = class extends AbstractCommand {
1664
2509
  __name(this, "GenerateCommand");
1665
2510
  }
1666
2511
  load(program) {
1667
- 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", CONFIG_FILE_NAME).option("--watch", "generate app in watching mode", false).action(async (rawOptions) => {
2512
+ program.command("generate").description("generate nanoforge files from config").option("-d, --directory [directory]", "specify the working directory of the command").option("-c, --config [config]", "path to the config file", CONFIG_FILE_NAME).option("--editor", "specify if the project must generate editor main file").option("--watch", "generate app in watching mode", false).action(async (rawOptions) => {
1668
2513
  const options = AbstractCommand.mapToInput({
1669
2514
  directory: rawOptions.directory,
1670
2515
  config: rawOptions.config,
2516
+ editor: rawOptions.editor,
1671
2517
  watch: rawOptions.watch
1672
2518
  });
1673
2519
  await this.action.run(/* @__PURE__ */ new Map(), options);
@@ -1681,9 +2527,15 @@ var InstallCommand = class extends AbstractCommand {
1681
2527
  __name(this, "InstallCommand");
1682
2528
  }
1683
2529
  load(program) {
1684
- program.command("install [names...]").alias("add").description("add NanoForge library to your project").option("-d, --directory [directory]", "specify the directory of your project").action(async (names, rawOptions) => {
2530
+ program.command("install [names...]").alias("add").description("add Nanoforge components and systems to your project").option("-d, --directory [directory]", "specify the working directory of the command").option("-l, --lib", "install library instead of component/system", false).option(
2531
+ "-s, --server",
2532
+ "install components/systems on server (default install on client)",
2533
+ false
2534
+ ).action(async (names, rawOptions) => {
1685
2535
  const options = AbstractCommand.mapToInput({
1686
- directory: rawOptions.directory
2536
+ directory: rawOptions.directory,
2537
+ lib: rawOptions.lib,
2538
+ server: rawOptions.server
1687
2539
  });
1688
2540
  const args = AbstractCommand.mapToInput({
1689
2541
  names: names.length ? names : void 0
@@ -1693,13 +2545,49 @@ var InstallCommand = class extends AbstractCommand {
1693
2545
  }
1694
2546
  };
1695
2547
 
2548
+ // src/command/commands/login.command.ts
2549
+ var LoginCommand = class extends AbstractCommand {
2550
+ static {
2551
+ __name(this, "LoginCommand");
2552
+ }
2553
+ load(program) {
2554
+ program.command("login").description("login to Nanoforge registry").option("-d, --directory [directory]", "specify the working directory of the command").option("-l, --local", "login only for the project", false).option("-k, --api-key <key>", "api key for Nanoforge registry").action(async (rawOptions) => {
2555
+ const options = AbstractCommand.mapToInput({
2556
+ directory: rawOptions.directory,
2557
+ local: rawOptions.local,
2558
+ apiKey: rawOptions.apiKey
2559
+ });
2560
+ await this.action.run(/* @__PURE__ */ new Map(), options);
2561
+ });
2562
+ }
2563
+ };
2564
+
2565
+ // src/command/commands/logout.command.ts
2566
+ var LogoutCommand = class extends AbstractCommand {
2567
+ static {
2568
+ __name(this, "LogoutCommand");
2569
+ }
2570
+ load(program) {
2571
+ program.command("logout").description("logout from Nanoforge registry").option("-d, --directory [directory]", "specify the working directory of the command").option("-l, --local", "logout only for the project").action(async (rawOptions) => {
2572
+ const options = AbstractCommand.mapToInput({
2573
+ directory: rawOptions.directory,
2574
+ local: rawOptions.local
2575
+ });
2576
+ await this.action.run(/* @__PURE__ */ new Map(), options);
2577
+ });
2578
+ }
2579
+ };
2580
+
1696
2581
  // src/command/commands/new.command.ts
1697
2582
  var NewCommand = class extends AbstractCommand {
1698
2583
  static {
1699
2584
  __name(this, "NewCommand");
1700
2585
  }
1701
2586
  load(program) {
1702
- program.command("new").description("create a new nanoforge project").option("-d, --directory [directory]", "specify the directory of your project").option("--name [name]", "specify the name of your project").option("--path [path]", "specify the path of your project").option("--package-manager [packageManager]", "specify the package manager of your project").option("--language [language]", "specify the language of your project").option("--strict", "use strict mode").option("--no-strict", "do not use strict mode").option("--server", "create a server").option("--no-server", "do not create a server").option("--init-functions", "initialize functions").option("--no-init-functions", "do not initialize functions").option("--skip-install", "skip installing dependencies").option("--no-skip-install", "do not skip installing dependencies").option("--docker", "generate docker files").option("--no-docker", "do not generate docker files").action(async (rawOptions) => {
2587
+ program.command("new").description("create a new nanoforge project").option("-d, --directory [directory]", "specify the working directory of the command").option("--name [name]", "specify the name of your project").option(
2588
+ "--path [path]",
2589
+ "specify the relative path where your project will be created (default: name of the project)"
2590
+ ).option("--package-manager [packageManager]", "specify the package manager of your project").option("--language [language]", "specify the language of your project").option("--strict", "use strict mode").option("--no-strict", "do not use strict mode").option("--server", "create a server").option("--no-server", "do not create a server").option("--init-functions", "initialize functions").option("--no-init-functions", "do not initialize functions").option("--skip-install", "skip installing dependencies").option("--no-skip-install", "do not skip installing dependencies").option("--docker", "generate docker files").option("--no-docker", "do not generate docker files").option("--no-lint", "do not generate lint files").option("--editor", "do add editor dependencies").action(async (rawOptions) => {
1703
2591
  const options = AbstractCommand.mapToInput({
1704
2592
  directory: rawOptions.directory,
1705
2593
  name: rawOptions.name,
@@ -1710,7 +2598,24 @@ var NewCommand = class extends AbstractCommand {
1710
2598
  server: rawOptions.server,
1711
2599
  initFunctions: rawOptions.initFunctions,
1712
2600
  skipInstall: rawOptions.skipInstall,
1713
- docker: rawOptions.docker
2601
+ docker: rawOptions.docker,
2602
+ lint: rawOptions.lint,
2603
+ editor: rawOptions.editor
2604
+ });
2605
+ await this.action.run(/* @__PURE__ */ new Map(), options);
2606
+ });
2607
+ }
2608
+ };
2609
+
2610
+ // src/command/commands/publish.command.ts
2611
+ var PublishCommand = class extends AbstractCommand {
2612
+ static {
2613
+ __name(this, "PublishCommand");
2614
+ }
2615
+ load(program) {
2616
+ program.command("publish").description("publish package to Nanoforge registry").option("-d, --directory [directory]", "specify the working directory of the command").action(async (rawOptions) => {
2617
+ const options = AbstractCommand.mapToInput({
2618
+ directory: rawOptions.directory
1714
2619
  });
1715
2620
  await this.action.run(/* @__PURE__ */ new Map(), options);
1716
2621
  });
@@ -1723,16 +2628,13 @@ var StartCommand = class extends AbstractCommand {
1723
2628
  __name(this, "StartCommand");
1724
2629
  }
1725
2630
  load(program) {
1726
- 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", CONFIG_FILE_NAME).option(
1727
- "-p, --client-port [clientPort]",
1728
- "specify the port of the loader (the website to load the game)"
1729
- ).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) => {
2631
+ program.command("start").description("start your game").option("-d, --directory [directory]", "specify the working directory of the command").option("-c, --config [config]", "path to the config file", CONFIG_FILE_NAME).option("-p, --port [port]", "specify the port of the loader (the website to load the game)").option("--client-dir [clientDirectory]", "specify the directory of the client").option("--server-dir [serverDirectory]", "specify the directory 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) => {
1730
2632
  const options = AbstractCommand.mapToInput({
1731
2633
  directory: rawOptions.directory,
1732
2634
  config: rawOptions.config,
1733
- clientPort: rawOptions.clientPort,
1734
- gameExposurePort: rawOptions.gameExposurePort,
1735
- serverPort: rawOptions.serverPort,
2635
+ port: rawOptions.port,
2636
+ clientDir: rawOptions.clientDir,
2637
+ serverDir: rawOptions.serverDir,
1736
2638
  watch: rawOptions.watch,
1737
2639
  cert: rawOptions.cert,
1738
2640
  key: rawOptions.key
@@ -1742,18 +2644,38 @@ var StartCommand = class extends AbstractCommand {
1742
2644
  }
1743
2645
  };
1744
2646
 
2647
+ // src/command/commands/unpublish.command.ts
2648
+ var UnpublishCommand = class extends AbstractCommand {
2649
+ static {
2650
+ __name(this, "UnpublishCommand");
2651
+ }
2652
+ load(program) {
2653
+ program.command("unpublish").description("unpublish package to Nanoforge registry").option("-d, --directory [directory]", "specify the working directory of the command").action(async (rawOptions) => {
2654
+ const options = AbstractCommand.mapToInput({
2655
+ directory: rawOptions.directory
2656
+ });
2657
+ await this.action.run(/* @__PURE__ */ new Map(), options);
2658
+ });
2659
+ }
2660
+ };
2661
+
1745
2662
  // src/command/command.loader.ts
1746
2663
  var CommandLoader = class {
1747
2664
  static {
1748
2665
  __name(this, "CommandLoader");
1749
2666
  }
1750
2667
  static async load(program) {
2668
+ new NewCommand(new NewAction()).load(program);
2669
+ new InstallCommand(new InstallAction()).load(program);
1751
2670
  new BuildCommand(new BuildAction()).load(program);
2671
+ new StartCommand(new StartAction()).load(program);
1752
2672
  new DevCommand(new DevAction()).load(program);
1753
2673
  new GenerateCommand(new GenerateAction()).load(program);
1754
- new InstallCommand(new InstallAction()).load(program);
1755
- new NewCommand(new NewAction()).load(program);
1756
- new StartCommand(new StartAction()).load(program);
2674
+ new CreateCommand(new CreateAction()).load(program);
2675
+ new LoginCommand(new LoginAction()).load(program);
2676
+ new LogoutCommand(new LogoutAction()).load(program);
2677
+ new PublishCommand(new PublishAction()).load(program);
2678
+ new UnpublishCommand(new UnpublishAction()).load(program);
1757
2679
  this.handleInvalidCommand(program);
1758
2680
  }
1759
2681
  static handleInvalidCommand(program) {