@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.
- package/dist/cli.js +193 -7
- package/dist/index.cjs +182 -5
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +182 -5
- package/package.json +1 -1
- package/templates/apps/microservices/auth/src/app/app.module.ts +33 -19
- package/templates/apps/microservices/notes/src/app/app.module.ts +39 -23
- package/templates/apps/microservices/upload/src/app/app.module.ts +41 -25
- package/templates/apps/templates/client-antd/vite.config.mts +16 -48
- package/templates/apps/templates/client-mui/vite.config.mts +16 -48
- package/templates/apps/templates/client-shadcn/vite.config.mts +16 -48
- package/templates/libs/shared/package.json +10 -0
- package/templates/libs/shared/src/__tests__/cross-boundary.unit.test.ts +121 -0
- package/templates/libs/shared/src/client.ts +5 -0
- package/templates/libs/shared/src/strategies/fakes/fake-auth.ts +8 -9
- package/templates/libs/shared/src/strategies/fakes/fake-storage.ts +1 -2
- package/templates/libs/template-shared/src/lib/abilities/ability-provider.tsx +1 -1
- package/templates/libs/vite-plugins/README.md +7 -0
- package/templates/libs/vite-plugins/eslint.config.mjs +19 -0
- package/templates/libs/vite-plugins/package.json +18 -0
- package/templates/libs/vite-plugins/project.json +19 -0
- package/templates/libs/vite-plugins/src/index.d.mts +21 -0
- package/templates/libs/vite-plugins/src/index.mjs +106 -0
- package/templates/libs/vite-plugins/tsconfig.json +20 -0
- package/templates/libs/vite-plugins/tsconfig.lib.json +9 -0
- 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({
|
|
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
|
|
496
|
-
|
|
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
|
|
512
|
-
|
|
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(`
|
|
537
|
-
p2.log.info(`
|
|
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
|
|
327
|
-
|
|
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 (
|
|
343
|
-
|
|
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({
|
|
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 };
|