@idevconn/create-icore 0.7.2 → 0.9.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/README.md +44 -9
- package/dist/cli.js +689 -363
- package/dist/index.cjs +806 -358
- package/dist/index.d.cts +12 -3
- package/dist/index.d.ts +12 -3
- package/dist/index.js +798 -351
- package/dist/manifest/audit.js +122 -0
- package/package.json +1 -1
- package/templates/apps/api/src/app/app.module.ts +2 -6
- package/templates/apps/api/src/app/features.module.ts +9 -0
- package/templates/apps/api/src/app/gateway-services.ts +7 -0
- package/templates/apps/api/src/main.ts +1 -5
- package/templates/apps/microservices/auth/src/app/app.module.ts +4 -93
- package/templates/apps/microservices/auth/src/app/auth.provider.ts +9 -0
- package/templates/apps/microservices/notes/src/app/app.module.ts +4 -86
- package/templates/apps/microservices/notes/src/app/db.provider.ts +9 -0
- package/templates/apps/microservices/upload/src/app/app.module.ts +4 -140
- package/templates/apps/microservices/upload/src/app/storage.provider.ts +9 -0
- package/templates/apps/templates/client-antd/src/components/layout/LayoutSider.tsx +15 -23
- package/templates/apps/templates/client-antd/src/nav.config.ts +17 -0
- package/templates/apps/templates/client-mui/src/components/layout/LayoutSider.tsx +19 -20
- package/templates/apps/templates/client-mui/src/nav.config.ts +17 -0
- package/templates/apps/templates/client-shadcn/src/components/layout/LayoutSider.tsx +20 -16
- package/templates/apps/templates/client-shadcn/src/nav.config.ts +17 -0
- package/templates/libs/auth-strategies/firebase/eslint.config.mjs +1 -0
- package/templates/libs/auth-strategies/firebase/package.json +4 -0
- package/templates/libs/auth-strategies/firebase/src/index.ts +1 -0
- package/templates/libs/auth-strategies/firebase/src/lib/__tests__/firebase-auth.module.unit.test.ts +49 -0
- package/templates/libs/auth-strategies/firebase/src/lib/firebase-auth.module.ts +41 -0
- package/templates/libs/auth-strategies/firebase/tsconfig.json +2 -0
- package/templates/libs/auth-strategies/mongodb/package.json +8 -1
- package/templates/libs/auth-strategies/mongodb/src/index.ts +1 -0
- package/templates/libs/auth-strategies/mongodb/src/lib/__tests__/mongodb-auth.module.unit.test.ts +16 -0
- package/templates/libs/auth-strategies/mongodb/src/lib/mongodb-auth.module.ts +45 -0
- package/templates/libs/auth-strategies/mongodb/tsconfig.json +2 -0
- package/templates/libs/auth-strategies/supabase/eslint.config.mjs +1 -0
- package/templates/libs/auth-strategies/supabase/package.json +3 -0
- package/templates/libs/auth-strategies/supabase/src/index.ts +1 -0
- package/templates/libs/auth-strategies/supabase/src/lib/__tests__/supabase-auth.module.unit.test.ts +43 -0
- package/templates/libs/auth-strategies/supabase/src/lib/supabase-auth.module.ts +41 -0
- package/templates/libs/auth-strategies/supabase/tsconfig.json +2 -0
- package/templates/libs/db-strategies/firestore/eslint.config.mjs +1 -1
- package/templates/libs/db-strategies/firestore/package.json +4 -0
- package/templates/libs/db-strategies/firestore/src/index.ts +1 -0
- package/templates/libs/db-strategies/firestore/src/lib/__tests__/firestore-db.module.unit.test.ts +37 -0
- package/templates/libs/db-strategies/firestore/src/lib/firestore-db.module.ts +41 -0
- package/templates/libs/db-strategies/firestore/tsconfig.json +2 -0
- package/templates/libs/db-strategies/mongodb/package.json +4 -1
- package/templates/libs/db-strategies/mongodb/src/index.ts +1 -0
- package/templates/libs/db-strategies/mongodb/src/lib/__tests__/mongodb-db.module.unit.test.ts +14 -0
- package/templates/libs/db-strategies/mongodb/src/lib/mongodb-db.module.ts +41 -0
- package/templates/libs/db-strategies/mongodb/tsconfig.json +2 -0
- package/templates/libs/db-strategies/supabase/eslint.config.mjs +6 -1
- package/templates/libs/db-strategies/supabase/package.json +3 -0
- package/templates/libs/db-strategies/supabase/src/index.ts +1 -0
- package/templates/libs/db-strategies/supabase/src/lib/__tests__/supabase-db.module.unit.test.ts +32 -0
- package/templates/libs/db-strategies/supabase/src/lib/supabase-db.module.ts +41 -0
- package/templates/libs/db-strategies/supabase/tsconfig.json +2 -0
- package/templates/libs/shared/src/strategies/__tests__/provide-strategy.unit.test.ts +73 -0
- package/templates/libs/shared/src/strategies/index.ts +1 -0
- package/templates/libs/shared/src/strategies/provide-strategy.ts +44 -0
- package/templates/libs/storage-strategies/cloudinary/eslint.config.mjs +1 -1
- package/templates/libs/storage-strategies/cloudinary/package.json +4 -0
- package/templates/libs/storage-strategies/cloudinary/src/index.ts +1 -0
- package/templates/libs/storage-strategies/cloudinary/src/lib/__tests__/cloudinary-storage.module.unit.test.ts +40 -0
- package/templates/libs/storage-strategies/cloudinary/src/lib/cloudinary-storage.module.ts +85 -0
- package/templates/libs/storage-strategies/cloudinary/tsconfig.json +2 -0
- package/templates/libs/storage-strategies/firebase/eslint.config.mjs +1 -1
- package/templates/libs/storage-strategies/firebase/package.json +4 -0
- package/templates/libs/storage-strategies/firebase/src/index.ts +1 -0
- package/templates/libs/storage-strategies/firebase/src/lib/__tests__/firebase-storage.module.unit.test.ts +42 -0
- package/templates/libs/storage-strategies/firebase/src/lib/firebase-storage.module.ts +46 -0
- package/templates/libs/storage-strategies/firebase/tsconfig.json +2 -0
- package/templates/libs/storage-strategies/mongodb/package.json +4 -1
- package/templates/libs/storage-strategies/mongodb/src/index.ts +1 -0
- package/templates/libs/storage-strategies/mongodb/src/lib/__tests__/mongodb-storage.module.unit.test.ts +14 -0
- package/templates/libs/storage-strategies/mongodb/src/lib/mongodb-storage.module.ts +41 -0
- package/templates/libs/storage-strategies/mongodb/tsconfig.json +2 -0
- package/templates/libs/storage-strategies/supabase/eslint.config.mjs +1 -0
- package/templates/libs/storage-strategies/supabase/package.json +3 -0
- package/templates/libs/storage-strategies/supabase/src/index.ts +1 -0
- package/templates/libs/storage-strategies/supabase/src/lib/__tests__/supabase-storage.module.unit.test.ts +46 -0
- package/templates/libs/storage-strategies/supabase/src/lib/supabase-storage.module.ts +46 -0
- package/templates/libs/storage-strategies/supabase/tsconfig.json +2 -0
- package/templates/package.json +1 -1
- package/templates/tools/create-icore/_template-shell/package.json +1 -1
- package/templates/tsconfig.base.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var src_exports = {};
|
|
32
32
|
__export(src_exports, {
|
|
33
|
+
auditProject: () => auditProject,
|
|
33
34
|
collectOptions: () => collectOptions,
|
|
34
35
|
pmRun: () => pmRun,
|
|
35
36
|
scaffold: () => scaffold
|
|
@@ -46,9 +47,9 @@ function pmRun(pm, script) {
|
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
// src/lib/scaffold.ts
|
|
49
|
-
var
|
|
50
|
+
var import_promises8 = require("fs/promises");
|
|
50
51
|
var import_node_fs = require("fs");
|
|
51
|
-
var
|
|
52
|
+
var import_node_path8 = require("path");
|
|
52
53
|
var import_node_child_process = require("child_process");
|
|
53
54
|
|
|
54
55
|
// src/lib/scaffold-env.ts
|
|
@@ -89,6 +90,31 @@ async function stripGatewayTransport(targetDir, prefix) {
|
|
|
89
90
|
} catch {
|
|
90
91
|
}
|
|
91
92
|
}
|
|
93
|
+
var ROOT_PROVIDER_SDKS = {
|
|
94
|
+
supabase: ["@supabase/supabase-js"],
|
|
95
|
+
cloudinary: ["cloudinary"],
|
|
96
|
+
mongodb: ["mongoose"],
|
|
97
|
+
firebase: ["firebase-admin"]
|
|
98
|
+
};
|
|
99
|
+
async function pruneRootProviderDeps(targetDir, opts) {
|
|
100
|
+
const chosen = /* @__PURE__ */ new Set([opts.authProvider, opts.dbProvider, opts.upload]);
|
|
101
|
+
const drop = /* @__PURE__ */ new Set();
|
|
102
|
+
for (const [provider, sdks] of Object.entries(ROOT_PROVIDER_SDKS)) {
|
|
103
|
+
if (!chosen.has(provider)) for (const sdk of sdks) drop.add(sdk);
|
|
104
|
+
}
|
|
105
|
+
if (drop.size === 0) return;
|
|
106
|
+
const pkgPath = (0, import_node_path.join)(targetDir, "package.json");
|
|
107
|
+
try {
|
|
108
|
+
const pkg = JSON.parse(await (0, import_promises.readFile)(pkgPath, "utf8"));
|
|
109
|
+
for (const field of ["dependencies", "devDependencies"]) {
|
|
110
|
+
const deps = pkg[field];
|
|
111
|
+
if (!deps) continue;
|
|
112
|
+
for (const sdk of drop) delete deps[sdk];
|
|
113
|
+
}
|
|
114
|
+
await (0, import_promises.writeFile)(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
115
|
+
} catch {
|
|
116
|
+
}
|
|
117
|
+
}
|
|
92
118
|
async function rewriteRootPackageJson(targetDir, opts) {
|
|
93
119
|
const pkgPath = (0, import_node_path.join)(targetDir, "package.json");
|
|
94
120
|
const raw = await (0, import_promises.readFile)(pkgPath, "utf8");
|
|
@@ -106,6 +132,11 @@ async function rewriteRootPackageJson(targetDir, opts) {
|
|
|
106
132
|
const deps = pkg["dependencies"] ??= {};
|
|
107
133
|
Object.assign(deps, MONGODB_DEPS);
|
|
108
134
|
}
|
|
135
|
+
if (opts.authProvider === "mongodb") {
|
|
136
|
+
const devDeps = pkg["devDependencies"] ??= {};
|
|
137
|
+
devDeps["@types/bcrypt"] = "^6.0.0";
|
|
138
|
+
devDeps["@types/jsonwebtoken"] = "^9.0.10";
|
|
139
|
+
}
|
|
109
140
|
if (opts.packageManager !== "yarn") {
|
|
110
141
|
delete pkg.packageManager;
|
|
111
142
|
} else {
|
|
@@ -228,326 +259,75 @@ async function stripTsconfigPath(targetDir, alias) {
|
|
|
228
259
|
} catch {
|
|
229
260
|
}
|
|
230
261
|
}
|
|
231
|
-
async function
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
"
|
|
236
|
-
"Dockerfile.ms-jobs"
|
|
237
|
-
];
|
|
238
|
-
for (const p2 of paths) {
|
|
239
|
-
await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, p2), { recursive: true, force: true });
|
|
240
|
-
}
|
|
241
|
-
const appModulePath = (0, import_node_path2.join)(targetDir, "apps/api/src/app/app.module.ts");
|
|
242
|
-
try {
|
|
243
|
-
const appModule = await (0, import_promises2.readFile)(appModulePath, "utf8");
|
|
244
|
-
const next = appModule.replace(/^import \{ AdminModule \} from '\.\/admin\/admin\.module';\n/m, "").replace(/,\s*AdminModule/g, "");
|
|
245
|
-
await (0, import_promises2.writeFile)(appModulePath, next);
|
|
246
|
-
} catch {
|
|
247
|
-
}
|
|
248
|
-
await stripDeps((0, import_node_path2.join)(targetDir, "apps/api/package.json"), [
|
|
249
|
-
"@icore/jobs-client",
|
|
250
|
-
"@bull-board/api",
|
|
251
|
-
"@bull-board/express"
|
|
262
|
+
async function removeFirebaseAdminLib(targetDir) {
|
|
263
|
+
await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "libs/firebase-admin"), { recursive: true, force: true });
|
|
264
|
+
await stripTsconfigPath(targetDir, "@icore/firebase-admin");
|
|
265
|
+
await stripDeps((0, import_node_path2.join)(targetDir, "apps/microservices/auth/package.json"), [
|
|
266
|
+
"@icore/firebase-admin"
|
|
252
267
|
]);
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
} catch {
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
async function removePaymentStack(targetDir) {
|
|
262
|
-
const paths = [
|
|
263
|
-
"apps/microservices/payment",
|
|
264
|
-
"apps/microservices/payment-e2e",
|
|
265
|
-
"libs/payment-client",
|
|
266
|
-
"apps/api/src/app/payment"
|
|
267
|
-
];
|
|
268
|
-
for (const p2 of paths) {
|
|
269
|
-
await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, p2), { recursive: true, force: true });
|
|
270
|
-
}
|
|
271
|
-
const appModulePath = (0, import_node_path2.join)(targetDir, "apps/api/src/app/app.module.ts");
|
|
272
|
-
try {
|
|
273
|
-
const appModule = await (0, import_promises2.readFile)(appModulePath, "utf8");
|
|
274
|
-
const next = appModule.replace(/^import \{ PaymentModule \} from '\.\/payment\/payment\.module';\n/m, "").replace(/,\s*PaymentModule/g, "");
|
|
275
|
-
await (0, import_promises2.writeFile)(appModulePath, next);
|
|
276
|
-
} catch {
|
|
277
|
-
}
|
|
278
|
-
await stripDeps((0, import_node_path2.join)(targetDir, "apps/api/package.json"), [
|
|
279
|
-
"@icore/payment-client",
|
|
280
|
-
"@idevconn/payment"
|
|
268
|
+
await stripDeps((0, import_node_path2.join)(targetDir, "apps/microservices/upload/package.json"), [
|
|
269
|
+
"@icore/firebase-admin"
|
|
270
|
+
]);
|
|
271
|
+
await stripDeps((0, import_node_path2.join)(targetDir, "apps/microservices/notes/package.json"), [
|
|
272
|
+
"@icore/firebase-admin"
|
|
281
273
|
]);
|
|
282
|
-
await stripGatewayTransport(targetDir, "PAYMENT");
|
|
283
|
-
const mainTsPath = (0, import_node_path2.join)(targetDir, "apps/api/src/main.ts");
|
|
284
|
-
try {
|
|
285
|
-
const src = await (0, import_promises2.readFile)(mainTsPath, "utf8");
|
|
286
|
-
const next = src.replace(/\n\s*\{ name: 'payment', prefix: 'PAYMENT' \},/, "");
|
|
287
|
-
await (0, import_promises2.writeFile)(mainTsPath, next);
|
|
288
|
-
} catch {
|
|
289
|
-
}
|
|
290
274
|
}
|
|
291
|
-
async function
|
|
292
|
-
|
|
293
|
-
"apps/microservices/
|
|
294
|
-
"
|
|
295
|
-
"libs/
|
|
296
|
-
"
|
|
297
|
-
"apps/
|
|
298
|
-
|
|
275
|
+
async function removeAuthStack(targetDir) {
|
|
276
|
+
const rmPaths = [
|
|
277
|
+
"apps/microservices/auth",
|
|
278
|
+
"libs/auth-strategies",
|
|
279
|
+
"libs/auth-client",
|
|
280
|
+
"Dockerfile.ms-auth",
|
|
281
|
+
"apps/api/src/app/auth",
|
|
282
|
+
"apps/api/src/app/profile",
|
|
283
|
+
"apps/api/src/app/abilities",
|
|
284
|
+
"apps/client/src/components/auth",
|
|
285
|
+
"apps/client/src/routes/login.tsx",
|
|
286
|
+
"apps/client/src/routes/auth.callback.tsx",
|
|
287
|
+
"apps/client/src/routes/auth.oauth.callback.tsx",
|
|
288
|
+
"apps/client/src/routes/_dashboard/profile.tsx"
|
|
289
|
+
];
|
|
290
|
+
for (const p2 of rmPaths) {
|
|
299
291
|
await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, p2), { recursive: true, force: true });
|
|
300
292
|
}
|
|
301
|
-
await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "apps/client/src/routes/_dashboard/notes.tsx"), { force: true });
|
|
302
|
-
await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "apps/client/src/queries/notes.ts"), { force: true });
|
|
303
293
|
const appModulePath = (0, import_node_path2.join)(targetDir, "apps/api/src/app/app.module.ts");
|
|
304
294
|
try {
|
|
305
295
|
const src = await (0, import_promises2.readFile)(appModulePath, "utf8");
|
|
306
|
-
const next = src.replace(/^import \{
|
|
296
|
+
const next = src.replace(/^import \{ AuthModule \} from '\.\/auth\/auth\.module';\n/m, "").replace(/^import \{ ProfileModule \} from '\.\/profile\/profile\.module';\n/m, "").replace(/^import \{ AbilitiesModule \} from '\.\/abilities\/abilities\.module';\n/m, "").replace(/\bAuthModule,\s*/g, "").replace(/,\s*AuthModule\b/g, "").replace(/\bProfileModule,\s*/g, "").replace(/,\s*ProfileModule\b/g, "").replace(/\bAbilitiesModule,\s*/g, "").replace(/,\s*AbilitiesModule\b/g, "");
|
|
307
297
|
await (0, import_promises2.writeFile)(appModulePath, next);
|
|
308
298
|
} catch {
|
|
309
299
|
}
|
|
310
|
-
|
|
311
|
-
"@icore/notes-client",
|
|
312
|
-
"@casl/ability"
|
|
313
|
-
]);
|
|
314
|
-
await stripGatewayTransport(targetDir, "NOTES");
|
|
315
|
-
const mainTsPath = (0, import_node_path2.join)(targetDir, "apps/api/src/main.ts");
|
|
300
|
+
const dashboardPath = (0, import_node_path2.join)(targetDir, "apps/client/src/routes/_dashboard.tsx");
|
|
316
301
|
try {
|
|
317
|
-
const src = await (0, import_promises2.readFile)(
|
|
318
|
-
const next = src.replace(
|
|
319
|
-
await (0, import_promises2.writeFile)(
|
|
302
|
+
const src = await (0, import_promises2.readFile)(dashboardPath, "utf8");
|
|
303
|
+
const next = src.replace(/^import \{ useAuthStore \} from '@icore\/template-shared';\n/m, "").replace(/, redirect/g, "").replace(/\n {2}beforeLoad: \(\) => \{[\s\S]*?\n {2}\},/m, "");
|
|
304
|
+
await (0, import_promises2.writeFile)(dashboardPath, next);
|
|
320
305
|
} catch {
|
|
321
306
|
}
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
const siderPath = (0, import_node_path2.join)(targetDir, "apps/client/src/components/layout/LayoutSider.tsx");
|
|
330
|
-
try {
|
|
331
|
-
const src = await (0, import_promises2.readFile)(siderPath, "utf8");
|
|
332
|
-
const next = src.replace(", StickyNote", "").replace(/\n {8}<Link\n {10}to="\/(?:_dashboard\/)?notes"[\s\S]*?<\/Link>/, "").replace(", FileTextOutlined", "").replace(
|
|
333
|
-
"const selectedKey = pathname.includes('/notes')\n ? 'notes'\n : pathname.includes('/profile')",
|
|
334
|
-
"const selectedKey = pathname.includes('/profile')"
|
|
335
|
-
).replace(
|
|
336
|
-
/\n {4}\{\n {6}key: 'notes',\n {6}icon: <FileTextOutlined \/>,\n {6}label: <Link to="\/(?:_dashboard\/)?notes">\{t\('notes\.title'\)\}<\/Link>,\n {4}\},/,
|
|
337
|
-
""
|
|
338
|
-
).replace("import NoteOutlinedIcon from '@mui/icons-material/NoteOutlined';\n", "").replace(
|
|
339
|
-
/\n {8}<ListItemButton\n {10}component=\{Link\}\n {10}to="\/(?:_dashboard\/)?notes"[\s\S]*?<\/ListItemButton>/,
|
|
340
|
-
""
|
|
341
|
-
).replace(/\n\s*<Link to="\/(?:_dashboard\/)?notes">[\s\S]*?<\/Link>/m, "");
|
|
342
|
-
await (0, import_promises2.writeFile)(siderPath, next);
|
|
343
|
-
} catch {
|
|
307
|
+
for (const alias of [
|
|
308
|
+
"@icore/auth-client",
|
|
309
|
+
"@icore/auth-supabase",
|
|
310
|
+
"@icore/auth-firebase",
|
|
311
|
+
"@icore/auth-mongodb"
|
|
312
|
+
]) {
|
|
313
|
+
await stripTsconfigPath(targetDir, alias);
|
|
344
314
|
}
|
|
345
|
-
|
|
315
|
+
await stripDeps((0, import_node_path2.join)(targetDir, "apps/api/package.json"), ["@icore/auth-client"]);
|
|
316
|
+
const gatewayEnv = (0, import_node_path2.join)(targetDir, "apps/api/.env");
|
|
346
317
|
try {
|
|
347
|
-
const
|
|
348
|
-
const next =
|
|
349
|
-
await (0, import_promises2.writeFile)(
|
|
318
|
+
const env = await (0, import_promises2.readFile)(gatewayEnv, "utf8");
|
|
319
|
+
const next = env.split("\n").filter((line) => !line.startsWith("AUTH_") && !line.startsWith("# AUTH_")).join("\n");
|
|
320
|
+
await (0, import_promises2.writeFile)(gatewayEnv, next);
|
|
350
321
|
} catch {
|
|
351
322
|
}
|
|
352
|
-
|
|
353
|
-
async function removeUnusedAuthStrategies(targetDir, authProvider) {
|
|
354
|
-
const modulePath = (0, import_node_path2.join)(targetDir, "apps/microservices/auth/src/app/app.module.ts");
|
|
355
|
-
const AUTH_BRANCH = /if \(provider === 'supabase'\) return makeSupabaseAuth\(cfg\);\n\s*if \(provider === 'mongodb'\) return makeMongoDbAuth\(connection, cfg\);\n\s*return makeFirebaseAuth\(cfg\);/m;
|
|
356
|
-
if (authProvider === "supabase") {
|
|
357
|
-
await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "libs/auth-strategies/firebase"), { recursive: true, force: true });
|
|
358
|
-
await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "libs/auth-strategies/mongodb"), { recursive: true, force: true });
|
|
359
|
-
await stripDeps((0, import_node_path2.join)(targetDir, "apps/microservices/auth/package.json"), [
|
|
360
|
-
"@icore/auth-firebase",
|
|
361
|
-
"@icore/firebase-admin",
|
|
362
|
-
"@icore/auth-mongodb"
|
|
363
|
-
]);
|
|
364
|
-
await stripTsconfigPath(targetDir, "@icore/auth-firebase");
|
|
365
|
-
await stripTsconfigPath(targetDir, "@icore/auth-mongodb");
|
|
366
|
-
try {
|
|
367
|
-
const src = await (0, import_promises2.readFile)(modulePath, "utf8");
|
|
368
|
-
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(
|
|
369
|
-
/^import \{ MongooseModule, getConnectionToken \} from '@nestjs\/mongoose';\n/gm,
|
|
370
|
-
""
|
|
371
|
-
).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\(\)/, "");
|
|
372
|
-
await (0, import_promises2.writeFile)(modulePath, next);
|
|
373
|
-
} catch {
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
if (authProvider === "firebase") {
|
|
377
|
-
await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "libs/auth-strategies/supabase"), { recursive: true, force: true });
|
|
378
|
-
await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "libs/auth-strategies/mongodb"), { recursive: true, force: true });
|
|
379
|
-
await stripDeps((0, import_node_path2.join)(targetDir, "apps/microservices/auth/package.json"), [
|
|
380
|
-
"@icore/auth-supabase",
|
|
381
|
-
"@icore/auth-mongodb"
|
|
382
|
-
]);
|
|
383
|
-
await stripTsconfigPath(targetDir, "@icore/auth-supabase");
|
|
384
|
-
await stripTsconfigPath(targetDir, "@icore/auth-mongodb");
|
|
385
|
-
try {
|
|
386
|
-
const src = await (0, import_promises2.readFile)(modulePath, "utf8");
|
|
387
|
-
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(
|
|
388
|
-
/^import \{ MongooseModule, getConnectionToken \} from '@nestjs\/mongoose';\n/gm,
|
|
389
|
-
""
|
|
390
|
-
).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\(\)/, "");
|
|
391
|
-
await (0, import_promises2.writeFile)(modulePath, next);
|
|
392
|
-
} catch {
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
if (authProvider === "mongodb") {
|
|
396
|
-
await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "libs/auth-strategies/supabase"), { recursive: true, force: true });
|
|
397
|
-
await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "libs/auth-strategies/firebase"), { recursive: true, force: true });
|
|
398
|
-
await stripDeps((0, import_node_path2.join)(targetDir, "apps/microservices/auth/package.json"), [
|
|
399
|
-
"@icore/auth-supabase",
|
|
400
|
-
"@icore/auth-firebase",
|
|
401
|
-
"@icore/firebase-admin"
|
|
402
|
-
]);
|
|
403
|
-
await stripTsconfigPath(targetDir, "@icore/auth-supabase");
|
|
404
|
-
await stripTsconfigPath(targetDir, "@icore/auth-firebase");
|
|
405
|
-
try {
|
|
406
|
-
const src = await (0, import_promises2.readFile)(modulePath, "utf8");
|
|
407
|
-
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);");
|
|
408
|
-
await (0, import_promises2.writeFile)(modulePath, next);
|
|
409
|
-
} catch {
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
async function removeUnusedStorageStrategies(targetDir, uploadProvider) {
|
|
414
|
-
if (uploadProvider === "none") return;
|
|
415
|
-
const modulePath = (0, import_node_path2.join)(targetDir, "apps/microservices/upload/src/app/app.module.ts");
|
|
416
|
-
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;
|
|
417
|
-
if (uploadProvider !== "firebase") {
|
|
418
|
-
await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "libs/storage-strategies/firebase"), { recursive: true, force: true });
|
|
419
|
-
await stripDeps((0, import_node_path2.join)(targetDir, "apps/microservices/upload/package.json"), [
|
|
420
|
-
"@icore/storage-firebase",
|
|
421
|
-
"@icore/firebase-admin"
|
|
422
|
-
]);
|
|
423
|
-
await stripTsconfigPath(targetDir, "@icore/storage-firebase");
|
|
424
|
-
}
|
|
425
|
-
if (uploadProvider !== "cloudinary") {
|
|
426
|
-
await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "libs/storage-strategies/cloudinary"), {
|
|
427
|
-
recursive: true,
|
|
428
|
-
force: true
|
|
429
|
-
});
|
|
430
|
-
await stripDeps((0, import_node_path2.join)(targetDir, "apps/microservices/upload/package.json"), [
|
|
431
|
-
"@icore/storage-cloudinary"
|
|
432
|
-
]);
|
|
433
|
-
await stripTsconfigPath(targetDir, "@icore/storage-cloudinary");
|
|
434
|
-
}
|
|
435
|
-
if (uploadProvider !== "supabase") {
|
|
436
|
-
await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "libs/storage-strategies/supabase"), { recursive: true, force: true });
|
|
437
|
-
await stripDeps((0, import_node_path2.join)(targetDir, "apps/microservices/upload/package.json"), [
|
|
438
|
-
"@icore/storage-supabase"
|
|
439
|
-
]);
|
|
440
|
-
await stripTsconfigPath(targetDir, "@icore/storage-supabase");
|
|
441
|
-
}
|
|
442
|
-
if (uploadProvider !== "mongodb") {
|
|
443
|
-
await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "libs/storage-strategies/mongodb"), { recursive: true, force: true });
|
|
444
|
-
await stripDeps((0, import_node_path2.join)(targetDir, "apps/microservices/upload/package.json"), [
|
|
445
|
-
"@icore/storage-mongodb"
|
|
446
|
-
]);
|
|
447
|
-
await stripTsconfigPath(targetDir, "@icore/storage-mongodb");
|
|
448
|
-
}
|
|
323
|
+
const composePath = (0, import_node_path2.join)(targetDir, "docker-compose.yml");
|
|
449
324
|
try {
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
/^import \{[^}]*FirebaseStorageStrategy[^}]*\} from '@icore\/storage-firebase';\n/gm,
|
|
454
|
-
""
|
|
455
|
-
).replace(/^ {2}firebase: \[[^\]]*\],\n/gm, "").replace(/\nfunction makeFirebaseStorage[\s\S]*?\n}\n/gm, "");
|
|
456
|
-
}
|
|
457
|
-
if (uploadProvider !== "cloudinary") {
|
|
458
|
-
src = src.replace(/^import \{ v2 as cloudinary \} from 'cloudinary';\n/gm, "").replace(
|
|
459
|
-
/^import \{[^}]*CloudinaryStorageStrategy[^}]*\} from '@icore\/storage-cloudinary';\n/gm,
|
|
460
|
-
""
|
|
461
|
-
).replace(/\nfunction makeCloudinaryStorage[\s\S]*?\n}\n/gm, "");
|
|
462
|
-
}
|
|
463
|
-
if (uploadProvider !== "supabase") {
|
|
464
|
-
src = src.replace(/^import \{ createClient \} from '@supabase\/supabase-js';\n/gm, "").replace(
|
|
465
|
-
/^import \{[^}]*SupabaseStorageStrategy[^}]*\} from '@icore\/storage-supabase';\n/gm,
|
|
466
|
-
""
|
|
467
|
-
).replace(/\nfunction makeSupabaseStorage[\s\S]*?\n}\n/gm, "");
|
|
468
|
-
}
|
|
469
|
-
if (uploadProvider !== "mongodb") {
|
|
470
|
-
src = src.replace(
|
|
471
|
-
/^import \{[^}]*MongoDbStorageStrategy[^}]*\} from '@icore\/storage-mongodb';\n/gm,
|
|
472
|
-
""
|
|
473
|
-
).replace(
|
|
474
|
-
/^import \{ MongooseModule, getConnectionToken \} from '@nestjs\/mongoose';\n/gm,
|
|
475
|
-
""
|
|
476
|
-
).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, "");
|
|
477
|
-
}
|
|
478
|
-
const chosenReturn = uploadProvider === "mongodb" ? `return makeMongoDbStorage(connection);` : `return make${uploadProvider.charAt(0).toUpperCase() + uploadProvider.slice(1)}Storage(cfg);`;
|
|
479
|
-
src = src.replace(STORAGE_BRANCH, chosenReturn);
|
|
480
|
-
if (uploadProvider !== "mongodb") {
|
|
481
|
-
src = src.replace(/, connection: Connection/, "").replace(/, getConnectionToken\(\)/, "");
|
|
482
|
-
}
|
|
483
|
-
await (0, import_promises2.writeFile)(modulePath, src);
|
|
325
|
+
const compose = await (0, import_promises2.readFile)(composePath, "utf8");
|
|
326
|
+
const next = compose.replace(/\n {2}auth:[\s\S]+?(?=\n {2}\w|\nnetworks:)/m, "\n").replace(/\n {6}auth:\n {8}condition: service_started/g, "").replace(/\n {6}AUTH_TRANSPORT:[^\n]*/g, "").replace(/\n {6}AUTH_REDIS_URL:[^\n]*/g, "");
|
|
327
|
+
await (0, import_promises2.writeFile)(composePath, next);
|
|
484
328
|
} catch {
|
|
485
329
|
}
|
|
486
330
|
}
|
|
487
|
-
async function removeUnusedDbStrategies(targetDir, dbProvider) {
|
|
488
|
-
const modulePath = (0, import_node_path2.join)(targetDir, "apps/microservices/notes/src/app/app.module.ts");
|
|
489
|
-
const DB_BRANCH = /if \(provider === 'supabase'\) return makeSupabaseDB\(cfg\);\n\s*if \(provider === 'mongodb'\) return makeMongoDb\(connection\);\n\s*return makeFirestoreDB\(cfg\);/m;
|
|
490
|
-
if (dbProvider === "supabase") {
|
|
491
|
-
await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "libs/db-strategies/firestore"), { recursive: true, force: true });
|
|
492
|
-
await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "libs/db-strategies/mongodb"), { recursive: true, force: true });
|
|
493
|
-
await stripDeps((0, import_node_path2.join)(targetDir, "apps/microservices/notes/package.json"), [
|
|
494
|
-
"@icore/db-firestore",
|
|
495
|
-
"@icore/firebase-admin",
|
|
496
|
-
"@icore/db-mongodb"
|
|
497
|
-
]);
|
|
498
|
-
await stripTsconfigPath(targetDir, "@icore/db-firestore");
|
|
499
|
-
await stripTsconfigPath(targetDir, "@icore/db-mongodb");
|
|
500
|
-
try {
|
|
501
|
-
const src = await (0, import_promises2.readFile)(modulePath, "utf8");
|
|
502
|
-
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(
|
|
503
|
-
/^import \{ MongooseModule, getConnectionToken \} from '@nestjs\/mongoose';\n/gm,
|
|
504
|
-
""
|
|
505
|
-
).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\(\)/, "");
|
|
506
|
-
await (0, import_promises2.writeFile)(modulePath, next);
|
|
507
|
-
} catch {
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
if (dbProvider === "firebase") {
|
|
511
|
-
await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "libs/db-strategies/supabase"), { recursive: true, force: true });
|
|
512
|
-
await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "libs/db-strategies/mongodb"), { recursive: true, force: true });
|
|
513
|
-
await stripDeps((0, import_node_path2.join)(targetDir, "apps/microservices/notes/package.json"), [
|
|
514
|
-
"@icore/db-supabase",
|
|
515
|
-
"@icore/db-mongodb"
|
|
516
|
-
]);
|
|
517
|
-
await stripTsconfigPath(targetDir, "@icore/db-supabase");
|
|
518
|
-
await stripTsconfigPath(targetDir, "@icore/db-mongodb");
|
|
519
|
-
try {
|
|
520
|
-
const src = await (0, import_promises2.readFile)(modulePath, "utf8");
|
|
521
|
-
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(
|
|
522
|
-
/^import \{ MongooseModule, getConnectionToken \} from '@nestjs\/mongoose';\n/gm,
|
|
523
|
-
""
|
|
524
|
-
).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\(\)/, "");
|
|
525
|
-
await (0, import_promises2.writeFile)(modulePath, next);
|
|
526
|
-
} catch {
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
if (dbProvider === "mongodb") {
|
|
530
|
-
await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "libs/db-strategies/supabase"), { recursive: true, force: true });
|
|
531
|
-
await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "libs/db-strategies/firestore"), { recursive: true, force: true });
|
|
532
|
-
await stripDeps((0, import_node_path2.join)(targetDir, "apps/microservices/notes/package.json"), [
|
|
533
|
-
"@icore/db-supabase",
|
|
534
|
-
"@icore/db-firestore",
|
|
535
|
-
"@icore/firebase-admin"
|
|
536
|
-
]);
|
|
537
|
-
await stripTsconfigPath(targetDir, "@icore/db-supabase");
|
|
538
|
-
await stripTsconfigPath(targetDir, "@icore/db-firestore");
|
|
539
|
-
try {
|
|
540
|
-
const src = await (0, import_promises2.readFile)(modulePath, "utf8");
|
|
541
|
-
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);");
|
|
542
|
-
await (0, import_promises2.writeFile)(modulePath, next);
|
|
543
|
-
} catch {
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
async function removeFirebaseAdminLib(targetDir) {
|
|
548
|
-
await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "libs/firebase-admin"), { recursive: true, force: true });
|
|
549
|
-
await stripTsconfigPath(targetDir, "@icore/firebase-admin");
|
|
550
|
-
}
|
|
551
331
|
async function removeUploadStack(targetDir) {
|
|
552
332
|
const paths = [
|
|
553
333
|
"apps/microservices/upload",
|
|
@@ -581,12 +361,443 @@ async function removeUploadStack(targetDir) {
|
|
|
581
361
|
]);
|
|
582
362
|
}
|
|
583
363
|
|
|
584
|
-
// src/
|
|
364
|
+
// src/manifest/wire-features.ts
|
|
365
|
+
var import_promises4 = require("fs/promises");
|
|
366
|
+
var import_node_path4 = require("path");
|
|
367
|
+
|
|
368
|
+
// src/manifest/index.ts
|
|
369
|
+
var EMPTY = { libDirs: [], deps: {}, tsPaths: {} };
|
|
370
|
+
var MANIFEST = {
|
|
371
|
+
auth: {
|
|
372
|
+
supabase: {
|
|
373
|
+
libDirs: ["libs/auth-strategies/supabase"],
|
|
374
|
+
deps: { "@supabase/supabase-js": "^2.106.2" },
|
|
375
|
+
tsPaths: { "@icore/auth-supabase": ["libs/auth-strategies/supabase/src/index.ts"] },
|
|
376
|
+
nestModule: {
|
|
377
|
+
importFrom: "@icore/auth-supabase",
|
|
378
|
+
symbol: "SupabaseAuthModule",
|
|
379
|
+
into: "auth"
|
|
380
|
+
},
|
|
381
|
+
appTests: [
|
|
382
|
+
"apps/microservices/auth/src/app/__tests__/auth.controller.supabase.integration.unit.test.ts"
|
|
383
|
+
]
|
|
384
|
+
},
|
|
385
|
+
firebase: {
|
|
386
|
+
libDirs: ["libs/auth-strategies/firebase"],
|
|
387
|
+
deps: {},
|
|
388
|
+
tsPaths: { "@icore/auth-firebase": ["libs/auth-strategies/firebase/src/index.ts"] },
|
|
389
|
+
nestModule: {
|
|
390
|
+
importFrom: "@icore/auth-firebase",
|
|
391
|
+
symbol: "FirebaseAuthModule",
|
|
392
|
+
into: "auth"
|
|
393
|
+
},
|
|
394
|
+
appTests: [
|
|
395
|
+
"apps/microservices/auth/src/app/__tests__/auth.controller.firebase.integration.unit.test.ts"
|
|
396
|
+
]
|
|
397
|
+
},
|
|
398
|
+
mongodb: {
|
|
399
|
+
libDirs: ["libs/auth-strategies/mongodb"],
|
|
400
|
+
deps: { mongoose: "^9.6.3" },
|
|
401
|
+
tsPaths: { "@icore/auth-mongodb": ["libs/auth-strategies/mongodb/src/index.ts"] },
|
|
402
|
+
nestModule: { importFrom: "@icore/auth-mongodb", symbol: "MongoDbAuthModule", into: "auth" }
|
|
403
|
+
}
|
|
404
|
+
},
|
|
405
|
+
storage: {
|
|
406
|
+
supabase: {
|
|
407
|
+
libDirs: ["libs/storage-strategies/supabase"],
|
|
408
|
+
deps: { "@supabase/supabase-js": "^2.106.2" },
|
|
409
|
+
tsPaths: { "@icore/storage-supabase": ["libs/storage-strategies/supabase/src/index.ts"] },
|
|
410
|
+
nestModule: {
|
|
411
|
+
importFrom: "@icore/storage-supabase",
|
|
412
|
+
symbol: "SupabaseStorageModule",
|
|
413
|
+
into: "upload"
|
|
414
|
+
}
|
|
415
|
+
},
|
|
416
|
+
firebase: {
|
|
417
|
+
libDirs: ["libs/storage-strategies/firebase"],
|
|
418
|
+
deps: {},
|
|
419
|
+
tsPaths: { "@icore/storage-firebase": ["libs/storage-strategies/firebase/src/index.ts"] },
|
|
420
|
+
nestModule: {
|
|
421
|
+
importFrom: "@icore/storage-firebase",
|
|
422
|
+
symbol: "FirebaseStorageModule",
|
|
423
|
+
into: "upload"
|
|
424
|
+
}
|
|
425
|
+
},
|
|
426
|
+
cloudinary: {
|
|
427
|
+
libDirs: ["libs/storage-strategies/cloudinary"],
|
|
428
|
+
deps: { cloudinary: "^2.10.0" },
|
|
429
|
+
tsPaths: { "@icore/storage-cloudinary": ["libs/storage-strategies/cloudinary/src/index.ts"] },
|
|
430
|
+
nestModule: {
|
|
431
|
+
importFrom: "@icore/storage-cloudinary",
|
|
432
|
+
symbol: "CloudinaryStorageModule",
|
|
433
|
+
into: "upload"
|
|
434
|
+
}
|
|
435
|
+
},
|
|
436
|
+
mongodb: {
|
|
437
|
+
libDirs: ["libs/storage-strategies/mongodb"],
|
|
438
|
+
deps: { mongoose: "^9.6.3" },
|
|
439
|
+
tsPaths: { "@icore/storage-mongodb": ["libs/storage-strategies/mongodb/src/index.ts"] },
|
|
440
|
+
nestModule: {
|
|
441
|
+
importFrom: "@icore/storage-mongodb",
|
|
442
|
+
symbol: "MongoDbStorageModule",
|
|
443
|
+
into: "upload"
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
},
|
|
447
|
+
db: {
|
|
448
|
+
supabase: {
|
|
449
|
+
libDirs: ["libs/db-strategies/supabase"],
|
|
450
|
+
deps: { "@supabase/supabase-js": "^2.106.2" },
|
|
451
|
+
tsPaths: { "@icore/db-supabase": ["libs/db-strategies/supabase/src/index.ts"] },
|
|
452
|
+
nestModule: { importFrom: "@icore/db-supabase", symbol: "SupabaseDbModule", into: "notes" }
|
|
453
|
+
},
|
|
454
|
+
firebase: {
|
|
455
|
+
libDirs: ["libs/db-strategies/firestore"],
|
|
456
|
+
deps: {},
|
|
457
|
+
tsPaths: { "@icore/db-firestore": ["libs/db-strategies/firestore/src/index.ts"] },
|
|
458
|
+
nestModule: { importFrom: "@icore/db-firestore", symbol: "FirestoreDbModule", into: "notes" }
|
|
459
|
+
},
|
|
460
|
+
mongodb: {
|
|
461
|
+
libDirs: ["libs/db-strategies/mongodb"],
|
|
462
|
+
deps: { mongoose: "^9.6.3" },
|
|
463
|
+
tsPaths: { "@icore/db-mongodb": ["libs/db-strategies/mongodb/src/index.ts"] },
|
|
464
|
+
nestModule: { importFrom: "@icore/db-mongodb", symbol: "MongoDbDbModule", into: "notes" }
|
|
465
|
+
}
|
|
466
|
+
},
|
|
467
|
+
feature: {
|
|
468
|
+
notes: {
|
|
469
|
+
libDirs: [
|
|
470
|
+
"apps/microservices/notes",
|
|
471
|
+
"apps/microservices/notes-e2e",
|
|
472
|
+
"libs/notes-client",
|
|
473
|
+
"libs/db-strategies",
|
|
474
|
+
"apps/api/src/app/notes",
|
|
475
|
+
"apps/client/src/components/notes",
|
|
476
|
+
"apps/client/src/routes/_dashboard/notes.tsx",
|
|
477
|
+
"apps/client/src/queries/notes.ts"
|
|
478
|
+
],
|
|
479
|
+
deps: { "@icore/notes-client": "*", "@casl/ability": "^7.0.0" },
|
|
480
|
+
tsPaths: { "@icore/notes-client": ["libs/notes-client/src/index.ts"] },
|
|
481
|
+
gatewayModule: { importFrom: "./notes/notes.module", symbol: "NotesModule" },
|
|
482
|
+
gatewayService: { name: "notes", prefix: "NOTES" },
|
|
483
|
+
clientNav: { route: "/notes", labelKey: "nav.notes", iconName: "notes" }
|
|
484
|
+
},
|
|
485
|
+
payment: {
|
|
486
|
+
libDirs: [
|
|
487
|
+
"apps/microservices/payment",
|
|
488
|
+
"apps/microservices/payment-e2e",
|
|
489
|
+
"libs/payment-client",
|
|
490
|
+
"apps/api/src/app/payment"
|
|
491
|
+
],
|
|
492
|
+
deps: { "@icore/payment-client": "*", "@idevconn/payment": "^1.2.0" },
|
|
493
|
+
tsPaths: { "@icore/payment-client": ["libs/payment-client/src/index.ts"] },
|
|
494
|
+
gatewayModule: { importFrom: "./payment/payment.module", symbol: "PaymentModule" },
|
|
495
|
+
gatewayService: { name: "payment", prefix: "PAYMENT" }
|
|
496
|
+
},
|
|
497
|
+
jobs: {
|
|
498
|
+
libDirs: [
|
|
499
|
+
"apps/microservices/jobs",
|
|
500
|
+
"libs/jobs-client",
|
|
501
|
+
"apps/api/src/app/admin",
|
|
502
|
+
"Dockerfile.ms-jobs"
|
|
503
|
+
],
|
|
504
|
+
deps: {
|
|
505
|
+
"@icore/jobs-client": "*",
|
|
506
|
+
"@bull-board/api": "^7.1.5",
|
|
507
|
+
"@bull-board/express": "^7.1.5"
|
|
508
|
+
},
|
|
509
|
+
tsPaths: { "@icore/jobs-client": ["libs/jobs-client/src/index.ts"] },
|
|
510
|
+
gatewayModule: { importFrom: "./admin/admin.module", symbol: "AdminModule" },
|
|
511
|
+
dockerService: "jobs"
|
|
512
|
+
}
|
|
513
|
+
},
|
|
514
|
+
ui: { shadcn: EMPTY, antd: EMPTY, mui: EMPTY },
|
|
515
|
+
transport: { tcp: EMPTY, redis: EMPTY, nats: EMPTY, mqtt: EMPTY, rmq: EMPTY, kafka: EMPTY },
|
|
516
|
+
shared: {
|
|
517
|
+
firebaseAdmin: {
|
|
518
|
+
libDirs: ["libs/firebase-admin"],
|
|
519
|
+
deps: { "firebase-admin": "^13.10.0" },
|
|
520
|
+
tsPaths: { "@icore/firebase-admin": ["libs/firebase-admin/src/index.ts"] }
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
|
|
525
|
+
// src/manifest/wire-provider.ts
|
|
585
526
|
var import_promises3 = require("fs/promises");
|
|
586
527
|
var import_node_path3 = require("path");
|
|
528
|
+
async function writeProvider(targetDir, axis, provider) {
|
|
529
|
+
const nestModule = axis.section[provider]?.nestModule;
|
|
530
|
+
if (!nestModule) throw new Error(`provider "${provider}" has no nestModule in the manifest`);
|
|
531
|
+
const { importFrom, symbol } = nestModule;
|
|
532
|
+
const content = `import { ${symbol} } from '${importFrom}';
|
|
533
|
+
|
|
534
|
+
const ENV_PATH = '${axis.envPath}';
|
|
535
|
+
|
|
536
|
+
export const ${axis.exportConst} = ${symbol}.forRoot(ENV_PATH);
|
|
537
|
+
`;
|
|
538
|
+
await (0, import_promises3.writeFile)((0, import_node_path3.join)(targetDir, axis.providerFile), content);
|
|
539
|
+
}
|
|
540
|
+
async function stripJsonKeys(path, drop) {
|
|
541
|
+
try {
|
|
542
|
+
const pkg = JSON.parse(await (0, import_promises3.readFile)(path, "utf8"));
|
|
543
|
+
for (const field of ["dependencies", "devDependencies"]) {
|
|
544
|
+
const deps = pkg[field];
|
|
545
|
+
if (!deps) continue;
|
|
546
|
+
for (const k of Object.keys(deps)) if (drop(k)) delete deps[k];
|
|
547
|
+
}
|
|
548
|
+
await (0, import_promises3.writeFile)(path, JSON.stringify(pkg, null, 2) + "\n");
|
|
549
|
+
} catch {
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
async function stripTsconfigKeys(targetDir, aliases) {
|
|
553
|
+
const path = (0, import_node_path3.join)(targetDir, "tsconfig.base.json");
|
|
554
|
+
try {
|
|
555
|
+
const parsed = JSON.parse(await (0, import_promises3.readFile)(path, "utf8"));
|
|
556
|
+
const paths = parsed.compilerOptions?.paths;
|
|
557
|
+
if (paths) for (const a of aliases) delete paths[a];
|
|
558
|
+
await (0, import_promises3.writeFile)(path, JSON.stringify(parsed, null, 2) + "\n");
|
|
559
|
+
} catch {
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
async function cleanupUnusedAxis(targetDir, axis, chosen) {
|
|
563
|
+
for (const provider of Object.keys(axis.section)) {
|
|
564
|
+
if (provider === chosen) continue;
|
|
565
|
+
const unit = axis.section[provider];
|
|
566
|
+
for (const dir of unit.libDirs)
|
|
567
|
+
await (0, import_promises3.rm)((0, import_node_path3.join)(targetDir, dir), { recursive: true, force: true });
|
|
568
|
+
for (const t of unit.appTests ?? []) await (0, import_promises3.rm)((0, import_node_path3.join)(targetDir, t), { force: true });
|
|
569
|
+
const dropKeys = /* @__PURE__ */ new Set([...Object.keys(unit.tsPaths), ...Object.keys(unit.deps)]);
|
|
570
|
+
await stripJsonKeys((0, import_node_path3.join)(targetDir, axis.msPackageJson), (k) => dropKeys.has(k));
|
|
571
|
+
await stripTsconfigKeys(targetDir, Object.keys(unit.tsPaths));
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// src/manifest/wire-features.ts
|
|
576
|
+
var FEATURES_MODULE = "apps/api/src/app/features.module.ts";
|
|
577
|
+
var GATEWAY_SERVICES = "apps/api/src/app/gateway-services.ts";
|
|
578
|
+
var API_PKG = "apps/api/package.json";
|
|
579
|
+
var FEATURES = MANIFEST.feature;
|
|
580
|
+
function selectedFeatures(opts) {
|
|
581
|
+
const out = [];
|
|
582
|
+
if (opts.example === "notes") out.push("notes");
|
|
583
|
+
if (opts.payment !== "none") out.push("payment");
|
|
584
|
+
if (opts.jobs !== "none") out.push("jobs");
|
|
585
|
+
return out;
|
|
586
|
+
}
|
|
587
|
+
async function writeFeaturesWiring(targetDir, opts) {
|
|
588
|
+
const chosen = selectedFeatures(opts);
|
|
589
|
+
const mods = chosen.map((k) => FEATURES[k].gatewayModule).filter((m) => !!m);
|
|
590
|
+
const imports = mods.map((m) => `import { ${m.symbol} } from '${m.importFrom}';`).join("\n");
|
|
591
|
+
const symbols = mods.map((m) => m.symbol).join(", ");
|
|
592
|
+
const featuresModule = `import { Module } from '@nestjs/common';
|
|
593
|
+
` + (imports ? imports + "\n" : "") + `
|
|
594
|
+
@Module({
|
|
595
|
+
imports: [${symbols}],
|
|
596
|
+
})
|
|
597
|
+
export class FeaturesModule {}
|
|
598
|
+
`;
|
|
599
|
+
await (0, import_promises4.writeFile)((0, import_node_path4.join)(targetDir, FEATURES_MODULE), featuresModule);
|
|
600
|
+
const services = [];
|
|
601
|
+
if (opts.authProvider !== "none") services.push({ name: "auth", prefix: "AUTH" });
|
|
602
|
+
if (opts.upload !== "none") services.push({ name: "upload", prefix: "UPLOAD" });
|
|
603
|
+
for (const k of chosen) {
|
|
604
|
+
const svc = FEATURES[k].gatewayService;
|
|
605
|
+
if (svc) services.push(svc);
|
|
606
|
+
}
|
|
607
|
+
const entries = services.map((s) => ` { name: '${s.name}', prefix: '${s.prefix}' },`).join("\n");
|
|
608
|
+
const gatewayServices = `/** Microservices the gateway proxies. Generated by create-icore. */
|
|
609
|
+
export const GATEWAY_SERVICES = [
|
|
610
|
+
${entries}
|
|
611
|
+
];
|
|
612
|
+
`;
|
|
613
|
+
await (0, import_promises4.writeFile)((0, import_node_path4.join)(targetDir, GATEWAY_SERVICES), gatewayServices);
|
|
614
|
+
}
|
|
615
|
+
async function stripJobsDockerCompose(targetDir) {
|
|
616
|
+
const composePath = (0, import_node_path4.join)(targetDir, "docker-compose.yml");
|
|
617
|
+
try {
|
|
618
|
+
const compose = await (0, import_promises4.readFile)(composePath, "utf8");
|
|
619
|
+
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, "");
|
|
620
|
+
await (0, import_promises4.writeFile)(composePath, next);
|
|
621
|
+
} catch {
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
async function cleanupUnusedFeatures(targetDir, opts) {
|
|
625
|
+
const chosen = new Set(selectedFeatures(opts));
|
|
626
|
+
for (const key of ["notes", "payment", "jobs"]) {
|
|
627
|
+
if (chosen.has(key)) continue;
|
|
628
|
+
const unit = FEATURES[key];
|
|
629
|
+
for (const dir of unit.libDirs)
|
|
630
|
+
await (0, import_promises4.rm)((0, import_node_path4.join)(targetDir, dir), { recursive: true, force: true });
|
|
631
|
+
const dropKeys = /* @__PURE__ */ new Set([...Object.keys(unit.tsPaths), ...Object.keys(unit.deps)]);
|
|
632
|
+
await stripJsonKeys((0, import_node_path4.join)(targetDir, API_PKG), (k) => dropKeys.has(k));
|
|
633
|
+
await stripTsconfigKeys(targetDir, Object.keys(unit.tsPaths));
|
|
634
|
+
if (unit.gatewayService) await stripGatewayTransport(targetDir, unit.gatewayService.prefix);
|
|
635
|
+
if (unit.dockerService === "jobs") await stripJobsDockerCompose(targetDir);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// src/manifest/wire-client.ts
|
|
640
|
+
var import_promises5 = require("fs/promises");
|
|
641
|
+
var import_node_path5 = require("path");
|
|
642
|
+
var NAV_CONFIG_FILE = "apps/client/src/nav.config.ts";
|
|
643
|
+
var BASE_NAV = [
|
|
644
|
+
{ to: "/dashboard", labelKey: "nav.dashboard", iconName: "dashboard", exact: true }
|
|
645
|
+
];
|
|
646
|
+
var PROFILE_NAV = { to: "/profile", labelKey: "nav.profile", iconName: "profile" };
|
|
647
|
+
function renderEntry(n) {
|
|
648
|
+
const parts = [`to: '${n.to}'`, `labelKey: '${n.labelKey}'`, `iconName: '${n.iconName}'`];
|
|
649
|
+
if (n.exact) parts.push("exact: true");
|
|
650
|
+
return ` { ${parts.join(", ")} },`;
|
|
651
|
+
}
|
|
652
|
+
async function writeNavConfig(targetDir, opts) {
|
|
653
|
+
const entries = [...BASE_NAV];
|
|
654
|
+
const notesNav = MANIFEST.feature.notes.clientNav;
|
|
655
|
+
if (opts.example === "notes" && notesNav) {
|
|
656
|
+
entries.push({
|
|
657
|
+
to: notesNav.route,
|
|
658
|
+
labelKey: notesNav.labelKey,
|
|
659
|
+
iconName: notesNav.iconName,
|
|
660
|
+
exact: notesNav.exact
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
entries.push(PROFILE_NAV);
|
|
664
|
+
const content = `/**
|
|
665
|
+
* Sidebar navigation. UI-agnostic: each LayoutSider maps \`iconName\` to its own
|
|
666
|
+
* icon library. Generated by create-icore.
|
|
667
|
+
*/
|
|
668
|
+
export interface NavItem {
|
|
669
|
+
to: string;
|
|
670
|
+
labelKey: string;
|
|
671
|
+
iconName: 'dashboard' | 'notes' | 'profile';
|
|
672
|
+
exact?: boolean;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
export const NAV_CONFIG: NavItem[] = [
|
|
676
|
+
` + entries.map(renderEntry).join("\n") + `
|
|
677
|
+
];
|
|
678
|
+
`;
|
|
679
|
+
await (0, import_promises5.writeFile)((0, import_node_path5.join)(targetDir, NAV_CONFIG_FILE), content);
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
// src/manifest/blueprint.ts
|
|
683
|
+
var import_promises6 = require("fs/promises");
|
|
684
|
+
var import_node_path6 = require("path");
|
|
685
|
+
async function writeBlueprintJson(targetDir, opts) {
|
|
686
|
+
const blueprint = {
|
|
687
|
+
schemaVersion: 1,
|
|
688
|
+
projectName: opts.projectName,
|
|
689
|
+
authProvider: opts.authProvider,
|
|
690
|
+
dbProvider: opts.dbProvider,
|
|
691
|
+
upload: opts.upload,
|
|
692
|
+
payment: opts.payment,
|
|
693
|
+
jobs: opts.jobs,
|
|
694
|
+
example: opts.example,
|
|
695
|
+
ui: opts.ui,
|
|
696
|
+
transport: opts.transport,
|
|
697
|
+
packageManager: opts.packageManager
|
|
698
|
+
};
|
|
699
|
+
await (0, import_promises6.writeFile)((0, import_node_path6.join)(targetDir, "blueprint.json"), JSON.stringify(blueprint, null, 2) + "\n");
|
|
700
|
+
}
|
|
701
|
+
async function writeJson(targetDir, rel, data) {
|
|
702
|
+
await (0, import_promises6.writeFile)((0, import_node_path6.join)(targetDir, rel, "blueprint.json"), JSON.stringify(data, null, 2) + "\n");
|
|
703
|
+
}
|
|
704
|
+
async function writeServiceBlueprints(targetDir, opts) {
|
|
705
|
+
const t = opts.transport;
|
|
706
|
+
if (opts.authProvider !== "none") {
|
|
707
|
+
await writeJson(targetDir, "apps/microservices/auth", {
|
|
708
|
+
schemaVersion: 1,
|
|
709
|
+
service: "auth",
|
|
710
|
+
authProvider: opts.authProvider,
|
|
711
|
+
transport: t
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
if (opts.upload !== "none") {
|
|
715
|
+
await writeJson(targetDir, "apps/microservices/upload", {
|
|
716
|
+
schemaVersion: 1,
|
|
717
|
+
service: "upload",
|
|
718
|
+
storageProvider: opts.upload,
|
|
719
|
+
transport: t
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
if (opts.example !== "none") {
|
|
723
|
+
await writeJson(targetDir, "apps/microservices/notes", {
|
|
724
|
+
schemaVersion: 1,
|
|
725
|
+
service: "notes",
|
|
726
|
+
dbProvider: opts.dbProvider,
|
|
727
|
+
transport: t
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
if (opts.payment !== "none") {
|
|
731
|
+
await writeJson(targetDir, "apps/microservices/payment", {
|
|
732
|
+
schemaVersion: 1,
|
|
733
|
+
service: "payment",
|
|
734
|
+
paymentProvider: opts.payment,
|
|
735
|
+
transport: t
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
if (opts.jobs !== "none") {
|
|
739
|
+
await writeJson(targetDir, "apps/microservices/jobs", {
|
|
740
|
+
schemaVersion: 1,
|
|
741
|
+
service: "jobs",
|
|
742
|
+
jobsProvider: opts.jobs
|
|
743
|
+
});
|
|
744
|
+
}
|
|
745
|
+
const features = [];
|
|
746
|
+
if (opts.example !== "none") features.push("notes");
|
|
747
|
+
if (opts.payment !== "none") features.push("payment");
|
|
748
|
+
if (opts.jobs !== "none") features.push("jobs");
|
|
749
|
+
await writeJson(targetDir, "apps/api", {
|
|
750
|
+
schemaVersion: 1,
|
|
751
|
+
service: "api",
|
|
752
|
+
features,
|
|
753
|
+
transport: t
|
|
754
|
+
});
|
|
755
|
+
await writeJson(targetDir, "apps/client", {
|
|
756
|
+
schemaVersion: 1,
|
|
757
|
+
service: "client",
|
|
758
|
+
ui: opts.ui
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
// src/manifest/wire-auth.ts
|
|
763
|
+
var AUTH = {
|
|
764
|
+
section: MANIFEST.auth,
|
|
765
|
+
providerFile: "apps/microservices/auth/src/app/auth.provider.ts",
|
|
766
|
+
exportConst: "AuthProviderModule",
|
|
767
|
+
msPackageJson: "apps/microservices/auth/package.json",
|
|
768
|
+
envPath: "apps/microservices/auth/.env"
|
|
769
|
+
};
|
|
770
|
+
var writeAuthProvider = (targetDir, provider) => writeProvider(targetDir, AUTH, provider);
|
|
771
|
+
var cleanupUnusedAuth = (targetDir, chosen) => cleanupUnusedAxis(targetDir, AUTH, chosen);
|
|
772
|
+
|
|
773
|
+
// src/manifest/wire-storage.ts
|
|
774
|
+
var STORAGE = {
|
|
775
|
+
section: MANIFEST.storage,
|
|
776
|
+
providerFile: "apps/microservices/upload/src/app/storage.provider.ts",
|
|
777
|
+
exportConst: "StorageProviderModule",
|
|
778
|
+
msPackageJson: "apps/microservices/upload/package.json",
|
|
779
|
+
envPath: "apps/microservices/upload/.env"
|
|
780
|
+
};
|
|
781
|
+
var writeStorageProvider = (targetDir, provider) => writeProvider(targetDir, STORAGE, provider);
|
|
782
|
+
var cleanupUnusedStorage = (targetDir, chosen) => cleanupUnusedAxis(targetDir, STORAGE, chosen);
|
|
783
|
+
|
|
784
|
+
// src/manifest/wire-db.ts
|
|
785
|
+
var DB = {
|
|
786
|
+
section: MANIFEST.db,
|
|
787
|
+
providerFile: "apps/microservices/notes/src/app/db.provider.ts",
|
|
788
|
+
exportConst: "DbProviderModule",
|
|
789
|
+
msPackageJson: "apps/microservices/notes/package.json",
|
|
790
|
+
envPath: "apps/microservices/notes/.env"
|
|
791
|
+
};
|
|
792
|
+
var writeDbProvider = (targetDir, provider) => writeProvider(targetDir, DB, provider);
|
|
793
|
+
var cleanupUnusedDb = (targetDir, chosen) => cleanupUnusedAxis(targetDir, DB, chosen);
|
|
794
|
+
|
|
795
|
+
// src/lib/scaffold-pkg.ts
|
|
796
|
+
var import_promises7 = require("fs/promises");
|
|
797
|
+
var import_node_path7 = require("path");
|
|
587
798
|
async function writePnpmWorkspace(targetDir) {
|
|
588
|
-
const pkgPath = (0,
|
|
589
|
-
const pkg = JSON.parse(await (0,
|
|
799
|
+
const pkgPath = (0, import_node_path7.join)(targetDir, "package.json");
|
|
800
|
+
const pkg = JSON.parse(await (0, import_promises7.readFile)(pkgPath, "utf8"));
|
|
590
801
|
const workspaces = pkg.workspaces ?? [];
|
|
591
802
|
const packagesBlock = workspaces.map((p2) => ` - '${p2}'`).join("\n");
|
|
592
803
|
const allowBuilds = [
|
|
@@ -595,7 +806,9 @@ async function writePnpmWorkspace(targetDir) {
|
|
|
595
806
|
"@parcel/watcher",
|
|
596
807
|
"@scarf/scarf",
|
|
597
808
|
"@swc/core",
|
|
809
|
+
"bcrypt",
|
|
598
810
|
"less",
|
|
811
|
+
"mongodb-memory-server",
|
|
599
812
|
"msgpackr-extract",
|
|
600
813
|
"nx",
|
|
601
814
|
"protobufjs",
|
|
@@ -607,40 +820,40 @@ ${packagesBlock}
|
|
|
607
820
|
allowBuilds:
|
|
608
821
|
${allowBuilds}
|
|
609
822
|
`;
|
|
610
|
-
await (0,
|
|
823
|
+
await (0, import_promises7.writeFile)((0, import_node_path7.join)(targetDir, "pnpm-workspace.yaml"), content);
|
|
611
824
|
}
|
|
612
825
|
async function rewritePnpmWorkspaceDeps(targetDir) {
|
|
613
|
-
async function
|
|
826
|
+
async function walk2(dir) {
|
|
614
827
|
const found = [];
|
|
615
828
|
let entries;
|
|
616
829
|
try {
|
|
617
|
-
entries = await (0,
|
|
830
|
+
entries = await (0, import_promises7.readdir)(dir, { withFileTypes: true });
|
|
618
831
|
} catch {
|
|
619
832
|
return found;
|
|
620
833
|
}
|
|
621
834
|
for (const e of entries) {
|
|
622
835
|
if (e.isDirectory() && e.name !== "node_modules") {
|
|
623
|
-
found.push(...await
|
|
836
|
+
found.push(...await walk2((0, import_node_path7.join)(dir, e.name)));
|
|
624
837
|
} else if (e.isFile() && e.name === "package.json") {
|
|
625
|
-
found.push((0,
|
|
838
|
+
found.push((0, import_node_path7.join)(dir, e.name));
|
|
626
839
|
}
|
|
627
840
|
}
|
|
628
841
|
return found;
|
|
629
842
|
}
|
|
630
|
-
const pkgFiles = await
|
|
843
|
+
const pkgFiles = await walk2(targetDir);
|
|
631
844
|
for (const f of pkgFiles) {
|
|
632
845
|
try {
|
|
633
|
-
const raw = await (0,
|
|
846
|
+
const raw = await (0, import_promises7.readFile)(f, "utf8");
|
|
634
847
|
const next = raw.replace(/"(@icore\/[^"]+)":\s*"\*"/g, '"$1": "workspace:*"');
|
|
635
|
-
if (next !== raw) await (0,
|
|
848
|
+
if (next !== raw) await (0, import_promises7.writeFile)(f, next);
|
|
636
849
|
} catch {
|
|
637
850
|
}
|
|
638
851
|
}
|
|
639
852
|
}
|
|
640
853
|
async function patchGitignoreForPm(targetDir, pm) {
|
|
641
|
-
const giPath = (0,
|
|
854
|
+
const giPath = (0, import_node_path7.join)(targetDir, ".gitignore");
|
|
642
855
|
try {
|
|
643
|
-
let src = await (0,
|
|
856
|
+
let src = await (0, import_promises7.readFile)(giPath, "utf8");
|
|
644
857
|
src = src.replace(/^# Build artifacts.*\ntools\/create-icore\/templates\/\s*\n/m, "");
|
|
645
858
|
if (pm !== "yarn") {
|
|
646
859
|
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, "");
|
|
@@ -655,7 +868,7 @@ async function patchGitignoreForPm(targetDir, pm) {
|
|
|
655
868
|
src += "\n# npm\nnpm-debug.log*\n";
|
|
656
869
|
}
|
|
657
870
|
}
|
|
658
|
-
await (0,
|
|
871
|
+
await (0, import_promises7.writeFile)(giPath, src);
|
|
659
872
|
} catch {
|
|
660
873
|
}
|
|
661
874
|
}
|
|
@@ -670,7 +883,7 @@ async function writeAiFiles(targetDir, opts) {
|
|
|
670
883
|
if (opts.jobs !== "none") activeMSes.push(`jobs (standalone)`);
|
|
671
884
|
const usesSupabase = opts.authProvider === "supabase" || opts.dbProvider === "supabase" || opts.upload === "supabase";
|
|
672
885
|
const usesFirebase = opts.authProvider === "firebase" || opts.dbProvider === "firebase" || opts.upload === "firebase";
|
|
673
|
-
await (0,
|
|
886
|
+
await (0, import_promises7.writeFile)((0, import_node_path7.join)(targetDir, "CLAUDE.md"), "@AGENTS.md\n");
|
|
674
887
|
const uiLabel = { shadcn: "shadcn/ui + Tailwind", antd: "Ant Design 6", mui: "MUI 6" }[opts.ui];
|
|
675
888
|
const readme = `# ${opts.projectName}
|
|
676
889
|
|
|
@@ -720,7 +933,7 @@ ${pm === "yarn" ? "yarn remove-notes" : pm === "pnpm" ? "pnpm remove-notes" : "n
|
|
|
720
933
|
|
|
721
934
|
Apache-2.0
|
|
722
935
|
`;
|
|
723
|
-
await (0,
|
|
936
|
+
await (0, import_promises7.writeFile)((0, import_node_path7.join)(targetDir, "README.md"), readme);
|
|
724
937
|
const agents = `# ${opts.projectName} \u2014 Agent Instructions
|
|
725
938
|
|
|
726
939
|
## Stack snapshot
|
|
@@ -801,8 +1014,8 @@ ${opts.upload !== "none" ? `| \`apps/microservices/upload/.env\` | \`STORAGE_PRO
|
|
|
801
1014
|
- Test behaviour, not implementation. Fake strategies from \`@icore/shared\` (FakeAuthStrategy etc.) serve as test doubles.
|
|
802
1015
|
- Run: \`${nx} test <project>\`
|
|
803
1016
|
`;
|
|
804
|
-
await (0,
|
|
805
|
-
await (0,
|
|
1017
|
+
await (0, import_promises7.writeFile)((0, import_node_path7.join)(targetDir, "AGENTS.md"), agents);
|
|
1018
|
+
await (0, import_promises7.mkdir)((0, import_node_path7.join)(targetDir, ".claude"), { recursive: true });
|
|
806
1019
|
const mcpServers = {
|
|
807
1020
|
nx: {
|
|
808
1021
|
command: "npx",
|
|
@@ -843,8 +1056,8 @@ ${opts.upload !== "none" ? `| \`apps/microservices/upload/.env\` | \`STORAGE_PRO
|
|
|
843
1056
|
]
|
|
844
1057
|
}
|
|
845
1058
|
};
|
|
846
|
-
await (0,
|
|
847
|
-
(0,
|
|
1059
|
+
await (0, import_promises7.writeFile)(
|
|
1060
|
+
(0, import_node_path7.join)(targetDir, ".claude", "settings.json"),
|
|
848
1061
|
JSON.stringify(settings, null, 2) + "\n"
|
|
849
1062
|
);
|
|
850
1063
|
}
|
|
@@ -864,30 +1077,30 @@ var IGNORE_TOP = /* @__PURE__ */ new Set([
|
|
|
864
1077
|
".vscode"
|
|
865
1078
|
]);
|
|
866
1079
|
async function copyTree(src, dest) {
|
|
867
|
-
await (0,
|
|
868
|
-
const entries = await (0,
|
|
1080
|
+
await (0, import_promises8.mkdir)(dest, { recursive: true });
|
|
1081
|
+
const entries = await (0, import_promises8.readdir)(src, { withFileTypes: true });
|
|
869
1082
|
for (const entry of entries) {
|
|
870
1083
|
if (IGNORE_TOP.has(entry.name)) continue;
|
|
871
|
-
const s = (0,
|
|
872
|
-
const d = (0,
|
|
1084
|
+
const s = (0, import_node_path8.join)(src, entry.name);
|
|
1085
|
+
const d = (0, import_node_path8.join)(dest, entry.name);
|
|
873
1086
|
if (entry.isDirectory()) await copyTree(s, d);
|
|
874
|
-
else if (entry.isFile()) await (0,
|
|
1087
|
+
else if (entry.isFile()) await (0, import_promises8.copyFile)(s, d);
|
|
875
1088
|
}
|
|
876
1089
|
}
|
|
877
1090
|
async function selectClientTemplate(targetDir, opts) {
|
|
878
|
-
const templatesRoot = (0,
|
|
879
|
-
const chosen = (0,
|
|
880
|
-
const destClient = (0,
|
|
1091
|
+
const templatesRoot = (0, import_node_path8.join)(targetDir, "apps/templates");
|
|
1092
|
+
const chosen = (0, import_node_path8.join)(templatesRoot, `client-${opts.ui}`);
|
|
1093
|
+
const destClient = (0, import_node_path8.join)(targetDir, "apps/client");
|
|
881
1094
|
let chosenUi = opts.ui;
|
|
882
1095
|
try {
|
|
883
|
-
const s = await (0,
|
|
1096
|
+
const s = await (0, import_promises8.stat)(chosen);
|
|
884
1097
|
if (!s.isDirectory()) throw new Error("not a dir");
|
|
885
1098
|
await copyTree(chosen, destClient);
|
|
886
1099
|
} catch {
|
|
887
1100
|
chosenUi = "shadcn";
|
|
888
|
-
await copyTree((0,
|
|
1101
|
+
await copyTree((0, import_node_path8.join)(templatesRoot, "client-shadcn"), destClient);
|
|
889
1102
|
}
|
|
890
|
-
await (0,
|
|
1103
|
+
await (0, import_promises8.rm)(templatesRoot, { recursive: true, force: true });
|
|
891
1104
|
await rewriteClientPaths(destClient, chosenUi);
|
|
892
1105
|
}
|
|
893
1106
|
async function rewriteClientPaths(clientDir, ui) {
|
|
@@ -900,11 +1113,11 @@ async function rewriteClientPaths(clientDir, ui) {
|
|
|
900
1113
|
"eslint.config.mjs"
|
|
901
1114
|
];
|
|
902
1115
|
for (const rel of candidates) {
|
|
903
|
-
const path = (0,
|
|
1116
|
+
const path = (0, import_node_path8.join)(clientDir, rel);
|
|
904
1117
|
try {
|
|
905
|
-
const raw = await (0,
|
|
1118
|
+
const raw = await (0, import_promises8.readFile)(path, "utf8");
|
|
906
1119
|
const next = raw.replaceAll("../../../", "../../").replaceAll(`apps/templates/client-${ui}`, "apps/client").replaceAll(`client-${ui}`, "client");
|
|
907
|
-
if (next !== raw) await (0,
|
|
1120
|
+
if (next !== raw) await (0, import_promises8.writeFile)(path, next);
|
|
908
1121
|
} catch {
|
|
909
1122
|
}
|
|
910
1123
|
}
|
|
@@ -920,12 +1133,12 @@ function gitInit(cwd, projectName) {
|
|
|
920
1133
|
}
|
|
921
1134
|
function resolveYarnBin(cwd) {
|
|
922
1135
|
try {
|
|
923
|
-
const yarnrc = (0, import_node_fs.readFileSync)((0,
|
|
1136
|
+
const yarnrc = (0, import_node_fs.readFileSync)((0, import_node_path8.join)(cwd, ".yarnrc.yml"), "utf8");
|
|
924
1137
|
const match = yarnrc.match(/^yarnPath:\s*(.+)$/m);
|
|
925
|
-
if (match?.[1]) return (0,
|
|
1138
|
+
if (match?.[1]) return (0, import_node_path8.join)(cwd, match[1].trim());
|
|
926
1139
|
} catch {
|
|
927
1140
|
}
|
|
928
|
-
return (0,
|
|
1141
|
+
return (0, import_node_path8.join)(cwd, ".yarn", "releases", "yarn-4.5.0.cjs");
|
|
929
1142
|
}
|
|
930
1143
|
function runInstall(cwd, pm) {
|
|
931
1144
|
if (pm === "yarn") {
|
|
@@ -939,7 +1152,7 @@ function runInstall(cwd, pm) {
|
|
|
939
1152
|
async function scaffold(opts, templatesDir) {
|
|
940
1153
|
await copyTree(templatesDir, opts.targetDir);
|
|
941
1154
|
await rewriteRootPackageJson(opts.targetDir, opts);
|
|
942
|
-
await writeAuthEnv(opts.targetDir, opts);
|
|
1155
|
+
if (opts.authProvider !== "none") await writeAuthEnv(opts.targetDir, opts);
|
|
943
1156
|
await writeUploadEnv(opts.targetDir, opts);
|
|
944
1157
|
await writeNotesEnv(opts.targetDir, opts);
|
|
945
1158
|
await writePaymentEnv(opts.targetDir, opts);
|
|
@@ -948,19 +1161,33 @@ async function scaffold(opts, templatesDir) {
|
|
|
948
1161
|
await selectClientTemplate(opts.targetDir, opts);
|
|
949
1162
|
await writeClientEnv(opts.targetDir);
|
|
950
1163
|
if (opts.upload === "none") await removeUploadStack(opts.targetDir);
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
1164
|
+
await cleanupUnusedFeatures(opts.targetDir, opts);
|
|
1165
|
+
await writeFeaturesWiring(opts.targetDir, opts);
|
|
1166
|
+
await writeNavConfig(opts.targetDir, opts);
|
|
1167
|
+
if (opts.authProvider !== "none") {
|
|
1168
|
+
await cleanupUnusedAuth(opts.targetDir, opts.authProvider);
|
|
1169
|
+
await writeAuthProvider(opts.targetDir, opts.authProvider);
|
|
1170
|
+
} else {
|
|
1171
|
+
await removeAuthStack(opts.targetDir);
|
|
1172
|
+
}
|
|
1173
|
+
if (opts.upload !== "none") {
|
|
1174
|
+
await cleanupUnusedStorage(opts.targetDir, opts.upload);
|
|
1175
|
+
await writeStorageProvider(opts.targetDir, opts.upload);
|
|
1176
|
+
}
|
|
957
1177
|
const firebaseUsed = opts.authProvider === "firebase" || opts.dbProvider === "firebase" || opts.upload === "firebase";
|
|
958
1178
|
if (!firebaseUsed) await removeFirebaseAdminLib(opts.targetDir);
|
|
1179
|
+
await cleanupUnusedDb(opts.targetDir, opts.dbProvider);
|
|
1180
|
+
if (opts.dbProvider !== "none" && opts.example !== "none") {
|
|
1181
|
+
await writeDbProvider(opts.targetDir, opts.dbProvider);
|
|
1182
|
+
}
|
|
1183
|
+
await pruneRootProviderDeps(opts.targetDir, opts);
|
|
1184
|
+
await writeBlueprintJson(opts.targetDir, opts);
|
|
1185
|
+
await writeServiceBlueprints(opts.targetDir, opts);
|
|
959
1186
|
if (opts.packageManager === "yarn") {
|
|
960
|
-
await (0,
|
|
1187
|
+
await (0, import_promises8.writeFile)((0, import_node_path8.join)(opts.targetDir, "yarn.lock"), "");
|
|
961
1188
|
} else {
|
|
962
|
-
await (0,
|
|
963
|
-
await (0,
|
|
1189
|
+
await (0, import_promises8.rm)((0, import_node_path8.join)(opts.targetDir, ".yarn"), { recursive: true, force: true });
|
|
1190
|
+
await (0, import_promises8.rm)((0, import_node_path8.join)(opts.targetDir, ".yarnrc.yml"), { force: true });
|
|
964
1191
|
}
|
|
965
1192
|
if (opts.packageManager === "pnpm") {
|
|
966
1193
|
await writePnpmWorkspace(opts.targetDir);
|
|
@@ -974,10 +1201,99 @@ async function scaffold(opts, templatesDir) {
|
|
|
974
1201
|
|
|
975
1202
|
// src/lib/prompts.ts
|
|
976
1203
|
var p = __toESM(require("@clack/prompts"), 1);
|
|
977
|
-
var
|
|
978
|
-
var
|
|
979
|
-
var
|
|
1204
|
+
var import_node_path9 = require("path");
|
|
1205
|
+
var import_promises10 = require("fs/promises");
|
|
1206
|
+
var import_node_path10 = require("path");
|
|
980
1207
|
var import_node_url = require("url");
|
|
1208
|
+
|
|
1209
|
+
// src/lib/config.ts
|
|
1210
|
+
var import_promises9 = require("fs/promises");
|
|
1211
|
+
var ConfigFileError = class extends Error {
|
|
1212
|
+
constructor(message) {
|
|
1213
|
+
super(message);
|
|
1214
|
+
this.name = "ConfigFileError";
|
|
1215
|
+
}
|
|
1216
|
+
};
|
|
1217
|
+
var AUTH_PROVIDERS = ["supabase", "firebase", "mongodb", "none"];
|
|
1218
|
+
var DB_PROVIDERS = ["supabase", "firebase", "mongodb", "none"];
|
|
1219
|
+
var UPLOAD_PROVIDERS = [
|
|
1220
|
+
"supabase",
|
|
1221
|
+
"firebase",
|
|
1222
|
+
"cloudinary",
|
|
1223
|
+
"mongodb",
|
|
1224
|
+
"none"
|
|
1225
|
+
];
|
|
1226
|
+
var PAYMENT_PROVIDERS = ["paypal", "none"];
|
|
1227
|
+
var JOBS_PROVIDERS = ["bullmq", "none"];
|
|
1228
|
+
var EXAMPLE_MODES = ["notes", "none"];
|
|
1229
|
+
var UI_LIBRARIES = ["shadcn", "antd", "mui"];
|
|
1230
|
+
var MS_TRANSPORTS = ["tcp", "redis", "nats", "mqtt", "rmq", "kafka"];
|
|
1231
|
+
var PACKAGE_MANAGERS = ["yarn", "npm", "pnpm"];
|
|
1232
|
+
function assertEnum(field, value, valid) {
|
|
1233
|
+
if (typeof value !== "string" || !valid.includes(value)) {
|
|
1234
|
+
throw new ConfigFileError(
|
|
1235
|
+
`config field "${field}" got "${String(value)}", expected one of: ${valid.join(", ")}`
|
|
1236
|
+
);
|
|
1237
|
+
}
|
|
1238
|
+
return value;
|
|
1239
|
+
}
|
|
1240
|
+
function assertBoolean(field, value) {
|
|
1241
|
+
if (typeof value !== "boolean") {
|
|
1242
|
+
throw new ConfigFileError(`config field "${field}" must be a boolean, got ${typeof value}`);
|
|
1243
|
+
}
|
|
1244
|
+
return value;
|
|
1245
|
+
}
|
|
1246
|
+
function validateConfig(raw) {
|
|
1247
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
1248
|
+
throw new ConfigFileError("config file must be a JSON object");
|
|
1249
|
+
}
|
|
1250
|
+
const obj = raw;
|
|
1251
|
+
const result = {};
|
|
1252
|
+
if ("projectName" in obj) {
|
|
1253
|
+
const v = obj["projectName"];
|
|
1254
|
+
if (typeof v !== "string" || !/^[a-z0-9-]+$/i.test(v)) {
|
|
1255
|
+
throw new ConfigFileError(
|
|
1256
|
+
`config field "projectName" must match /^[a-z0-9-]+$/i, got "${String(v)}"`
|
|
1257
|
+
);
|
|
1258
|
+
}
|
|
1259
|
+
result.projectName = v;
|
|
1260
|
+
}
|
|
1261
|
+
if ("authProvider" in obj)
|
|
1262
|
+
result.authProvider = assertEnum("authProvider", obj["authProvider"], AUTH_PROVIDERS);
|
|
1263
|
+
if ("dbProvider" in obj)
|
|
1264
|
+
result.dbProvider = assertEnum("dbProvider", obj["dbProvider"], DB_PROVIDERS);
|
|
1265
|
+
if ("upload" in obj) result.upload = assertEnum("upload", obj["upload"], UPLOAD_PROVIDERS);
|
|
1266
|
+
if ("payment" in obj) result.payment = assertEnum("payment", obj["payment"], PAYMENT_PROVIDERS);
|
|
1267
|
+
if ("jobs" in obj) result.jobs = assertEnum("jobs", obj["jobs"], JOBS_PROVIDERS);
|
|
1268
|
+
if ("example" in obj) result.example = assertEnum("example", obj["example"], EXAMPLE_MODES);
|
|
1269
|
+
if ("ui" in obj) result.ui = assertEnum("ui", obj["ui"], UI_LIBRARIES);
|
|
1270
|
+
if ("transport" in obj)
|
|
1271
|
+
result.transport = assertEnum("transport", obj["transport"], MS_TRANSPORTS);
|
|
1272
|
+
if ("packageManager" in obj)
|
|
1273
|
+
result.packageManager = assertEnum("packageManager", obj["packageManager"], PACKAGE_MANAGERS);
|
|
1274
|
+
if ("initGit" in obj) result.initGit = assertBoolean("initGit", obj["initGit"]);
|
|
1275
|
+
if ("install" in obj) result.install = assertBoolean("install", obj["install"]);
|
|
1276
|
+
return result;
|
|
1277
|
+
}
|
|
1278
|
+
async function loadConfig(filePath) {
|
|
1279
|
+
let raw;
|
|
1280
|
+
try {
|
|
1281
|
+
raw = await (0, import_promises9.readFile)(filePath, "utf8");
|
|
1282
|
+
} catch {
|
|
1283
|
+
throw new ConfigFileError(`config file not found: ${filePath}`);
|
|
1284
|
+
}
|
|
1285
|
+
let parsed;
|
|
1286
|
+
try {
|
|
1287
|
+
parsed = JSON.parse(raw);
|
|
1288
|
+
} catch (e) {
|
|
1289
|
+
throw new ConfigFileError(
|
|
1290
|
+
`config file is not valid JSON: ${e instanceof Error ? e.message : String(e)}`
|
|
1291
|
+
);
|
|
1292
|
+
}
|
|
1293
|
+
return validateConfig(parsed);
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
// src/lib/prompts.ts
|
|
981
1297
|
function detectPackageManager() {
|
|
982
1298
|
const ua = process.env["npm_config_user_agent"] ?? "";
|
|
983
1299
|
if (ua.startsWith("yarn/")) return "yarn";
|
|
@@ -987,8 +1303,8 @@ function detectPackageManager() {
|
|
|
987
1303
|
}
|
|
988
1304
|
async function readSelfVersion() {
|
|
989
1305
|
try {
|
|
990
|
-
const here = (0,
|
|
991
|
-
const pkgRaw = await (0,
|
|
1306
|
+
const here = (0, import_node_path10.dirname)((0, import_node_url.fileURLToPath)(importMetaUrl));
|
|
1307
|
+
const pkgRaw = await (0, import_promises10.readFile)((0, import_node_path10.join)(here, "..", "package.json"), "utf8");
|
|
992
1308
|
const pkg = JSON.parse(pkgRaw);
|
|
993
1309
|
return pkg.version ?? null;
|
|
994
1310
|
} catch {
|
|
@@ -1062,12 +1378,21 @@ function parseFlags(argv) {
|
|
|
1062
1378
|
case "no-install":
|
|
1063
1379
|
out.install = false;
|
|
1064
1380
|
break;
|
|
1381
|
+
case "config":
|
|
1382
|
+
out._configPath = v;
|
|
1383
|
+
break;
|
|
1065
1384
|
}
|
|
1066
1385
|
}
|
|
1067
1386
|
return out;
|
|
1068
1387
|
}
|
|
1069
1388
|
async function collectOptions({ argv, cwd }) {
|
|
1070
1389
|
const flags = parseFlags(argv);
|
|
1390
|
+
const configPath = flags._configPath;
|
|
1391
|
+
delete flags._configPath;
|
|
1392
|
+
if (configPath) {
|
|
1393
|
+
const configValues = await loadConfig(configPath);
|
|
1394
|
+
Object.assign(flags, { ...configValues, ...flags });
|
|
1395
|
+
}
|
|
1071
1396
|
const [selfVersion, latestVersion] = await Promise.all([readSelfVersion(), fetchLatestVersion()]);
|
|
1072
1397
|
const versionTag = selfVersion ? ` v${selfVersion}` : "";
|
|
1073
1398
|
p.intro(`iCore${versionTag} \u2014 bootstrap a new project`);
|
|
@@ -1090,11 +1415,12 @@ Re-run with @latest to refresh:
|
|
|
1090
1415
|
options: [
|
|
1091
1416
|
{ value: "supabase", label: "Supabase" },
|
|
1092
1417
|
{ value: "firebase", label: "Firebase" },
|
|
1093
|
-
{ value: "mongodb", label: "MongoDB (Custom Auth)" }
|
|
1418
|
+
{ value: "mongodb", label: "MongoDB (Custom Auth)" },
|
|
1419
|
+
{ value: "none", label: "None \u2014 no login, open API (simple SPA)" }
|
|
1094
1420
|
]
|
|
1095
1421
|
});
|
|
1096
1422
|
if (p.isCancel(authProvider)) throw new Error("cancelled");
|
|
1097
|
-
const dbProvider = flags.dbProvider ?? await p.select({
|
|
1423
|
+
const dbProvider = authProvider === "none" ? "none" : flags.dbProvider ?? await p.select({
|
|
1098
1424
|
message: "Database backend",
|
|
1099
1425
|
options: [
|
|
1100
1426
|
{ value: "supabase", label: "Supabase Postgres" },
|
|
@@ -1133,7 +1459,7 @@ Re-run with @latest to refresh:
|
|
|
1133
1459
|
initialValue: "none"
|
|
1134
1460
|
});
|
|
1135
1461
|
if (p.isCancel(jobs)) throw new Error("cancelled");
|
|
1136
|
-
const example = flags.example ?? await p.select({
|
|
1462
|
+
const example = authProvider === "none" ? "none" : flags.example ?? await p.select({
|
|
1137
1463
|
message: "Include notes sample feature? (CRUD demo \u2014 remove before production)",
|
|
1138
1464
|
options: [
|
|
1139
1465
|
{ value: "notes", label: "Yes \u2014 include notes sample" },
|
|
@@ -1158,7 +1484,8 @@ Re-run with @latest to refresh:
|
|
|
1158
1484
|
initialValue: "shadcn"
|
|
1159
1485
|
});
|
|
1160
1486
|
if (p.isCancel(ui)) throw new Error("cancelled");
|
|
1161
|
-
const
|
|
1487
|
+
const noMicroservices = authProvider === "none" && upload === "none" && payment === "none";
|
|
1488
|
+
const transport = flags.transport ?? (noMicroservices ? "tcp" : await p.select({
|
|
1162
1489
|
message: "Microservice transport",
|
|
1163
1490
|
options: [
|
|
1164
1491
|
{ value: "tcp", label: "TCP (default, no broker required)" },
|
|
@@ -1169,7 +1496,7 @@ Re-run with @latest to refresh:
|
|
|
1169
1496
|
{ value: "kafka", label: "Kafka" }
|
|
1170
1497
|
],
|
|
1171
1498
|
initialValue: "tcp"
|
|
1172
|
-
});
|
|
1499
|
+
}));
|
|
1173
1500
|
if (p.isCancel(transport)) throw new Error("cancelled");
|
|
1174
1501
|
const packageManager = flags.packageManager ?? detectPackageManager();
|
|
1175
1502
|
if (packageManager === "yarn") {
|
|
@@ -1185,7 +1512,7 @@ Re-run with @latest to refresh:
|
|
|
1185
1512
|
}) === false;
|
|
1186
1513
|
return {
|
|
1187
1514
|
projectName,
|
|
1188
|
-
targetDir: (0,
|
|
1515
|
+
targetDir: (0, import_node_path9.resolve)(cwd, projectName),
|
|
1189
1516
|
authProvider,
|
|
1190
1517
|
dbProvider,
|
|
1191
1518
|
upload,
|
|
@@ -1199,8 +1526,129 @@ Re-run with @latest to refresh:
|
|
|
1199
1526
|
install
|
|
1200
1527
|
};
|
|
1201
1528
|
}
|
|
1529
|
+
|
|
1530
|
+
// src/manifest/audit.ts
|
|
1531
|
+
var import_promises11 = require("fs/promises");
|
|
1532
|
+
var import_node_path11 = require("path");
|
|
1533
|
+
var IGNORE_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", ".nx"]);
|
|
1534
|
+
async function walk(dir, out = []) {
|
|
1535
|
+
const entries = await (0, import_promises11.readdir)(dir, { withFileTypes: true });
|
|
1536
|
+
for (const e of entries) {
|
|
1537
|
+
if (e.isDirectory()) {
|
|
1538
|
+
if (!IGNORE_DIRS.has(e.name)) await walk((0, import_node_path11.join)(dir, e.name), out);
|
|
1539
|
+
} else if (/\.(ts|tsx|mjs)$/.test(e.name)) {
|
|
1540
|
+
out.push((0, import_node_path11.join)(dir, e.name));
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
return out;
|
|
1544
|
+
}
|
|
1545
|
+
async function tsconfigAliases(dir) {
|
|
1546
|
+
try {
|
|
1547
|
+
const raw = await (0, import_promises11.readFile)((0, import_node_path11.join)(dir, "tsconfig.base.json"), "utf8");
|
|
1548
|
+
const aliases = /* @__PURE__ */ new Set();
|
|
1549
|
+
for (const m of raw.matchAll(/"(@icore\/[a-z0-9.-]+)"\s*:/g)) {
|
|
1550
|
+
if (m[1]) aliases.add(m[1]);
|
|
1551
|
+
}
|
|
1552
|
+
return aliases;
|
|
1553
|
+
} catch {
|
|
1554
|
+
return /* @__PURE__ */ new Set();
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
var PROVIDER_SDKS = {
|
|
1558
|
+
supabase: ["@supabase/supabase-js"],
|
|
1559
|
+
cloudinary: ["cloudinary"],
|
|
1560
|
+
mongodb: ["mongoose"],
|
|
1561
|
+
firebase: ["firebase-admin", "@icore/firebase-admin"]
|
|
1562
|
+
};
|
|
1563
|
+
async function readBlueprint(dir) {
|
|
1564
|
+
try {
|
|
1565
|
+
return JSON.parse(await (0, import_promises11.readFile)((0, import_node_path11.join)(dir, "blueprint.json"), "utf8"));
|
|
1566
|
+
} catch {
|
|
1567
|
+
return null;
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
function forbiddenFromBlueprint(bp) {
|
|
1571
|
+
const chosen = new Set(
|
|
1572
|
+
[bp.authProvider, bp.dbProvider, bp.upload].filter((p2) => Boolean(p2))
|
|
1573
|
+
);
|
|
1574
|
+
const forbidden = [];
|
|
1575
|
+
for (const [provider, sdks] of Object.entries(PROVIDER_SDKS)) {
|
|
1576
|
+
if (!chosen.has(provider)) forbidden.push(...sdks);
|
|
1577
|
+
}
|
|
1578
|
+
return forbidden;
|
|
1579
|
+
}
|
|
1580
|
+
async function allPackageJsons(dir) {
|
|
1581
|
+
const out = [];
|
|
1582
|
+
const root = (0, import_node_path11.join)(dir, "package.json");
|
|
1583
|
+
out.push(root);
|
|
1584
|
+
async function walk2(d) {
|
|
1585
|
+
let entries;
|
|
1586
|
+
try {
|
|
1587
|
+
entries = await (0, import_promises11.readdir)(d, { withFileTypes: true });
|
|
1588
|
+
} catch {
|
|
1589
|
+
return;
|
|
1590
|
+
}
|
|
1591
|
+
for (const e of entries) {
|
|
1592
|
+
if (e.isDirectory()) {
|
|
1593
|
+
if (!IGNORE_DIRS.has(e.name)) await walk2((0, import_node_path11.join)(d, e.name));
|
|
1594
|
+
} else if (e.name === "package.json") {
|
|
1595
|
+
out.push((0, import_node_path11.join)(d, e.name));
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
}
|
|
1599
|
+
await walk2((0, import_node_path11.join)(dir, "apps"));
|
|
1600
|
+
return out;
|
|
1601
|
+
}
|
|
1602
|
+
async function depKeys(pkgPath) {
|
|
1603
|
+
try {
|
|
1604
|
+
const pkg = JSON.parse(await (0, import_promises11.readFile)(pkgPath, "utf8"));
|
|
1605
|
+
return /* @__PURE__ */ new Set([
|
|
1606
|
+
...Object.keys(pkg.dependencies ?? {}),
|
|
1607
|
+
...Object.keys(pkg.devDependencies ?? {})
|
|
1608
|
+
]);
|
|
1609
|
+
} catch {
|
|
1610
|
+
return /* @__PURE__ */ new Set();
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
var ICORE_IMPORT = /(?:from|import\()\s*['"](@icore\/[a-z0-9.-]+)/g;
|
|
1614
|
+
async function auditProject(dir, opts = {}) {
|
|
1615
|
+
const violations = [];
|
|
1616
|
+
const aliases = await tsconfigAliases(dir);
|
|
1617
|
+
for (const file of await walk(dir)) {
|
|
1618
|
+
const src = await (0, import_promises11.readFile)(file, "utf8");
|
|
1619
|
+
for (const m of src.matchAll(ICORE_IMPORT)) {
|
|
1620
|
+
const alias = m[1];
|
|
1621
|
+
if (alias && !aliases.has(alias)) {
|
|
1622
|
+
violations.push({
|
|
1623
|
+
kind: "import-of-absent-lib",
|
|
1624
|
+
detail: `${file} imports ${alias} (no tsconfig path \u2192 lib absent)`
|
|
1625
|
+
});
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
const bp = await readBlueprint(dir);
|
|
1630
|
+
const forbidden = /* @__PURE__ */ new Set([
|
|
1631
|
+
...opts.forbiddenDeps ?? [],
|
|
1632
|
+
...bp ? forbiddenFromBlueprint(bp) : []
|
|
1633
|
+
]);
|
|
1634
|
+
if (forbidden.size > 0) {
|
|
1635
|
+
for (const pkgPath of await allPackageJsons(dir)) {
|
|
1636
|
+
const deps = await depKeys(pkgPath);
|
|
1637
|
+
for (const f of forbidden) {
|
|
1638
|
+
if (deps.has(f)) {
|
|
1639
|
+
violations.push({
|
|
1640
|
+
kind: "forbidden-dep",
|
|
1641
|
+
detail: `${pkgPath} keeps forbidden dep ${f}`
|
|
1642
|
+
});
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
}
|
|
1647
|
+
return violations;
|
|
1648
|
+
}
|
|
1202
1649
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1203
1650
|
0 && (module.exports = {
|
|
1651
|
+
auditProject,
|
|
1204
1652
|
collectOptions,
|
|
1205
1653
|
pmRun,
|
|
1206
1654
|
scaffold
|