@idevconn/create-icore 0.3.0 → 0.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.
Files changed (27) hide show
  1. package/dist/cli.js +193 -7
  2. package/dist/index.cjs +182 -5
  3. package/dist/index.d.cts +3 -1
  4. package/dist/index.d.ts +3 -1
  5. package/dist/index.js +182 -5
  6. package/package.json +1 -1
  7. package/templates/apps/microservices/auth/src/app/app.module.ts +33 -19
  8. package/templates/apps/microservices/notes/src/app/app.module.ts +39 -23
  9. package/templates/apps/microservices/upload/src/app/app.module.ts +41 -25
  10. package/templates/apps/templates/client-antd/vite.config.mts +16 -48
  11. package/templates/apps/templates/client-mui/vite.config.mts +16 -48
  12. package/templates/apps/templates/client-shadcn/vite.config.mts +16 -48
  13. package/templates/libs/shared/package.json +10 -0
  14. package/templates/libs/shared/src/__tests__/cross-boundary.unit.test.ts +121 -0
  15. package/templates/libs/shared/src/client.ts +5 -0
  16. package/templates/libs/shared/src/strategies/fakes/fake-auth.ts +8 -9
  17. package/templates/libs/shared/src/strategies/fakes/fake-storage.ts +1 -2
  18. package/templates/libs/template-shared/src/lib/abilities/ability-provider.tsx +1 -1
  19. package/templates/libs/vite-plugins/README.md +7 -0
  20. package/templates/libs/vite-plugins/eslint.config.mjs +19 -0
  21. package/templates/libs/vite-plugins/package.json +18 -0
  22. package/templates/libs/vite-plugins/project.json +19 -0
  23. package/templates/libs/vite-plugins/src/index.d.mts +21 -0
  24. package/templates/libs/vite-plugins/src/index.mjs +106 -0
  25. package/templates/libs/vite-plugins/tsconfig.json +20 -0
  26. package/templates/libs/vite-plugins/tsconfig.lib.json +9 -0
  27. package/templates/tsconfig.base.json +3 -1
package/dist/cli.js CHANGED
@@ -13,6 +13,13 @@ import { resolve } from "path";
13
13
  import { readFile } from "fs/promises";
14
14
  import { dirname, join } from "path";
15
15
  import { fileURLToPath } from "url";
16
+ function detectPackageManager() {
17
+ const ua = process.env["npm_config_user_agent"] ?? "";
18
+ if (ua.startsWith("yarn/")) return "yarn";
19
+ if (ua.startsWith("pnpm/")) return "pnpm";
20
+ if (ua.startsWith("npm/")) return "npm";
21
+ return "yarn";
22
+ }
16
23
  async function readSelfVersion() {
17
24
  try {
18
25
  const here2 = dirname(fileURLToPath(import.meta.url));
@@ -81,6 +88,9 @@ function parseFlags(argv) {
81
88
  case "transport":
82
89
  out.transport = v;
83
90
  break;
91
+ case "package-manager":
92
+ out.packageManager = v;
93
+ break;
84
94
  case "no-git":
85
95
  out.initGit = false;
86
96
  break;
@@ -190,8 +200,12 @@ Re-run with @latest to refresh:
190
200
  initialValue: "tcp"
191
201
  });
192
202
  if (p.isCancel(transport)) throw new Error("cancelled");
203
+ const packageManager = flags.packageManager ?? detectPackageManager();
193
204
  const initGit = flags.initGit ?? !await p.confirm({ message: "Initialise git repo?", initialValue: true }) === false;
194
- const install = flags.install ?? !await p.confirm({ message: "Run yarn install?", initialValue: true }) === false;
205
+ const install = flags.install ?? !await p.confirm({
206
+ message: `Run ${packageManager} install?`,
207
+ initialValue: true
208
+ }) === false;
195
209
  return {
196
210
  projectName,
197
211
  targetDir: resolve(cwd, projectName),
@@ -203,6 +217,7 @@ Re-run with @latest to refresh:
203
217
  example,
204
218
  ui,
205
219
  transport,
220
+ packageManager,
206
221
  initGit,
207
222
  install
208
223
  };
@@ -244,6 +259,9 @@ async function rewriteRootPackageJson(targetDir, opts) {
244
259
  pkg["version"] = "0.0.1";
245
260
  pkg["private"] = true;
246
261
  delete pkg.description;
262
+ if (opts.packageManager !== "yarn") {
263
+ delete pkg.packageManager;
264
+ }
247
265
  await writeFile(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
248
266
  }
249
267
  async function writeAuthEnv(targetDir, opts) {
@@ -265,6 +283,19 @@ async function writeUploadEnv(targetDir, opts) {
265
283
  }
266
284
  await writeFile(join2(targetDir, "apps/microservices/upload/.env"), next);
267
285
  }
286
+ async function writeNotesEnv(targetDir, opts) {
287
+ if (opts.example === "none") return;
288
+ const envExample = join2(targetDir, "apps/microservices/notes/.env.example");
289
+ try {
290
+ const env = await readFile2(envExample, "utf8");
291
+ let next = env.replace(/^NOTES_TRANSPORT=.*$/m, `NOTES_TRANSPORT=${opts.transport}`);
292
+ if (opts.transport !== "tcp") {
293
+ next = next.replace(/^# (NOTES_(?:REDIS|NATS)_URL=)/m, "$1");
294
+ }
295
+ await writeFile(join2(targetDir, "apps/microservices/notes/.env"), next);
296
+ } catch {
297
+ }
298
+ }
268
299
  async function writeGatewayEnv(targetDir, opts) {
269
300
  const envExample = join2(targetDir, "apps/api/.env.example");
270
301
  const env = await readFile2(envExample, "utf8");
@@ -416,6 +447,145 @@ async function removeNotesStack(targetDir) {
416
447
  } catch {
417
448
  }
418
449
  }
450
+ async function stripTsconfigPath(targetDir, alias) {
451
+ const tsconfigPath = join2(targetDir, "tsconfig.base.json");
452
+ try {
453
+ const src = await readFile2(tsconfigPath, "utf8");
454
+ const escaped = alias.replace(/[@/]/g, (c) => c === "@" ? "@" : "\\/");
455
+ const pretty = src.replace(new RegExp(`^\\s*"${escaped}": \\[[^\\]]*\\],?\\n`, "m"), "");
456
+ if (pretty !== src) {
457
+ await writeFile(tsconfigPath, pretty);
458
+ return;
459
+ }
460
+ const parsed = JSON.parse(src);
461
+ if (parsed.compilerOptions?.paths) {
462
+ delete parsed.compilerOptions.paths[alias];
463
+ }
464
+ await writeFile(tsconfigPath, JSON.stringify(parsed));
465
+ } catch {
466
+ }
467
+ }
468
+ async function removeUnusedAuthStrategies(targetDir, authProvider) {
469
+ const modulePath = join2(targetDir, "apps/microservices/auth/src/app/app.module.ts");
470
+ if (authProvider === "supabase") {
471
+ await rm(join2(targetDir, "libs/auth-strategies/firebase"), { recursive: true, force: true });
472
+ await stripDeps(join2(targetDir, "apps/microservices/auth/package.json"), [
473
+ "@icore/auth-firebase"
474
+ ]);
475
+ await stripTsconfigPath(targetDir, "@icore/auth-firebase");
476
+ try {
477
+ const src = await readFile2(modulePath, "utf8");
478
+ const next = src.replace(/^import \* as admin from 'firebase-admin';\n/m, "").replace(/^import \{[^}]*FirebaseAuthStrategy[^}]*\} from '@icore\/auth-firebase';\n/m, "").replace(/^function makeFirebaseStrategy\b[\s\S]*?\n^}\n/m, "").replace(/(?<=\n) *case 'firebase':\n *return makeFirebaseStrategy\(cfg\);\n/, "");
479
+ await writeFile(modulePath, next);
480
+ } catch {
481
+ }
482
+ }
483
+ if (authProvider === "firebase") {
484
+ await rm(join2(targetDir, "libs/auth-strategies/supabase"), { recursive: true, force: true });
485
+ await stripDeps(join2(targetDir, "apps/microservices/auth/package.json"), [
486
+ "@icore/auth-supabase"
487
+ ]);
488
+ await stripTsconfigPath(targetDir, "@icore/auth-supabase");
489
+ try {
490
+ const src = await readFile2(modulePath, "utf8");
491
+ const next = src.replace(/^import \{ createClient \} from '@supabase\/supabase-js';\n/m, "").replace(/^import \{[^}]*SupabaseAuthStrategy[^}]*\} from '@icore\/auth-supabase';\n/m, "").replace(
492
+ /\n {10}case 'supabase': \{[\s\S]*?return new SupabaseAuthStrategy\(\{ client \}\);\n {10}\}\n/m,
493
+ ""
494
+ );
495
+ await writeFile(modulePath, next);
496
+ } catch {
497
+ }
498
+ }
499
+ }
500
+ async function removeUnusedStorageStrategies(targetDir, uploadProvider) {
501
+ if (uploadProvider === "none") return;
502
+ const modulePath = join2(targetDir, "apps/microservices/upload/src/app/app.module.ts");
503
+ if (uploadProvider !== "firebase") {
504
+ await rm(join2(targetDir, "libs/storage-strategies/firebase"), { recursive: true, force: true });
505
+ await stripDeps(join2(targetDir, "apps/microservices/upload/package.json"), [
506
+ "@icore/storage-firebase"
507
+ ]);
508
+ await stripTsconfigPath(targetDir, "@icore/storage-firebase");
509
+ }
510
+ if (uploadProvider !== "cloudinary") {
511
+ await rm(join2(targetDir, "libs/storage-strategies/cloudinary"), {
512
+ recursive: true,
513
+ force: true
514
+ });
515
+ await stripDeps(join2(targetDir, "apps/microservices/upload/package.json"), [
516
+ "@icore/storage-cloudinary"
517
+ ]);
518
+ await stripTsconfigPath(targetDir, "@icore/storage-cloudinary");
519
+ }
520
+ if (uploadProvider !== "supabase") {
521
+ await rm(join2(targetDir, "libs/storage-strategies/supabase"), { recursive: true, force: true });
522
+ await stripDeps(join2(targetDir, "apps/microservices/upload/package.json"), [
523
+ "@icore/storage-supabase"
524
+ ]);
525
+ await stripTsconfigPath(targetDir, "@icore/storage-supabase");
526
+ }
527
+ try {
528
+ let src = await readFile2(modulePath, "utf8");
529
+ if (uploadProvider !== "firebase") {
530
+ src = src.replace(/^import \* as admin from 'firebase-admin';\n/m, "").replace(
531
+ /^import \{[^}]*FirebaseStorageStrategy[^}]*\} from '@icore\/storage-firebase';\n/m,
532
+ ""
533
+ ).replace(/^function makeFirebaseStorage\b[\s\S]*?\n^}\n/m, "").replace(/(?<=\n) *case 'firebase':\n *return makeFirebaseStorage\(cfg\);\n/, "");
534
+ }
535
+ if (uploadProvider !== "cloudinary") {
536
+ src = src.replace(/^import \{ v2 as cloudinary \} from 'cloudinary';\n/m, "").replace(
537
+ /^import \{[^}]*CloudinaryStorageStrategy[^}]*\} from '@icore\/storage-cloudinary';\n/m,
538
+ ""
539
+ ).replace(/^function makeCloudinaryStorage\b[\s\S]*?\n^}\n/m, "").replace(/(?<=\n) *case 'cloudinary':\n *return makeCloudinaryStorage\(cfg\);\n/, "");
540
+ }
541
+ if (uploadProvider !== "supabase") {
542
+ src = src.replace(/^import \{ createClient \} from '@supabase\/supabase-js';\n/m, "").replace(
543
+ /^import \{[^}]*SupabaseStorageStrategy[^}]*\} from '@icore\/storage-supabase';\n/m,
544
+ ""
545
+ ).replace(
546
+ /\n {10}case 'supabase': \{[\s\S]*?bucket: requireEnv\(cfg, 'SUPABASE_STORAGE_BUCKET'\),\n {12}\}\);\n {10}\}\n/m,
547
+ ""
548
+ );
549
+ }
550
+ await writeFile(modulePath, src);
551
+ } catch {
552
+ }
553
+ }
554
+ async function removeUnusedDbStrategies(targetDir, dbProvider) {
555
+ const modulePath = join2(targetDir, "apps/microservices/notes/src/app/app.module.ts");
556
+ if (dbProvider === "supabase") {
557
+ await rm(join2(targetDir, "libs/db-strategies/firestore"), { recursive: true, force: true });
558
+ await stripDeps(join2(targetDir, "apps/microservices/notes/package.json"), [
559
+ "@icore/db-firestore"
560
+ ]);
561
+ await stripTsconfigPath(targetDir, "@icore/db-firestore");
562
+ try {
563
+ const src = await readFile2(modulePath, "utf8");
564
+ const next = src.replace(/^import \* as admin from 'firebase-admin';\n/m, "").replace(/^import \{[^}]*FirestoreDBStrategy[^}]*\} from '@icore\/db-firestore';\n/m, "").replace(
565
+ /\n {8}if \(provider === 'firestore'[\s\S]*?return new FirestoreDBStrategy\(\{[\s\S]*?\}\);\n {8}\}\n/m,
566
+ ""
567
+ );
568
+ await writeFile(modulePath, next);
569
+ } catch {
570
+ }
571
+ }
572
+ if (dbProvider === "firebase") {
573
+ await rm(join2(targetDir, "libs/db-strategies/supabase"), { recursive: true, force: true });
574
+ await stripDeps(join2(targetDir, "apps/microservices/notes/package.json"), [
575
+ "@icore/db-supabase"
576
+ ]);
577
+ await stripTsconfigPath(targetDir, "@icore/db-supabase");
578
+ try {
579
+ const src = await readFile2(modulePath, "utf8");
580
+ const next = src.replace(/^import \{ createClient \} from '@supabase\/supabase-js';\n/m, "").replace(/^import \{[^}]*SupabaseDBStrategy[^}]*\} from '@icore\/db-supabase';\n/m, "").replace(
581
+ /\n {8}if \(provider === 'supabase'\) \{[\s\S]*?return new SupabaseDBStrategy\(\{ client \}\);\n {8}\}\n/m,
582
+ ""
583
+ );
584
+ await writeFile(modulePath, next);
585
+ } catch {
586
+ }
587
+ }
588
+ }
419
589
  async function removeUploadStack(targetDir) {
420
590
  const paths = [
421
591
  "apps/microservices/upload",
@@ -492,14 +662,16 @@ function gitInit(cwd, projectName) {
492
662
  { cwd, stdio: "inherit" }
493
663
  );
494
664
  }
495
- function yarnInstall(cwd) {
496
- spawnSync("yarn", ["install"], { cwd, stdio: "inherit" });
665
+ function runInstall(cwd, pm) {
666
+ const [cmd, ...args] = pm === "npm" ? ["npm", "install"] : pm === "pnpm" ? ["pnpm", "install"] : ["yarn", "install"];
667
+ spawnSync(cmd, args, { cwd, stdio: "inherit" });
497
668
  }
498
669
  async function scaffold(opts, templatesDir2) {
499
670
  await copyTree(templatesDir2, opts.targetDir);
500
671
  await rewriteRootPackageJson(opts.targetDir, opts);
501
672
  await writeAuthEnv(opts.targetDir, opts);
502
673
  await writeUploadEnv(opts.targetDir, opts);
674
+ await writeNotesEnv(opts.targetDir, opts);
503
675
  await writePaymentEnv(opts.targetDir, opts);
504
676
  await writeGatewayEnv(opts.targetDir, opts);
505
677
  await writeRootEnv(opts.targetDir, opts);
@@ -508,12 +680,26 @@ async function scaffold(opts, templatesDir2) {
508
680
  if (opts.payment === "none") await removePaymentStack(opts.targetDir);
509
681
  if (opts.jobs === "none") await removeJobsStack(opts.targetDir);
510
682
  if (opts.example === "none") await removeNotesStack(opts.targetDir);
511
- await writeFile(join2(opts.targetDir, "yarn.lock"), "");
512
- if (opts.install) yarnInstall(opts.targetDir);
683
+ await removeUnusedAuthStrategies(opts.targetDir, opts.authProvider);
684
+ await removeUnusedStorageStrategies(opts.targetDir, opts.upload);
685
+ await removeUnusedDbStrategies(opts.targetDir, opts.dbProvider);
686
+ if (opts.packageManager === "yarn") {
687
+ await writeFile(join2(opts.targetDir, "yarn.lock"), "");
688
+ }
689
+ if (opts.install) runInstall(opts.targetDir, opts.packageManager);
513
690
  if (opts.initGit) gitInit(opts.targetDir, opts.projectName);
514
691
  }
515
692
 
516
693
  // src/cli.ts
694
+ var [nodeMajor] = process.versions.node.split(".").map(Number);
695
+ if (nodeMajor < 22) {
696
+ process.stderr.write(
697
+ `Error: iCore requires Node.js >= 22. You are running ${process.versions.node}.
698
+ Upgrade: https://nodejs.org
699
+ `
700
+ );
701
+ process.exit(1);
702
+ }
517
703
  var here = dirname2(fileURLToPath2(import.meta.url));
518
704
  var templatesDir = resolve2(here, "..", "templates");
519
705
  async function main() {
@@ -533,8 +719,8 @@ async function main() {
533
719
  p2.outro(kleur.green("Done."));
534
720
  p2.log.info(`Next:`);
535
721
  p2.log.info(` cd ${opts.projectName}`);
536
- if (!opts.install) p2.log.info(` yarn install`);
537
- p2.log.info(` yarn dev # gateway + auth MS + upload MS + client`);
722
+ if (!opts.install) p2.log.info(` ${opts.packageManager} install`);
723
+ p2.log.info(` ${opts.packageManager} dev # gateway + auth MS + upload MS + client`);
538
724
  p2.log.info(` open http://localhost:4200`);
539
725
  p2.log.info(` edit apps/microservices/auth/.env to plug in real ${opts.authProvider} creds`);
540
726
  }
package/dist/index.cjs CHANGED
@@ -75,6 +75,9 @@ async function rewriteRootPackageJson(targetDir, opts) {
75
75
  pkg["version"] = "0.0.1";
76
76
  pkg["private"] = true;
77
77
  delete pkg.description;
78
+ if (opts.packageManager !== "yarn") {
79
+ delete pkg.packageManager;
80
+ }
78
81
  await (0, import_promises.writeFile)(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
79
82
  }
80
83
  async function writeAuthEnv(targetDir, opts) {
@@ -96,6 +99,19 @@ async function writeUploadEnv(targetDir, opts) {
96
99
  }
97
100
  await (0, import_promises.writeFile)((0, import_node_path.join)(targetDir, "apps/microservices/upload/.env"), next);
98
101
  }
102
+ async function writeNotesEnv(targetDir, opts) {
103
+ if (opts.example === "none") return;
104
+ const envExample = (0, import_node_path.join)(targetDir, "apps/microservices/notes/.env.example");
105
+ try {
106
+ const env = await (0, import_promises.readFile)(envExample, "utf8");
107
+ let next = env.replace(/^NOTES_TRANSPORT=.*$/m, `NOTES_TRANSPORT=${opts.transport}`);
108
+ if (opts.transport !== "tcp") {
109
+ next = next.replace(/^# (NOTES_(?:REDIS|NATS)_URL=)/m, "$1");
110
+ }
111
+ await (0, import_promises.writeFile)((0, import_node_path.join)(targetDir, "apps/microservices/notes/.env"), next);
112
+ } catch {
113
+ }
114
+ }
99
115
  async function writeGatewayEnv(targetDir, opts) {
100
116
  const envExample = (0, import_node_path.join)(targetDir, "apps/api/.env.example");
101
117
  const env = await (0, import_promises.readFile)(envExample, "utf8");
@@ -247,6 +263,145 @@ async function removeNotesStack(targetDir) {
247
263
  } catch {
248
264
  }
249
265
  }
266
+ async function stripTsconfigPath(targetDir, alias) {
267
+ const tsconfigPath = (0, import_node_path.join)(targetDir, "tsconfig.base.json");
268
+ try {
269
+ const src = await (0, import_promises.readFile)(tsconfigPath, "utf8");
270
+ const escaped = alias.replace(/[@/]/g, (c) => c === "@" ? "@" : "\\/");
271
+ const pretty = src.replace(new RegExp(`^\\s*"${escaped}": \\[[^\\]]*\\],?\\n`, "m"), "");
272
+ if (pretty !== src) {
273
+ await (0, import_promises.writeFile)(tsconfigPath, pretty);
274
+ return;
275
+ }
276
+ const parsed = JSON.parse(src);
277
+ if (parsed.compilerOptions?.paths) {
278
+ delete parsed.compilerOptions.paths[alias];
279
+ }
280
+ await (0, import_promises.writeFile)(tsconfigPath, JSON.stringify(parsed));
281
+ } catch {
282
+ }
283
+ }
284
+ async function removeUnusedAuthStrategies(targetDir, authProvider) {
285
+ const modulePath = (0, import_node_path.join)(targetDir, "apps/microservices/auth/src/app/app.module.ts");
286
+ if (authProvider === "supabase") {
287
+ await (0, import_promises.rm)((0, import_node_path.join)(targetDir, "libs/auth-strategies/firebase"), { recursive: true, force: true });
288
+ await stripDeps((0, import_node_path.join)(targetDir, "apps/microservices/auth/package.json"), [
289
+ "@icore/auth-firebase"
290
+ ]);
291
+ await stripTsconfigPath(targetDir, "@icore/auth-firebase");
292
+ try {
293
+ const src = await (0, import_promises.readFile)(modulePath, "utf8");
294
+ const next = src.replace(/^import \* as admin from 'firebase-admin';\n/m, "").replace(/^import \{[^}]*FirebaseAuthStrategy[^}]*\} from '@icore\/auth-firebase';\n/m, "").replace(/^function makeFirebaseStrategy\b[\s\S]*?\n^}\n/m, "").replace(/(?<=\n) *case 'firebase':\n *return makeFirebaseStrategy\(cfg\);\n/, "");
295
+ await (0, import_promises.writeFile)(modulePath, next);
296
+ } catch {
297
+ }
298
+ }
299
+ if (authProvider === "firebase") {
300
+ await (0, import_promises.rm)((0, import_node_path.join)(targetDir, "libs/auth-strategies/supabase"), { recursive: true, force: true });
301
+ await stripDeps((0, import_node_path.join)(targetDir, "apps/microservices/auth/package.json"), [
302
+ "@icore/auth-supabase"
303
+ ]);
304
+ await stripTsconfigPath(targetDir, "@icore/auth-supabase");
305
+ try {
306
+ const src = await (0, import_promises.readFile)(modulePath, "utf8");
307
+ const next = src.replace(/^import \{ createClient \} from '@supabase\/supabase-js';\n/m, "").replace(/^import \{[^}]*SupabaseAuthStrategy[^}]*\} from '@icore\/auth-supabase';\n/m, "").replace(
308
+ /\n {10}case 'supabase': \{[\s\S]*?return new SupabaseAuthStrategy\(\{ client \}\);\n {10}\}\n/m,
309
+ ""
310
+ );
311
+ await (0, import_promises.writeFile)(modulePath, next);
312
+ } catch {
313
+ }
314
+ }
315
+ }
316
+ async function removeUnusedStorageStrategies(targetDir, uploadProvider) {
317
+ if (uploadProvider === "none") return;
318
+ const modulePath = (0, import_node_path.join)(targetDir, "apps/microservices/upload/src/app/app.module.ts");
319
+ if (uploadProvider !== "firebase") {
320
+ await (0, import_promises.rm)((0, import_node_path.join)(targetDir, "libs/storage-strategies/firebase"), { recursive: true, force: true });
321
+ await stripDeps((0, import_node_path.join)(targetDir, "apps/microservices/upload/package.json"), [
322
+ "@icore/storage-firebase"
323
+ ]);
324
+ await stripTsconfigPath(targetDir, "@icore/storage-firebase");
325
+ }
326
+ if (uploadProvider !== "cloudinary") {
327
+ await (0, import_promises.rm)((0, import_node_path.join)(targetDir, "libs/storage-strategies/cloudinary"), {
328
+ recursive: true,
329
+ force: true
330
+ });
331
+ await stripDeps((0, import_node_path.join)(targetDir, "apps/microservices/upload/package.json"), [
332
+ "@icore/storage-cloudinary"
333
+ ]);
334
+ await stripTsconfigPath(targetDir, "@icore/storage-cloudinary");
335
+ }
336
+ if (uploadProvider !== "supabase") {
337
+ await (0, import_promises.rm)((0, import_node_path.join)(targetDir, "libs/storage-strategies/supabase"), { recursive: true, force: true });
338
+ await stripDeps((0, import_node_path.join)(targetDir, "apps/microservices/upload/package.json"), [
339
+ "@icore/storage-supabase"
340
+ ]);
341
+ await stripTsconfigPath(targetDir, "@icore/storage-supabase");
342
+ }
343
+ try {
344
+ let src = await (0, import_promises.readFile)(modulePath, "utf8");
345
+ if (uploadProvider !== "firebase") {
346
+ src = src.replace(/^import \* as admin from 'firebase-admin';\n/m, "").replace(
347
+ /^import \{[^}]*FirebaseStorageStrategy[^}]*\} from '@icore\/storage-firebase';\n/m,
348
+ ""
349
+ ).replace(/^function makeFirebaseStorage\b[\s\S]*?\n^}\n/m, "").replace(/(?<=\n) *case 'firebase':\n *return makeFirebaseStorage\(cfg\);\n/, "");
350
+ }
351
+ if (uploadProvider !== "cloudinary") {
352
+ src = src.replace(/^import \{ v2 as cloudinary \} from 'cloudinary';\n/m, "").replace(
353
+ /^import \{[^}]*CloudinaryStorageStrategy[^}]*\} from '@icore\/storage-cloudinary';\n/m,
354
+ ""
355
+ ).replace(/^function makeCloudinaryStorage\b[\s\S]*?\n^}\n/m, "").replace(/(?<=\n) *case 'cloudinary':\n *return makeCloudinaryStorage\(cfg\);\n/, "");
356
+ }
357
+ if (uploadProvider !== "supabase") {
358
+ src = src.replace(/^import \{ createClient \} from '@supabase\/supabase-js';\n/m, "").replace(
359
+ /^import \{[^}]*SupabaseStorageStrategy[^}]*\} from '@icore\/storage-supabase';\n/m,
360
+ ""
361
+ ).replace(
362
+ /\n {10}case 'supabase': \{[\s\S]*?bucket: requireEnv\(cfg, 'SUPABASE_STORAGE_BUCKET'\),\n {12}\}\);\n {10}\}\n/m,
363
+ ""
364
+ );
365
+ }
366
+ await (0, import_promises.writeFile)(modulePath, src);
367
+ } catch {
368
+ }
369
+ }
370
+ async function removeUnusedDbStrategies(targetDir, dbProvider) {
371
+ const modulePath = (0, import_node_path.join)(targetDir, "apps/microservices/notes/src/app/app.module.ts");
372
+ if (dbProvider === "supabase") {
373
+ await (0, import_promises.rm)((0, import_node_path.join)(targetDir, "libs/db-strategies/firestore"), { recursive: true, force: true });
374
+ await stripDeps((0, import_node_path.join)(targetDir, "apps/microservices/notes/package.json"), [
375
+ "@icore/db-firestore"
376
+ ]);
377
+ await stripTsconfigPath(targetDir, "@icore/db-firestore");
378
+ try {
379
+ const src = await (0, import_promises.readFile)(modulePath, "utf8");
380
+ const next = src.replace(/^import \* as admin from 'firebase-admin';\n/m, "").replace(/^import \{[^}]*FirestoreDBStrategy[^}]*\} from '@icore\/db-firestore';\n/m, "").replace(
381
+ /\n {8}if \(provider === 'firestore'[\s\S]*?return new FirestoreDBStrategy\(\{[\s\S]*?\}\);\n {8}\}\n/m,
382
+ ""
383
+ );
384
+ await (0, import_promises.writeFile)(modulePath, next);
385
+ } catch {
386
+ }
387
+ }
388
+ if (dbProvider === "firebase") {
389
+ await (0, import_promises.rm)((0, import_node_path.join)(targetDir, "libs/db-strategies/supabase"), { recursive: true, force: true });
390
+ await stripDeps((0, import_node_path.join)(targetDir, "apps/microservices/notes/package.json"), [
391
+ "@icore/db-supabase"
392
+ ]);
393
+ await stripTsconfigPath(targetDir, "@icore/db-supabase");
394
+ try {
395
+ const src = await (0, import_promises.readFile)(modulePath, "utf8");
396
+ const next = src.replace(/^import \{ createClient \} from '@supabase\/supabase-js';\n/m, "").replace(/^import \{[^}]*SupabaseDBStrategy[^}]*\} from '@icore\/db-supabase';\n/m, "").replace(
397
+ /\n {8}if \(provider === 'supabase'\) \{[\s\S]*?return new SupabaseDBStrategy\(\{ client \}\);\n {8}\}\n/m,
398
+ ""
399
+ );
400
+ await (0, import_promises.writeFile)(modulePath, next);
401
+ } catch {
402
+ }
403
+ }
404
+ }
250
405
  async function removeUploadStack(targetDir) {
251
406
  const paths = [
252
407
  "apps/microservices/upload",
@@ -323,14 +478,16 @@ function gitInit(cwd, projectName) {
323
478
  { cwd, stdio: "inherit" }
324
479
  );
325
480
  }
326
- function yarnInstall(cwd) {
327
- (0, import_node_child_process.spawnSync)("yarn", ["install"], { cwd, stdio: "inherit" });
481
+ function runInstall(cwd, pm) {
482
+ const [cmd, ...args] = pm === "npm" ? ["npm", "install"] : pm === "pnpm" ? ["pnpm", "install"] : ["yarn", "install"];
483
+ (0, import_node_child_process.spawnSync)(cmd, args, { cwd, stdio: "inherit" });
328
484
  }
329
485
  async function scaffold(opts, templatesDir) {
330
486
  await copyTree(templatesDir, opts.targetDir);
331
487
  await rewriteRootPackageJson(opts.targetDir, opts);
332
488
  await writeAuthEnv(opts.targetDir, opts);
333
489
  await writeUploadEnv(opts.targetDir, opts);
490
+ await writeNotesEnv(opts.targetDir, opts);
334
491
  await writePaymentEnv(opts.targetDir, opts);
335
492
  await writeGatewayEnv(opts.targetDir, opts);
336
493
  await writeRootEnv(opts.targetDir, opts);
@@ -339,8 +496,13 @@ async function scaffold(opts, templatesDir) {
339
496
  if (opts.payment === "none") await removePaymentStack(opts.targetDir);
340
497
  if (opts.jobs === "none") await removeJobsStack(opts.targetDir);
341
498
  if (opts.example === "none") await removeNotesStack(opts.targetDir);
342
- await (0, import_promises.writeFile)((0, import_node_path.join)(opts.targetDir, "yarn.lock"), "");
343
- if (opts.install) yarnInstall(opts.targetDir);
499
+ await removeUnusedAuthStrategies(opts.targetDir, opts.authProvider);
500
+ await removeUnusedStorageStrategies(opts.targetDir, opts.upload);
501
+ await removeUnusedDbStrategies(opts.targetDir, opts.dbProvider);
502
+ if (opts.packageManager === "yarn") {
503
+ await (0, import_promises.writeFile)((0, import_node_path.join)(opts.targetDir, "yarn.lock"), "");
504
+ }
505
+ if (opts.install) runInstall(opts.targetDir, opts.packageManager);
344
506
  if (opts.initGit) gitInit(opts.targetDir, opts.projectName);
345
507
  }
346
508
 
@@ -350,6 +512,13 @@ var import_node_path2 = require("path");
350
512
  var import_promises2 = require("fs/promises");
351
513
  var import_node_path3 = require("path");
352
514
  var import_node_url = require("url");
515
+ function detectPackageManager() {
516
+ const ua = process.env["npm_config_user_agent"] ?? "";
517
+ if (ua.startsWith("yarn/")) return "yarn";
518
+ if (ua.startsWith("pnpm/")) return "pnpm";
519
+ if (ua.startsWith("npm/")) return "npm";
520
+ return "yarn";
521
+ }
353
522
  async function readSelfVersion() {
354
523
  try {
355
524
  const here = (0, import_node_path3.dirname)((0, import_node_url.fileURLToPath)(importMetaUrl));
@@ -418,6 +587,9 @@ function parseFlags(argv) {
418
587
  case "transport":
419
588
  out.transport = v;
420
589
  break;
590
+ case "package-manager":
591
+ out.packageManager = v;
592
+ break;
421
593
  case "no-git":
422
594
  out.initGit = false;
423
595
  break;
@@ -527,8 +699,12 @@ Re-run with @latest to refresh:
527
699
  initialValue: "tcp"
528
700
  });
529
701
  if (p.isCancel(transport)) throw new Error("cancelled");
702
+ const packageManager = flags.packageManager ?? detectPackageManager();
530
703
  const initGit = flags.initGit ?? !await p.confirm({ message: "Initialise git repo?", initialValue: true }) === false;
531
- const install = flags.install ?? !await p.confirm({ message: "Run yarn install?", initialValue: true }) === false;
704
+ const install = flags.install ?? !await p.confirm({
705
+ message: `Run ${packageManager} install?`,
706
+ initialValue: true
707
+ }) === false;
532
708
  return {
533
709
  projectName,
534
710
  targetDir: (0, import_node_path2.resolve)(cwd, projectName),
@@ -540,6 +716,7 @@ Re-run with @latest to refresh:
540
716
  example,
541
717
  ui,
542
718
  transport,
719
+ packageManager,
543
720
  initGit,
544
721
  install
545
722
  };
package/dist/index.d.cts CHANGED
@@ -6,6 +6,7 @@ type JobsProvider = 'bullmq' | 'none';
6
6
  type ExampleMode = 'notes' | 'none';
7
7
  type UiLibrary = 'shadcn' | 'antd' | 'mui';
8
8
  type MsTransport = 'tcp' | 'redis' | 'nats';
9
+ type PackageManager = 'yarn' | 'npm' | 'pnpm';
9
10
  interface CreateIcoreOptions {
10
11
  projectName: string;
11
12
  targetDir: string;
@@ -17,6 +18,7 @@ interface CreateIcoreOptions {
17
18
  example: ExampleMode;
18
19
  ui: UiLibrary;
19
20
  transport: MsTransport;
21
+ packageManager: PackageManager;
20
22
  initGit: boolean;
21
23
  install: boolean;
22
24
  }
@@ -29,4 +31,4 @@ interface PromptInput {
29
31
  }
30
32
  declare function collectOptions({ argv, cwd }: PromptInput): Promise<CreateIcoreOptions>;
31
33
 
32
- export { type AuthProvider, type CreateIcoreOptions, type DbProvider, type ExampleMode, type JobsProvider, type MsTransport, type PaymentProvider, type UiLibrary, type UploadProvider, collectOptions, scaffold };
34
+ export { type AuthProvider, type CreateIcoreOptions, type DbProvider, type ExampleMode, type JobsProvider, type MsTransport, type PackageManager, type PaymentProvider, type UiLibrary, type UploadProvider, collectOptions, scaffold };
package/dist/index.d.ts CHANGED
@@ -6,6 +6,7 @@ type JobsProvider = 'bullmq' | 'none';
6
6
  type ExampleMode = 'notes' | 'none';
7
7
  type UiLibrary = 'shadcn' | 'antd' | 'mui';
8
8
  type MsTransport = 'tcp' | 'redis' | 'nats';
9
+ type PackageManager = 'yarn' | 'npm' | 'pnpm';
9
10
  interface CreateIcoreOptions {
10
11
  projectName: string;
11
12
  targetDir: string;
@@ -17,6 +18,7 @@ interface CreateIcoreOptions {
17
18
  example: ExampleMode;
18
19
  ui: UiLibrary;
19
20
  transport: MsTransport;
21
+ packageManager: PackageManager;
20
22
  initGit: boolean;
21
23
  install: boolean;
22
24
  }
@@ -29,4 +31,4 @@ interface PromptInput {
29
31
  }
30
32
  declare function collectOptions({ argv, cwd }: PromptInput): Promise<CreateIcoreOptions>;
31
33
 
32
- export { type AuthProvider, type CreateIcoreOptions, type DbProvider, type ExampleMode, type JobsProvider, type MsTransport, type PaymentProvider, type UiLibrary, type UploadProvider, collectOptions, scaffold };
34
+ export { type AuthProvider, type CreateIcoreOptions, type DbProvider, type ExampleMode, type JobsProvider, type MsTransport, type PackageManager, type PaymentProvider, type UiLibrary, type UploadProvider, collectOptions, scaffold };