@idevconn/create-icore 0.6.3 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +384 -276
- package/dist/index.cjs +385 -277
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +382 -274
- package/package.json +1 -1
- package/templates/.yarn/releases/yarn-4.16.0.cjs +944 -0
- package/templates/.yarnrc.yml +1 -1
- package/templates/apps/api/src/app/storage/storage.controller.ts +28 -0
- package/templates/apps/microservices/auth/src/app/app.module.ts +20 -2
- package/templates/apps/microservices/notes/src/app/app.module.ts +17 -2
- package/templates/apps/microservices/upload/src/app/app.module.ts +17 -2
- package/templates/apps/microservices/upload/src/app/storage.controller.ts +7 -0
- package/templates/apps/templates/client-antd/src/components/auth/AuthBrandPanel.tsx +59 -0
- package/templates/apps/templates/client-antd/src/components/auth/CheckEmailScreen.tsx +28 -0
- package/templates/apps/templates/client-antd/src/components/auth/LoginForm.tsx +116 -0
- package/templates/apps/templates/client-antd/src/components/auth/MagicLinkForm.tsx +95 -0
- package/templates/apps/templates/client-antd/src/components/auth/RegisterForm.tsx +98 -0
- package/templates/apps/templates/client-antd/src/globals.less +6 -0
- package/templates/apps/templates/client-antd/src/main.tsx +1 -1
- package/templates/apps/templates/client-antd/src/routes/login.tsx +45 -181
- package/templates/apps/templates/client-mui/src/components/auth/AuthBrandPanel.tsx +59 -0
- package/templates/apps/templates/client-mui/src/components/auth/CheckEmailScreen.tsx +28 -0
- package/templates/apps/templates/client-mui/src/components/auth/LoginForm.tsx +141 -0
- package/templates/apps/templates/client-mui/src/components/auth/MagicLinkForm.tsx +106 -0
- package/templates/apps/templates/client-mui/src/components/auth/RegisterForm.tsx +113 -0
- package/templates/apps/templates/client-mui/src/main.tsx +1 -1
- package/templates/apps/templates/client-mui/src/routes/login.tsx +50 -186
- package/templates/apps/templates/client-shadcn/src/components/auth/AuthBrandPanel.tsx +52 -0
- package/templates/apps/templates/client-shadcn/src/components/auth/CheckEmailScreen.tsx +29 -0
- package/templates/apps/templates/client-shadcn/src/components/auth/LoginForm.tsx +161 -0
- package/templates/apps/templates/client-shadcn/src/components/auth/MagicLinkForm.tsx +110 -0
- package/templates/apps/templates/client-shadcn/src/components/auth/RegisterForm.tsx +107 -0
- package/templates/apps/templates/client-shadcn/src/components/layout/LayoutHeader.tsx +31 -10
- package/templates/apps/templates/client-shadcn/src/components/layout/LayoutSider.tsx +22 -27
- package/templates/apps/templates/client-shadcn/src/components/ui/card.tsx +1 -1
- package/templates/apps/templates/client-shadcn/src/globals.css +39 -13
- package/templates/apps/templates/client-shadcn/src/routes/auth.callback.tsx +1 -1
- package/templates/apps/templates/client-shadcn/src/routes/login.tsx +55 -165
- package/templates/libs/auth-strategies/mongodb/CHANGELOG.md +8 -0
- package/templates/libs/auth-strategies/mongodb/README.md +11 -0
- package/templates/libs/auth-strategies/mongodb/eslint.config.mjs +19 -0
- package/templates/libs/auth-strategies/mongodb/jest.config.cts +10 -0
- package/templates/libs/auth-strategies/mongodb/package.json +16 -0
- package/templates/libs/auth-strategies/mongodb/project.json +19 -0
- package/templates/libs/auth-strategies/mongodb/src/index.ts +1 -0
- package/templates/libs/auth-strategies/mongodb/src/lib/__tests__/mongodb-auth.strategy.unit.test.ts +42 -0
- package/templates/libs/auth-strategies/mongodb/src/lib/auth-mongodb.spec.ts +7 -0
- package/templates/libs/auth-strategies/mongodb/src/lib/auth-mongodb.ts +3 -0
- package/templates/libs/auth-strategies/mongodb/src/lib/mongodb-auth.strategy.ts +188 -0
- package/templates/libs/auth-strategies/mongodb/tsconfig.json +23 -0
- package/templates/libs/auth-strategies/mongodb/tsconfig.lib.json +10 -0
- package/templates/libs/auth-strategies/mongodb/tsconfig.spec.json +16 -0
- package/templates/libs/db-strategies/mongodb/CHANGELOG.md +7 -0
- package/templates/libs/db-strategies/mongodb/README.md +11 -0
- package/templates/libs/db-strategies/mongodb/eslint.config.mjs +19 -0
- package/templates/libs/db-strategies/mongodb/jest.config.cts +10 -0
- package/templates/libs/db-strategies/mongodb/package.json +14 -0
- package/templates/libs/db-strategies/mongodb/project.json +19 -0
- package/templates/libs/db-strategies/mongodb/src/index.ts +1 -0
- package/templates/libs/db-strategies/mongodb/src/lib/__tests__/mongodb-db.strategy.unit.test.ts +38 -0
- package/templates/libs/db-strategies/mongodb/src/lib/mongodb-db.strategy.ts +108 -0
- package/templates/libs/db-strategies/mongodb/src/lib/mongodb.spec.ts +7 -0
- package/templates/libs/db-strategies/mongodb/src/lib/mongodb.ts +3 -0
- package/templates/libs/db-strategies/mongodb/tsconfig.json +23 -0
- package/templates/libs/db-strategies/mongodb/tsconfig.lib.json +10 -0
- package/templates/libs/db-strategies/mongodb/tsconfig.spec.json +16 -0
- package/templates/libs/shared/src/strategies/storage.ts +3 -0
- package/templates/libs/storage-strategies/mongodb/CHANGELOG.md +8 -0
- package/templates/libs/storage-strategies/mongodb/README.md +11 -0
- package/templates/libs/storage-strategies/mongodb/eslint.config.mjs +19 -0
- package/templates/libs/storage-strategies/mongodb/jest.config.cts +10 -0
- package/templates/libs/storage-strategies/mongodb/package.json +14 -0
- package/templates/libs/storage-strategies/mongodb/project.json +19 -0
- package/templates/libs/storage-strategies/mongodb/src/index.ts +1 -0
- package/templates/libs/storage-strategies/mongodb/src/lib/__tests__/mongodb-storage.strategy.unit.test.ts +38 -0
- package/templates/libs/storage-strategies/mongodb/src/lib/mongodb-storage.strategy.ts +93 -0
- package/templates/libs/storage-strategies/mongodb/src/lib/storage-mongodb.spec.ts +7 -0
- package/templates/libs/storage-strategies/mongodb/src/lib/storage-mongodb.ts +3 -0
- package/templates/libs/storage-strategies/mongodb/tsconfig.json +23 -0
- package/templates/libs/storage-strategies/mongodb/tsconfig.lib.json +10 -0
- package/templates/libs/storage-strategies/mongodb/tsconfig.spec.json +16 -0
- package/templates/libs/template-shared/src/lib/i18n/keys.ts +216 -56
- package/templates/libs/template-shared/src/lib/stores/theme.store.ts +1 -6
- package/templates/libs/upload-client/src/lib/upload-client.service.ts +7 -0
- package/templates/tsconfig.base.json +4 -1
- package/templates/.yarn/releases/yarn-4.15.0.cjs +0 -940
package/dist/cli.js
CHANGED
|
@@ -124,7 +124,8 @@ Re-run with @latest to refresh:
|
|
|
124
124
|
message: "Auth provider",
|
|
125
125
|
options: [
|
|
126
126
|
{ value: "supabase", label: "Supabase" },
|
|
127
|
-
{ value: "firebase", label: "Firebase" }
|
|
127
|
+
{ value: "firebase", label: "Firebase" },
|
|
128
|
+
{ value: "mongodb", label: "MongoDB (Custom Auth)" }
|
|
128
129
|
]
|
|
129
130
|
});
|
|
130
131
|
if (p.isCancel(authProvider)) throw new Error("cancelled");
|
|
@@ -132,7 +133,8 @@ Re-run with @latest to refresh:
|
|
|
132
133
|
message: "Database backend",
|
|
133
134
|
options: [
|
|
134
135
|
{ value: "supabase", label: "Supabase Postgres" },
|
|
135
|
-
{ value: "firebase", label: "Firestore" }
|
|
136
|
+
{ value: "firebase", label: "Firestore" },
|
|
137
|
+
{ value: "mongodb", label: "MongoDB" }
|
|
136
138
|
],
|
|
137
139
|
initialValue: authProvider
|
|
138
140
|
});
|
|
@@ -143,6 +145,7 @@ Re-run with @latest to refresh:
|
|
|
143
145
|
{ value: "supabase", label: "Supabase Storage" },
|
|
144
146
|
{ value: "firebase", label: "Firebase Cloud Storage" },
|
|
145
147
|
{ value: "cloudinary", label: "Cloudinary" },
|
|
148
|
+
{ value: "mongodb", label: "MongoDB GridFS" },
|
|
146
149
|
{ value: "none", label: "None \u2014 skip the upload microservice" }
|
|
147
150
|
]
|
|
148
151
|
});
|
|
@@ -233,41 +236,14 @@ Re-run with @latest to refresh:
|
|
|
233
236
|
}
|
|
234
237
|
|
|
235
238
|
// src/lib/scaffold.ts
|
|
236
|
-
import { copyFile, mkdir, readdir, readFile as
|
|
239
|
+
import { copyFile, mkdir as mkdir2, readdir as readdir2, readFile as readFile5, stat, writeFile as writeFile4, rm as rm2 } from "fs/promises";
|
|
237
240
|
import { readFileSync } from "fs";
|
|
238
|
-
import { join as
|
|
241
|
+
import { join as join5 } from "path";
|
|
239
242
|
import { spawnSync } from "child_process";
|
|
240
243
|
|
|
241
|
-
// src/lib/
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// src/lib/scaffold.ts
|
|
247
|
-
var IGNORE_TOP = /* @__PURE__ */ new Set([
|
|
248
|
-
".git",
|
|
249
|
-
"node_modules",
|
|
250
|
-
".yarn/cache",
|
|
251
|
-
".yarn/unplugged",
|
|
252
|
-
".yarn/install-state.gz",
|
|
253
|
-
".nx",
|
|
254
|
-
"dist",
|
|
255
|
-
"tmp",
|
|
256
|
-
"coverage",
|
|
257
|
-
".idea",
|
|
258
|
-
".vscode"
|
|
259
|
-
]);
|
|
260
|
-
async function copyTree(src, dest) {
|
|
261
|
-
await mkdir(dest, { recursive: true });
|
|
262
|
-
const entries = await readdir(src, { withFileTypes: true });
|
|
263
|
-
for (const entry of entries) {
|
|
264
|
-
if (IGNORE_TOP.has(entry.name)) continue;
|
|
265
|
-
const s = join2(src, entry.name);
|
|
266
|
-
const d = join2(dest, entry.name);
|
|
267
|
-
if (entry.isDirectory()) await copyTree(s, d);
|
|
268
|
-
else if (entry.isFile()) await copyFile(s, d);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
244
|
+
// src/lib/scaffold-env.ts
|
|
245
|
+
import { readFile as readFile2, writeFile } from "fs/promises";
|
|
246
|
+
import { join as join2 } from "path";
|
|
271
247
|
var TRANSPORT_ENV_TOKEN = {
|
|
272
248
|
redis: "REDIS",
|
|
273
249
|
nats: "NATS",
|
|
@@ -281,11 +257,28 @@ var TRANSPORT_DEPS = {
|
|
|
281
257
|
rmq: { amqplib: "^2.0.1", "amqp-connection-manager": "^5.0.0" },
|
|
282
258
|
kafka: { kafkajs: "^2.2.4" }
|
|
283
259
|
};
|
|
260
|
+
var MONGODB_DEPS = {
|
|
261
|
+
mongoose: "^9.6.3",
|
|
262
|
+
"@nestjs/mongoose": "^11.0.4",
|
|
263
|
+
bcrypt: "^6.0.0",
|
|
264
|
+
jsonwebtoken: "^9.0.3"
|
|
265
|
+
};
|
|
284
266
|
function uncommentTransportEnv(text2, prefix, transport) {
|
|
285
267
|
const token = TRANSPORT_ENV_TOKEN[transport];
|
|
286
268
|
if (!token) return text2;
|
|
287
269
|
return text2.replace(new RegExp(`^# (${prefix}_${token}_[A-Z0-9_]*=)`, "gm"), "$1");
|
|
288
270
|
}
|
|
271
|
+
async function stripGatewayTransport(targetDir, prefix) {
|
|
272
|
+
const gatewayEnv = join2(targetDir, "apps/api/.env");
|
|
273
|
+
try {
|
|
274
|
+
const env = await readFile2(gatewayEnv, "utf8");
|
|
275
|
+
const next = env.split("\n").filter(
|
|
276
|
+
(line) => !line.startsWith(`${prefix}_`) && !line.startsWith(`# ${prefix}_`) && !line.includes(`${prefix} MS transport`)
|
|
277
|
+
).join("\n");
|
|
278
|
+
await writeFile(gatewayEnv, next);
|
|
279
|
+
} catch {
|
|
280
|
+
}
|
|
281
|
+
}
|
|
289
282
|
async function rewriteRootPackageJson(targetDir, opts) {
|
|
290
283
|
const pkgPath = join2(targetDir, "package.json");
|
|
291
284
|
const raw = await readFile2(pkgPath, "utf8");
|
|
@@ -299,6 +292,10 @@ async function rewriteRootPackageJson(targetDir, opts) {
|
|
|
299
292
|
const deps = pkg["dependencies"] ??= {};
|
|
300
293
|
Object.assign(deps, transportDeps);
|
|
301
294
|
}
|
|
295
|
+
if (opts.authProvider === "mongodb" || opts.dbProvider === "mongodb" || opts.upload === "mongodb") {
|
|
296
|
+
const deps = pkg["dependencies"] ??= {};
|
|
297
|
+
Object.assign(deps, MONGODB_DEPS);
|
|
298
|
+
}
|
|
302
299
|
if (opts.packageManager !== "yarn") {
|
|
303
300
|
delete pkg.packageManager;
|
|
304
301
|
} else {
|
|
@@ -319,6 +316,9 @@ async function writeAuthEnv(targetDir, opts) {
|
|
|
319
316
|
const env = await readFile2(envExample, "utf8");
|
|
320
317
|
let next = env.replace(/^AUTH_PROVIDER=.*$/m, `AUTH_PROVIDER=${opts.authProvider}`).replace(/^AUTH_TRANSPORT=.*$/m, `AUTH_TRANSPORT=${opts.transport}`);
|
|
321
318
|
next = uncommentTransportEnv(next, "AUTH", opts.transport);
|
|
319
|
+
if (opts.authProvider === "mongodb") {
|
|
320
|
+
next += "\nMONGODB_URI=mongodb://localhost:27017/icore-auth\nJWT_SECRET=change-me-in-production\n";
|
|
321
|
+
}
|
|
322
322
|
await writeFile(join2(targetDir, "apps/microservices/auth/.env"), next);
|
|
323
323
|
}
|
|
324
324
|
async function writeUploadEnv(targetDir, opts) {
|
|
@@ -327,6 +327,9 @@ async function writeUploadEnv(targetDir, opts) {
|
|
|
327
327
|
const env = await readFile2(envExample, "utf8");
|
|
328
328
|
let next = env.replace(/^STORAGE_PROVIDER=.*$/m, `STORAGE_PROVIDER=${opts.upload}`).replace(/^UPLOAD_TRANSPORT=.*$/m, `UPLOAD_TRANSPORT=${opts.transport}`);
|
|
329
329
|
next = uncommentTransportEnv(next, "UPLOAD", opts.transport);
|
|
330
|
+
if (opts.upload === "mongodb") {
|
|
331
|
+
next += "\nMONGODB_URI=mongodb://localhost:27017/icore-upload\n";
|
|
332
|
+
}
|
|
330
333
|
await writeFile(join2(targetDir, "apps/microservices/upload/.env"), next);
|
|
331
334
|
}
|
|
332
335
|
async function writeNotesEnv(targetDir, opts) {
|
|
@@ -356,18 +359,11 @@ async function writeRootEnv(targetDir, opts) {
|
|
|
356
359
|
`DB_PROVIDER=${opts.dbProvider}`,
|
|
357
360
|
``
|
|
358
361
|
];
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
const gatewayEnv = join2(targetDir, "apps/api/.env");
|
|
363
|
-
try {
|
|
364
|
-
const env = await readFile2(gatewayEnv, "utf8");
|
|
365
|
-
const next = env.split("\n").filter(
|
|
366
|
-
(line) => !line.startsWith(`${prefix}_`) && !line.startsWith(`# ${prefix}_`) && !line.includes(`${prefix} MS transport`)
|
|
367
|
-
).join("\n");
|
|
368
|
-
await writeFile(gatewayEnv, next);
|
|
369
|
-
} catch {
|
|
362
|
+
if (opts.dbProvider === "mongodb") {
|
|
363
|
+
lines.push(`MONGODB_URI=mongodb://localhost:27017/icore-data`);
|
|
364
|
+
lines.push(``);
|
|
370
365
|
}
|
|
366
|
+
await writeFile(join2(targetDir, ".env"), lines.join("\n"));
|
|
371
367
|
}
|
|
372
368
|
async function writeClientEnv(targetDir) {
|
|
373
369
|
const envExample = join2(targetDir, "apps/client/.env.example");
|
|
@@ -388,15 +384,37 @@ async function writePaymentEnv(targetDir, opts) {
|
|
|
388
384
|
} catch {
|
|
389
385
|
}
|
|
390
386
|
}
|
|
387
|
+
|
|
388
|
+
// src/lib/scaffold-strip.ts
|
|
389
|
+
import { readFile as readFile3, writeFile as writeFile2, rm } from "fs/promises";
|
|
390
|
+
import { join as join3 } from "path";
|
|
391
391
|
async function stripDeps(pkgPath, names) {
|
|
392
392
|
try {
|
|
393
|
-
const raw = await
|
|
393
|
+
const raw = await readFile3(pkgPath, "utf8");
|
|
394
394
|
const pkg = JSON.parse(raw);
|
|
395
395
|
for (const n of names) {
|
|
396
396
|
if (pkg.dependencies) delete pkg.dependencies[n];
|
|
397
397
|
if (pkg.devDependencies) delete pkg.devDependencies[n];
|
|
398
398
|
}
|
|
399
|
-
await
|
|
399
|
+
await writeFile2(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
400
|
+
} catch {
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
async function stripTsconfigPath(targetDir, alias) {
|
|
404
|
+
const tsconfigPath = join3(targetDir, "tsconfig.base.json");
|
|
405
|
+
try {
|
|
406
|
+
const src = await readFile3(tsconfigPath, "utf8");
|
|
407
|
+
const escaped = alias.replace(/[@/]/g, (c) => c === "@" ? "@" : "\\/");
|
|
408
|
+
const pretty = src.replace(new RegExp(`^\\s*"${escaped}": \\[[^\\]]*\\],?\\n`, "m"), "");
|
|
409
|
+
if (pretty !== src) {
|
|
410
|
+
await writeFile2(tsconfigPath, pretty);
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
const parsed = JSON.parse(src);
|
|
414
|
+
if (parsed.compilerOptions?.paths) {
|
|
415
|
+
delete parsed.compilerOptions.paths[alias];
|
|
416
|
+
}
|
|
417
|
+
await writeFile2(tsconfigPath, JSON.stringify(parsed));
|
|
400
418
|
} catch {
|
|
401
419
|
}
|
|
402
420
|
}
|
|
@@ -408,25 +426,25 @@ async function removeJobsStack(targetDir) {
|
|
|
408
426
|
"Dockerfile.ms-jobs"
|
|
409
427
|
];
|
|
410
428
|
for (const p3 of paths) {
|
|
411
|
-
await rm(
|
|
429
|
+
await rm(join3(targetDir, p3), { recursive: true, force: true });
|
|
412
430
|
}
|
|
413
|
-
const appModulePath =
|
|
431
|
+
const appModulePath = join3(targetDir, "apps/api/src/app/app.module.ts");
|
|
414
432
|
try {
|
|
415
|
-
const appModule = await
|
|
433
|
+
const appModule = await readFile3(appModulePath, "utf8");
|
|
416
434
|
const next = appModule.replace(/^import \{ AdminModule \} from '\.\/admin\/admin\.module';\n/m, "").replace(/,\s*AdminModule/g, "");
|
|
417
|
-
await
|
|
435
|
+
await writeFile2(appModulePath, next);
|
|
418
436
|
} catch {
|
|
419
437
|
}
|
|
420
|
-
await stripDeps(
|
|
438
|
+
await stripDeps(join3(targetDir, "apps/api/package.json"), [
|
|
421
439
|
"@icore/jobs-client",
|
|
422
440
|
"@bull-board/api",
|
|
423
441
|
"@bull-board/express"
|
|
424
442
|
]);
|
|
425
|
-
const composePath =
|
|
443
|
+
const composePath = join3(targetDir, "docker-compose.yml");
|
|
426
444
|
try {
|
|
427
|
-
const compose = await
|
|
445
|
+
const compose = await readFile3(composePath, "utf8");
|
|
428
446
|
const next = compose.replace(/\n {2}jobs:[\s\S]+?(?=\n {2}\w+:|\nnetworks:)/m, "\n").replace(/\n {6}jobs:\n {8}condition: service_started/g, "").replace(/\n {6}JOBS_REDIS_URL:[^\n]*/g, "");
|
|
429
|
-
await
|
|
447
|
+
await writeFile2(composePath, next);
|
|
430
448
|
} catch {
|
|
431
449
|
}
|
|
432
450
|
}
|
|
@@ -438,25 +456,25 @@ async function removePaymentStack(targetDir) {
|
|
|
438
456
|
"apps/api/src/app/payment"
|
|
439
457
|
];
|
|
440
458
|
for (const p3 of paths) {
|
|
441
|
-
await rm(
|
|
459
|
+
await rm(join3(targetDir, p3), { recursive: true, force: true });
|
|
442
460
|
}
|
|
443
|
-
const appModulePath =
|
|
461
|
+
const appModulePath = join3(targetDir, "apps/api/src/app/app.module.ts");
|
|
444
462
|
try {
|
|
445
|
-
const appModule = await
|
|
463
|
+
const appModule = await readFile3(appModulePath, "utf8");
|
|
446
464
|
const next = appModule.replace(/^import \{ PaymentModule \} from '\.\/payment\/payment\.module';\n/m, "").replace(/,\s*PaymentModule/g, "");
|
|
447
|
-
await
|
|
465
|
+
await writeFile2(appModulePath, next);
|
|
448
466
|
} catch {
|
|
449
467
|
}
|
|
450
|
-
await stripDeps(
|
|
468
|
+
await stripDeps(join3(targetDir, "apps/api/package.json"), [
|
|
451
469
|
"@icore/payment-client",
|
|
452
470
|
"@idevconn/payment"
|
|
453
471
|
]);
|
|
454
472
|
await stripGatewayTransport(targetDir, "PAYMENT");
|
|
455
|
-
const mainTsPath =
|
|
473
|
+
const mainTsPath = join3(targetDir, "apps/api/src/main.ts");
|
|
456
474
|
try {
|
|
457
|
-
const src = await
|
|
475
|
+
const src = await readFile3(mainTsPath, "utf8");
|
|
458
476
|
const next = src.replace(/\n\s*\{ name: 'payment', prefix: 'PAYMENT' \},/, "");
|
|
459
|
-
await
|
|
477
|
+
await writeFile2(mainTsPath, next);
|
|
460
478
|
} catch {
|
|
461
479
|
}
|
|
462
480
|
}
|
|
@@ -468,39 +486,39 @@ async function removeNotesStack(targetDir) {
|
|
|
468
486
|
"apps/api/src/app/notes",
|
|
469
487
|
"apps/client/src/components/notes"
|
|
470
488
|
]) {
|
|
471
|
-
await rm(
|
|
489
|
+
await rm(join3(targetDir, p3), { recursive: true, force: true });
|
|
472
490
|
}
|
|
473
|
-
await rm(
|
|
474
|
-
await rm(
|
|
475
|
-
const appModulePath =
|
|
491
|
+
await rm(join3(targetDir, "apps/client/src/routes/_dashboard/notes.tsx"), { force: true });
|
|
492
|
+
await rm(join3(targetDir, "apps/client/src/queries/notes.ts"), { force: true });
|
|
493
|
+
const appModulePath = join3(targetDir, "apps/api/src/app/app.module.ts");
|
|
476
494
|
try {
|
|
477
|
-
const src = await
|
|
495
|
+
const src = await readFile3(appModulePath, "utf8");
|
|
478
496
|
const next = src.replace(/^import \{ NotesModule \} from '\.\/notes\/notes\.module';\n/m, "").replace(/,\s*NotesModule/g, "");
|
|
479
|
-
await
|
|
497
|
+
await writeFile2(appModulePath, next);
|
|
480
498
|
} catch {
|
|
481
499
|
}
|
|
482
|
-
await stripDeps(
|
|
500
|
+
await stripDeps(join3(targetDir, "apps/api/package.json"), [
|
|
483
501
|
"@icore/notes-client",
|
|
484
502
|
"@casl/ability"
|
|
485
503
|
]);
|
|
486
504
|
await stripGatewayTransport(targetDir, "NOTES");
|
|
487
|
-
const mainTsPath =
|
|
505
|
+
const mainTsPath = join3(targetDir, "apps/api/src/main.ts");
|
|
488
506
|
try {
|
|
489
|
-
const src = await
|
|
507
|
+
const src = await readFile3(mainTsPath, "utf8");
|
|
490
508
|
const next = src.replace(/\n\s*\{ name: 'notes', prefix: 'NOTES' \},/, "");
|
|
491
|
-
await
|
|
509
|
+
await writeFile2(mainTsPath, next);
|
|
492
510
|
} catch {
|
|
493
511
|
}
|
|
494
|
-
const tsconfigPath =
|
|
512
|
+
const tsconfigPath = join3(targetDir, "tsconfig.base.json");
|
|
495
513
|
try {
|
|
496
|
-
const src = await
|
|
514
|
+
const src = await readFile3(tsconfigPath, "utf8");
|
|
497
515
|
const next = src.replace(/^\s*"@icore\/notes-client": \[[^\]]*\],?\n/m, "");
|
|
498
|
-
await
|
|
516
|
+
await writeFile2(tsconfigPath, next);
|
|
499
517
|
} catch {
|
|
500
518
|
}
|
|
501
|
-
const siderPath =
|
|
519
|
+
const siderPath = join3(targetDir, "apps/client/src/components/layout/LayoutSider.tsx");
|
|
502
520
|
try {
|
|
503
|
-
const src = await
|
|
521
|
+
const src = await readFile3(siderPath, "utf8");
|
|
504
522
|
const next = src.replace(", StickyNote", "").replace(/\n {8}<Link\n {10}to="\/(?:_dashboard\/)?notes"[\s\S]*?<\/Link>/, "").replace(", FileTextOutlined", "").replace(
|
|
505
523
|
"const selectedKey = pathname.includes('/notes')\n ? 'notes'\n : pathname.includes('/profile')",
|
|
506
524
|
"const selectedKey = pathname.includes('/profile')"
|
|
@@ -511,159 +529,213 @@ async function removeNotesStack(targetDir) {
|
|
|
511
529
|
/\n {8}<ListItemButton\n {10}component=\{Link\}\n {10}to="\/(?:_dashboard\/)?notes"[\s\S]*?<\/ListItemButton>/,
|
|
512
530
|
""
|
|
513
531
|
).replace(/\n\s*<Link to="\/(?:_dashboard\/)?notes">[\s\S]*?<\/Link>/m, "");
|
|
514
|
-
await
|
|
532
|
+
await writeFile2(siderPath, next);
|
|
515
533
|
} catch {
|
|
516
534
|
}
|
|
517
|
-
const keysPath =
|
|
535
|
+
const keysPath = join3(targetDir, "libs/template-shared/src/lib/i18n/keys.ts");
|
|
518
536
|
try {
|
|
519
|
-
const src = await
|
|
537
|
+
const src = await readFile3(keysPath, "utf8");
|
|
520
538
|
const next = src.replace(/^\s{4}notes: \{\n(?:\s+.*\n)*?\s{4}\},\n/m, "");
|
|
521
|
-
await
|
|
522
|
-
} catch {
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
async function stripTsconfigPath(targetDir, alias) {
|
|
526
|
-
const tsconfigPath = join2(targetDir, "tsconfig.base.json");
|
|
527
|
-
try {
|
|
528
|
-
const src = await readFile2(tsconfigPath, "utf8");
|
|
529
|
-
const escaped = alias.replace(/[@/]/g, (c) => c === "@" ? "@" : "\\/");
|
|
530
|
-
const pretty = src.replace(new RegExp(`^\\s*"${escaped}": \\[[^\\]]*\\],?\\n`, "m"), "");
|
|
531
|
-
if (pretty !== src) {
|
|
532
|
-
await writeFile(tsconfigPath, pretty);
|
|
533
|
-
return;
|
|
534
|
-
}
|
|
535
|
-
const parsed = JSON.parse(src);
|
|
536
|
-
if (parsed.compilerOptions?.paths) {
|
|
537
|
-
delete parsed.compilerOptions.paths[alias];
|
|
538
|
-
}
|
|
539
|
-
await writeFile(tsconfigPath, JSON.stringify(parsed));
|
|
539
|
+
await writeFile2(keysPath, next);
|
|
540
540
|
} catch {
|
|
541
541
|
}
|
|
542
542
|
}
|
|
543
543
|
async function removeUnusedAuthStrategies(targetDir, authProvider) {
|
|
544
|
-
const modulePath =
|
|
545
|
-
const AUTH_BRANCH = /if \(provider === 'supabase'\) return makeSupabaseAuth\(cfg\);\n\s*return makeFirebaseAuth\(cfg\);/m;
|
|
544
|
+
const modulePath = join3(targetDir, "apps/microservices/auth/src/app/app.module.ts");
|
|
545
|
+
const AUTH_BRANCH = /if \(provider === 'supabase'\) return makeSupabaseAuth\(cfg\);\n\s*if \(provider === 'mongodb'\) return makeMongoDbAuth\(connection, cfg\);\n\s*return makeFirebaseAuth\(cfg\);/m;
|
|
546
546
|
if (authProvider === "supabase") {
|
|
547
|
-
await rm(
|
|
548
|
-
await
|
|
547
|
+
await rm(join3(targetDir, "libs/auth-strategies/firebase"), { recursive: true, force: true });
|
|
548
|
+
await rm(join3(targetDir, "libs/auth-strategies/mongodb"), { recursive: true, force: true });
|
|
549
|
+
await stripDeps(join3(targetDir, "apps/microservices/auth/package.json"), [
|
|
549
550
|
"@icore/auth-firebase",
|
|
550
|
-
"@icore/firebase-admin"
|
|
551
|
+
"@icore/firebase-admin",
|
|
552
|
+
"@icore/auth-mongodb"
|
|
551
553
|
]);
|
|
552
554
|
await stripTsconfigPath(targetDir, "@icore/auth-firebase");
|
|
555
|
+
await stripTsconfigPath(targetDir, "@icore/auth-mongodb");
|
|
553
556
|
try {
|
|
554
|
-
const src = await
|
|
555
|
-
const next = src.replace(/^import \{[^}]*\} from '@icore\/firebase-admin';\n/
|
|
556
|
-
|
|
557
|
+
const src = await readFile3(modulePath, "utf8");
|
|
558
|
+
const next = src.replace(/^import \{[^}]*\} from '@icore\/firebase-admin';\n/gm, "").replace(/^import \{[^}]*FirebaseAuthStrategy[^}]*\} from '@icore\/auth-firebase';\n/gm, "").replace(/^import \{[^}]*MongoDbAuthStrategy[^}]*\} from '@icore\/auth-mongodb';\n/gm, "").replace(
|
|
559
|
+
/^import \{ MongooseModule, getConnectionToken \} from '@nestjs\/mongoose';\n/gm,
|
|
560
|
+
""
|
|
561
|
+
).replace(/^import \{ Connection \} from 'mongoose';\n/gm, "").replace(/^ {2}firebase: \[[^\]]*\],\n/gm, "").replace(/^ {2}mongodb: \[[^\]]*\],\n/gm, "").replace(/\nfunction makeFirebaseAuth[\s\S]*?\n}\n/gm, "").replace(/\nfunction makeMongoDbAuth[\s\S]*?\n}\n/gm, "").replace(/^ {4}MongooseModule\.forRootAsync[\s\S]*?\n {4}\}\),\n/gm, "").replace(AUTH_BRANCH, "return makeSupabaseAuth(cfg);").replace(/, connection: Connection/, "").replace(/, getConnectionToken\(\)/, "");
|
|
562
|
+
await writeFile2(modulePath, next);
|
|
557
563
|
} catch {
|
|
558
564
|
}
|
|
559
565
|
}
|
|
560
566
|
if (authProvider === "firebase") {
|
|
561
|
-
await rm(
|
|
562
|
-
await
|
|
563
|
-
|
|
567
|
+
await rm(join3(targetDir, "libs/auth-strategies/supabase"), { recursive: true, force: true });
|
|
568
|
+
await rm(join3(targetDir, "libs/auth-strategies/mongodb"), { recursive: true, force: true });
|
|
569
|
+
await stripDeps(join3(targetDir, "apps/microservices/auth/package.json"), [
|
|
570
|
+
"@icore/auth-supabase",
|
|
571
|
+
"@icore/auth-mongodb"
|
|
572
|
+
]);
|
|
573
|
+
await stripTsconfigPath(targetDir, "@icore/auth-supabase");
|
|
574
|
+
await stripTsconfigPath(targetDir, "@icore/auth-mongodb");
|
|
575
|
+
try {
|
|
576
|
+
const src = await readFile3(modulePath, "utf8");
|
|
577
|
+
const next = src.replace(/^import \{ createClient \} from '@supabase\/supabase-js';\n/gm, "").replace(/^import \{[^}]*SupabaseAuthStrategy[^}]*\} from '@icore\/auth-supabase';\n/gm, "").replace(/^import \{[^}]*MongoDbAuthStrategy[^}]*\} from '@icore\/auth-mongodb';\n/gm, "").replace(
|
|
578
|
+
/^import \{ MongooseModule, getConnectionToken \} from '@nestjs\/mongoose';\n/gm,
|
|
579
|
+
""
|
|
580
|
+
).replace(/^import \{ Connection \} from 'mongoose';\n/gm, "").replace(/^ {2}supabase: \[[^\]]*\],\n/gm, "").replace(/^ {2}mongodb: \[[^\]]*\],\n/gm, "").replace(/\nfunction makeSupabaseAuth[\s\S]*?\n}\n/gm, "").replace(/\nfunction makeMongoDbAuth[\s\S]*?\n}\n/gm, "").replace(/^ {4}MongooseModule\.forRootAsync[\s\S]*?\n {4}\}\),\n/gm, "").replace(AUTH_BRANCH, "return makeFirebaseAuth(cfg);").replace(/, connection: Connection/, "").replace(/, getConnectionToken\(\)/, "");
|
|
581
|
+
await writeFile2(modulePath, next);
|
|
582
|
+
} catch {
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
if (authProvider === "mongodb") {
|
|
586
|
+
await rm(join3(targetDir, "libs/auth-strategies/supabase"), { recursive: true, force: true });
|
|
587
|
+
await rm(join3(targetDir, "libs/auth-strategies/firebase"), { recursive: true, force: true });
|
|
588
|
+
await stripDeps(join3(targetDir, "apps/microservices/auth/package.json"), [
|
|
589
|
+
"@icore/auth-supabase",
|
|
590
|
+
"@icore/auth-firebase",
|
|
591
|
+
"@icore/firebase-admin"
|
|
564
592
|
]);
|
|
565
593
|
await stripTsconfigPath(targetDir, "@icore/auth-supabase");
|
|
594
|
+
await stripTsconfigPath(targetDir, "@icore/auth-firebase");
|
|
566
595
|
try {
|
|
567
|
-
const src = await
|
|
568
|
-
const next = src.replace(/^import \{ createClient \} from '@supabase\/supabase-js';\n/
|
|
569
|
-
await
|
|
596
|
+
const src = await readFile3(modulePath, "utf8");
|
|
597
|
+
const next = src.replace(/^import \{ createClient \} from '@supabase\/supabase-js';\n/gm, "").replace(/^import \{[^}]*SupabaseAuthStrategy[^}]*\} from '@icore\/auth-supabase';\n/gm, "").replace(/^import \{[^}]*\} from '@icore\/firebase-admin';\n/gm, "").replace(/^import \{[^}]*FirebaseAuthStrategy[^}]*\} from '@icore\/auth-firebase';\n/gm, "").replace(/^ {2}supabase: \[[^\]]*\],\n/gm, "").replace(/^ {2}firebase: \[[^\]]*\],\n/gm, "").replace(/\nfunction makeSupabaseAuth[\s\S]*?\n}\n/gm, "").replace(/\nfunction makeFirebaseAuth[\s\S]*?\n}\n/gm, "").replace(AUTH_BRANCH, "return makeMongoDbAuth(connection, cfg);");
|
|
598
|
+
await writeFile2(modulePath, next);
|
|
570
599
|
} catch {
|
|
571
600
|
}
|
|
572
601
|
}
|
|
573
602
|
}
|
|
574
603
|
async function removeUnusedStorageStrategies(targetDir, uploadProvider) {
|
|
575
604
|
if (uploadProvider === "none") return;
|
|
576
|
-
const modulePath =
|
|
605
|
+
const modulePath = join3(targetDir, "apps/microservices/upload/src/app/app.module.ts");
|
|
606
|
+
const STORAGE_BRANCH = /if \(provider === 'supabase'\) return makeSupabaseStorage\(cfg\);\n\s*if \(provider === 'firebase'\) return makeFirebaseStorage\(cfg\);\n\s*if \(provider === 'mongodb'\) return makeMongoDbStorage\(connection\);\n\s*return makeCloudinaryStorage\(cfg\);/m;
|
|
577
607
|
if (uploadProvider !== "firebase") {
|
|
578
|
-
await rm(
|
|
579
|
-
await stripDeps(
|
|
608
|
+
await rm(join3(targetDir, "libs/storage-strategies/firebase"), { recursive: true, force: true });
|
|
609
|
+
await stripDeps(join3(targetDir, "apps/microservices/upload/package.json"), [
|
|
580
610
|
"@icore/storage-firebase",
|
|
581
611
|
"@icore/firebase-admin"
|
|
582
612
|
]);
|
|
583
613
|
await stripTsconfigPath(targetDir, "@icore/storage-firebase");
|
|
584
614
|
}
|
|
585
615
|
if (uploadProvider !== "cloudinary") {
|
|
586
|
-
await rm(
|
|
616
|
+
await rm(join3(targetDir, "libs/storage-strategies/cloudinary"), {
|
|
587
617
|
recursive: true,
|
|
588
618
|
force: true
|
|
589
619
|
});
|
|
590
|
-
await stripDeps(
|
|
620
|
+
await stripDeps(join3(targetDir, "apps/microservices/upload/package.json"), [
|
|
591
621
|
"@icore/storage-cloudinary"
|
|
592
622
|
]);
|
|
593
623
|
await stripTsconfigPath(targetDir, "@icore/storage-cloudinary");
|
|
594
624
|
}
|
|
595
625
|
if (uploadProvider !== "supabase") {
|
|
596
|
-
await rm(
|
|
597
|
-
await stripDeps(
|
|
626
|
+
await rm(join3(targetDir, "libs/storage-strategies/supabase"), { recursive: true, force: true });
|
|
627
|
+
await stripDeps(join3(targetDir, "apps/microservices/upload/package.json"), [
|
|
598
628
|
"@icore/storage-supabase"
|
|
599
629
|
]);
|
|
600
630
|
await stripTsconfigPath(targetDir, "@icore/storage-supabase");
|
|
601
631
|
}
|
|
632
|
+
if (uploadProvider !== "mongodb") {
|
|
633
|
+
await rm(join3(targetDir, "libs/storage-strategies/mongodb"), { recursive: true, force: true });
|
|
634
|
+
await stripDeps(join3(targetDir, "apps/microservices/upload/package.json"), [
|
|
635
|
+
"@icore/storage-mongodb"
|
|
636
|
+
]);
|
|
637
|
+
await stripTsconfigPath(targetDir, "@icore/storage-mongodb");
|
|
638
|
+
}
|
|
602
639
|
try {
|
|
603
|
-
let src = await
|
|
640
|
+
let src = await readFile3(modulePath, "utf8");
|
|
604
641
|
if (uploadProvider !== "firebase") {
|
|
605
|
-
src = src.replace(/^import \{[^}]*\} from '@icore\/firebase-admin';\n/
|
|
606
|
-
/^import \{[^}]*FirebaseStorageStrategy[^}]*\} from '@icore\/storage-firebase';\n/
|
|
642
|
+
src = src.replace(/^import \{[^}]*\} from '@icore\/firebase-admin';\n/gm, "").replace(
|
|
643
|
+
/^import \{[^}]*FirebaseStorageStrategy[^}]*\} from '@icore\/storage-firebase';\n/gm,
|
|
607
644
|
""
|
|
608
|
-
).replace(/^ {2}firebase: \[[^\]]*\],\n/
|
|
645
|
+
).replace(/^ {2}firebase: \[[^\]]*\],\n/gm, "").replace(/\nfunction makeFirebaseStorage[\s\S]*?\n}\n/gm, "");
|
|
609
646
|
}
|
|
610
647
|
if (uploadProvider !== "cloudinary") {
|
|
611
|
-
src = src.replace(/^import \{ v2 as cloudinary \} from 'cloudinary';\n/
|
|
612
|
-
/^import \{[^}]*CloudinaryStorageStrategy[^}]*\} from '@icore\/storage-cloudinary';\n/
|
|
648
|
+
src = src.replace(/^import \{ v2 as cloudinary \} from 'cloudinary';\n/gm, "").replace(
|
|
649
|
+
/^import \{[^}]*CloudinaryStorageStrategy[^}]*\} from '@icore\/storage-cloudinary';\n/gm,
|
|
613
650
|
""
|
|
614
|
-
).replace(/\nfunction makeCloudinaryStorage[\s\S]*?\n}\n/
|
|
651
|
+
).replace(/\nfunction makeCloudinaryStorage[\s\S]*?\n}\n/gm, "");
|
|
615
652
|
}
|
|
616
653
|
if (uploadProvider !== "supabase") {
|
|
617
|
-
src = src.replace(/^import \{ createClient \} from '@supabase\/supabase-js';\n/
|
|
618
|
-
/^import \{[^}]*SupabaseStorageStrategy[^}]*\} from '@icore\/storage-supabase';\n/
|
|
654
|
+
src = src.replace(/^import \{ createClient \} from '@supabase\/supabase-js';\n/gm, "").replace(
|
|
655
|
+
/^import \{[^}]*SupabaseStorageStrategy[^}]*\} from '@icore\/storage-supabase';\n/gm,
|
|
619
656
|
""
|
|
620
|
-
).replace(/\nfunction makeSupabaseStorage[\s\S]*?\n}\n/
|
|
657
|
+
).replace(/\nfunction makeSupabaseStorage[\s\S]*?\n}\n/gm, "");
|
|
621
658
|
}
|
|
622
|
-
|
|
623
|
-
|
|
659
|
+
if (uploadProvider !== "mongodb") {
|
|
660
|
+
src = src.replace(
|
|
661
|
+
/^import \{[^}]*MongoDbStorageStrategy[^}]*\} from '@icore\/storage-mongodb';\n/gm,
|
|
662
|
+
""
|
|
663
|
+
).replace(
|
|
664
|
+
/^import \{ MongooseModule, getConnectionToken \} from '@nestjs\/mongoose';\n/gm,
|
|
665
|
+
""
|
|
666
|
+
).replace(/^import \{ Connection \} from 'mongoose';\n/gm, "").replace(/^ {2}mongodb: \[[^\]]*\],\n/gm, "").replace(/\nfunction makeMongoDbStorage[\s\S]*?\n}\n/gm, "").replace(/^ {4}MongooseModule\.forRootAsync[\s\S]*?\n {4}\}\),\n/gm, "");
|
|
667
|
+
}
|
|
668
|
+
const chosenReturn = uploadProvider === "mongodb" ? `return makeMongoDbStorage(connection);` : `return make${uploadProvider.charAt(0).toUpperCase() + uploadProvider.slice(1)}Storage(cfg);`;
|
|
624
669
|
src = src.replace(STORAGE_BRANCH, chosenReturn);
|
|
625
|
-
|
|
670
|
+
if (uploadProvider !== "mongodb") {
|
|
671
|
+
src = src.replace(/, connection: Connection/, "").replace(/, getConnectionToken\(\)/, "");
|
|
672
|
+
}
|
|
673
|
+
await writeFile2(modulePath, src);
|
|
626
674
|
} catch {
|
|
627
675
|
}
|
|
628
676
|
}
|
|
629
677
|
async function removeUnusedDbStrategies(targetDir, dbProvider) {
|
|
630
|
-
const modulePath =
|
|
678
|
+
const modulePath = join3(targetDir, "apps/microservices/notes/src/app/app.module.ts");
|
|
679
|
+
const DB_BRANCH = /if \(provider === 'supabase'\) return makeSupabaseDB\(cfg\);\n\s*if \(provider === 'mongodb'\) return makeMongoDb\(connection\);\n\s*return makeFirestoreDB\(cfg\);/m;
|
|
631
680
|
if (dbProvider === "supabase") {
|
|
632
|
-
await rm(
|
|
633
|
-
await
|
|
681
|
+
await rm(join3(targetDir, "libs/db-strategies/firestore"), { recursive: true, force: true });
|
|
682
|
+
await rm(join3(targetDir, "libs/db-strategies/mongodb"), { recursive: true, force: true });
|
|
683
|
+
await stripDeps(join3(targetDir, "apps/microservices/notes/package.json"), [
|
|
634
684
|
"@icore/db-firestore",
|
|
635
|
-
"@icore/firebase-admin"
|
|
685
|
+
"@icore/firebase-admin",
|
|
686
|
+
"@icore/db-mongodb"
|
|
636
687
|
]);
|
|
637
688
|
await stripTsconfigPath(targetDir, "@icore/db-firestore");
|
|
689
|
+
await stripTsconfigPath(targetDir, "@icore/db-mongodb");
|
|
638
690
|
try {
|
|
639
|
-
const src = await
|
|
640
|
-
const next = src.replace(/^import \{[^}]*\} from '@icore\/firebase-admin';\n/
|
|
641
|
-
|
|
642
|
-
"
|
|
643
|
-
);
|
|
644
|
-
await
|
|
691
|
+
const src = await readFile3(modulePath, "utf8");
|
|
692
|
+
const next = src.replace(/^import \{[^}]*\} from '@icore\/firebase-admin';\n/gm, "").replace(/^import \{[^}]*FirestoreDBStrategy[^}]*\} from '@icore\/db-firestore';\n/gm, "").replace(/^import \{[^}]*MongoDbDBStrategy[^}]*\} from '@icore\/db-mongodb';\n/gm, "").replace(
|
|
693
|
+
/^import \{ MongooseModule, getConnectionToken \} from '@nestjs\/mongoose';\n/gm,
|
|
694
|
+
""
|
|
695
|
+
).replace(/^import \{ Connection \} from 'mongoose';\n/gm, "").replace(/^ {2}firestore: \[[^\]]*\],\n/gm, "").replace(/^ {2}firebase: \[[^\]]*\],\n/gm, "").replace(/^ {2}mongodb: \[[^\]]*\],\n/gm, "").replace(/\nfunction makeFirestoreDB[\s\S]*?\n}\n/gm, "").replace(/\nfunction makeMongoDb[\s\S]*?\n}\n/gm, "").replace(/^ {4}MongooseModule\.forRootAsync[\s\S]*?\n {4}\}\),\n/gm, "").replace(DB_BRANCH, "return makeSupabaseDB(cfg);").replace(/, connection: Connection/, "").replace(/, getConnectionToken\(\)/, "");
|
|
696
|
+
await writeFile2(modulePath, next);
|
|
645
697
|
} catch {
|
|
646
698
|
}
|
|
647
699
|
}
|
|
648
700
|
if (dbProvider === "firebase") {
|
|
649
|
-
await rm(
|
|
650
|
-
await
|
|
651
|
-
|
|
701
|
+
await rm(join3(targetDir, "libs/db-strategies/supabase"), { recursive: true, force: true });
|
|
702
|
+
await rm(join3(targetDir, "libs/db-strategies/mongodb"), { recursive: true, force: true });
|
|
703
|
+
await stripDeps(join3(targetDir, "apps/microservices/notes/package.json"), [
|
|
704
|
+
"@icore/db-supabase",
|
|
705
|
+
"@icore/db-mongodb"
|
|
652
706
|
]);
|
|
653
707
|
await stripTsconfigPath(targetDir, "@icore/db-supabase");
|
|
708
|
+
await stripTsconfigPath(targetDir, "@icore/db-mongodb");
|
|
654
709
|
try {
|
|
655
|
-
const src = await
|
|
656
|
-
const next = src.replace(/^import \{ createClient \} from '@supabase\/supabase-js';\n/
|
|
657
|
-
|
|
658
|
-
"
|
|
659
|
-
);
|
|
660
|
-
await
|
|
710
|
+
const src = await readFile3(modulePath, "utf8");
|
|
711
|
+
const next = src.replace(/^import \{ createClient \} from '@supabase\/supabase-js';\n/gm, "").replace(/^import \{[^}]*SupabaseDBStrategy[^}]*\} from '@icore\/db-supabase';\n/gm, "").replace(/^import \{[^}]*MongoDbDBStrategy[^}]*\} from '@icore\/db-mongodb';\n/gm, "").replace(
|
|
712
|
+
/^import \{ MongooseModule, getConnectionToken \} from '@nestjs\/mongoose';\n/gm,
|
|
713
|
+
""
|
|
714
|
+
).replace(/^import \{ Connection \} from 'mongoose';\n/gm, "").replace(/^ {2}supabase: \[[^\]]*\],\n/gm, "").replace(/^ {2}mongodb: \[[^\]]*\],\n/gm, "").replace(/\nfunction makeSupabaseDB[\s\S]*?\n}\n/gm, "").replace(/\nfunction makeMongoDb[\s\S]*?\n}\n/gm, "").replace(/^ {4}MongooseModule\.forRootAsync[\s\S]*?\n {4}\}\),\n/gm, "").replace(/\nfunction requireEnv[\s\S]*?\n}\n/gm, "").replace(DB_BRANCH, "return makeFirestoreDB(cfg);").replace(/, connection: Connection/, "").replace(/, getConnectionToken\(\)/, "");
|
|
715
|
+
await writeFile2(modulePath, next);
|
|
716
|
+
} catch {
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
if (dbProvider === "mongodb") {
|
|
720
|
+
await rm(join3(targetDir, "libs/db-strategies/supabase"), { recursive: true, force: true });
|
|
721
|
+
await rm(join3(targetDir, "libs/db-strategies/firestore"), { recursive: true, force: true });
|
|
722
|
+
await stripDeps(join3(targetDir, "apps/microservices/notes/package.json"), [
|
|
723
|
+
"@icore/db-supabase",
|
|
724
|
+
"@icore/db-firestore",
|
|
725
|
+
"@icore/firebase-admin"
|
|
726
|
+
]);
|
|
727
|
+
await stripTsconfigPath(targetDir, "@icore/db-supabase");
|
|
728
|
+
await stripTsconfigPath(targetDir, "@icore/db-firestore");
|
|
729
|
+
try {
|
|
730
|
+
const src = await readFile3(modulePath, "utf8");
|
|
731
|
+
const next = src.replace(/^import \{ createClient \} from '@supabase\/supabase-js';\n/gm, "").replace(/^import \{[^}]*SupabaseDBStrategy[^}]*\} from '@icore\/db-supabase';\n/gm, "").replace(/^import \{[^}]*\} from '@icore\/firebase-admin';\n/gm, "").replace(/^import \{[^}]*FirestoreDBStrategy[^}]*\} from '@icore\/db-firestore';\n/gm, "").replace(/^ {2}supabase: \[[^\]]*\],\n/gm, "").replace(/^ {2}firestore: \[[^\]]*\],\n/gm, "").replace(/^ {2}firebase: \[[^\]]*\],\n/gm, "").replace(/\nfunction makeSupabaseDB[\s\S]*?\n}\n/gm, "").replace(/\nfunction makeFirestoreDB[\s\S]*?\n}\n/gm, "").replace(/\nfunction requireEnv[\s\S]*?\n}\n/gm, "").replace(DB_BRANCH, "return makeMongoDb(connection);");
|
|
732
|
+
await writeFile2(modulePath, next);
|
|
661
733
|
} catch {
|
|
662
734
|
}
|
|
663
735
|
}
|
|
664
736
|
}
|
|
665
737
|
async function removeFirebaseAdminLib(targetDir) {
|
|
666
|
-
await rm(
|
|
738
|
+
await rm(join3(targetDir, "libs/firebase-admin"), { recursive: true, force: true });
|
|
667
739
|
await stripTsconfigPath(targetDir, "@icore/firebase-admin");
|
|
668
740
|
}
|
|
669
741
|
async function removeUploadStack(targetDir) {
|
|
@@ -675,129 +747,43 @@ async function removeUploadStack(targetDir) {
|
|
|
675
747
|
"apps/api/src/app/storage"
|
|
676
748
|
];
|
|
677
749
|
for (const p3 of paths) {
|
|
678
|
-
await rm(
|
|
750
|
+
await rm(join3(targetDir, p3), { recursive: true, force: true });
|
|
679
751
|
}
|
|
680
|
-
const appModulePath =
|
|
752
|
+
const appModulePath = join3(targetDir, "apps/api/src/app/app.module.ts");
|
|
681
753
|
try {
|
|
682
|
-
const appModule = await
|
|
754
|
+
const appModule = await readFile3(appModulePath, "utf8");
|
|
683
755
|
const next = appModule.replace(/^import \{ StorageModule \} from '\.\/storage\/storage\.module';\n/m, "").replace(/,\s*StorageModule/g, "");
|
|
684
|
-
await
|
|
756
|
+
await writeFile2(appModulePath, next);
|
|
685
757
|
} catch {
|
|
686
758
|
}
|
|
687
|
-
const gatewayEnv =
|
|
759
|
+
const gatewayEnv = join3(targetDir, "apps/api/.env");
|
|
688
760
|
try {
|
|
689
|
-
const env = await
|
|
761
|
+
const env = await readFile3(gatewayEnv, "utf8");
|
|
690
762
|
const next = env.split("\n").filter(
|
|
691
763
|
(line) => !line.startsWith("UPLOAD_") && !line.startsWith("# UPLOAD_") && !line.startsWith("MAX_FILE_SIZE_KB")
|
|
692
764
|
).join("\n");
|
|
693
|
-
await
|
|
765
|
+
await writeFile2(gatewayEnv, next);
|
|
694
766
|
} catch {
|
|
695
767
|
}
|
|
696
|
-
await stripDeps(
|
|
768
|
+
await stripDeps(join3(targetDir, "apps/api/package.json"), [
|
|
697
769
|
"@icore/upload-client",
|
|
698
770
|
"@types/multer"
|
|
699
771
|
]);
|
|
700
772
|
}
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
await copyTree(chosen, destClient);
|
|
710
|
-
} catch {
|
|
711
|
-
chosenUi = "shadcn";
|
|
712
|
-
await copyTree(join2(templatesRoot, "client-shadcn"), destClient);
|
|
713
|
-
}
|
|
714
|
-
await rm(templatesRoot, { recursive: true, force: true });
|
|
715
|
-
await rewriteClientPaths(destClient, chosenUi);
|
|
716
|
-
}
|
|
717
|
-
async function rewriteClientPaths(clientDir, ui) {
|
|
718
|
-
const candidates = [
|
|
719
|
-
"vite.config.mts",
|
|
720
|
-
"tsconfig.json",
|
|
721
|
-
"tsconfig.app.json",
|
|
722
|
-
"tsconfig.spec.json",
|
|
723
|
-
"project.json",
|
|
724
|
-
"eslint.config.mjs"
|
|
725
|
-
];
|
|
726
|
-
for (const rel of candidates) {
|
|
727
|
-
const path = join2(clientDir, rel);
|
|
728
|
-
try {
|
|
729
|
-
const raw = await readFile2(path, "utf8");
|
|
730
|
-
const next = raw.replaceAll("../../../", "../../").replaceAll(`apps/templates/client-${ui}`, "apps/client").replaceAll(`client-${ui}`, "client");
|
|
731
|
-
if (next !== raw) await writeFile(path, next);
|
|
732
|
-
} catch {
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
function gitInit(cwd, projectName) {
|
|
737
|
-
spawnSync("git", ["init"], { cwd, stdio: "inherit" });
|
|
738
|
-
spawnSync("git", ["add", "."], { cwd, stdio: "inherit" });
|
|
739
|
-
spawnSync(
|
|
740
|
-
"git",
|
|
741
|
-
["commit", "-m", `chore: bootstrap ${projectName} from @idevconn/create-icore`],
|
|
742
|
-
{ cwd, stdio: "inherit" }
|
|
743
|
-
);
|
|
744
|
-
}
|
|
745
|
-
function resolveYarnBin(cwd) {
|
|
746
|
-
try {
|
|
747
|
-
const yarnrc = readFileSync(join2(cwd, ".yarnrc.yml"), "utf8");
|
|
748
|
-
const match = yarnrc.match(/^yarnPath:\s*(.+)$/m);
|
|
749
|
-
if (match?.[1]) return join2(cwd, match[1].trim());
|
|
750
|
-
} catch {
|
|
751
|
-
}
|
|
752
|
-
return join2(cwd, ".yarn", "releases", "yarn-4.5.0.cjs");
|
|
753
|
-
}
|
|
754
|
-
function runInstall(cwd, pm) {
|
|
755
|
-
if (pm === "yarn") {
|
|
756
|
-
spawnSync("node", [resolveYarnBin(cwd), "install"], { cwd, stdio: "inherit" });
|
|
757
|
-
} else if (pm === "npm") {
|
|
758
|
-
spawnSync("npm", ["install"], { cwd, stdio: "inherit" });
|
|
759
|
-
} else {
|
|
760
|
-
spawnSync("pnpm", ["install"], { cwd, stdio: "inherit" });
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
async function scaffold(opts, templatesDir2) {
|
|
764
|
-
await copyTree(templatesDir2, opts.targetDir);
|
|
765
|
-
await rewriteRootPackageJson(opts.targetDir, opts);
|
|
766
|
-
await writeAuthEnv(opts.targetDir, opts);
|
|
767
|
-
await writeUploadEnv(opts.targetDir, opts);
|
|
768
|
-
await writeNotesEnv(opts.targetDir, opts);
|
|
769
|
-
await writePaymentEnv(opts.targetDir, opts);
|
|
770
|
-
await writeGatewayEnv(opts.targetDir, opts);
|
|
771
|
-
await writeRootEnv(opts.targetDir, opts);
|
|
772
|
-
await selectClientTemplate(opts.targetDir, opts);
|
|
773
|
-
await writeClientEnv(opts.targetDir);
|
|
774
|
-
if (opts.upload === "none") await removeUploadStack(opts.targetDir);
|
|
775
|
-
if (opts.payment === "none") await removePaymentStack(opts.targetDir);
|
|
776
|
-
if (opts.jobs === "none") await removeJobsStack(opts.targetDir);
|
|
777
|
-
if (opts.example === "none") await removeNotesStack(opts.targetDir);
|
|
778
|
-
await removeUnusedAuthStrategies(opts.targetDir, opts.authProvider);
|
|
779
|
-
await removeUnusedStorageStrategies(opts.targetDir, opts.upload);
|
|
780
|
-
await removeUnusedDbStrategies(opts.targetDir, opts.dbProvider);
|
|
781
|
-
const firebaseUsed = opts.authProvider === "firebase" || opts.dbProvider === "firebase" || opts.upload === "firebase";
|
|
782
|
-
if (!firebaseUsed) await removeFirebaseAdminLib(opts.targetDir);
|
|
783
|
-
if (opts.packageManager === "yarn") {
|
|
784
|
-
await writeFile(join2(opts.targetDir, "yarn.lock"), "");
|
|
785
|
-
} else {
|
|
786
|
-
await rm(join2(opts.targetDir, ".yarn"), { recursive: true, force: true });
|
|
787
|
-
await rm(join2(opts.targetDir, ".yarnrc.yml"), { force: true });
|
|
788
|
-
}
|
|
789
|
-
if (opts.packageManager === "pnpm") {
|
|
790
|
-
await writePnpmWorkspace(opts.targetDir);
|
|
791
|
-
await rewritePnpmWorkspaceDeps(opts.targetDir);
|
|
792
|
-
}
|
|
793
|
-
await patchGitignoreForPm(opts.targetDir, opts.packageManager);
|
|
794
|
-
await writeAiFiles(opts.targetDir, opts);
|
|
795
|
-
if (opts.install) runInstall(opts.targetDir, opts.packageManager);
|
|
796
|
-
if (opts.initGit) gitInit(opts.targetDir, opts.projectName);
|
|
773
|
+
|
|
774
|
+
// src/lib/scaffold-pkg.ts
|
|
775
|
+
import { readFile as readFile4, writeFile as writeFile3, mkdir, readdir } from "fs/promises";
|
|
776
|
+
import { join as join4 } from "path";
|
|
777
|
+
|
|
778
|
+
// src/lib/options.ts
|
|
779
|
+
function pmRun(pm, script) {
|
|
780
|
+
return pm === "npm" ? `npm run ${script}` : `${pm} ${script}`;
|
|
797
781
|
}
|
|
782
|
+
|
|
783
|
+
// src/lib/scaffold-pkg.ts
|
|
798
784
|
async function writePnpmWorkspace(targetDir) {
|
|
799
|
-
const pkgPath =
|
|
800
|
-
const pkg = JSON.parse(await
|
|
785
|
+
const pkgPath = join4(targetDir, "package.json");
|
|
786
|
+
const pkg = JSON.parse(await readFile4(pkgPath, "utf8"));
|
|
801
787
|
const workspaces = pkg.workspaces ?? [];
|
|
802
788
|
const packagesBlock = workspaces.map((p3) => ` - '${p3}'`).join("\n");
|
|
803
789
|
const allowBuilds = [
|
|
@@ -818,23 +804,22 @@ ${packagesBlock}
|
|
|
818
804
|
allowBuilds:
|
|
819
805
|
${allowBuilds}
|
|
820
806
|
`;
|
|
821
|
-
await
|
|
807
|
+
await writeFile3(join4(targetDir, "pnpm-workspace.yaml"), content);
|
|
822
808
|
}
|
|
823
809
|
async function rewritePnpmWorkspaceDeps(targetDir) {
|
|
824
|
-
const { readdir: rd } = await import("fs/promises");
|
|
825
810
|
async function walk(dir) {
|
|
826
811
|
const found = [];
|
|
827
812
|
let entries;
|
|
828
813
|
try {
|
|
829
|
-
entries = await
|
|
814
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
830
815
|
} catch {
|
|
831
816
|
return found;
|
|
832
817
|
}
|
|
833
818
|
for (const e of entries) {
|
|
834
819
|
if (e.isDirectory() && e.name !== "node_modules") {
|
|
835
|
-
found.push(...await walk(
|
|
820
|
+
found.push(...await walk(join4(dir, e.name)));
|
|
836
821
|
} else if (e.isFile() && e.name === "package.json") {
|
|
837
|
-
found.push(
|
|
822
|
+
found.push(join4(dir, e.name));
|
|
838
823
|
}
|
|
839
824
|
}
|
|
840
825
|
return found;
|
|
@@ -842,17 +827,17 @@ async function rewritePnpmWorkspaceDeps(targetDir) {
|
|
|
842
827
|
const pkgFiles = await walk(targetDir);
|
|
843
828
|
for (const f of pkgFiles) {
|
|
844
829
|
try {
|
|
845
|
-
const raw = await
|
|
830
|
+
const raw = await readFile4(f, "utf8");
|
|
846
831
|
const next = raw.replace(/"(@icore\/[^"]+)":\s*"\*"/g, '"$1": "workspace:*"');
|
|
847
|
-
if (next !== raw) await
|
|
832
|
+
if (next !== raw) await writeFile3(f, next);
|
|
848
833
|
} catch {
|
|
849
834
|
}
|
|
850
835
|
}
|
|
851
836
|
}
|
|
852
837
|
async function patchGitignoreForPm(targetDir, pm) {
|
|
853
|
-
const giPath =
|
|
838
|
+
const giPath = join4(targetDir, ".gitignore");
|
|
854
839
|
try {
|
|
855
|
-
let src = await
|
|
840
|
+
let src = await readFile4(giPath, "utf8");
|
|
856
841
|
src = src.replace(/^# Build artifacts.*\ntools\/create-icore\/templates\/\s*\n/m, "");
|
|
857
842
|
if (pm !== "yarn") {
|
|
858
843
|
src = src.replace(/^\.yarn\/\*\s*\n/m, "").replace(/^!\.yarn\/patches\s*\n/m, "").replace(/^!\.yarn\/plugins\s*\n/m, "").replace(/^!\.yarn\/releases\s*\n/m, "").replace(/^!\.yarn\/sdks\s*\n/m, "").replace(/^!\.yarn\/versions\s*\n/m, "").replace(/^\.pnp\.\*\s*\n/m, "");
|
|
@@ -867,7 +852,7 @@ async function patchGitignoreForPm(targetDir, pm) {
|
|
|
867
852
|
src += "\n# npm\nnpm-debug.log*\n";
|
|
868
853
|
}
|
|
869
854
|
}
|
|
870
|
-
await
|
|
855
|
+
await writeFile3(giPath, src);
|
|
871
856
|
} catch {
|
|
872
857
|
}
|
|
873
858
|
}
|
|
@@ -882,7 +867,7 @@ async function writeAiFiles(targetDir, opts) {
|
|
|
882
867
|
if (opts.jobs !== "none") activeMSes.push(`jobs (standalone)`);
|
|
883
868
|
const usesSupabase = opts.authProvider === "supabase" || opts.dbProvider === "supabase" || opts.upload === "supabase";
|
|
884
869
|
const usesFirebase = opts.authProvider === "firebase" || opts.dbProvider === "firebase" || opts.upload === "firebase";
|
|
885
|
-
await
|
|
870
|
+
await writeFile3(join4(targetDir, "CLAUDE.md"), "@AGENTS.md\n");
|
|
886
871
|
const uiLabel = { shadcn: "shadcn/ui + Tailwind", antd: "Ant Design 6", mui: "MUI 6" }[opts.ui];
|
|
887
872
|
const readme = `# ${opts.projectName}
|
|
888
873
|
|
|
@@ -932,7 +917,7 @@ ${pm === "yarn" ? "yarn remove-notes" : pm === "pnpm" ? "pnpm remove-notes" : "n
|
|
|
932
917
|
|
|
933
918
|
Apache-2.0
|
|
934
919
|
`;
|
|
935
|
-
await
|
|
920
|
+
await writeFile3(join4(targetDir, "README.md"), readme);
|
|
936
921
|
const agents = `# ${opts.projectName} \u2014 Agent Instructions
|
|
937
922
|
|
|
938
923
|
## Stack snapshot
|
|
@@ -1013,8 +998,8 @@ ${opts.upload !== "none" ? `| \`apps/microservices/upload/.env\` | \`STORAGE_PRO
|
|
|
1013
998
|
- Test behaviour, not implementation. Fake strategies from \`@icore/shared\` (FakeAuthStrategy etc.) serve as test doubles.
|
|
1014
999
|
- Run: \`${nx} test <project>\`
|
|
1015
1000
|
`;
|
|
1016
|
-
await
|
|
1017
|
-
await mkdir(
|
|
1001
|
+
await writeFile3(join4(targetDir, "AGENTS.md"), agents);
|
|
1002
|
+
await mkdir(join4(targetDir, ".claude"), { recursive: true });
|
|
1018
1003
|
const mcpServers = {
|
|
1019
1004
|
nx: {
|
|
1020
1005
|
command: "npx",
|
|
@@ -1055,12 +1040,135 @@ ${opts.upload !== "none" ? `| \`apps/microservices/upload/.env\` | \`STORAGE_PRO
|
|
|
1055
1040
|
]
|
|
1056
1041
|
}
|
|
1057
1042
|
};
|
|
1058
|
-
await
|
|
1059
|
-
|
|
1043
|
+
await writeFile3(
|
|
1044
|
+
join4(targetDir, ".claude", "settings.json"),
|
|
1060
1045
|
JSON.stringify(settings, null, 2) + "\n"
|
|
1061
1046
|
);
|
|
1062
1047
|
}
|
|
1063
1048
|
|
|
1049
|
+
// src/lib/scaffold.ts
|
|
1050
|
+
var IGNORE_TOP = /* @__PURE__ */ new Set([
|
|
1051
|
+
".git",
|
|
1052
|
+
"node_modules",
|
|
1053
|
+
".yarn/cache",
|
|
1054
|
+
".yarn/unplugged",
|
|
1055
|
+
".yarn/install-state.gz",
|
|
1056
|
+
".nx",
|
|
1057
|
+
"dist",
|
|
1058
|
+
"tmp",
|
|
1059
|
+
"coverage",
|
|
1060
|
+
".idea",
|
|
1061
|
+
".vscode"
|
|
1062
|
+
]);
|
|
1063
|
+
async function copyTree(src, dest) {
|
|
1064
|
+
await mkdir2(dest, { recursive: true });
|
|
1065
|
+
const entries = await readdir2(src, { withFileTypes: true });
|
|
1066
|
+
for (const entry of entries) {
|
|
1067
|
+
if (IGNORE_TOP.has(entry.name)) continue;
|
|
1068
|
+
const s = join5(src, entry.name);
|
|
1069
|
+
const d = join5(dest, entry.name);
|
|
1070
|
+
if (entry.isDirectory()) await copyTree(s, d);
|
|
1071
|
+
else if (entry.isFile()) await copyFile(s, d);
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
async function selectClientTemplate(targetDir, opts) {
|
|
1075
|
+
const templatesRoot = join5(targetDir, "apps/templates");
|
|
1076
|
+
const chosen = join5(templatesRoot, `client-${opts.ui}`);
|
|
1077
|
+
const destClient = join5(targetDir, "apps/client");
|
|
1078
|
+
let chosenUi = opts.ui;
|
|
1079
|
+
try {
|
|
1080
|
+
const s = await stat(chosen);
|
|
1081
|
+
if (!s.isDirectory()) throw new Error("not a dir");
|
|
1082
|
+
await copyTree(chosen, destClient);
|
|
1083
|
+
} catch {
|
|
1084
|
+
chosenUi = "shadcn";
|
|
1085
|
+
await copyTree(join5(templatesRoot, "client-shadcn"), destClient);
|
|
1086
|
+
}
|
|
1087
|
+
await rm2(templatesRoot, { recursive: true, force: true });
|
|
1088
|
+
await rewriteClientPaths(destClient, chosenUi);
|
|
1089
|
+
}
|
|
1090
|
+
async function rewriteClientPaths(clientDir, ui) {
|
|
1091
|
+
const candidates = [
|
|
1092
|
+
"vite.config.mts",
|
|
1093
|
+
"tsconfig.json",
|
|
1094
|
+
"tsconfig.app.json",
|
|
1095
|
+
"tsconfig.spec.json",
|
|
1096
|
+
"project.json",
|
|
1097
|
+
"eslint.config.mjs"
|
|
1098
|
+
];
|
|
1099
|
+
for (const rel of candidates) {
|
|
1100
|
+
const path = join5(clientDir, rel);
|
|
1101
|
+
try {
|
|
1102
|
+
const raw = await readFile5(path, "utf8");
|
|
1103
|
+
const next = raw.replaceAll("../../../", "../../").replaceAll(`apps/templates/client-${ui}`, "apps/client").replaceAll(`client-${ui}`, "client");
|
|
1104
|
+
if (next !== raw) await writeFile4(path, next);
|
|
1105
|
+
} catch {
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
function gitInit(cwd, projectName) {
|
|
1110
|
+
spawnSync("git", ["init"], { cwd, stdio: "inherit" });
|
|
1111
|
+
spawnSync("git", ["add", "."], { cwd, stdio: "inherit" });
|
|
1112
|
+
spawnSync(
|
|
1113
|
+
"git",
|
|
1114
|
+
["commit", "-m", `chore: bootstrap ${projectName} from @idevconn/create-icore`],
|
|
1115
|
+
{ cwd, stdio: "inherit" }
|
|
1116
|
+
);
|
|
1117
|
+
}
|
|
1118
|
+
function resolveYarnBin(cwd) {
|
|
1119
|
+
try {
|
|
1120
|
+
const yarnrc = readFileSync(join5(cwd, ".yarnrc.yml"), "utf8");
|
|
1121
|
+
const match = yarnrc.match(/^yarnPath:\s*(.+)$/m);
|
|
1122
|
+
if (match?.[1]) return join5(cwd, match[1].trim());
|
|
1123
|
+
} catch {
|
|
1124
|
+
}
|
|
1125
|
+
return join5(cwd, ".yarn", "releases", "yarn-4.5.0.cjs");
|
|
1126
|
+
}
|
|
1127
|
+
function runInstall(cwd, pm) {
|
|
1128
|
+
if (pm === "yarn") {
|
|
1129
|
+
spawnSync("node", [resolveYarnBin(cwd), "install"], { cwd, stdio: "inherit" });
|
|
1130
|
+
} else if (pm === "npm") {
|
|
1131
|
+
spawnSync("npm", ["install"], { cwd, stdio: "inherit" });
|
|
1132
|
+
} else {
|
|
1133
|
+
spawnSync("pnpm", ["install"], { cwd, stdio: "inherit" });
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
async function scaffold(opts, templatesDir2) {
|
|
1137
|
+
await copyTree(templatesDir2, opts.targetDir);
|
|
1138
|
+
await rewriteRootPackageJson(opts.targetDir, opts);
|
|
1139
|
+
await writeAuthEnv(opts.targetDir, opts);
|
|
1140
|
+
await writeUploadEnv(opts.targetDir, opts);
|
|
1141
|
+
await writeNotesEnv(opts.targetDir, opts);
|
|
1142
|
+
await writePaymentEnv(opts.targetDir, opts);
|
|
1143
|
+
await writeGatewayEnv(opts.targetDir, opts);
|
|
1144
|
+
await writeRootEnv(opts.targetDir, opts);
|
|
1145
|
+
await selectClientTemplate(opts.targetDir, opts);
|
|
1146
|
+
await writeClientEnv(opts.targetDir);
|
|
1147
|
+
if (opts.upload === "none") await removeUploadStack(opts.targetDir);
|
|
1148
|
+
if (opts.payment === "none") await removePaymentStack(opts.targetDir);
|
|
1149
|
+
if (opts.jobs === "none") await removeJobsStack(opts.targetDir);
|
|
1150
|
+
if (opts.example === "none") await removeNotesStack(opts.targetDir);
|
|
1151
|
+
await removeUnusedAuthStrategies(opts.targetDir, opts.authProvider);
|
|
1152
|
+
await removeUnusedStorageStrategies(opts.targetDir, opts.upload);
|
|
1153
|
+
await removeUnusedDbStrategies(opts.targetDir, opts.dbProvider);
|
|
1154
|
+
const firebaseUsed = opts.authProvider === "firebase" || opts.dbProvider === "firebase" || opts.upload === "firebase";
|
|
1155
|
+
if (!firebaseUsed) await removeFirebaseAdminLib(opts.targetDir);
|
|
1156
|
+
if (opts.packageManager === "yarn") {
|
|
1157
|
+
await writeFile4(join5(opts.targetDir, "yarn.lock"), "");
|
|
1158
|
+
} else {
|
|
1159
|
+
await rm2(join5(opts.targetDir, ".yarn"), { recursive: true, force: true });
|
|
1160
|
+
await rm2(join5(opts.targetDir, ".yarnrc.yml"), { force: true });
|
|
1161
|
+
}
|
|
1162
|
+
if (opts.packageManager === "pnpm") {
|
|
1163
|
+
await writePnpmWorkspace(opts.targetDir);
|
|
1164
|
+
await rewritePnpmWorkspaceDeps(opts.targetDir);
|
|
1165
|
+
}
|
|
1166
|
+
await patchGitignoreForPm(opts.targetDir, opts.packageManager);
|
|
1167
|
+
await writeAiFiles(opts.targetDir, opts);
|
|
1168
|
+
if (opts.install) runInstall(opts.targetDir, opts.packageManager);
|
|
1169
|
+
if (opts.initGit) gitInit(opts.targetDir, opts.projectName);
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1064
1172
|
// src/cli.ts
|
|
1065
1173
|
var [nodeMajor] = process.versions.node.split(".").map(Number);
|
|
1066
1174
|
if (nodeMajor < 22) {
|