@idevconn/create-icore 0.6.2 → 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.
- package/dist/cli.js +384 -276
- package/dist/index.cjs +385 -277
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +382 -274
- package/package.json +1 -1
- package/templates/.yarn/releases/yarn-4.16.0.cjs +944 -0
- package/templates/.yarnrc.yml +1 -1
- package/templates/apps/api/src/app/storage/storage.controller.ts +28 -0
- package/templates/apps/microservices/auth/src/app/app.module.ts +20 -2
- package/templates/apps/microservices/notes/src/app/app.module.ts +17 -2
- package/templates/apps/microservices/upload/src/app/app.module.ts +17 -2
- package/templates/apps/microservices/upload/src/app/storage.controller.ts +7 -0
- package/templates/apps/templates/client-antd/src/components/auth/AuthBrandPanel.tsx +59 -0
- package/templates/apps/templates/client-antd/src/components/auth/CheckEmailScreen.tsx +28 -0
- package/templates/apps/templates/client-antd/src/components/auth/LoginForm.tsx +116 -0
- package/templates/apps/templates/client-antd/src/components/auth/MagicLinkForm.tsx +95 -0
- package/templates/apps/templates/client-antd/src/components/auth/RegisterForm.tsx +98 -0
- package/templates/apps/templates/client-antd/src/globals.less +6 -0
- package/templates/apps/templates/client-antd/src/main.tsx +1 -1
- package/templates/apps/templates/client-antd/src/routes/login.tsx +45 -181
- package/templates/apps/templates/client-mui/src/components/auth/AuthBrandPanel.tsx +59 -0
- package/templates/apps/templates/client-mui/src/components/auth/CheckEmailScreen.tsx +28 -0
- package/templates/apps/templates/client-mui/src/components/auth/LoginForm.tsx +141 -0
- package/templates/apps/templates/client-mui/src/components/auth/MagicLinkForm.tsx +106 -0
- package/templates/apps/templates/client-mui/src/components/auth/RegisterForm.tsx +113 -0
- package/templates/apps/templates/client-mui/src/main.tsx +1 -1
- package/templates/apps/templates/client-mui/src/routes/login.tsx +50 -186
- package/templates/apps/templates/client-shadcn/src/components/auth/AuthBrandPanel.tsx +52 -0
- package/templates/apps/templates/client-shadcn/src/components/auth/CheckEmailScreen.tsx +29 -0
- package/templates/apps/templates/client-shadcn/src/components/auth/LoginForm.tsx +161 -0
- package/templates/apps/templates/client-shadcn/src/components/auth/MagicLinkForm.tsx +110 -0
- package/templates/apps/templates/client-shadcn/src/components/auth/RegisterForm.tsx +107 -0
- package/templates/apps/templates/client-shadcn/src/components/layout/LayoutHeader.tsx +31 -10
- package/templates/apps/templates/client-shadcn/src/components/layout/LayoutSider.tsx +22 -27
- package/templates/apps/templates/client-shadcn/src/components/ui/card.tsx +1 -1
- package/templates/apps/templates/client-shadcn/src/globals.css +39 -13
- package/templates/apps/templates/client-shadcn/src/routes/auth.callback.tsx +1 -1
- package/templates/apps/templates/client-shadcn/src/routes/login.tsx +55 -165
- package/templates/libs/auth-strategies/mongodb/CHANGELOG.md +8 -0
- package/templates/libs/auth-strategies/mongodb/README.md +11 -0
- package/templates/libs/auth-strategies/mongodb/eslint.config.mjs +19 -0
- package/templates/libs/auth-strategies/mongodb/jest.config.cts +10 -0
- package/templates/libs/auth-strategies/mongodb/package.json +16 -0
- package/templates/libs/auth-strategies/mongodb/project.json +19 -0
- package/templates/libs/auth-strategies/mongodb/src/index.ts +1 -0
- package/templates/libs/auth-strategies/mongodb/src/lib/__tests__/mongodb-auth.strategy.unit.test.ts +42 -0
- package/templates/libs/auth-strategies/mongodb/src/lib/auth-mongodb.spec.ts +7 -0
- package/templates/libs/auth-strategies/mongodb/src/lib/auth-mongodb.ts +3 -0
- package/templates/libs/auth-strategies/mongodb/src/lib/mongodb-auth.strategy.ts +188 -0
- package/templates/libs/auth-strategies/mongodb/tsconfig.json +23 -0
- package/templates/libs/auth-strategies/mongodb/tsconfig.lib.json +10 -0
- package/templates/libs/auth-strategies/mongodb/tsconfig.spec.json +16 -0
- package/templates/libs/db-strategies/mongodb/CHANGELOG.md +7 -0
- package/templates/libs/db-strategies/mongodb/README.md +11 -0
- package/templates/libs/db-strategies/mongodb/eslint.config.mjs +19 -0
- package/templates/libs/db-strategies/mongodb/jest.config.cts +10 -0
- package/templates/libs/db-strategies/mongodb/package.json +14 -0
- package/templates/libs/db-strategies/mongodb/project.json +19 -0
- package/templates/libs/db-strategies/mongodb/src/index.ts +1 -0
- package/templates/libs/db-strategies/mongodb/src/lib/__tests__/mongodb-db.strategy.unit.test.ts +38 -0
- package/templates/libs/db-strategies/mongodb/src/lib/mongodb-db.strategy.ts +108 -0
- package/templates/libs/db-strategies/mongodb/src/lib/mongodb.spec.ts +7 -0
- package/templates/libs/db-strategies/mongodb/src/lib/mongodb.ts +3 -0
- package/templates/libs/db-strategies/mongodb/tsconfig.json +23 -0
- package/templates/libs/db-strategies/mongodb/tsconfig.lib.json +10 -0
- package/templates/libs/db-strategies/mongodb/tsconfig.spec.json +16 -0
- package/templates/libs/shared/src/strategies/storage.ts +3 -0
- package/templates/libs/storage-strategies/mongodb/CHANGELOG.md +8 -0
- package/templates/libs/storage-strategies/mongodb/README.md +11 -0
- package/templates/libs/storage-strategies/mongodb/eslint.config.mjs +19 -0
- package/templates/libs/storage-strategies/mongodb/jest.config.cts +10 -0
- package/templates/libs/storage-strategies/mongodb/package.json +14 -0
- package/templates/libs/storage-strategies/mongodb/project.json +19 -0
- package/templates/libs/storage-strategies/mongodb/src/index.ts +1 -0
- package/templates/libs/storage-strategies/mongodb/src/lib/__tests__/mongodb-storage.strategy.unit.test.ts +38 -0
- package/templates/libs/storage-strategies/mongodb/src/lib/mongodb-storage.strategy.ts +93 -0
- package/templates/libs/storage-strategies/mongodb/src/lib/storage-mongodb.spec.ts +7 -0
- package/templates/libs/storage-strategies/mongodb/src/lib/storage-mongodb.ts +3 -0
- package/templates/libs/storage-strategies/mongodb/tsconfig.json +23 -0
- package/templates/libs/storage-strategies/mongodb/tsconfig.lib.json +10 -0
- package/templates/libs/storage-strategies/mongodb/tsconfig.spec.json +16 -0
- package/templates/libs/template-shared/src/lib/i18n/keys.ts +216 -56
- package/templates/libs/template-shared/src/lib/stores/theme.store.ts +1 -6
- package/templates/libs/upload-client/src/lib/upload-client.service.ts +7 -0
- package/templates/tsconfig.base.json +4 -1
- package/templates/.yarn/releases/yarn-4.15.0.cjs +0 -940
package/dist/index.js
CHANGED
|
@@ -4,34 +4,14 @@ function pmRun(pm, script) {
|
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
// src/lib/scaffold.ts
|
|
7
|
-
import { copyFile, mkdir, readdir, readFile, stat, writeFile, rm } from "fs/promises";
|
|
7
|
+
import { copyFile, mkdir as mkdir2, readdir as readdir2, readFile as readFile4, stat, writeFile as writeFile4, rm as rm2 } from "fs/promises";
|
|
8
8
|
import { readFileSync } from "fs";
|
|
9
|
-
import { join } from "path";
|
|
9
|
+
import { join as join4 } from "path";
|
|
10
10
|
import { spawnSync } from "child_process";
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
".yarn/unplugged",
|
|
16
|
-
".yarn/install-state.gz",
|
|
17
|
-
".nx",
|
|
18
|
-
"dist",
|
|
19
|
-
"tmp",
|
|
20
|
-
"coverage",
|
|
21
|
-
".idea",
|
|
22
|
-
".vscode"
|
|
23
|
-
]);
|
|
24
|
-
async function copyTree(src, dest) {
|
|
25
|
-
await mkdir(dest, { recursive: true });
|
|
26
|
-
const entries = await readdir(src, { withFileTypes: true });
|
|
27
|
-
for (const entry of entries) {
|
|
28
|
-
if (IGNORE_TOP.has(entry.name)) continue;
|
|
29
|
-
const s = join(src, entry.name);
|
|
30
|
-
const d = join(dest, entry.name);
|
|
31
|
-
if (entry.isDirectory()) await copyTree(s, d);
|
|
32
|
-
else if (entry.isFile()) await copyFile(s, d);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
11
|
+
|
|
12
|
+
// src/lib/scaffold-env.ts
|
|
13
|
+
import { readFile, writeFile } from "fs/promises";
|
|
14
|
+
import { join } from "path";
|
|
35
15
|
var TRANSPORT_ENV_TOKEN = {
|
|
36
16
|
redis: "REDIS",
|
|
37
17
|
nats: "NATS",
|
|
@@ -45,11 +25,28 @@ var TRANSPORT_DEPS = {
|
|
|
45
25
|
rmq: { amqplib: "^2.0.1", "amqp-connection-manager": "^5.0.0" },
|
|
46
26
|
kafka: { kafkajs: "^2.2.4" }
|
|
47
27
|
};
|
|
28
|
+
var MONGODB_DEPS = {
|
|
29
|
+
mongoose: "^9.6.3",
|
|
30
|
+
"@nestjs/mongoose": "^11.0.4",
|
|
31
|
+
bcrypt: "^6.0.0",
|
|
32
|
+
jsonwebtoken: "^9.0.3"
|
|
33
|
+
};
|
|
48
34
|
function uncommentTransportEnv(text2, prefix, transport) {
|
|
49
35
|
const token = TRANSPORT_ENV_TOKEN[transport];
|
|
50
36
|
if (!token) return text2;
|
|
51
37
|
return text2.replace(new RegExp(`^# (${prefix}_${token}_[A-Z0-9_]*=)`, "gm"), "$1");
|
|
52
38
|
}
|
|
39
|
+
async function stripGatewayTransport(targetDir, prefix) {
|
|
40
|
+
const gatewayEnv = join(targetDir, "apps/api/.env");
|
|
41
|
+
try {
|
|
42
|
+
const env = await readFile(gatewayEnv, "utf8");
|
|
43
|
+
const next = env.split("\n").filter(
|
|
44
|
+
(line) => !line.startsWith(`${prefix}_`) && !line.startsWith(`# ${prefix}_`) && !line.includes(`${prefix} MS transport`)
|
|
45
|
+
).join("\n");
|
|
46
|
+
await writeFile(gatewayEnv, next);
|
|
47
|
+
} catch {
|
|
48
|
+
}
|
|
49
|
+
}
|
|
53
50
|
async function rewriteRootPackageJson(targetDir, opts) {
|
|
54
51
|
const pkgPath = join(targetDir, "package.json");
|
|
55
52
|
const raw = await readFile(pkgPath, "utf8");
|
|
@@ -63,6 +60,10 @@ async function rewriteRootPackageJson(targetDir, opts) {
|
|
|
63
60
|
const deps = pkg["dependencies"] ??= {};
|
|
64
61
|
Object.assign(deps, transportDeps);
|
|
65
62
|
}
|
|
63
|
+
if (opts.authProvider === "mongodb" || opts.dbProvider === "mongodb" || opts.upload === "mongodb") {
|
|
64
|
+
const deps = pkg["dependencies"] ??= {};
|
|
65
|
+
Object.assign(deps, MONGODB_DEPS);
|
|
66
|
+
}
|
|
66
67
|
if (opts.packageManager !== "yarn") {
|
|
67
68
|
delete pkg.packageManager;
|
|
68
69
|
} else {
|
|
@@ -83,6 +84,9 @@ async function writeAuthEnv(targetDir, opts) {
|
|
|
83
84
|
const env = await readFile(envExample, "utf8");
|
|
84
85
|
let next = env.replace(/^AUTH_PROVIDER=.*$/m, `AUTH_PROVIDER=${opts.authProvider}`).replace(/^AUTH_TRANSPORT=.*$/m, `AUTH_TRANSPORT=${opts.transport}`);
|
|
85
86
|
next = uncommentTransportEnv(next, "AUTH", opts.transport);
|
|
87
|
+
if (opts.authProvider === "mongodb") {
|
|
88
|
+
next += "\nMONGODB_URI=mongodb://localhost:27017/icore-auth\nJWT_SECRET=change-me-in-production\n";
|
|
89
|
+
}
|
|
86
90
|
await writeFile(join(targetDir, "apps/microservices/auth/.env"), next);
|
|
87
91
|
}
|
|
88
92
|
async function writeUploadEnv(targetDir, opts) {
|
|
@@ -91,6 +95,9 @@ async function writeUploadEnv(targetDir, opts) {
|
|
|
91
95
|
const env = await readFile(envExample, "utf8");
|
|
92
96
|
let next = env.replace(/^STORAGE_PROVIDER=.*$/m, `STORAGE_PROVIDER=${opts.upload}`).replace(/^UPLOAD_TRANSPORT=.*$/m, `UPLOAD_TRANSPORT=${opts.transport}`);
|
|
93
97
|
next = uncommentTransportEnv(next, "UPLOAD", opts.transport);
|
|
98
|
+
if (opts.upload === "mongodb") {
|
|
99
|
+
next += "\nMONGODB_URI=mongodb://localhost:27017/icore-upload\n";
|
|
100
|
+
}
|
|
94
101
|
await writeFile(join(targetDir, "apps/microservices/upload/.env"), next);
|
|
95
102
|
}
|
|
96
103
|
async function writeNotesEnv(targetDir, opts) {
|
|
@@ -120,18 +127,11 @@ async function writeRootEnv(targetDir, opts) {
|
|
|
120
127
|
`DB_PROVIDER=${opts.dbProvider}`,
|
|
121
128
|
``
|
|
122
129
|
];
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const gatewayEnv = join(targetDir, "apps/api/.env");
|
|
127
|
-
try {
|
|
128
|
-
const env = await readFile(gatewayEnv, "utf8");
|
|
129
|
-
const next = env.split("\n").filter(
|
|
130
|
-
(line) => !line.startsWith(`${prefix}_`) && !line.startsWith(`# ${prefix}_`) && !line.includes(`${prefix} MS transport`)
|
|
131
|
-
).join("\n");
|
|
132
|
-
await writeFile(gatewayEnv, next);
|
|
133
|
-
} catch {
|
|
130
|
+
if (opts.dbProvider === "mongodb") {
|
|
131
|
+
lines.push(`MONGODB_URI=mongodb://localhost:27017/icore-data`);
|
|
132
|
+
lines.push(``);
|
|
134
133
|
}
|
|
134
|
+
await writeFile(join(targetDir, ".env"), lines.join("\n"));
|
|
135
135
|
}
|
|
136
136
|
async function writeClientEnv(targetDir) {
|
|
137
137
|
const envExample = join(targetDir, "apps/client/.env.example");
|
|
@@ -152,15 +152,37 @@ async function writePaymentEnv(targetDir, opts) {
|
|
|
152
152
|
} catch {
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
|
+
|
|
156
|
+
// src/lib/scaffold-strip.ts
|
|
157
|
+
import { readFile as readFile2, writeFile as writeFile2, rm } from "fs/promises";
|
|
158
|
+
import { join as join2 } from "path";
|
|
155
159
|
async function stripDeps(pkgPath, names) {
|
|
156
160
|
try {
|
|
157
|
-
const raw = await
|
|
161
|
+
const raw = await readFile2(pkgPath, "utf8");
|
|
158
162
|
const pkg = JSON.parse(raw);
|
|
159
163
|
for (const n of names) {
|
|
160
164
|
if (pkg.dependencies) delete pkg.dependencies[n];
|
|
161
165
|
if (pkg.devDependencies) delete pkg.devDependencies[n];
|
|
162
166
|
}
|
|
163
|
-
await
|
|
167
|
+
await writeFile2(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
168
|
+
} catch {
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
async function stripTsconfigPath(targetDir, alias) {
|
|
172
|
+
const tsconfigPath = join2(targetDir, "tsconfig.base.json");
|
|
173
|
+
try {
|
|
174
|
+
const src = await readFile2(tsconfigPath, "utf8");
|
|
175
|
+
const escaped = alias.replace(/[@/]/g, (c) => c === "@" ? "@" : "\\/");
|
|
176
|
+
const pretty = src.replace(new RegExp(`^\\s*"${escaped}": \\[[^\\]]*\\],?\\n`, "m"), "");
|
|
177
|
+
if (pretty !== src) {
|
|
178
|
+
await writeFile2(tsconfigPath, pretty);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const parsed = JSON.parse(src);
|
|
182
|
+
if (parsed.compilerOptions?.paths) {
|
|
183
|
+
delete parsed.compilerOptions.paths[alias];
|
|
184
|
+
}
|
|
185
|
+
await writeFile2(tsconfigPath, JSON.stringify(parsed));
|
|
164
186
|
} catch {
|
|
165
187
|
}
|
|
166
188
|
}
|
|
@@ -172,25 +194,25 @@ async function removeJobsStack(targetDir) {
|
|
|
172
194
|
"Dockerfile.ms-jobs"
|
|
173
195
|
];
|
|
174
196
|
for (const p2 of paths) {
|
|
175
|
-
await rm(
|
|
197
|
+
await rm(join2(targetDir, p2), { recursive: true, force: true });
|
|
176
198
|
}
|
|
177
|
-
const appModulePath =
|
|
199
|
+
const appModulePath = join2(targetDir, "apps/api/src/app/app.module.ts");
|
|
178
200
|
try {
|
|
179
|
-
const appModule = await
|
|
201
|
+
const appModule = await readFile2(appModulePath, "utf8");
|
|
180
202
|
const next = appModule.replace(/^import \{ AdminModule \} from '\.\/admin\/admin\.module';\n/m, "").replace(/,\s*AdminModule/g, "");
|
|
181
|
-
await
|
|
203
|
+
await writeFile2(appModulePath, next);
|
|
182
204
|
} catch {
|
|
183
205
|
}
|
|
184
|
-
await stripDeps(
|
|
206
|
+
await stripDeps(join2(targetDir, "apps/api/package.json"), [
|
|
185
207
|
"@icore/jobs-client",
|
|
186
208
|
"@bull-board/api",
|
|
187
209
|
"@bull-board/express"
|
|
188
210
|
]);
|
|
189
|
-
const composePath =
|
|
211
|
+
const composePath = join2(targetDir, "docker-compose.yml");
|
|
190
212
|
try {
|
|
191
|
-
const compose = await
|
|
213
|
+
const compose = await readFile2(composePath, "utf8");
|
|
192
214
|
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, "");
|
|
193
|
-
await
|
|
215
|
+
await writeFile2(composePath, next);
|
|
194
216
|
} catch {
|
|
195
217
|
}
|
|
196
218
|
}
|
|
@@ -202,25 +224,25 @@ async function removePaymentStack(targetDir) {
|
|
|
202
224
|
"apps/api/src/app/payment"
|
|
203
225
|
];
|
|
204
226
|
for (const p2 of paths) {
|
|
205
|
-
await rm(
|
|
227
|
+
await rm(join2(targetDir, p2), { recursive: true, force: true });
|
|
206
228
|
}
|
|
207
|
-
const appModulePath =
|
|
229
|
+
const appModulePath = join2(targetDir, "apps/api/src/app/app.module.ts");
|
|
208
230
|
try {
|
|
209
|
-
const appModule = await
|
|
231
|
+
const appModule = await readFile2(appModulePath, "utf8");
|
|
210
232
|
const next = appModule.replace(/^import \{ PaymentModule \} from '\.\/payment\/payment\.module';\n/m, "").replace(/,\s*PaymentModule/g, "");
|
|
211
|
-
await
|
|
233
|
+
await writeFile2(appModulePath, next);
|
|
212
234
|
} catch {
|
|
213
235
|
}
|
|
214
|
-
await stripDeps(
|
|
236
|
+
await stripDeps(join2(targetDir, "apps/api/package.json"), [
|
|
215
237
|
"@icore/payment-client",
|
|
216
238
|
"@idevconn/payment"
|
|
217
239
|
]);
|
|
218
240
|
await stripGatewayTransport(targetDir, "PAYMENT");
|
|
219
|
-
const mainTsPath =
|
|
241
|
+
const mainTsPath = join2(targetDir, "apps/api/src/main.ts");
|
|
220
242
|
try {
|
|
221
|
-
const src = await
|
|
243
|
+
const src = await readFile2(mainTsPath, "utf8");
|
|
222
244
|
const next = src.replace(/\n\s*\{ name: 'payment', prefix: 'PAYMENT' \},/, "");
|
|
223
|
-
await
|
|
245
|
+
await writeFile2(mainTsPath, next);
|
|
224
246
|
} catch {
|
|
225
247
|
}
|
|
226
248
|
}
|
|
@@ -232,39 +254,39 @@ async function removeNotesStack(targetDir) {
|
|
|
232
254
|
"apps/api/src/app/notes",
|
|
233
255
|
"apps/client/src/components/notes"
|
|
234
256
|
]) {
|
|
235
|
-
await rm(
|
|
257
|
+
await rm(join2(targetDir, p2), { recursive: true, force: true });
|
|
236
258
|
}
|
|
237
|
-
await rm(
|
|
238
|
-
await rm(
|
|
239
|
-
const appModulePath =
|
|
259
|
+
await rm(join2(targetDir, "apps/client/src/routes/_dashboard/notes.tsx"), { force: true });
|
|
260
|
+
await rm(join2(targetDir, "apps/client/src/queries/notes.ts"), { force: true });
|
|
261
|
+
const appModulePath = join2(targetDir, "apps/api/src/app/app.module.ts");
|
|
240
262
|
try {
|
|
241
|
-
const src = await
|
|
263
|
+
const src = await readFile2(appModulePath, "utf8");
|
|
242
264
|
const next = src.replace(/^import \{ NotesModule \} from '\.\/notes\/notes\.module';\n/m, "").replace(/,\s*NotesModule/g, "");
|
|
243
|
-
await
|
|
265
|
+
await writeFile2(appModulePath, next);
|
|
244
266
|
} catch {
|
|
245
267
|
}
|
|
246
|
-
await stripDeps(
|
|
268
|
+
await stripDeps(join2(targetDir, "apps/api/package.json"), [
|
|
247
269
|
"@icore/notes-client",
|
|
248
270
|
"@casl/ability"
|
|
249
271
|
]);
|
|
250
272
|
await stripGatewayTransport(targetDir, "NOTES");
|
|
251
|
-
const mainTsPath =
|
|
273
|
+
const mainTsPath = join2(targetDir, "apps/api/src/main.ts");
|
|
252
274
|
try {
|
|
253
|
-
const src = await
|
|
275
|
+
const src = await readFile2(mainTsPath, "utf8");
|
|
254
276
|
const next = src.replace(/\n\s*\{ name: 'notes', prefix: 'NOTES' \},/, "");
|
|
255
|
-
await
|
|
277
|
+
await writeFile2(mainTsPath, next);
|
|
256
278
|
} catch {
|
|
257
279
|
}
|
|
258
|
-
const tsconfigPath =
|
|
280
|
+
const tsconfigPath = join2(targetDir, "tsconfig.base.json");
|
|
259
281
|
try {
|
|
260
|
-
const src = await
|
|
282
|
+
const src = await readFile2(tsconfigPath, "utf8");
|
|
261
283
|
const next = src.replace(/^\s*"@icore\/notes-client": \[[^\]]*\],?\n/m, "");
|
|
262
|
-
await
|
|
284
|
+
await writeFile2(tsconfigPath, next);
|
|
263
285
|
} catch {
|
|
264
286
|
}
|
|
265
|
-
const siderPath =
|
|
287
|
+
const siderPath = join2(targetDir, "apps/client/src/components/layout/LayoutSider.tsx");
|
|
266
288
|
try {
|
|
267
|
-
const src = await
|
|
289
|
+
const src = await readFile2(siderPath, "utf8");
|
|
268
290
|
const next = src.replace(", StickyNote", "").replace(/\n {8}<Link\n {10}to="\/(?:_dashboard\/)?notes"[\s\S]*?<\/Link>/, "").replace(", FileTextOutlined", "").replace(
|
|
269
291
|
"const selectedKey = pathname.includes('/notes')\n ? 'notes'\n : pathname.includes('/profile')",
|
|
270
292
|
"const selectedKey = pathname.includes('/profile')"
|
|
@@ -275,159 +297,213 @@ async function removeNotesStack(targetDir) {
|
|
|
275
297
|
/\n {8}<ListItemButton\n {10}component=\{Link\}\n {10}to="\/(?:_dashboard\/)?notes"[\s\S]*?<\/ListItemButton>/,
|
|
276
298
|
""
|
|
277
299
|
).replace(/\n\s*<Link to="\/(?:_dashboard\/)?notes">[\s\S]*?<\/Link>/m, "");
|
|
278
|
-
await
|
|
300
|
+
await writeFile2(siderPath, next);
|
|
279
301
|
} catch {
|
|
280
302
|
}
|
|
281
|
-
const keysPath =
|
|
303
|
+
const keysPath = join2(targetDir, "libs/template-shared/src/lib/i18n/keys.ts");
|
|
282
304
|
try {
|
|
283
|
-
const src = await
|
|
305
|
+
const src = await readFile2(keysPath, "utf8");
|
|
284
306
|
const next = src.replace(/^\s{4}notes: \{\n(?:\s+.*\n)*?\s{4}\},\n/m, "");
|
|
285
|
-
await
|
|
286
|
-
} catch {
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
async function stripTsconfigPath(targetDir, alias) {
|
|
290
|
-
const tsconfigPath = join(targetDir, "tsconfig.base.json");
|
|
291
|
-
try {
|
|
292
|
-
const src = await readFile(tsconfigPath, "utf8");
|
|
293
|
-
const escaped = alias.replace(/[@/]/g, (c) => c === "@" ? "@" : "\\/");
|
|
294
|
-
const pretty = src.replace(new RegExp(`^\\s*"${escaped}": \\[[^\\]]*\\],?\\n`, "m"), "");
|
|
295
|
-
if (pretty !== src) {
|
|
296
|
-
await writeFile(tsconfigPath, pretty);
|
|
297
|
-
return;
|
|
298
|
-
}
|
|
299
|
-
const parsed = JSON.parse(src);
|
|
300
|
-
if (parsed.compilerOptions?.paths) {
|
|
301
|
-
delete parsed.compilerOptions.paths[alias];
|
|
302
|
-
}
|
|
303
|
-
await writeFile(tsconfigPath, JSON.stringify(parsed));
|
|
307
|
+
await writeFile2(keysPath, next);
|
|
304
308
|
} catch {
|
|
305
309
|
}
|
|
306
310
|
}
|
|
307
311
|
async function removeUnusedAuthStrategies(targetDir, authProvider) {
|
|
308
|
-
const modulePath =
|
|
309
|
-
const AUTH_BRANCH = /if \(provider === 'supabase'\) return makeSupabaseAuth\(cfg\);\n\s*return makeFirebaseAuth\(cfg\);/m;
|
|
312
|
+
const modulePath = join2(targetDir, "apps/microservices/auth/src/app/app.module.ts");
|
|
313
|
+
const AUTH_BRANCH = /if \(provider === 'supabase'\) return makeSupabaseAuth\(cfg\);\n\s*if \(provider === 'mongodb'\) return makeMongoDbAuth\(connection, cfg\);\n\s*return makeFirebaseAuth\(cfg\);/m;
|
|
310
314
|
if (authProvider === "supabase") {
|
|
311
|
-
await rm(
|
|
312
|
-
await
|
|
315
|
+
await rm(join2(targetDir, "libs/auth-strategies/firebase"), { recursive: true, force: true });
|
|
316
|
+
await rm(join2(targetDir, "libs/auth-strategies/mongodb"), { recursive: true, force: true });
|
|
317
|
+
await stripDeps(join2(targetDir, "apps/microservices/auth/package.json"), [
|
|
313
318
|
"@icore/auth-firebase",
|
|
314
|
-
"@icore/firebase-admin"
|
|
319
|
+
"@icore/firebase-admin",
|
|
320
|
+
"@icore/auth-mongodb"
|
|
315
321
|
]);
|
|
316
322
|
await stripTsconfigPath(targetDir, "@icore/auth-firebase");
|
|
323
|
+
await stripTsconfigPath(targetDir, "@icore/auth-mongodb");
|
|
317
324
|
try {
|
|
318
|
-
const src = await
|
|
319
|
-
const next = src.replace(/^import \{[^}]*\} from '@icore\/firebase-admin';\n/
|
|
320
|
-
|
|
325
|
+
const src = await readFile2(modulePath, "utf8");
|
|
326
|
+
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(
|
|
327
|
+
/^import \{ MongooseModule, getConnectionToken \} from '@nestjs\/mongoose';\n/gm,
|
|
328
|
+
""
|
|
329
|
+
).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\(\)/, "");
|
|
330
|
+
await writeFile2(modulePath, next);
|
|
321
331
|
} catch {
|
|
322
332
|
}
|
|
323
333
|
}
|
|
324
334
|
if (authProvider === "firebase") {
|
|
325
|
-
await rm(
|
|
326
|
-
await
|
|
327
|
-
|
|
335
|
+
await rm(join2(targetDir, "libs/auth-strategies/supabase"), { recursive: true, force: true });
|
|
336
|
+
await rm(join2(targetDir, "libs/auth-strategies/mongodb"), { recursive: true, force: true });
|
|
337
|
+
await stripDeps(join2(targetDir, "apps/microservices/auth/package.json"), [
|
|
338
|
+
"@icore/auth-supabase",
|
|
339
|
+
"@icore/auth-mongodb"
|
|
328
340
|
]);
|
|
329
341
|
await stripTsconfigPath(targetDir, "@icore/auth-supabase");
|
|
342
|
+
await stripTsconfigPath(targetDir, "@icore/auth-mongodb");
|
|
330
343
|
try {
|
|
331
|
-
const src = await
|
|
332
|
-
const next = src.replace(/^import \{ createClient \} from '@supabase\/supabase-js';\n/
|
|
333
|
-
|
|
344
|
+
const src = await readFile2(modulePath, "utf8");
|
|
345
|
+
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(
|
|
346
|
+
/^import \{ MongooseModule, getConnectionToken \} from '@nestjs\/mongoose';\n/gm,
|
|
347
|
+
""
|
|
348
|
+
).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\(\)/, "");
|
|
349
|
+
await writeFile2(modulePath, next);
|
|
350
|
+
} catch {
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
if (authProvider === "mongodb") {
|
|
354
|
+
await rm(join2(targetDir, "libs/auth-strategies/supabase"), { recursive: true, force: true });
|
|
355
|
+
await rm(join2(targetDir, "libs/auth-strategies/firebase"), { recursive: true, force: true });
|
|
356
|
+
await stripDeps(join2(targetDir, "apps/microservices/auth/package.json"), [
|
|
357
|
+
"@icore/auth-supabase",
|
|
358
|
+
"@icore/auth-firebase",
|
|
359
|
+
"@icore/firebase-admin"
|
|
360
|
+
]);
|
|
361
|
+
await stripTsconfigPath(targetDir, "@icore/auth-supabase");
|
|
362
|
+
await stripTsconfigPath(targetDir, "@icore/auth-firebase");
|
|
363
|
+
try {
|
|
364
|
+
const src = await readFile2(modulePath, "utf8");
|
|
365
|
+
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);");
|
|
366
|
+
await writeFile2(modulePath, next);
|
|
334
367
|
} catch {
|
|
335
368
|
}
|
|
336
369
|
}
|
|
337
370
|
}
|
|
338
371
|
async function removeUnusedStorageStrategies(targetDir, uploadProvider) {
|
|
339
372
|
if (uploadProvider === "none") return;
|
|
340
|
-
const modulePath =
|
|
373
|
+
const modulePath = join2(targetDir, "apps/microservices/upload/src/app/app.module.ts");
|
|
374
|
+
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;
|
|
341
375
|
if (uploadProvider !== "firebase") {
|
|
342
|
-
await rm(
|
|
343
|
-
await stripDeps(
|
|
376
|
+
await rm(join2(targetDir, "libs/storage-strategies/firebase"), { recursive: true, force: true });
|
|
377
|
+
await stripDeps(join2(targetDir, "apps/microservices/upload/package.json"), [
|
|
344
378
|
"@icore/storage-firebase",
|
|
345
379
|
"@icore/firebase-admin"
|
|
346
380
|
]);
|
|
347
381
|
await stripTsconfigPath(targetDir, "@icore/storage-firebase");
|
|
348
382
|
}
|
|
349
383
|
if (uploadProvider !== "cloudinary") {
|
|
350
|
-
await rm(
|
|
384
|
+
await rm(join2(targetDir, "libs/storage-strategies/cloudinary"), {
|
|
351
385
|
recursive: true,
|
|
352
386
|
force: true
|
|
353
387
|
});
|
|
354
|
-
await stripDeps(
|
|
388
|
+
await stripDeps(join2(targetDir, "apps/microservices/upload/package.json"), [
|
|
355
389
|
"@icore/storage-cloudinary"
|
|
356
390
|
]);
|
|
357
391
|
await stripTsconfigPath(targetDir, "@icore/storage-cloudinary");
|
|
358
392
|
}
|
|
359
393
|
if (uploadProvider !== "supabase") {
|
|
360
|
-
await rm(
|
|
361
|
-
await stripDeps(
|
|
394
|
+
await rm(join2(targetDir, "libs/storage-strategies/supabase"), { recursive: true, force: true });
|
|
395
|
+
await stripDeps(join2(targetDir, "apps/microservices/upload/package.json"), [
|
|
362
396
|
"@icore/storage-supabase"
|
|
363
397
|
]);
|
|
364
398
|
await stripTsconfigPath(targetDir, "@icore/storage-supabase");
|
|
365
399
|
}
|
|
400
|
+
if (uploadProvider !== "mongodb") {
|
|
401
|
+
await rm(join2(targetDir, "libs/storage-strategies/mongodb"), { recursive: true, force: true });
|
|
402
|
+
await stripDeps(join2(targetDir, "apps/microservices/upload/package.json"), [
|
|
403
|
+
"@icore/storage-mongodb"
|
|
404
|
+
]);
|
|
405
|
+
await stripTsconfigPath(targetDir, "@icore/storage-mongodb");
|
|
406
|
+
}
|
|
366
407
|
try {
|
|
367
|
-
let src = await
|
|
408
|
+
let src = await readFile2(modulePath, "utf8");
|
|
368
409
|
if (uploadProvider !== "firebase") {
|
|
369
|
-
src = src.replace(/^import \{[^}]*\} from '@icore\/firebase-admin';\n/
|
|
370
|
-
/^import \{[^}]*FirebaseStorageStrategy[^}]*\} from '@icore\/storage-firebase';\n/
|
|
410
|
+
src = src.replace(/^import \{[^}]*\} from '@icore\/firebase-admin';\n/gm, "").replace(
|
|
411
|
+
/^import \{[^}]*FirebaseStorageStrategy[^}]*\} from '@icore\/storage-firebase';\n/gm,
|
|
371
412
|
""
|
|
372
|
-
).replace(/^ {2}firebase: \[[^\]]*\],\n/
|
|
413
|
+
).replace(/^ {2}firebase: \[[^\]]*\],\n/gm, "").replace(/\nfunction makeFirebaseStorage[\s\S]*?\n}\n/gm, "");
|
|
373
414
|
}
|
|
374
415
|
if (uploadProvider !== "cloudinary") {
|
|
375
|
-
src = src.replace(/^import \{ v2 as cloudinary \} from 'cloudinary';\n/
|
|
376
|
-
/^import \{[^}]*CloudinaryStorageStrategy[^}]*\} from '@icore\/storage-cloudinary';\n/
|
|
416
|
+
src = src.replace(/^import \{ v2 as cloudinary \} from 'cloudinary';\n/gm, "").replace(
|
|
417
|
+
/^import \{[^}]*CloudinaryStorageStrategy[^}]*\} from '@icore\/storage-cloudinary';\n/gm,
|
|
377
418
|
""
|
|
378
|
-
).replace(/\nfunction makeCloudinaryStorage[\s\S]*?\n}\n/
|
|
419
|
+
).replace(/\nfunction makeCloudinaryStorage[\s\S]*?\n}\n/gm, "");
|
|
379
420
|
}
|
|
380
421
|
if (uploadProvider !== "supabase") {
|
|
381
|
-
src = src.replace(/^import \{ createClient \} from '@supabase\/supabase-js';\n/
|
|
382
|
-
/^import \{[^}]*SupabaseStorageStrategy[^}]*\} from '@icore\/storage-supabase';\n/
|
|
422
|
+
src = src.replace(/^import \{ createClient \} from '@supabase\/supabase-js';\n/gm, "").replace(
|
|
423
|
+
/^import \{[^}]*SupabaseStorageStrategy[^}]*\} from '@icore\/storage-supabase';\n/gm,
|
|
424
|
+
""
|
|
425
|
+
).replace(/\nfunction makeSupabaseStorage[\s\S]*?\n}\n/gm, "");
|
|
426
|
+
}
|
|
427
|
+
if (uploadProvider !== "mongodb") {
|
|
428
|
+
src = src.replace(
|
|
429
|
+
/^import \{[^}]*MongoDbStorageStrategy[^}]*\} from '@icore\/storage-mongodb';\n/gm,
|
|
430
|
+
""
|
|
431
|
+
).replace(
|
|
432
|
+
/^import \{ MongooseModule, getConnectionToken \} from '@nestjs\/mongoose';\n/gm,
|
|
383
433
|
""
|
|
384
|
-
).replace(/\nfunction
|
|
434
|
+
).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, "");
|
|
385
435
|
}
|
|
386
|
-
const
|
|
387
|
-
const chosenReturn = `return make${uploadProvider.charAt(0).toUpperCase() + uploadProvider.slice(1)}Storage(cfg);`;
|
|
436
|
+
const chosenReturn = uploadProvider === "mongodb" ? `return makeMongoDbStorage(connection);` : `return make${uploadProvider.charAt(0).toUpperCase() + uploadProvider.slice(1)}Storage(cfg);`;
|
|
388
437
|
src = src.replace(STORAGE_BRANCH, chosenReturn);
|
|
389
|
-
|
|
438
|
+
if (uploadProvider !== "mongodb") {
|
|
439
|
+
src = src.replace(/, connection: Connection/, "").replace(/, getConnectionToken\(\)/, "");
|
|
440
|
+
}
|
|
441
|
+
await writeFile2(modulePath, src);
|
|
390
442
|
} catch {
|
|
391
443
|
}
|
|
392
444
|
}
|
|
393
445
|
async function removeUnusedDbStrategies(targetDir, dbProvider) {
|
|
394
|
-
const modulePath =
|
|
446
|
+
const modulePath = join2(targetDir, "apps/microservices/notes/src/app/app.module.ts");
|
|
447
|
+
const DB_BRANCH = /if \(provider === 'supabase'\) return makeSupabaseDB\(cfg\);\n\s*if \(provider === 'mongodb'\) return makeMongoDb\(connection\);\n\s*return makeFirestoreDB\(cfg\);/m;
|
|
395
448
|
if (dbProvider === "supabase") {
|
|
396
|
-
await rm(
|
|
397
|
-
await
|
|
449
|
+
await rm(join2(targetDir, "libs/db-strategies/firestore"), { recursive: true, force: true });
|
|
450
|
+
await rm(join2(targetDir, "libs/db-strategies/mongodb"), { recursive: true, force: true });
|
|
451
|
+
await stripDeps(join2(targetDir, "apps/microservices/notes/package.json"), [
|
|
398
452
|
"@icore/db-firestore",
|
|
399
|
-
"@icore/firebase-admin"
|
|
453
|
+
"@icore/firebase-admin",
|
|
454
|
+
"@icore/db-mongodb"
|
|
400
455
|
]);
|
|
401
456
|
await stripTsconfigPath(targetDir, "@icore/db-firestore");
|
|
457
|
+
await stripTsconfigPath(targetDir, "@icore/db-mongodb");
|
|
402
458
|
try {
|
|
403
|
-
const src = await
|
|
404
|
-
const next = src.replace(/^import \{[^}]*\} from '@icore\/firebase-admin';\n/
|
|
405
|
-
|
|
406
|
-
"
|
|
407
|
-
);
|
|
408
|
-
await
|
|
459
|
+
const src = await readFile2(modulePath, "utf8");
|
|
460
|
+
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(
|
|
461
|
+
/^import \{ MongooseModule, getConnectionToken \} from '@nestjs\/mongoose';\n/gm,
|
|
462
|
+
""
|
|
463
|
+
).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\(\)/, "");
|
|
464
|
+
await writeFile2(modulePath, next);
|
|
409
465
|
} catch {
|
|
410
466
|
}
|
|
411
467
|
}
|
|
412
468
|
if (dbProvider === "firebase") {
|
|
413
|
-
await rm(
|
|
414
|
-
await
|
|
415
|
-
|
|
469
|
+
await rm(join2(targetDir, "libs/db-strategies/supabase"), { recursive: true, force: true });
|
|
470
|
+
await rm(join2(targetDir, "libs/db-strategies/mongodb"), { recursive: true, force: true });
|
|
471
|
+
await stripDeps(join2(targetDir, "apps/microservices/notes/package.json"), [
|
|
472
|
+
"@icore/db-supabase",
|
|
473
|
+
"@icore/db-mongodb"
|
|
416
474
|
]);
|
|
417
475
|
await stripTsconfigPath(targetDir, "@icore/db-supabase");
|
|
476
|
+
await stripTsconfigPath(targetDir, "@icore/db-mongodb");
|
|
418
477
|
try {
|
|
419
|
-
const src = await
|
|
420
|
-
const next = src.replace(/^import \{ createClient \} from '@supabase\/supabase-js';\n/
|
|
421
|
-
|
|
422
|
-
"
|
|
423
|
-
);
|
|
424
|
-
await
|
|
478
|
+
const src = await readFile2(modulePath, "utf8");
|
|
479
|
+
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(
|
|
480
|
+
/^import \{ MongooseModule, getConnectionToken \} from '@nestjs\/mongoose';\n/gm,
|
|
481
|
+
""
|
|
482
|
+
).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\(\)/, "");
|
|
483
|
+
await writeFile2(modulePath, next);
|
|
484
|
+
} catch {
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
if (dbProvider === "mongodb") {
|
|
488
|
+
await rm(join2(targetDir, "libs/db-strategies/supabase"), { recursive: true, force: true });
|
|
489
|
+
await rm(join2(targetDir, "libs/db-strategies/firestore"), { recursive: true, force: true });
|
|
490
|
+
await stripDeps(join2(targetDir, "apps/microservices/notes/package.json"), [
|
|
491
|
+
"@icore/db-supabase",
|
|
492
|
+
"@icore/db-firestore",
|
|
493
|
+
"@icore/firebase-admin"
|
|
494
|
+
]);
|
|
495
|
+
await stripTsconfigPath(targetDir, "@icore/db-supabase");
|
|
496
|
+
await stripTsconfigPath(targetDir, "@icore/db-firestore");
|
|
497
|
+
try {
|
|
498
|
+
const src = await readFile2(modulePath, "utf8");
|
|
499
|
+
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);");
|
|
500
|
+
await writeFile2(modulePath, next);
|
|
425
501
|
} catch {
|
|
426
502
|
}
|
|
427
503
|
}
|
|
428
504
|
}
|
|
429
505
|
async function removeFirebaseAdminLib(targetDir) {
|
|
430
|
-
await rm(
|
|
506
|
+
await rm(join2(targetDir, "libs/firebase-admin"), { recursive: true, force: true });
|
|
431
507
|
await stripTsconfigPath(targetDir, "@icore/firebase-admin");
|
|
432
508
|
}
|
|
433
509
|
async function removeUploadStack(targetDir) {
|
|
@@ -439,129 +515,36 @@ async function removeUploadStack(targetDir) {
|
|
|
439
515
|
"apps/api/src/app/storage"
|
|
440
516
|
];
|
|
441
517
|
for (const p2 of paths) {
|
|
442
|
-
await rm(
|
|
518
|
+
await rm(join2(targetDir, p2), { recursive: true, force: true });
|
|
443
519
|
}
|
|
444
|
-
const appModulePath =
|
|
520
|
+
const appModulePath = join2(targetDir, "apps/api/src/app/app.module.ts");
|
|
445
521
|
try {
|
|
446
|
-
const appModule = await
|
|
522
|
+
const appModule = await readFile2(appModulePath, "utf8");
|
|
447
523
|
const next = appModule.replace(/^import \{ StorageModule \} from '\.\/storage\/storage\.module';\n/m, "").replace(/,\s*StorageModule/g, "");
|
|
448
|
-
await
|
|
524
|
+
await writeFile2(appModulePath, next);
|
|
449
525
|
} catch {
|
|
450
526
|
}
|
|
451
|
-
const gatewayEnv =
|
|
527
|
+
const gatewayEnv = join2(targetDir, "apps/api/.env");
|
|
452
528
|
try {
|
|
453
|
-
const env = await
|
|
529
|
+
const env = await readFile2(gatewayEnv, "utf8");
|
|
454
530
|
const next = env.split("\n").filter(
|
|
455
531
|
(line) => !line.startsWith("UPLOAD_") && !line.startsWith("# UPLOAD_") && !line.startsWith("MAX_FILE_SIZE_KB")
|
|
456
532
|
).join("\n");
|
|
457
|
-
await
|
|
533
|
+
await writeFile2(gatewayEnv, next);
|
|
458
534
|
} catch {
|
|
459
535
|
}
|
|
460
|
-
await stripDeps(
|
|
536
|
+
await stripDeps(join2(targetDir, "apps/api/package.json"), [
|
|
461
537
|
"@icore/upload-client",
|
|
462
538
|
"@types/multer"
|
|
463
539
|
]);
|
|
464
540
|
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
let chosenUi = opts.ui;
|
|
470
|
-
try {
|
|
471
|
-
const s = await stat(chosen);
|
|
472
|
-
if (!s.isDirectory()) throw new Error("not a dir");
|
|
473
|
-
await copyTree(chosen, destClient);
|
|
474
|
-
} catch {
|
|
475
|
-
chosenUi = "shadcn";
|
|
476
|
-
await copyTree(join(templatesRoot, "client-shadcn"), destClient);
|
|
477
|
-
}
|
|
478
|
-
await rm(templatesRoot, { recursive: true, force: true });
|
|
479
|
-
await rewriteClientPaths(destClient, chosenUi);
|
|
480
|
-
}
|
|
481
|
-
async function rewriteClientPaths(clientDir, ui) {
|
|
482
|
-
const candidates = [
|
|
483
|
-
"vite.config.mts",
|
|
484
|
-
"tsconfig.json",
|
|
485
|
-
"tsconfig.app.json",
|
|
486
|
-
"tsconfig.spec.json",
|
|
487
|
-
"project.json",
|
|
488
|
-
"eslint.config.mjs"
|
|
489
|
-
];
|
|
490
|
-
for (const rel of candidates) {
|
|
491
|
-
const path = join(clientDir, rel);
|
|
492
|
-
try {
|
|
493
|
-
const raw = await readFile(path, "utf8");
|
|
494
|
-
const next = raw.replaceAll("../../../", "../../").replaceAll(`apps/templates/client-${ui}`, "apps/client").replaceAll(`client-${ui}`, "client");
|
|
495
|
-
if (next !== raw) await writeFile(path, next);
|
|
496
|
-
} catch {
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
function gitInit(cwd, projectName) {
|
|
501
|
-
spawnSync("git", ["init"], { cwd, stdio: "inherit" });
|
|
502
|
-
spawnSync("git", ["add", "."], { cwd, stdio: "inherit" });
|
|
503
|
-
spawnSync(
|
|
504
|
-
"git",
|
|
505
|
-
["commit", "-m", `chore: bootstrap ${projectName} from @idevconn/create-icore`],
|
|
506
|
-
{ cwd, stdio: "inherit" }
|
|
507
|
-
);
|
|
508
|
-
}
|
|
509
|
-
function resolveYarnBin(cwd) {
|
|
510
|
-
try {
|
|
511
|
-
const yarnrc = readFileSync(join(cwd, ".yarnrc.yml"), "utf8");
|
|
512
|
-
const match = yarnrc.match(/^yarnPath:\s*(.+)$/m);
|
|
513
|
-
if (match?.[1]) return join(cwd, match[1].trim());
|
|
514
|
-
} catch {
|
|
515
|
-
}
|
|
516
|
-
return join(cwd, ".yarn", "releases", "yarn-4.5.0.cjs");
|
|
517
|
-
}
|
|
518
|
-
function runInstall(cwd, pm) {
|
|
519
|
-
if (pm === "yarn") {
|
|
520
|
-
spawnSync("node", [resolveYarnBin(cwd), "install"], { cwd, stdio: "inherit" });
|
|
521
|
-
} else if (pm === "npm") {
|
|
522
|
-
spawnSync("npm", ["install"], { cwd, stdio: "inherit" });
|
|
523
|
-
} else {
|
|
524
|
-
spawnSync("pnpm", ["install"], { cwd, stdio: "inherit" });
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
async function scaffold(opts, templatesDir) {
|
|
528
|
-
await copyTree(templatesDir, opts.targetDir);
|
|
529
|
-
await rewriteRootPackageJson(opts.targetDir, opts);
|
|
530
|
-
await writeAuthEnv(opts.targetDir, opts);
|
|
531
|
-
await writeUploadEnv(opts.targetDir, opts);
|
|
532
|
-
await writeNotesEnv(opts.targetDir, opts);
|
|
533
|
-
await writePaymentEnv(opts.targetDir, opts);
|
|
534
|
-
await writeGatewayEnv(opts.targetDir, opts);
|
|
535
|
-
await writeRootEnv(opts.targetDir, opts);
|
|
536
|
-
await selectClientTemplate(opts.targetDir, opts);
|
|
537
|
-
await writeClientEnv(opts.targetDir);
|
|
538
|
-
if (opts.upload === "none") await removeUploadStack(opts.targetDir);
|
|
539
|
-
if (opts.payment === "none") await removePaymentStack(opts.targetDir);
|
|
540
|
-
if (opts.jobs === "none") await removeJobsStack(opts.targetDir);
|
|
541
|
-
if (opts.example === "none") await removeNotesStack(opts.targetDir);
|
|
542
|
-
await removeUnusedAuthStrategies(opts.targetDir, opts.authProvider);
|
|
543
|
-
await removeUnusedStorageStrategies(opts.targetDir, opts.upload);
|
|
544
|
-
await removeUnusedDbStrategies(opts.targetDir, opts.dbProvider);
|
|
545
|
-
const firebaseUsed = opts.authProvider === "firebase" || opts.dbProvider === "firebase" || opts.upload === "firebase";
|
|
546
|
-
if (!firebaseUsed) await removeFirebaseAdminLib(opts.targetDir);
|
|
547
|
-
if (opts.packageManager === "yarn") {
|
|
548
|
-
await writeFile(join(opts.targetDir, "yarn.lock"), "");
|
|
549
|
-
} else {
|
|
550
|
-
await rm(join(opts.targetDir, ".yarn"), { recursive: true, force: true });
|
|
551
|
-
await rm(join(opts.targetDir, ".yarnrc.yml"), { force: true });
|
|
552
|
-
}
|
|
553
|
-
if (opts.packageManager === "pnpm") {
|
|
554
|
-
await writePnpmWorkspace(opts.targetDir);
|
|
555
|
-
await rewritePnpmWorkspaceDeps(opts.targetDir);
|
|
556
|
-
}
|
|
557
|
-
await patchGitignoreForPm(opts.targetDir, opts.packageManager);
|
|
558
|
-
await writeAiFiles(opts.targetDir, opts);
|
|
559
|
-
if (opts.install) runInstall(opts.targetDir, opts.packageManager);
|
|
560
|
-
if (opts.initGit) gitInit(opts.targetDir, opts.projectName);
|
|
561
|
-
}
|
|
541
|
+
|
|
542
|
+
// src/lib/scaffold-pkg.ts
|
|
543
|
+
import { readFile as readFile3, writeFile as writeFile3, mkdir, readdir } from "fs/promises";
|
|
544
|
+
import { join as join3 } from "path";
|
|
562
545
|
async function writePnpmWorkspace(targetDir) {
|
|
563
|
-
const pkgPath =
|
|
564
|
-
const pkg = JSON.parse(await
|
|
546
|
+
const pkgPath = join3(targetDir, "package.json");
|
|
547
|
+
const pkg = JSON.parse(await readFile3(pkgPath, "utf8"));
|
|
565
548
|
const workspaces = pkg.workspaces ?? [];
|
|
566
549
|
const packagesBlock = workspaces.map((p2) => ` - '${p2}'`).join("\n");
|
|
567
550
|
const allowBuilds = [
|
|
@@ -582,23 +565,22 @@ ${packagesBlock}
|
|
|
582
565
|
allowBuilds:
|
|
583
566
|
${allowBuilds}
|
|
584
567
|
`;
|
|
585
|
-
await
|
|
568
|
+
await writeFile3(join3(targetDir, "pnpm-workspace.yaml"), content);
|
|
586
569
|
}
|
|
587
570
|
async function rewritePnpmWorkspaceDeps(targetDir) {
|
|
588
|
-
const { readdir: rd } = await import("fs/promises");
|
|
589
571
|
async function walk(dir) {
|
|
590
572
|
const found = [];
|
|
591
573
|
let entries;
|
|
592
574
|
try {
|
|
593
|
-
entries = await
|
|
575
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
594
576
|
} catch {
|
|
595
577
|
return found;
|
|
596
578
|
}
|
|
597
579
|
for (const e of entries) {
|
|
598
580
|
if (e.isDirectory() && e.name !== "node_modules") {
|
|
599
|
-
found.push(...await walk(
|
|
581
|
+
found.push(...await walk(join3(dir, e.name)));
|
|
600
582
|
} else if (e.isFile() && e.name === "package.json") {
|
|
601
|
-
found.push(
|
|
583
|
+
found.push(join3(dir, e.name));
|
|
602
584
|
}
|
|
603
585
|
}
|
|
604
586
|
return found;
|
|
@@ -606,17 +588,17 @@ async function rewritePnpmWorkspaceDeps(targetDir) {
|
|
|
606
588
|
const pkgFiles = await walk(targetDir);
|
|
607
589
|
for (const f of pkgFiles) {
|
|
608
590
|
try {
|
|
609
|
-
const raw = await
|
|
591
|
+
const raw = await readFile3(f, "utf8");
|
|
610
592
|
const next = raw.replace(/"(@icore\/[^"]+)":\s*"\*"/g, '"$1": "workspace:*"');
|
|
611
|
-
if (next !== raw) await
|
|
593
|
+
if (next !== raw) await writeFile3(f, next);
|
|
612
594
|
} catch {
|
|
613
595
|
}
|
|
614
596
|
}
|
|
615
597
|
}
|
|
616
598
|
async function patchGitignoreForPm(targetDir, pm) {
|
|
617
|
-
const giPath =
|
|
599
|
+
const giPath = join3(targetDir, ".gitignore");
|
|
618
600
|
try {
|
|
619
|
-
let src = await
|
|
601
|
+
let src = await readFile3(giPath, "utf8");
|
|
620
602
|
src = src.replace(/^# Build artifacts.*\ntools\/create-icore\/templates\/\s*\n/m, "");
|
|
621
603
|
if (pm !== "yarn") {
|
|
622
604
|
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, "");
|
|
@@ -631,7 +613,7 @@ async function patchGitignoreForPm(targetDir, pm) {
|
|
|
631
613
|
src += "\n# npm\nnpm-debug.log*\n";
|
|
632
614
|
}
|
|
633
615
|
}
|
|
634
|
-
await
|
|
616
|
+
await writeFile3(giPath, src);
|
|
635
617
|
} catch {
|
|
636
618
|
}
|
|
637
619
|
}
|
|
@@ -646,7 +628,7 @@ async function writeAiFiles(targetDir, opts) {
|
|
|
646
628
|
if (opts.jobs !== "none") activeMSes.push(`jobs (standalone)`);
|
|
647
629
|
const usesSupabase = opts.authProvider === "supabase" || opts.dbProvider === "supabase" || opts.upload === "supabase";
|
|
648
630
|
const usesFirebase = opts.authProvider === "firebase" || opts.dbProvider === "firebase" || opts.upload === "firebase";
|
|
649
|
-
await
|
|
631
|
+
await writeFile3(join3(targetDir, "CLAUDE.md"), "@AGENTS.md\n");
|
|
650
632
|
const uiLabel = { shadcn: "shadcn/ui + Tailwind", antd: "Ant Design 6", mui: "MUI 6" }[opts.ui];
|
|
651
633
|
const readme = `# ${opts.projectName}
|
|
652
634
|
|
|
@@ -696,7 +678,7 @@ ${pm === "yarn" ? "yarn remove-notes" : pm === "pnpm" ? "pnpm remove-notes" : "n
|
|
|
696
678
|
|
|
697
679
|
Apache-2.0
|
|
698
680
|
`;
|
|
699
|
-
await
|
|
681
|
+
await writeFile3(join3(targetDir, "README.md"), readme);
|
|
700
682
|
const agents = `# ${opts.projectName} \u2014 Agent Instructions
|
|
701
683
|
|
|
702
684
|
## Stack snapshot
|
|
@@ -777,8 +759,8 @@ ${opts.upload !== "none" ? `| \`apps/microservices/upload/.env\` | \`STORAGE_PRO
|
|
|
777
759
|
- Test behaviour, not implementation. Fake strategies from \`@icore/shared\` (FakeAuthStrategy etc.) serve as test doubles.
|
|
778
760
|
- Run: \`${nx} test <project>\`
|
|
779
761
|
`;
|
|
780
|
-
await
|
|
781
|
-
await mkdir(
|
|
762
|
+
await writeFile3(join3(targetDir, "AGENTS.md"), agents);
|
|
763
|
+
await mkdir(join3(targetDir, ".claude"), { recursive: true });
|
|
782
764
|
const mcpServers = {
|
|
783
765
|
nx: {
|
|
784
766
|
command: "npx",
|
|
@@ -819,17 +801,140 @@ ${opts.upload !== "none" ? `| \`apps/microservices/upload/.env\` | \`STORAGE_PRO
|
|
|
819
801
|
]
|
|
820
802
|
}
|
|
821
803
|
};
|
|
822
|
-
await
|
|
823
|
-
|
|
804
|
+
await writeFile3(
|
|
805
|
+
join3(targetDir, ".claude", "settings.json"),
|
|
824
806
|
JSON.stringify(settings, null, 2) + "\n"
|
|
825
807
|
);
|
|
826
808
|
}
|
|
827
809
|
|
|
810
|
+
// src/lib/scaffold.ts
|
|
811
|
+
var IGNORE_TOP = /* @__PURE__ */ new Set([
|
|
812
|
+
".git",
|
|
813
|
+
"node_modules",
|
|
814
|
+
".yarn/cache",
|
|
815
|
+
".yarn/unplugged",
|
|
816
|
+
".yarn/install-state.gz",
|
|
817
|
+
".nx",
|
|
818
|
+
"dist",
|
|
819
|
+
"tmp",
|
|
820
|
+
"coverage",
|
|
821
|
+
".idea",
|
|
822
|
+
".vscode"
|
|
823
|
+
]);
|
|
824
|
+
async function copyTree(src, dest) {
|
|
825
|
+
await mkdir2(dest, { recursive: true });
|
|
826
|
+
const entries = await readdir2(src, { withFileTypes: true });
|
|
827
|
+
for (const entry of entries) {
|
|
828
|
+
if (IGNORE_TOP.has(entry.name)) continue;
|
|
829
|
+
const s = join4(src, entry.name);
|
|
830
|
+
const d = join4(dest, entry.name);
|
|
831
|
+
if (entry.isDirectory()) await copyTree(s, d);
|
|
832
|
+
else if (entry.isFile()) await copyFile(s, d);
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
async function selectClientTemplate(targetDir, opts) {
|
|
836
|
+
const templatesRoot = join4(targetDir, "apps/templates");
|
|
837
|
+
const chosen = join4(templatesRoot, `client-${opts.ui}`);
|
|
838
|
+
const destClient = join4(targetDir, "apps/client");
|
|
839
|
+
let chosenUi = opts.ui;
|
|
840
|
+
try {
|
|
841
|
+
const s = await stat(chosen);
|
|
842
|
+
if (!s.isDirectory()) throw new Error("not a dir");
|
|
843
|
+
await copyTree(chosen, destClient);
|
|
844
|
+
} catch {
|
|
845
|
+
chosenUi = "shadcn";
|
|
846
|
+
await copyTree(join4(templatesRoot, "client-shadcn"), destClient);
|
|
847
|
+
}
|
|
848
|
+
await rm2(templatesRoot, { recursive: true, force: true });
|
|
849
|
+
await rewriteClientPaths(destClient, chosenUi);
|
|
850
|
+
}
|
|
851
|
+
async function rewriteClientPaths(clientDir, ui) {
|
|
852
|
+
const candidates = [
|
|
853
|
+
"vite.config.mts",
|
|
854
|
+
"tsconfig.json",
|
|
855
|
+
"tsconfig.app.json",
|
|
856
|
+
"tsconfig.spec.json",
|
|
857
|
+
"project.json",
|
|
858
|
+
"eslint.config.mjs"
|
|
859
|
+
];
|
|
860
|
+
for (const rel of candidates) {
|
|
861
|
+
const path = join4(clientDir, rel);
|
|
862
|
+
try {
|
|
863
|
+
const raw = await readFile4(path, "utf8");
|
|
864
|
+
const next = raw.replaceAll("../../../", "../../").replaceAll(`apps/templates/client-${ui}`, "apps/client").replaceAll(`client-${ui}`, "client");
|
|
865
|
+
if (next !== raw) await writeFile4(path, next);
|
|
866
|
+
} catch {
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
function gitInit(cwd, projectName) {
|
|
871
|
+
spawnSync("git", ["init"], { cwd, stdio: "inherit" });
|
|
872
|
+
spawnSync("git", ["add", "."], { cwd, stdio: "inherit" });
|
|
873
|
+
spawnSync(
|
|
874
|
+
"git",
|
|
875
|
+
["commit", "-m", `chore: bootstrap ${projectName} from @idevconn/create-icore`],
|
|
876
|
+
{ cwd, stdio: "inherit" }
|
|
877
|
+
);
|
|
878
|
+
}
|
|
879
|
+
function resolveYarnBin(cwd) {
|
|
880
|
+
try {
|
|
881
|
+
const yarnrc = readFileSync(join4(cwd, ".yarnrc.yml"), "utf8");
|
|
882
|
+
const match = yarnrc.match(/^yarnPath:\s*(.+)$/m);
|
|
883
|
+
if (match?.[1]) return join4(cwd, match[1].trim());
|
|
884
|
+
} catch {
|
|
885
|
+
}
|
|
886
|
+
return join4(cwd, ".yarn", "releases", "yarn-4.5.0.cjs");
|
|
887
|
+
}
|
|
888
|
+
function runInstall(cwd, pm) {
|
|
889
|
+
if (pm === "yarn") {
|
|
890
|
+
spawnSync("node", [resolveYarnBin(cwd), "install"], { cwd, stdio: "inherit" });
|
|
891
|
+
} else if (pm === "npm") {
|
|
892
|
+
spawnSync("npm", ["install"], { cwd, stdio: "inherit" });
|
|
893
|
+
} else {
|
|
894
|
+
spawnSync("pnpm", ["install"], { cwd, stdio: "inherit" });
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
async function scaffold(opts, templatesDir) {
|
|
898
|
+
await copyTree(templatesDir, opts.targetDir);
|
|
899
|
+
await rewriteRootPackageJson(opts.targetDir, opts);
|
|
900
|
+
await writeAuthEnv(opts.targetDir, opts);
|
|
901
|
+
await writeUploadEnv(opts.targetDir, opts);
|
|
902
|
+
await writeNotesEnv(opts.targetDir, opts);
|
|
903
|
+
await writePaymentEnv(opts.targetDir, opts);
|
|
904
|
+
await writeGatewayEnv(opts.targetDir, opts);
|
|
905
|
+
await writeRootEnv(opts.targetDir, opts);
|
|
906
|
+
await selectClientTemplate(opts.targetDir, opts);
|
|
907
|
+
await writeClientEnv(opts.targetDir);
|
|
908
|
+
if (opts.upload === "none") await removeUploadStack(opts.targetDir);
|
|
909
|
+
if (opts.payment === "none") await removePaymentStack(opts.targetDir);
|
|
910
|
+
if (opts.jobs === "none") await removeJobsStack(opts.targetDir);
|
|
911
|
+
if (opts.example === "none") await removeNotesStack(opts.targetDir);
|
|
912
|
+
await removeUnusedAuthStrategies(opts.targetDir, opts.authProvider);
|
|
913
|
+
await removeUnusedStorageStrategies(opts.targetDir, opts.upload);
|
|
914
|
+
await removeUnusedDbStrategies(opts.targetDir, opts.dbProvider);
|
|
915
|
+
const firebaseUsed = opts.authProvider === "firebase" || opts.dbProvider === "firebase" || opts.upload === "firebase";
|
|
916
|
+
if (!firebaseUsed) await removeFirebaseAdminLib(opts.targetDir);
|
|
917
|
+
if (opts.packageManager === "yarn") {
|
|
918
|
+
await writeFile4(join4(opts.targetDir, "yarn.lock"), "");
|
|
919
|
+
} else {
|
|
920
|
+
await rm2(join4(opts.targetDir, ".yarn"), { recursive: true, force: true });
|
|
921
|
+
await rm2(join4(opts.targetDir, ".yarnrc.yml"), { force: true });
|
|
922
|
+
}
|
|
923
|
+
if (opts.packageManager === "pnpm") {
|
|
924
|
+
await writePnpmWorkspace(opts.targetDir);
|
|
925
|
+
await rewritePnpmWorkspaceDeps(opts.targetDir);
|
|
926
|
+
}
|
|
927
|
+
await patchGitignoreForPm(opts.targetDir, opts.packageManager);
|
|
928
|
+
await writeAiFiles(opts.targetDir, opts);
|
|
929
|
+
if (opts.install) runInstall(opts.targetDir, opts.packageManager);
|
|
930
|
+
if (opts.initGit) gitInit(opts.targetDir, opts.projectName);
|
|
931
|
+
}
|
|
932
|
+
|
|
828
933
|
// src/lib/prompts.ts
|
|
829
934
|
import * as p from "@clack/prompts";
|
|
830
935
|
import { resolve } from "path";
|
|
831
|
-
import { readFile as
|
|
832
|
-
import { dirname, join as
|
|
936
|
+
import { readFile as readFile5 } from "fs/promises";
|
|
937
|
+
import { dirname, join as join5 } from "path";
|
|
833
938
|
import { fileURLToPath } from "url";
|
|
834
939
|
function detectPackageManager() {
|
|
835
940
|
const ua = process.env["npm_config_user_agent"] ?? "";
|
|
@@ -841,7 +946,7 @@ function detectPackageManager() {
|
|
|
841
946
|
async function readSelfVersion() {
|
|
842
947
|
try {
|
|
843
948
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
844
|
-
const pkgRaw = await
|
|
949
|
+
const pkgRaw = await readFile5(join5(here, "..", "package.json"), "utf8");
|
|
845
950
|
const pkg = JSON.parse(pkgRaw);
|
|
846
951
|
return pkg.version ?? null;
|
|
847
952
|
} catch {
|
|
@@ -942,7 +1047,8 @@ Re-run with @latest to refresh:
|
|
|
942
1047
|
message: "Auth provider",
|
|
943
1048
|
options: [
|
|
944
1049
|
{ value: "supabase", label: "Supabase" },
|
|
945
|
-
{ value: "firebase", label: "Firebase" }
|
|
1050
|
+
{ value: "firebase", label: "Firebase" },
|
|
1051
|
+
{ value: "mongodb", label: "MongoDB (Custom Auth)" }
|
|
946
1052
|
]
|
|
947
1053
|
});
|
|
948
1054
|
if (p.isCancel(authProvider)) throw new Error("cancelled");
|
|
@@ -950,7 +1056,8 @@ Re-run with @latest to refresh:
|
|
|
950
1056
|
message: "Database backend",
|
|
951
1057
|
options: [
|
|
952
1058
|
{ value: "supabase", label: "Supabase Postgres" },
|
|
953
|
-
{ value: "firebase", label: "Firestore" }
|
|
1059
|
+
{ value: "firebase", label: "Firestore" },
|
|
1060
|
+
{ value: "mongodb", label: "MongoDB" }
|
|
954
1061
|
],
|
|
955
1062
|
initialValue: authProvider
|
|
956
1063
|
});
|
|
@@ -961,6 +1068,7 @@ Re-run with @latest to refresh:
|
|
|
961
1068
|
{ value: "supabase", label: "Supabase Storage" },
|
|
962
1069
|
{ value: "firebase", label: "Firebase Cloud Storage" },
|
|
963
1070
|
{ value: "cloudinary", label: "Cloudinary" },
|
|
1071
|
+
{ value: "mongodb", label: "MongoDB GridFS" },
|
|
964
1072
|
{ value: "none", label: "None \u2014 skip the upload microservice" }
|
|
965
1073
|
]
|
|
966
1074
|
});
|