@idevconn/create-icore 0.6.3 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/dist/cli.js +384 -276
  2. package/dist/index.cjs +385 -277
  3. package/dist/index.d.cts +3 -3
  4. package/dist/index.d.ts +3 -3
  5. package/dist/index.js +382 -274
  6. package/package.json +1 -1
  7. package/templates/.yarn/releases/yarn-4.16.0.cjs +944 -0
  8. package/templates/.yarnrc.yml +1 -1
  9. package/templates/apps/api/src/app/storage/storage.controller.ts +28 -0
  10. package/templates/apps/microservices/auth/src/app/app.module.ts +20 -2
  11. package/templates/apps/microservices/notes/src/app/app.module.ts +17 -2
  12. package/templates/apps/microservices/upload/src/app/app.module.ts +17 -2
  13. package/templates/apps/microservices/upload/src/app/storage.controller.ts +7 -0
  14. package/templates/apps/templates/client-antd/src/components/auth/AuthBrandPanel.tsx +59 -0
  15. package/templates/apps/templates/client-antd/src/components/auth/CheckEmailScreen.tsx +28 -0
  16. package/templates/apps/templates/client-antd/src/components/auth/LoginForm.tsx +116 -0
  17. package/templates/apps/templates/client-antd/src/components/auth/MagicLinkForm.tsx +95 -0
  18. package/templates/apps/templates/client-antd/src/components/auth/RegisterForm.tsx +98 -0
  19. package/templates/apps/templates/client-antd/src/globals.less +6 -0
  20. package/templates/apps/templates/client-antd/src/main.tsx +1 -1
  21. package/templates/apps/templates/client-antd/src/routes/login.tsx +45 -181
  22. package/templates/apps/templates/client-mui/src/components/auth/AuthBrandPanel.tsx +59 -0
  23. package/templates/apps/templates/client-mui/src/components/auth/CheckEmailScreen.tsx +28 -0
  24. package/templates/apps/templates/client-mui/src/components/auth/LoginForm.tsx +141 -0
  25. package/templates/apps/templates/client-mui/src/components/auth/MagicLinkForm.tsx +106 -0
  26. package/templates/apps/templates/client-mui/src/components/auth/RegisterForm.tsx +113 -0
  27. package/templates/apps/templates/client-mui/src/main.tsx +1 -1
  28. package/templates/apps/templates/client-mui/src/routes/login.tsx +50 -186
  29. package/templates/apps/templates/client-shadcn/src/components/auth/AuthBrandPanel.tsx +52 -0
  30. package/templates/apps/templates/client-shadcn/src/components/auth/CheckEmailScreen.tsx +29 -0
  31. package/templates/apps/templates/client-shadcn/src/components/auth/LoginForm.tsx +161 -0
  32. package/templates/apps/templates/client-shadcn/src/components/auth/MagicLinkForm.tsx +110 -0
  33. package/templates/apps/templates/client-shadcn/src/components/auth/RegisterForm.tsx +107 -0
  34. package/templates/apps/templates/client-shadcn/src/components/layout/LayoutHeader.tsx +31 -10
  35. package/templates/apps/templates/client-shadcn/src/components/layout/LayoutSider.tsx +22 -27
  36. package/templates/apps/templates/client-shadcn/src/components/ui/card.tsx +1 -1
  37. package/templates/apps/templates/client-shadcn/src/globals.css +39 -13
  38. package/templates/apps/templates/client-shadcn/src/routes/auth.callback.tsx +1 -1
  39. package/templates/apps/templates/client-shadcn/src/routes/login.tsx +55 -165
  40. package/templates/libs/auth-strategies/mongodb/CHANGELOG.md +8 -0
  41. package/templates/libs/auth-strategies/mongodb/README.md +11 -0
  42. package/templates/libs/auth-strategies/mongodb/eslint.config.mjs +19 -0
  43. package/templates/libs/auth-strategies/mongodb/jest.config.cts +10 -0
  44. package/templates/libs/auth-strategies/mongodb/package.json +16 -0
  45. package/templates/libs/auth-strategies/mongodb/project.json +19 -0
  46. package/templates/libs/auth-strategies/mongodb/src/index.ts +1 -0
  47. package/templates/libs/auth-strategies/mongodb/src/lib/__tests__/mongodb-auth.strategy.unit.test.ts +42 -0
  48. package/templates/libs/auth-strategies/mongodb/src/lib/auth-mongodb.spec.ts +7 -0
  49. package/templates/libs/auth-strategies/mongodb/src/lib/auth-mongodb.ts +3 -0
  50. package/templates/libs/auth-strategies/mongodb/src/lib/mongodb-auth.strategy.ts +188 -0
  51. package/templates/libs/auth-strategies/mongodb/tsconfig.json +23 -0
  52. package/templates/libs/auth-strategies/mongodb/tsconfig.lib.json +10 -0
  53. package/templates/libs/auth-strategies/mongodb/tsconfig.spec.json +16 -0
  54. package/templates/libs/db-strategies/mongodb/CHANGELOG.md +7 -0
  55. package/templates/libs/db-strategies/mongodb/README.md +11 -0
  56. package/templates/libs/db-strategies/mongodb/eslint.config.mjs +19 -0
  57. package/templates/libs/db-strategies/mongodb/jest.config.cts +10 -0
  58. package/templates/libs/db-strategies/mongodb/package.json +14 -0
  59. package/templates/libs/db-strategies/mongodb/project.json +19 -0
  60. package/templates/libs/db-strategies/mongodb/src/index.ts +1 -0
  61. package/templates/libs/db-strategies/mongodb/src/lib/__tests__/mongodb-db.strategy.unit.test.ts +38 -0
  62. package/templates/libs/db-strategies/mongodb/src/lib/mongodb-db.strategy.ts +108 -0
  63. package/templates/libs/db-strategies/mongodb/src/lib/mongodb.spec.ts +7 -0
  64. package/templates/libs/db-strategies/mongodb/src/lib/mongodb.ts +3 -0
  65. package/templates/libs/db-strategies/mongodb/tsconfig.json +23 -0
  66. package/templates/libs/db-strategies/mongodb/tsconfig.lib.json +10 -0
  67. package/templates/libs/db-strategies/mongodb/tsconfig.spec.json +16 -0
  68. package/templates/libs/shared/src/strategies/storage.ts +3 -0
  69. package/templates/libs/storage-strategies/mongodb/CHANGELOG.md +8 -0
  70. package/templates/libs/storage-strategies/mongodb/README.md +11 -0
  71. package/templates/libs/storage-strategies/mongodb/eslint.config.mjs +19 -0
  72. package/templates/libs/storage-strategies/mongodb/jest.config.cts +10 -0
  73. package/templates/libs/storage-strategies/mongodb/package.json +14 -0
  74. package/templates/libs/storage-strategies/mongodb/project.json +19 -0
  75. package/templates/libs/storage-strategies/mongodb/src/index.ts +1 -0
  76. package/templates/libs/storage-strategies/mongodb/src/lib/__tests__/mongodb-storage.strategy.unit.test.ts +38 -0
  77. package/templates/libs/storage-strategies/mongodb/src/lib/mongodb-storage.strategy.ts +93 -0
  78. package/templates/libs/storage-strategies/mongodb/src/lib/storage-mongodb.spec.ts +7 -0
  79. package/templates/libs/storage-strategies/mongodb/src/lib/storage-mongodb.ts +3 -0
  80. package/templates/libs/storage-strategies/mongodb/tsconfig.json +23 -0
  81. package/templates/libs/storage-strategies/mongodb/tsconfig.lib.json +10 -0
  82. package/templates/libs/storage-strategies/mongodb/tsconfig.spec.json +16 -0
  83. package/templates/libs/template-shared/src/lib/i18n/keys.ts +216 -56
  84. package/templates/libs/template-shared/src/lib/stores/theme.store.ts +1 -6
  85. package/templates/libs/upload-client/src/lib/upload-client.service.ts +7 -0
  86. package/templates/tsconfig.base.json +4 -1
  87. package/templates/.yarn/releases/yarn-4.15.0.cjs +0 -940
package/dist/index.cjs CHANGED
@@ -46,34 +46,14 @@ function pmRun(pm, script) {
46
46
  }
47
47
 
48
48
  // src/lib/scaffold.ts
49
- var import_promises = require("fs/promises");
49
+ var import_promises4 = require("fs/promises");
50
50
  var import_node_fs = require("fs");
51
- var import_node_path = require("path");
51
+ var import_node_path4 = require("path");
52
52
  var import_node_child_process = require("child_process");
53
- var IGNORE_TOP = /* @__PURE__ */ new Set([
54
- ".git",
55
- "node_modules",
56
- ".yarn/cache",
57
- ".yarn/unplugged",
58
- ".yarn/install-state.gz",
59
- ".nx",
60
- "dist",
61
- "tmp",
62
- "coverage",
63
- ".idea",
64
- ".vscode"
65
- ]);
66
- async function copyTree(src, dest) {
67
- await (0, import_promises.mkdir)(dest, { recursive: true });
68
- const entries = await (0, import_promises.readdir)(src, { withFileTypes: true });
69
- for (const entry of entries) {
70
- if (IGNORE_TOP.has(entry.name)) continue;
71
- const s = (0, import_node_path.join)(src, entry.name);
72
- const d = (0, import_node_path.join)(dest, entry.name);
73
- if (entry.isDirectory()) await copyTree(s, d);
74
- else if (entry.isFile()) await (0, import_promises.copyFile)(s, d);
75
- }
76
- }
53
+
54
+ // src/lib/scaffold-env.ts
55
+ var import_promises = require("fs/promises");
56
+ var import_node_path = require("path");
77
57
  var TRANSPORT_ENV_TOKEN = {
78
58
  redis: "REDIS",
79
59
  nats: "NATS",
@@ -87,11 +67,28 @@ var TRANSPORT_DEPS = {
87
67
  rmq: { amqplib: "^2.0.1", "amqp-connection-manager": "^5.0.0" },
88
68
  kafka: { kafkajs: "^2.2.4" }
89
69
  };
70
+ var MONGODB_DEPS = {
71
+ mongoose: "^9.6.3",
72
+ "@nestjs/mongoose": "^11.0.4",
73
+ bcrypt: "^6.0.0",
74
+ jsonwebtoken: "^9.0.3"
75
+ };
90
76
  function uncommentTransportEnv(text2, prefix, transport) {
91
77
  const token = TRANSPORT_ENV_TOKEN[transport];
92
78
  if (!token) return text2;
93
79
  return text2.replace(new RegExp(`^# (${prefix}_${token}_[A-Z0-9_]*=)`, "gm"), "$1");
94
80
  }
81
+ async function stripGatewayTransport(targetDir, prefix) {
82
+ const gatewayEnv = (0, import_node_path.join)(targetDir, "apps/api/.env");
83
+ try {
84
+ const env = await (0, import_promises.readFile)(gatewayEnv, "utf8");
85
+ const next = env.split("\n").filter(
86
+ (line) => !line.startsWith(`${prefix}_`) && !line.startsWith(`# ${prefix}_`) && !line.includes(`${prefix} MS transport`)
87
+ ).join("\n");
88
+ await (0, import_promises.writeFile)(gatewayEnv, next);
89
+ } catch {
90
+ }
91
+ }
95
92
  async function rewriteRootPackageJson(targetDir, opts) {
96
93
  const pkgPath = (0, import_node_path.join)(targetDir, "package.json");
97
94
  const raw = await (0, import_promises.readFile)(pkgPath, "utf8");
@@ -105,6 +102,10 @@ async function rewriteRootPackageJson(targetDir, opts) {
105
102
  const deps = pkg["dependencies"] ??= {};
106
103
  Object.assign(deps, transportDeps);
107
104
  }
105
+ if (opts.authProvider === "mongodb" || opts.dbProvider === "mongodb" || opts.upload === "mongodb") {
106
+ const deps = pkg["dependencies"] ??= {};
107
+ Object.assign(deps, MONGODB_DEPS);
108
+ }
108
109
  if (opts.packageManager !== "yarn") {
109
110
  delete pkg.packageManager;
110
111
  } else {
@@ -125,6 +126,9 @@ async function writeAuthEnv(targetDir, opts) {
125
126
  const env = await (0, import_promises.readFile)(envExample, "utf8");
126
127
  let next = env.replace(/^AUTH_PROVIDER=.*$/m, `AUTH_PROVIDER=${opts.authProvider}`).replace(/^AUTH_TRANSPORT=.*$/m, `AUTH_TRANSPORT=${opts.transport}`);
127
128
  next = uncommentTransportEnv(next, "AUTH", opts.transport);
129
+ if (opts.authProvider === "mongodb") {
130
+ next += "\nMONGODB_URI=mongodb://localhost:27017/icore-auth\nJWT_SECRET=change-me-in-production\n";
131
+ }
128
132
  await (0, import_promises.writeFile)((0, import_node_path.join)(targetDir, "apps/microservices/auth/.env"), next);
129
133
  }
130
134
  async function writeUploadEnv(targetDir, opts) {
@@ -133,6 +137,9 @@ async function writeUploadEnv(targetDir, opts) {
133
137
  const env = await (0, import_promises.readFile)(envExample, "utf8");
134
138
  let next = env.replace(/^STORAGE_PROVIDER=.*$/m, `STORAGE_PROVIDER=${opts.upload}`).replace(/^UPLOAD_TRANSPORT=.*$/m, `UPLOAD_TRANSPORT=${opts.transport}`);
135
139
  next = uncommentTransportEnv(next, "UPLOAD", opts.transport);
140
+ if (opts.upload === "mongodb") {
141
+ next += "\nMONGODB_URI=mongodb://localhost:27017/icore-upload\n";
142
+ }
136
143
  await (0, import_promises.writeFile)((0, import_node_path.join)(targetDir, "apps/microservices/upload/.env"), next);
137
144
  }
138
145
  async function writeNotesEnv(targetDir, opts) {
@@ -162,18 +169,11 @@ async function writeRootEnv(targetDir, opts) {
162
169
  `DB_PROVIDER=${opts.dbProvider}`,
163
170
  ``
164
171
  ];
165
- await (0, import_promises.writeFile)((0, import_node_path.join)(targetDir, ".env"), lines.join("\n"));
166
- }
167
- async function stripGatewayTransport(targetDir, prefix) {
168
- const gatewayEnv = (0, import_node_path.join)(targetDir, "apps/api/.env");
169
- try {
170
- const env = await (0, import_promises.readFile)(gatewayEnv, "utf8");
171
- const next = env.split("\n").filter(
172
- (line) => !line.startsWith(`${prefix}_`) && !line.startsWith(`# ${prefix}_`) && !line.includes(`${prefix} MS transport`)
173
- ).join("\n");
174
- await (0, import_promises.writeFile)(gatewayEnv, next);
175
- } catch {
172
+ if (opts.dbProvider === "mongodb") {
173
+ lines.push(`MONGODB_URI=mongodb://localhost:27017/icore-data`);
174
+ lines.push(``);
176
175
  }
176
+ await (0, import_promises.writeFile)((0, import_node_path.join)(targetDir, ".env"), lines.join("\n"));
177
177
  }
178
178
  async function writeClientEnv(targetDir) {
179
179
  const envExample = (0, import_node_path.join)(targetDir, "apps/client/.env.example");
@@ -194,15 +194,37 @@ async function writePaymentEnv(targetDir, opts) {
194
194
  } catch {
195
195
  }
196
196
  }
197
+
198
+ // src/lib/scaffold-strip.ts
199
+ var import_promises2 = require("fs/promises");
200
+ var import_node_path2 = require("path");
197
201
  async function stripDeps(pkgPath, names) {
198
202
  try {
199
- const raw = await (0, import_promises.readFile)(pkgPath, "utf8");
203
+ const raw = await (0, import_promises2.readFile)(pkgPath, "utf8");
200
204
  const pkg = JSON.parse(raw);
201
205
  for (const n of names) {
202
206
  if (pkg.dependencies) delete pkg.dependencies[n];
203
207
  if (pkg.devDependencies) delete pkg.devDependencies[n];
204
208
  }
205
- await (0, import_promises.writeFile)(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
209
+ await (0, import_promises2.writeFile)(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
210
+ } catch {
211
+ }
212
+ }
213
+ async function stripTsconfigPath(targetDir, alias) {
214
+ const tsconfigPath = (0, import_node_path2.join)(targetDir, "tsconfig.base.json");
215
+ try {
216
+ const src = await (0, import_promises2.readFile)(tsconfigPath, "utf8");
217
+ const escaped = alias.replace(/[@/]/g, (c) => c === "@" ? "@" : "\\/");
218
+ const pretty = src.replace(new RegExp(`^\\s*"${escaped}": \\[[^\\]]*\\],?\\n`, "m"), "");
219
+ if (pretty !== src) {
220
+ await (0, import_promises2.writeFile)(tsconfigPath, pretty);
221
+ return;
222
+ }
223
+ const parsed = JSON.parse(src);
224
+ if (parsed.compilerOptions?.paths) {
225
+ delete parsed.compilerOptions.paths[alias];
226
+ }
227
+ await (0, import_promises2.writeFile)(tsconfigPath, JSON.stringify(parsed));
206
228
  } catch {
207
229
  }
208
230
  }
@@ -214,25 +236,25 @@ async function removeJobsStack(targetDir) {
214
236
  "Dockerfile.ms-jobs"
215
237
  ];
216
238
  for (const p2 of paths) {
217
- await (0, import_promises.rm)((0, import_node_path.join)(targetDir, p2), { recursive: true, force: true });
239
+ await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, p2), { recursive: true, force: true });
218
240
  }
219
- const appModulePath = (0, import_node_path.join)(targetDir, "apps/api/src/app/app.module.ts");
241
+ const appModulePath = (0, import_node_path2.join)(targetDir, "apps/api/src/app/app.module.ts");
220
242
  try {
221
- const appModule = await (0, import_promises.readFile)(appModulePath, "utf8");
243
+ const appModule = await (0, import_promises2.readFile)(appModulePath, "utf8");
222
244
  const next = appModule.replace(/^import \{ AdminModule \} from '\.\/admin\/admin\.module';\n/m, "").replace(/,\s*AdminModule/g, "");
223
- await (0, import_promises.writeFile)(appModulePath, next);
245
+ await (0, import_promises2.writeFile)(appModulePath, next);
224
246
  } catch {
225
247
  }
226
- await stripDeps((0, import_node_path.join)(targetDir, "apps/api/package.json"), [
248
+ await stripDeps((0, import_node_path2.join)(targetDir, "apps/api/package.json"), [
227
249
  "@icore/jobs-client",
228
250
  "@bull-board/api",
229
251
  "@bull-board/express"
230
252
  ]);
231
- const composePath = (0, import_node_path.join)(targetDir, "docker-compose.yml");
253
+ const composePath = (0, import_node_path2.join)(targetDir, "docker-compose.yml");
232
254
  try {
233
- const compose = await (0, import_promises.readFile)(composePath, "utf8");
255
+ const compose = await (0, import_promises2.readFile)(composePath, "utf8");
234
256
  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, "");
235
- await (0, import_promises.writeFile)(composePath, next);
257
+ await (0, import_promises2.writeFile)(composePath, next);
236
258
  } catch {
237
259
  }
238
260
  }
@@ -244,25 +266,25 @@ async function removePaymentStack(targetDir) {
244
266
  "apps/api/src/app/payment"
245
267
  ];
246
268
  for (const p2 of paths) {
247
- await (0, import_promises.rm)((0, import_node_path.join)(targetDir, p2), { recursive: true, force: true });
269
+ await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, p2), { recursive: true, force: true });
248
270
  }
249
- const appModulePath = (0, import_node_path.join)(targetDir, "apps/api/src/app/app.module.ts");
271
+ const appModulePath = (0, import_node_path2.join)(targetDir, "apps/api/src/app/app.module.ts");
250
272
  try {
251
- const appModule = await (0, import_promises.readFile)(appModulePath, "utf8");
273
+ const appModule = await (0, import_promises2.readFile)(appModulePath, "utf8");
252
274
  const next = appModule.replace(/^import \{ PaymentModule \} from '\.\/payment\/payment\.module';\n/m, "").replace(/,\s*PaymentModule/g, "");
253
- await (0, import_promises.writeFile)(appModulePath, next);
275
+ await (0, import_promises2.writeFile)(appModulePath, next);
254
276
  } catch {
255
277
  }
256
- await stripDeps((0, import_node_path.join)(targetDir, "apps/api/package.json"), [
278
+ await stripDeps((0, import_node_path2.join)(targetDir, "apps/api/package.json"), [
257
279
  "@icore/payment-client",
258
280
  "@idevconn/payment"
259
281
  ]);
260
282
  await stripGatewayTransport(targetDir, "PAYMENT");
261
- const mainTsPath = (0, import_node_path.join)(targetDir, "apps/api/src/main.ts");
283
+ const mainTsPath = (0, import_node_path2.join)(targetDir, "apps/api/src/main.ts");
262
284
  try {
263
- const src = await (0, import_promises.readFile)(mainTsPath, "utf8");
285
+ const src = await (0, import_promises2.readFile)(mainTsPath, "utf8");
264
286
  const next = src.replace(/\n\s*\{ name: 'payment', prefix: 'PAYMENT' \},/, "");
265
- await (0, import_promises.writeFile)(mainTsPath, next);
287
+ await (0, import_promises2.writeFile)(mainTsPath, next);
266
288
  } catch {
267
289
  }
268
290
  }
@@ -274,39 +296,39 @@ async function removeNotesStack(targetDir) {
274
296
  "apps/api/src/app/notes",
275
297
  "apps/client/src/components/notes"
276
298
  ]) {
277
- await (0, import_promises.rm)((0, import_node_path.join)(targetDir, p2), { recursive: true, force: true });
299
+ await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, p2), { recursive: true, force: true });
278
300
  }
279
- await (0, import_promises.rm)((0, import_node_path.join)(targetDir, "apps/client/src/routes/_dashboard/notes.tsx"), { force: true });
280
- await (0, import_promises.rm)((0, import_node_path.join)(targetDir, "apps/client/src/queries/notes.ts"), { force: true });
281
- const appModulePath = (0, import_node_path.join)(targetDir, "apps/api/src/app/app.module.ts");
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
+ const appModulePath = (0, import_node_path2.join)(targetDir, "apps/api/src/app/app.module.ts");
282
304
  try {
283
- const src = await (0, import_promises.readFile)(appModulePath, "utf8");
305
+ const src = await (0, import_promises2.readFile)(appModulePath, "utf8");
284
306
  const next = src.replace(/^import \{ NotesModule \} from '\.\/notes\/notes\.module';\n/m, "").replace(/,\s*NotesModule/g, "");
285
- await (0, import_promises.writeFile)(appModulePath, next);
307
+ await (0, import_promises2.writeFile)(appModulePath, next);
286
308
  } catch {
287
309
  }
288
- await stripDeps((0, import_node_path.join)(targetDir, "apps/api/package.json"), [
310
+ await stripDeps((0, import_node_path2.join)(targetDir, "apps/api/package.json"), [
289
311
  "@icore/notes-client",
290
312
  "@casl/ability"
291
313
  ]);
292
314
  await stripGatewayTransport(targetDir, "NOTES");
293
- const mainTsPath = (0, import_node_path.join)(targetDir, "apps/api/src/main.ts");
315
+ const mainTsPath = (0, import_node_path2.join)(targetDir, "apps/api/src/main.ts");
294
316
  try {
295
- const src = await (0, import_promises.readFile)(mainTsPath, "utf8");
317
+ const src = await (0, import_promises2.readFile)(mainTsPath, "utf8");
296
318
  const next = src.replace(/\n\s*\{ name: 'notes', prefix: 'NOTES' \},/, "");
297
- await (0, import_promises.writeFile)(mainTsPath, next);
319
+ await (0, import_promises2.writeFile)(mainTsPath, next);
298
320
  } catch {
299
321
  }
300
- const tsconfigPath = (0, import_node_path.join)(targetDir, "tsconfig.base.json");
322
+ const tsconfigPath = (0, import_node_path2.join)(targetDir, "tsconfig.base.json");
301
323
  try {
302
- const src = await (0, import_promises.readFile)(tsconfigPath, "utf8");
324
+ const src = await (0, import_promises2.readFile)(tsconfigPath, "utf8");
303
325
  const next = src.replace(/^\s*"@icore\/notes-client": \[[^\]]*\],?\n/m, "");
304
- await (0, import_promises.writeFile)(tsconfigPath, next);
326
+ await (0, import_promises2.writeFile)(tsconfigPath, next);
305
327
  } catch {
306
328
  }
307
- const siderPath = (0, import_node_path.join)(targetDir, "apps/client/src/components/layout/LayoutSider.tsx");
329
+ const siderPath = (0, import_node_path2.join)(targetDir, "apps/client/src/components/layout/LayoutSider.tsx");
308
330
  try {
309
- const src = await (0, import_promises.readFile)(siderPath, "utf8");
331
+ const src = await (0, import_promises2.readFile)(siderPath, "utf8");
310
332
  const next = src.replace(", StickyNote", "").replace(/\n {8}<Link\n {10}to="\/(?:_dashboard\/)?notes"[\s\S]*?<\/Link>/, "").replace(", FileTextOutlined", "").replace(
311
333
  "const selectedKey = pathname.includes('/notes')\n ? 'notes'\n : pathname.includes('/profile')",
312
334
  "const selectedKey = pathname.includes('/profile')"
@@ -317,159 +339,213 @@ async function removeNotesStack(targetDir) {
317
339
  /\n {8}<ListItemButton\n {10}component=\{Link\}\n {10}to="\/(?:_dashboard\/)?notes"[\s\S]*?<\/ListItemButton>/,
318
340
  ""
319
341
  ).replace(/\n\s*<Link to="\/(?:_dashboard\/)?notes">[\s\S]*?<\/Link>/m, "");
320
- await (0, import_promises.writeFile)(siderPath, next);
342
+ await (0, import_promises2.writeFile)(siderPath, next);
321
343
  } catch {
322
344
  }
323
- const keysPath = (0, import_node_path.join)(targetDir, "libs/template-shared/src/lib/i18n/keys.ts");
345
+ const keysPath = (0, import_node_path2.join)(targetDir, "libs/template-shared/src/lib/i18n/keys.ts");
324
346
  try {
325
- const src = await (0, import_promises.readFile)(keysPath, "utf8");
347
+ const src = await (0, import_promises2.readFile)(keysPath, "utf8");
326
348
  const next = src.replace(/^\s{4}notes: \{\n(?:\s+.*\n)*?\s{4}\},\n/m, "");
327
- await (0, import_promises.writeFile)(keysPath, next);
328
- } catch {
329
- }
330
- }
331
- async function stripTsconfigPath(targetDir, alias) {
332
- const tsconfigPath = (0, import_node_path.join)(targetDir, "tsconfig.base.json");
333
- try {
334
- const src = await (0, import_promises.readFile)(tsconfigPath, "utf8");
335
- const escaped = alias.replace(/[@/]/g, (c) => c === "@" ? "@" : "\\/");
336
- const pretty = src.replace(new RegExp(`^\\s*"${escaped}": \\[[^\\]]*\\],?\\n`, "m"), "");
337
- if (pretty !== src) {
338
- await (0, import_promises.writeFile)(tsconfigPath, pretty);
339
- return;
340
- }
341
- const parsed = JSON.parse(src);
342
- if (parsed.compilerOptions?.paths) {
343
- delete parsed.compilerOptions.paths[alias];
344
- }
345
- await (0, import_promises.writeFile)(tsconfigPath, JSON.stringify(parsed));
349
+ await (0, import_promises2.writeFile)(keysPath, next);
346
350
  } catch {
347
351
  }
348
352
  }
349
353
  async function removeUnusedAuthStrategies(targetDir, authProvider) {
350
- const modulePath = (0, import_node_path.join)(targetDir, "apps/microservices/auth/src/app/app.module.ts");
351
- const AUTH_BRANCH = /if \(provider === 'supabase'\) return makeSupabaseAuth\(cfg\);\n\s*return makeFirebaseAuth\(cfg\);/m;
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;
352
356
  if (authProvider === "supabase") {
353
- await (0, import_promises.rm)((0, import_node_path.join)(targetDir, "libs/auth-strategies/firebase"), { recursive: true, force: true });
354
- await stripDeps((0, import_node_path.join)(targetDir, "apps/microservices/auth/package.json"), [
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"), [
355
360
  "@icore/auth-firebase",
356
- "@icore/firebase-admin"
361
+ "@icore/firebase-admin",
362
+ "@icore/auth-mongodb"
357
363
  ]);
358
364
  await stripTsconfigPath(targetDir, "@icore/auth-firebase");
365
+ await stripTsconfigPath(targetDir, "@icore/auth-mongodb");
359
366
  try {
360
- const src = await (0, import_promises.readFile)(modulePath, "utf8");
361
- const next = src.replace(/^import \{[^}]*\} from '@icore\/firebase-admin';\n/m, "").replace(/^import \{[^}]*FirebaseAuthStrategy[^}]*\} from '@icore\/auth-firebase';\n/m, "").replace(/^ {2}firebase: \[[^\]]*\],\n/m, "").replace(/\nfunction makeFirebaseAuth[\s\S]*?\n}\n/m, "").replace(AUTH_BRANCH, "return makeSupabaseAuth(cfg);");
362
- await (0, import_promises.writeFile)(modulePath, next);
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);
363
373
  } catch {
364
374
  }
365
375
  }
366
376
  if (authProvider === "firebase") {
367
- await (0, import_promises.rm)((0, import_node_path.join)(targetDir, "libs/auth-strategies/supabase"), { recursive: true, force: true });
368
- await stripDeps((0, import_node_path.join)(targetDir, "apps/microservices/auth/package.json"), [
369
- "@icore/auth-supabase"
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"
370
402
  ]);
371
403
  await stripTsconfigPath(targetDir, "@icore/auth-supabase");
404
+ await stripTsconfigPath(targetDir, "@icore/auth-firebase");
372
405
  try {
373
- const src = await (0, import_promises.readFile)(modulePath, "utf8");
374
- const next = src.replace(/^import \{ createClient \} from '@supabase\/supabase-js';\n/m, "").replace(/^import \{[^}]*SupabaseAuthStrategy[^}]*\} from '@icore\/auth-supabase';\n/m, "").replace(/\nfunction makeSupabaseAuth[\s\S]*?\n}\n/m, "").replace(AUTH_BRANCH, "return makeFirebaseAuth(cfg);");
375
- await (0, import_promises.writeFile)(modulePath, next);
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);
376
409
  } catch {
377
410
  }
378
411
  }
379
412
  }
380
413
  async function removeUnusedStorageStrategies(targetDir, uploadProvider) {
381
414
  if (uploadProvider === "none") return;
382
- const modulePath = (0, import_node_path.join)(targetDir, "apps/microservices/upload/src/app/app.module.ts");
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;
383
417
  if (uploadProvider !== "firebase") {
384
- await (0, import_promises.rm)((0, import_node_path.join)(targetDir, "libs/storage-strategies/firebase"), { recursive: true, force: true });
385
- await stripDeps((0, import_node_path.join)(targetDir, "apps/microservices/upload/package.json"), [
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"), [
386
420
  "@icore/storage-firebase",
387
421
  "@icore/firebase-admin"
388
422
  ]);
389
423
  await stripTsconfigPath(targetDir, "@icore/storage-firebase");
390
424
  }
391
425
  if (uploadProvider !== "cloudinary") {
392
- await (0, import_promises.rm)((0, import_node_path.join)(targetDir, "libs/storage-strategies/cloudinary"), {
426
+ await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "libs/storage-strategies/cloudinary"), {
393
427
  recursive: true,
394
428
  force: true
395
429
  });
396
- await stripDeps((0, import_node_path.join)(targetDir, "apps/microservices/upload/package.json"), [
430
+ await stripDeps((0, import_node_path2.join)(targetDir, "apps/microservices/upload/package.json"), [
397
431
  "@icore/storage-cloudinary"
398
432
  ]);
399
433
  await stripTsconfigPath(targetDir, "@icore/storage-cloudinary");
400
434
  }
401
435
  if (uploadProvider !== "supabase") {
402
- await (0, import_promises.rm)((0, import_node_path.join)(targetDir, "libs/storage-strategies/supabase"), { recursive: true, force: true });
403
- await stripDeps((0, import_node_path.join)(targetDir, "apps/microservices/upload/package.json"), [
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"), [
404
438
  "@icore/storage-supabase"
405
439
  ]);
406
440
  await stripTsconfigPath(targetDir, "@icore/storage-supabase");
407
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
+ }
408
449
  try {
409
- let src = await (0, import_promises.readFile)(modulePath, "utf8");
450
+ let src = await (0, import_promises2.readFile)(modulePath, "utf8");
410
451
  if (uploadProvider !== "firebase") {
411
- src = src.replace(/^import \{[^}]*\} from '@icore\/firebase-admin';\n/m, "").replace(
412
- /^import \{[^}]*FirebaseStorageStrategy[^}]*\} from '@icore\/storage-firebase';\n/m,
452
+ src = src.replace(/^import \{[^}]*\} from '@icore\/firebase-admin';\n/gm, "").replace(
453
+ /^import \{[^}]*FirebaseStorageStrategy[^}]*\} from '@icore\/storage-firebase';\n/gm,
413
454
  ""
414
- ).replace(/^ {2}firebase: \[[^\]]*\],\n/m, "").replace(/\nfunction makeFirebaseStorage[\s\S]*?\n}\n/m, "");
455
+ ).replace(/^ {2}firebase: \[[^\]]*\],\n/gm, "").replace(/\nfunction makeFirebaseStorage[\s\S]*?\n}\n/gm, "");
415
456
  }
416
457
  if (uploadProvider !== "cloudinary") {
417
- src = src.replace(/^import \{ v2 as cloudinary \} from 'cloudinary';\n/m, "").replace(
418
- /^import \{[^}]*CloudinaryStorageStrategy[^}]*\} from '@icore\/storage-cloudinary';\n/m,
458
+ src = src.replace(/^import \{ v2 as cloudinary \} from 'cloudinary';\n/gm, "").replace(
459
+ /^import \{[^}]*CloudinaryStorageStrategy[^}]*\} from '@icore\/storage-cloudinary';\n/gm,
419
460
  ""
420
- ).replace(/\nfunction makeCloudinaryStorage[\s\S]*?\n}\n/m, "");
461
+ ).replace(/\nfunction makeCloudinaryStorage[\s\S]*?\n}\n/gm, "");
421
462
  }
422
463
  if (uploadProvider !== "supabase") {
423
- src = src.replace(/^import \{ createClient \} from '@supabase\/supabase-js';\n/m, "").replace(
424
- /^import \{[^}]*SupabaseStorageStrategy[^}]*\} from '@icore\/storage-supabase';\n/m,
464
+ src = src.replace(/^import \{ createClient \} from '@supabase\/supabase-js';\n/gm, "").replace(
465
+ /^import \{[^}]*SupabaseStorageStrategy[^}]*\} from '@icore\/storage-supabase';\n/gm,
425
466
  ""
426
- ).replace(/\nfunction makeSupabaseStorage[\s\S]*?\n}\n/m, "");
467
+ ).replace(/\nfunction makeSupabaseStorage[\s\S]*?\n}\n/gm, "");
427
468
  }
428
- const STORAGE_BRANCH = /if \(provider === 'supabase'\) return makeSupabaseStorage\(cfg\);\n\s*if \(provider === 'firebase'\) return makeFirebaseStorage\(cfg\);\n\s*return makeCloudinaryStorage\(cfg\);/m;
429
- const chosenReturn = `return make${uploadProvider.charAt(0).toUpperCase() + uploadProvider.slice(1)}Storage(cfg);`;
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);`;
430
479
  src = src.replace(STORAGE_BRANCH, chosenReturn);
431
- await (0, import_promises.writeFile)(modulePath, src);
480
+ if (uploadProvider !== "mongodb") {
481
+ src = src.replace(/, connection: Connection/, "").replace(/, getConnectionToken\(\)/, "");
482
+ }
483
+ await (0, import_promises2.writeFile)(modulePath, src);
432
484
  } catch {
433
485
  }
434
486
  }
435
487
  async function removeUnusedDbStrategies(targetDir, dbProvider) {
436
- const modulePath = (0, import_node_path.join)(targetDir, "apps/microservices/notes/src/app/app.module.ts");
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;
437
490
  if (dbProvider === "supabase") {
438
- await (0, import_promises.rm)((0, import_node_path.join)(targetDir, "libs/db-strategies/firestore"), { recursive: true, force: true });
439
- await stripDeps((0, import_node_path.join)(targetDir, "apps/microservices/notes/package.json"), [
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"), [
440
494
  "@icore/db-firestore",
441
- "@icore/firebase-admin"
495
+ "@icore/firebase-admin",
496
+ "@icore/db-mongodb"
442
497
  ]);
443
498
  await stripTsconfigPath(targetDir, "@icore/db-firestore");
499
+ await stripTsconfigPath(targetDir, "@icore/db-mongodb");
444
500
  try {
445
- const src = await (0, import_promises.readFile)(modulePath, "utf8");
446
- const next = src.replace(/^import \{[^}]*\} from '@icore\/firebase-admin';\n/m, "").replace(/^import \{[^}]*FirestoreDBStrategy[^}]*\} from '@icore\/db-firestore';\n/m, "").replace(/^ {2}firestore: \[[^\]]*\],\n/m, "").replace(/^ {2}firebase: \[[^\]]*\],\n/m, "").replace(/\nfunction makeFirestoreDB[\s\S]*?\n}\n/m, "").replace(
447
- /if \(provider === 'supabase'\) return makeSupabaseDB\(cfg\);\n\s*return makeFirestoreDB\(cfg\);/m,
448
- "return makeSupabaseDB(cfg);"
449
- );
450
- await (0, import_promises.writeFile)(modulePath, next);
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);
451
507
  } catch {
452
508
  }
453
509
  }
454
510
  if (dbProvider === "firebase") {
455
- await (0, import_promises.rm)((0, import_node_path.join)(targetDir, "libs/db-strategies/supabase"), { recursive: true, force: true });
456
- await stripDeps((0, import_node_path.join)(targetDir, "apps/microservices/notes/package.json"), [
457
- "@icore/db-supabase"
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"
458
516
  ]);
459
517
  await stripTsconfigPath(targetDir, "@icore/db-supabase");
518
+ await stripTsconfigPath(targetDir, "@icore/db-mongodb");
460
519
  try {
461
- const src = await (0, import_promises.readFile)(modulePath, "utf8");
462
- const next = src.replace(/^import \{ createClient \} from '@supabase\/supabase-js';\n/m, "").replace(/^import \{[^}]*SupabaseDBStrategy[^}]*\} from '@icore\/db-supabase';\n/m, "").replace(/\nfunction makeSupabaseDB[\s\S]*?\n}\n/m, "").replace(/\nfunction requireEnv[\s\S]*?\n}\n/m, "").replace(
463
- /if \(provider === 'supabase'\) return makeSupabaseDB\(cfg\);\n\s*return makeFirestoreDB\(cfg\);/m,
464
- "return makeFirestoreDB(cfg);"
465
- );
466
- await (0, import_promises.writeFile)(modulePath, next);
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);
467
543
  } catch {
468
544
  }
469
545
  }
470
546
  }
471
547
  async function removeFirebaseAdminLib(targetDir) {
472
- await (0, import_promises.rm)((0, import_node_path.join)(targetDir, "libs/firebase-admin"), { recursive: true, force: true });
548
+ await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, "libs/firebase-admin"), { recursive: true, force: true });
473
549
  await stripTsconfigPath(targetDir, "@icore/firebase-admin");
474
550
  }
475
551
  async function removeUploadStack(targetDir) {
@@ -481,129 +557,36 @@ async function removeUploadStack(targetDir) {
481
557
  "apps/api/src/app/storage"
482
558
  ];
483
559
  for (const p2 of paths) {
484
- await (0, import_promises.rm)((0, import_node_path.join)(targetDir, p2), { recursive: true, force: true });
560
+ await (0, import_promises2.rm)((0, import_node_path2.join)(targetDir, p2), { recursive: true, force: true });
485
561
  }
486
- const appModulePath = (0, import_node_path.join)(targetDir, "apps/api/src/app/app.module.ts");
562
+ const appModulePath = (0, import_node_path2.join)(targetDir, "apps/api/src/app/app.module.ts");
487
563
  try {
488
- const appModule = await (0, import_promises.readFile)(appModulePath, "utf8");
564
+ const appModule = await (0, import_promises2.readFile)(appModulePath, "utf8");
489
565
  const next = appModule.replace(/^import \{ StorageModule \} from '\.\/storage\/storage\.module';\n/m, "").replace(/,\s*StorageModule/g, "");
490
- await (0, import_promises.writeFile)(appModulePath, next);
566
+ await (0, import_promises2.writeFile)(appModulePath, next);
491
567
  } catch {
492
568
  }
493
- const gatewayEnv = (0, import_node_path.join)(targetDir, "apps/api/.env");
569
+ const gatewayEnv = (0, import_node_path2.join)(targetDir, "apps/api/.env");
494
570
  try {
495
- const env = await (0, import_promises.readFile)(gatewayEnv, "utf8");
571
+ const env = await (0, import_promises2.readFile)(gatewayEnv, "utf8");
496
572
  const next = env.split("\n").filter(
497
573
  (line) => !line.startsWith("UPLOAD_") && !line.startsWith("# UPLOAD_") && !line.startsWith("MAX_FILE_SIZE_KB")
498
574
  ).join("\n");
499
- await (0, import_promises.writeFile)(gatewayEnv, next);
575
+ await (0, import_promises2.writeFile)(gatewayEnv, next);
500
576
  } catch {
501
577
  }
502
- await stripDeps((0, import_node_path.join)(targetDir, "apps/api/package.json"), [
578
+ await stripDeps((0, import_node_path2.join)(targetDir, "apps/api/package.json"), [
503
579
  "@icore/upload-client",
504
580
  "@types/multer"
505
581
  ]);
506
582
  }
507
- async function selectClientTemplate(targetDir, opts) {
508
- const templatesRoot = (0, import_node_path.join)(targetDir, "apps/templates");
509
- const chosen = (0, import_node_path.join)(templatesRoot, `client-${opts.ui}`);
510
- const destClient = (0, import_node_path.join)(targetDir, "apps/client");
511
- let chosenUi = opts.ui;
512
- try {
513
- const s = await (0, import_promises.stat)(chosen);
514
- if (!s.isDirectory()) throw new Error("not a dir");
515
- await copyTree(chosen, destClient);
516
- } catch {
517
- chosenUi = "shadcn";
518
- await copyTree((0, import_node_path.join)(templatesRoot, "client-shadcn"), destClient);
519
- }
520
- await (0, import_promises.rm)(templatesRoot, { recursive: true, force: true });
521
- await rewriteClientPaths(destClient, chosenUi);
522
- }
523
- async function rewriteClientPaths(clientDir, ui) {
524
- const candidates = [
525
- "vite.config.mts",
526
- "tsconfig.json",
527
- "tsconfig.app.json",
528
- "tsconfig.spec.json",
529
- "project.json",
530
- "eslint.config.mjs"
531
- ];
532
- for (const rel of candidates) {
533
- const path = (0, import_node_path.join)(clientDir, rel);
534
- try {
535
- const raw = await (0, import_promises.readFile)(path, "utf8");
536
- const next = raw.replaceAll("../../../", "../../").replaceAll(`apps/templates/client-${ui}`, "apps/client").replaceAll(`client-${ui}`, "client");
537
- if (next !== raw) await (0, import_promises.writeFile)(path, next);
538
- } catch {
539
- }
540
- }
541
- }
542
- function gitInit(cwd, projectName) {
543
- (0, import_node_child_process.spawnSync)("git", ["init"], { cwd, stdio: "inherit" });
544
- (0, import_node_child_process.spawnSync)("git", ["add", "."], { cwd, stdio: "inherit" });
545
- (0, import_node_child_process.spawnSync)(
546
- "git",
547
- ["commit", "-m", `chore: bootstrap ${projectName} from @idevconn/create-icore`],
548
- { cwd, stdio: "inherit" }
549
- );
550
- }
551
- function resolveYarnBin(cwd) {
552
- try {
553
- const yarnrc = (0, import_node_fs.readFileSync)((0, import_node_path.join)(cwd, ".yarnrc.yml"), "utf8");
554
- const match = yarnrc.match(/^yarnPath:\s*(.+)$/m);
555
- if (match?.[1]) return (0, import_node_path.join)(cwd, match[1].trim());
556
- } catch {
557
- }
558
- return (0, import_node_path.join)(cwd, ".yarn", "releases", "yarn-4.5.0.cjs");
559
- }
560
- function runInstall(cwd, pm) {
561
- if (pm === "yarn") {
562
- (0, import_node_child_process.spawnSync)("node", [resolveYarnBin(cwd), "install"], { cwd, stdio: "inherit" });
563
- } else if (pm === "npm") {
564
- (0, import_node_child_process.spawnSync)("npm", ["install"], { cwd, stdio: "inherit" });
565
- } else {
566
- (0, import_node_child_process.spawnSync)("pnpm", ["install"], { cwd, stdio: "inherit" });
567
- }
568
- }
569
- async function scaffold(opts, templatesDir) {
570
- await copyTree(templatesDir, opts.targetDir);
571
- await rewriteRootPackageJson(opts.targetDir, opts);
572
- await writeAuthEnv(opts.targetDir, opts);
573
- await writeUploadEnv(opts.targetDir, opts);
574
- await writeNotesEnv(opts.targetDir, opts);
575
- await writePaymentEnv(opts.targetDir, opts);
576
- await writeGatewayEnv(opts.targetDir, opts);
577
- await writeRootEnv(opts.targetDir, opts);
578
- await selectClientTemplate(opts.targetDir, opts);
579
- await writeClientEnv(opts.targetDir);
580
- if (opts.upload === "none") await removeUploadStack(opts.targetDir);
581
- if (opts.payment === "none") await removePaymentStack(opts.targetDir);
582
- if (opts.jobs === "none") await removeJobsStack(opts.targetDir);
583
- if (opts.example === "none") await removeNotesStack(opts.targetDir);
584
- await removeUnusedAuthStrategies(opts.targetDir, opts.authProvider);
585
- await removeUnusedStorageStrategies(opts.targetDir, opts.upload);
586
- await removeUnusedDbStrategies(opts.targetDir, opts.dbProvider);
587
- const firebaseUsed = opts.authProvider === "firebase" || opts.dbProvider === "firebase" || opts.upload === "firebase";
588
- if (!firebaseUsed) await removeFirebaseAdminLib(opts.targetDir);
589
- if (opts.packageManager === "yarn") {
590
- await (0, import_promises.writeFile)((0, import_node_path.join)(opts.targetDir, "yarn.lock"), "");
591
- } else {
592
- await (0, import_promises.rm)((0, import_node_path.join)(opts.targetDir, ".yarn"), { recursive: true, force: true });
593
- await (0, import_promises.rm)((0, import_node_path.join)(opts.targetDir, ".yarnrc.yml"), { force: true });
594
- }
595
- if (opts.packageManager === "pnpm") {
596
- await writePnpmWorkspace(opts.targetDir);
597
- await rewritePnpmWorkspaceDeps(opts.targetDir);
598
- }
599
- await patchGitignoreForPm(opts.targetDir, opts.packageManager);
600
- await writeAiFiles(opts.targetDir, opts);
601
- if (opts.install) runInstall(opts.targetDir, opts.packageManager);
602
- if (opts.initGit) gitInit(opts.targetDir, opts.projectName);
603
- }
583
+
584
+ // src/lib/scaffold-pkg.ts
585
+ var import_promises3 = require("fs/promises");
586
+ var import_node_path3 = require("path");
604
587
  async function writePnpmWorkspace(targetDir) {
605
- const pkgPath = (0, import_node_path.join)(targetDir, "package.json");
606
- const pkg = JSON.parse(await (0, import_promises.readFile)(pkgPath, "utf8"));
588
+ const pkgPath = (0, import_node_path3.join)(targetDir, "package.json");
589
+ const pkg = JSON.parse(await (0, import_promises3.readFile)(pkgPath, "utf8"));
607
590
  const workspaces = pkg.workspaces ?? [];
608
591
  const packagesBlock = workspaces.map((p2) => ` - '${p2}'`).join("\n");
609
592
  const allowBuilds = [
@@ -624,23 +607,22 @@ ${packagesBlock}
624
607
  allowBuilds:
625
608
  ${allowBuilds}
626
609
  `;
627
- await (0, import_promises.writeFile)((0, import_node_path.join)(targetDir, "pnpm-workspace.yaml"), content);
610
+ await (0, import_promises3.writeFile)((0, import_node_path3.join)(targetDir, "pnpm-workspace.yaml"), content);
628
611
  }
629
612
  async function rewritePnpmWorkspaceDeps(targetDir) {
630
- const { readdir: rd } = await import("fs/promises");
631
613
  async function walk(dir) {
632
614
  const found = [];
633
615
  let entries;
634
616
  try {
635
- entries = await rd(dir, { withFileTypes: true });
617
+ entries = await (0, import_promises3.readdir)(dir, { withFileTypes: true });
636
618
  } catch {
637
619
  return found;
638
620
  }
639
621
  for (const e of entries) {
640
622
  if (e.isDirectory() && e.name !== "node_modules") {
641
- found.push(...await walk((0, import_node_path.join)(dir, e.name)));
623
+ found.push(...await walk((0, import_node_path3.join)(dir, e.name)));
642
624
  } else if (e.isFile() && e.name === "package.json") {
643
- found.push((0, import_node_path.join)(dir, e.name));
625
+ found.push((0, import_node_path3.join)(dir, e.name));
644
626
  }
645
627
  }
646
628
  return found;
@@ -648,17 +630,17 @@ async function rewritePnpmWorkspaceDeps(targetDir) {
648
630
  const pkgFiles = await walk(targetDir);
649
631
  for (const f of pkgFiles) {
650
632
  try {
651
- const raw = await (0, import_promises.readFile)(f, "utf8");
633
+ const raw = await (0, import_promises3.readFile)(f, "utf8");
652
634
  const next = raw.replace(/"(@icore\/[^"]+)":\s*"\*"/g, '"$1": "workspace:*"');
653
- if (next !== raw) await (0, import_promises.writeFile)(f, next);
635
+ if (next !== raw) await (0, import_promises3.writeFile)(f, next);
654
636
  } catch {
655
637
  }
656
638
  }
657
639
  }
658
640
  async function patchGitignoreForPm(targetDir, pm) {
659
- const giPath = (0, import_node_path.join)(targetDir, ".gitignore");
641
+ const giPath = (0, import_node_path3.join)(targetDir, ".gitignore");
660
642
  try {
661
- let src = await (0, import_promises.readFile)(giPath, "utf8");
643
+ let src = await (0, import_promises3.readFile)(giPath, "utf8");
662
644
  src = src.replace(/^# Build artifacts.*\ntools\/create-icore\/templates\/\s*\n/m, "");
663
645
  if (pm !== "yarn") {
664
646
  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, "");
@@ -673,7 +655,7 @@ async function patchGitignoreForPm(targetDir, pm) {
673
655
  src += "\n# npm\nnpm-debug.log*\n";
674
656
  }
675
657
  }
676
- await (0, import_promises.writeFile)(giPath, src);
658
+ await (0, import_promises3.writeFile)(giPath, src);
677
659
  } catch {
678
660
  }
679
661
  }
@@ -688,7 +670,7 @@ async function writeAiFiles(targetDir, opts) {
688
670
  if (opts.jobs !== "none") activeMSes.push(`jobs (standalone)`);
689
671
  const usesSupabase = opts.authProvider === "supabase" || opts.dbProvider === "supabase" || opts.upload === "supabase";
690
672
  const usesFirebase = opts.authProvider === "firebase" || opts.dbProvider === "firebase" || opts.upload === "firebase";
691
- await (0, import_promises.writeFile)((0, import_node_path.join)(targetDir, "CLAUDE.md"), "@AGENTS.md\n");
673
+ await (0, import_promises3.writeFile)((0, import_node_path3.join)(targetDir, "CLAUDE.md"), "@AGENTS.md\n");
692
674
  const uiLabel = { shadcn: "shadcn/ui + Tailwind", antd: "Ant Design 6", mui: "MUI 6" }[opts.ui];
693
675
  const readme = `# ${opts.projectName}
694
676
 
@@ -738,7 +720,7 @@ ${pm === "yarn" ? "yarn remove-notes" : pm === "pnpm" ? "pnpm remove-notes" : "n
738
720
 
739
721
  Apache-2.0
740
722
  `;
741
- await (0, import_promises.writeFile)((0, import_node_path.join)(targetDir, "README.md"), readme);
723
+ await (0, import_promises3.writeFile)((0, import_node_path3.join)(targetDir, "README.md"), readme);
742
724
  const agents = `# ${opts.projectName} \u2014 Agent Instructions
743
725
 
744
726
  ## Stack snapshot
@@ -819,8 +801,8 @@ ${opts.upload !== "none" ? `| \`apps/microservices/upload/.env\` | \`STORAGE_PRO
819
801
  - Test behaviour, not implementation. Fake strategies from \`@icore/shared\` (FakeAuthStrategy etc.) serve as test doubles.
820
802
  - Run: \`${nx} test <project>\`
821
803
  `;
822
- await (0, import_promises.writeFile)((0, import_node_path.join)(targetDir, "AGENTS.md"), agents);
823
- await (0, import_promises.mkdir)((0, import_node_path.join)(targetDir, ".claude"), { recursive: true });
804
+ await (0, import_promises3.writeFile)((0, import_node_path3.join)(targetDir, "AGENTS.md"), agents);
805
+ await (0, import_promises3.mkdir)((0, import_node_path3.join)(targetDir, ".claude"), { recursive: true });
824
806
  const mcpServers = {
825
807
  nx: {
826
808
  command: "npx",
@@ -861,17 +843,140 @@ ${opts.upload !== "none" ? `| \`apps/microservices/upload/.env\` | \`STORAGE_PRO
861
843
  ]
862
844
  }
863
845
  };
864
- await (0, import_promises.writeFile)(
865
- (0, import_node_path.join)(targetDir, ".claude", "settings.json"),
846
+ await (0, import_promises3.writeFile)(
847
+ (0, import_node_path3.join)(targetDir, ".claude", "settings.json"),
866
848
  JSON.stringify(settings, null, 2) + "\n"
867
849
  );
868
850
  }
869
851
 
852
+ // src/lib/scaffold.ts
853
+ var IGNORE_TOP = /* @__PURE__ */ new Set([
854
+ ".git",
855
+ "node_modules",
856
+ ".yarn/cache",
857
+ ".yarn/unplugged",
858
+ ".yarn/install-state.gz",
859
+ ".nx",
860
+ "dist",
861
+ "tmp",
862
+ "coverage",
863
+ ".idea",
864
+ ".vscode"
865
+ ]);
866
+ async function copyTree(src, dest) {
867
+ await (0, import_promises4.mkdir)(dest, { recursive: true });
868
+ const entries = await (0, import_promises4.readdir)(src, { withFileTypes: true });
869
+ for (const entry of entries) {
870
+ if (IGNORE_TOP.has(entry.name)) continue;
871
+ const s = (0, import_node_path4.join)(src, entry.name);
872
+ const d = (0, import_node_path4.join)(dest, entry.name);
873
+ if (entry.isDirectory()) await copyTree(s, d);
874
+ else if (entry.isFile()) await (0, import_promises4.copyFile)(s, d);
875
+ }
876
+ }
877
+ async function selectClientTemplate(targetDir, opts) {
878
+ const templatesRoot = (0, import_node_path4.join)(targetDir, "apps/templates");
879
+ const chosen = (0, import_node_path4.join)(templatesRoot, `client-${opts.ui}`);
880
+ const destClient = (0, import_node_path4.join)(targetDir, "apps/client");
881
+ let chosenUi = opts.ui;
882
+ try {
883
+ const s = await (0, import_promises4.stat)(chosen);
884
+ if (!s.isDirectory()) throw new Error("not a dir");
885
+ await copyTree(chosen, destClient);
886
+ } catch {
887
+ chosenUi = "shadcn";
888
+ await copyTree((0, import_node_path4.join)(templatesRoot, "client-shadcn"), destClient);
889
+ }
890
+ await (0, import_promises4.rm)(templatesRoot, { recursive: true, force: true });
891
+ await rewriteClientPaths(destClient, chosenUi);
892
+ }
893
+ async function rewriteClientPaths(clientDir, ui) {
894
+ const candidates = [
895
+ "vite.config.mts",
896
+ "tsconfig.json",
897
+ "tsconfig.app.json",
898
+ "tsconfig.spec.json",
899
+ "project.json",
900
+ "eslint.config.mjs"
901
+ ];
902
+ for (const rel of candidates) {
903
+ const path = (0, import_node_path4.join)(clientDir, rel);
904
+ try {
905
+ const raw = await (0, import_promises4.readFile)(path, "utf8");
906
+ const next = raw.replaceAll("../../../", "../../").replaceAll(`apps/templates/client-${ui}`, "apps/client").replaceAll(`client-${ui}`, "client");
907
+ if (next !== raw) await (0, import_promises4.writeFile)(path, next);
908
+ } catch {
909
+ }
910
+ }
911
+ }
912
+ function gitInit(cwd, projectName) {
913
+ (0, import_node_child_process.spawnSync)("git", ["init"], { cwd, stdio: "inherit" });
914
+ (0, import_node_child_process.spawnSync)("git", ["add", "."], { cwd, stdio: "inherit" });
915
+ (0, import_node_child_process.spawnSync)(
916
+ "git",
917
+ ["commit", "-m", `chore: bootstrap ${projectName} from @idevconn/create-icore`],
918
+ { cwd, stdio: "inherit" }
919
+ );
920
+ }
921
+ function resolveYarnBin(cwd) {
922
+ try {
923
+ const yarnrc = (0, import_node_fs.readFileSync)((0, import_node_path4.join)(cwd, ".yarnrc.yml"), "utf8");
924
+ const match = yarnrc.match(/^yarnPath:\s*(.+)$/m);
925
+ if (match?.[1]) return (0, import_node_path4.join)(cwd, match[1].trim());
926
+ } catch {
927
+ }
928
+ return (0, import_node_path4.join)(cwd, ".yarn", "releases", "yarn-4.5.0.cjs");
929
+ }
930
+ function runInstall(cwd, pm) {
931
+ if (pm === "yarn") {
932
+ (0, import_node_child_process.spawnSync)("node", [resolveYarnBin(cwd), "install"], { cwd, stdio: "inherit" });
933
+ } else if (pm === "npm") {
934
+ (0, import_node_child_process.spawnSync)("npm", ["install"], { cwd, stdio: "inherit" });
935
+ } else {
936
+ (0, import_node_child_process.spawnSync)("pnpm", ["install"], { cwd, stdio: "inherit" });
937
+ }
938
+ }
939
+ async function scaffold(opts, templatesDir) {
940
+ await copyTree(templatesDir, opts.targetDir);
941
+ await rewriteRootPackageJson(opts.targetDir, opts);
942
+ await writeAuthEnv(opts.targetDir, opts);
943
+ await writeUploadEnv(opts.targetDir, opts);
944
+ await writeNotesEnv(opts.targetDir, opts);
945
+ await writePaymentEnv(opts.targetDir, opts);
946
+ await writeGatewayEnv(opts.targetDir, opts);
947
+ await writeRootEnv(opts.targetDir, opts);
948
+ await selectClientTemplate(opts.targetDir, opts);
949
+ await writeClientEnv(opts.targetDir);
950
+ if (opts.upload === "none") await removeUploadStack(opts.targetDir);
951
+ if (opts.payment === "none") await removePaymentStack(opts.targetDir);
952
+ if (opts.jobs === "none") await removeJobsStack(opts.targetDir);
953
+ if (opts.example === "none") await removeNotesStack(opts.targetDir);
954
+ await removeUnusedAuthStrategies(opts.targetDir, opts.authProvider);
955
+ await removeUnusedStorageStrategies(opts.targetDir, opts.upload);
956
+ await removeUnusedDbStrategies(opts.targetDir, opts.dbProvider);
957
+ const firebaseUsed = opts.authProvider === "firebase" || opts.dbProvider === "firebase" || opts.upload === "firebase";
958
+ if (!firebaseUsed) await removeFirebaseAdminLib(opts.targetDir);
959
+ if (opts.packageManager === "yarn") {
960
+ await (0, import_promises4.writeFile)((0, import_node_path4.join)(opts.targetDir, "yarn.lock"), "");
961
+ } else {
962
+ await (0, import_promises4.rm)((0, import_node_path4.join)(opts.targetDir, ".yarn"), { recursive: true, force: true });
963
+ await (0, import_promises4.rm)((0, import_node_path4.join)(opts.targetDir, ".yarnrc.yml"), { force: true });
964
+ }
965
+ if (opts.packageManager === "pnpm") {
966
+ await writePnpmWorkspace(opts.targetDir);
967
+ await rewritePnpmWorkspaceDeps(opts.targetDir);
968
+ }
969
+ await patchGitignoreForPm(opts.targetDir, opts.packageManager);
970
+ await writeAiFiles(opts.targetDir, opts);
971
+ if (opts.install) runInstall(opts.targetDir, opts.packageManager);
972
+ if (opts.initGit) gitInit(opts.targetDir, opts.projectName);
973
+ }
974
+
870
975
  // src/lib/prompts.ts
871
976
  var p = __toESM(require("@clack/prompts"), 1);
872
- var import_node_path2 = require("path");
873
- var import_promises2 = require("fs/promises");
874
- var import_node_path3 = require("path");
977
+ var import_node_path5 = require("path");
978
+ var import_promises5 = require("fs/promises");
979
+ var import_node_path6 = require("path");
875
980
  var import_node_url = require("url");
876
981
  function detectPackageManager() {
877
982
  const ua = process.env["npm_config_user_agent"] ?? "";
@@ -882,8 +987,8 @@ function detectPackageManager() {
882
987
  }
883
988
  async function readSelfVersion() {
884
989
  try {
885
- const here = (0, import_node_path3.dirname)((0, import_node_url.fileURLToPath)(importMetaUrl));
886
- const pkgRaw = await (0, import_promises2.readFile)((0, import_node_path3.join)(here, "..", "package.json"), "utf8");
990
+ const here = (0, import_node_path6.dirname)((0, import_node_url.fileURLToPath)(importMetaUrl));
991
+ const pkgRaw = await (0, import_promises5.readFile)((0, import_node_path6.join)(here, "..", "package.json"), "utf8");
887
992
  const pkg = JSON.parse(pkgRaw);
888
993
  return pkg.version ?? null;
889
994
  } catch {
@@ -984,7 +1089,8 @@ Re-run with @latest to refresh:
984
1089
  message: "Auth provider",
985
1090
  options: [
986
1091
  { value: "supabase", label: "Supabase" },
987
- { value: "firebase", label: "Firebase" }
1092
+ { value: "firebase", label: "Firebase" },
1093
+ { value: "mongodb", label: "MongoDB (Custom Auth)" }
988
1094
  ]
989
1095
  });
990
1096
  if (p.isCancel(authProvider)) throw new Error("cancelled");
@@ -992,7 +1098,8 @@ Re-run with @latest to refresh:
992
1098
  message: "Database backend",
993
1099
  options: [
994
1100
  { value: "supabase", label: "Supabase Postgres" },
995
- { value: "firebase", label: "Firestore" }
1101
+ { value: "firebase", label: "Firestore" },
1102
+ { value: "mongodb", label: "MongoDB" }
996
1103
  ],
997
1104
  initialValue: authProvider
998
1105
  });
@@ -1003,6 +1110,7 @@ Re-run with @latest to refresh:
1003
1110
  { value: "supabase", label: "Supabase Storage" },
1004
1111
  { value: "firebase", label: "Firebase Cloud Storage" },
1005
1112
  { value: "cloudinary", label: "Cloudinary" },
1113
+ { value: "mongodb", label: "MongoDB GridFS" },
1006
1114
  { value: "none", label: "None \u2014 skip the upload microservice" }
1007
1115
  ]
1008
1116
  });
@@ -1077,7 +1185,7 @@ Re-run with @latest to refresh:
1077
1185
  }) === false;
1078
1186
  return {
1079
1187
  projectName,
1080
- targetDir: (0, import_node_path2.resolve)(cwd, projectName),
1188
+ targetDir: (0, import_node_path5.resolve)(cwd, projectName),
1081
1189
  authProvider,
1082
1190
  dbProvider,
1083
1191
  upload,