@idevconn/create-icore 0.5.2 → 0.6.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 +36 -27
- package/dist/index.cjs +36 -27
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +36 -27
- package/package.json +1 -1
- package/templates/apps/api/.env.example +20 -0
- package/templates/apps/api/tsconfig.json +6 -1
- package/templates/apps/microservices/auth/.env.example +5 -0
- package/templates/apps/microservices/auth/tsconfig.json +6 -1
- package/templates/apps/microservices/jobs/tsconfig.json +6 -1
- package/templates/apps/microservices/notes/.env.example +5 -0
- package/templates/apps/microservices/notes/tsconfig.json +6 -1
- package/templates/apps/microservices/notes-e2e/src/support/global.d.ts +6 -0
- package/templates/apps/microservices/payment/.env.example +5 -0
- package/templates/apps/microservices/payment/tsconfig.json +6 -1
- package/templates/apps/microservices/upload/.env.example +5 -0
- package/templates/apps/microservices/upload/tsconfig.json +6 -1
- package/templates/apps/templates/client-antd/src/components/AccessDeniedPage.tsx +1 -1
- package/templates/apps/templates/client-antd/src/components/layout/LayoutHeader.tsx +1 -1
- package/templates/apps/templates/client-antd/src/components/layout/LayoutSider.tsx +3 -3
- package/templates/apps/templates/client-antd/src/routes/_dashboard/dashboard.tsx +2 -2
- package/templates/apps/templates/client-antd/src/routes/_dashboard/notes.tsx +2 -2
- package/templates/apps/templates/client-antd/src/routes/_dashboard/profile.tsx +2 -2
- package/templates/apps/templates/client-antd/src/routes/auth.callback.tsx +1 -1
- package/templates/apps/templates/client-antd/src/routes/auth.oauth.callback.tsx +1 -1
- package/templates/apps/templates/client-antd/src/routes/login.tsx +1 -1
- package/templates/apps/templates/client-antd/tsconfig.json +6 -1
- package/templates/apps/templates/client-antd-e2e/src/icore.spec.ts +2 -2
- package/templates/apps/templates/client-mui/src/components/AccessDeniedPage.tsx +1 -1
- package/templates/apps/templates/client-mui/src/components/layout/LayoutHeader.tsx +1 -1
- package/templates/apps/templates/client-mui/src/components/layout/LayoutSider.tsx +3 -15
- package/templates/apps/templates/client-mui/src/routes/_dashboard/dashboard.tsx +2 -6
- package/templates/apps/templates/client-mui/src/routes/_dashboard/notes.tsx +2 -2
- package/templates/apps/templates/client-mui/src/routes/_dashboard/profile.tsx +3 -3
- package/templates/apps/templates/client-mui/src/routes/auth.callback.tsx +1 -1
- package/templates/apps/templates/client-mui/src/routes/auth.oauth.callback.tsx +1 -1
- package/templates/apps/templates/client-mui/src/routes/login.tsx +3 -3
- package/templates/apps/templates/client-mui/tsconfig.json +6 -1
- package/templates/apps/templates/client-mui-e2e/src/icore.spec.ts +2 -2
- package/templates/apps/templates/client-shadcn/src/components/AccessDeniedPage.tsx +1 -1
- package/templates/apps/templates/client-shadcn/src/components/layout/LayoutSider.tsx +3 -3
- package/templates/apps/templates/client-shadcn/src/components/notes/DeleteNoteConfirm.tsx +1 -1
- package/templates/apps/templates/client-shadcn/src/components/notes/NoteDialog.tsx +3 -3
- package/templates/apps/templates/client-shadcn/src/components/notes/NotesTable.tsx +1 -1
- package/templates/apps/templates/client-shadcn/src/components/ui/button.tsx +1 -1
- package/templates/apps/templates/client-shadcn/src/components/ui/card.tsx +1 -1
- package/templates/apps/templates/client-shadcn/src/components/ui/input.tsx +1 -1
- package/templates/apps/templates/client-shadcn/src/components/ui/label.tsx +1 -1
- package/templates/apps/templates/client-shadcn/src/routes/_dashboard/dashboard.tsx +3 -9
- package/templates/apps/templates/client-shadcn/src/routes/_dashboard/notes.tsx +6 -6
- package/templates/apps/templates/client-shadcn/src/routes/_dashboard/profile.tsx +7 -7
- package/templates/apps/templates/client-shadcn/src/routes/auth.callback.tsx +1 -1
- package/templates/apps/templates/client-shadcn/src/routes/auth.oauth.callback.tsx +1 -1
- package/templates/apps/templates/client-shadcn/src/routes/login.tsx +19 -12
- package/templates/apps/templates/client-shadcn/tsconfig.json +6 -1
- package/templates/libs/auth-strategies/firebase/src/lib/__tests__/firebase-auth.contract.unit.test.ts +6 -3
- package/templates/libs/auth-strategies/supabase/src/lib/__tests__/supabase-auth.contract.unit.test.ts +5 -2
- package/templates/libs/db-strategies/firestore/src/lib/__tests__/firestore-db.contract.unit.test.ts +1 -2
- package/templates/libs/db-strategies/supabase/src/lib/__tests__/supabase-db.contract.unit.test.ts +1 -2
- package/templates/libs/shared/src/__tests__/cross-boundary.unit.test.ts +2 -1
- package/templates/libs/shared/src/__tests__/transport.unit.test.ts +47 -8
- package/templates/libs/shared/src/abilities/subjects.ts +12 -1
- package/templates/libs/shared/src/strategies/__tests__/fake-auth.contract.unit.test.ts +2 -2
- package/templates/libs/shared/src/strategies/__tests__/fake-db.contract.unit.test.ts +2 -2
- package/templates/libs/shared/src/strategies/__tests__/fake-storage.contract.unit.test.ts +2 -2
- package/templates/libs/shared/src/transport.ts +41 -0
- package/templates/libs/storage-strategies/cloudinary/src/lib/__tests__/cloudinary-storage.contract.unit.test.ts +1 -2
- package/templates/libs/storage-strategies/firebase/src/lib/__tests__/firebase-storage.contract.unit.test.ts +1 -2
- package/templates/libs/storage-strategies/supabase/src/lib/__tests__/supabase-storage.contract.unit.test.ts +1 -2
- package/templates/libs/vite-plugins/src/index.d.mts +5 -7
- package/templates/libs/vite-plugins/src/index.mjs +1 -1
- package/templates/libs/vite-plugins/tsconfig.json +2 -1
package/dist/cli.js
CHANGED
|
@@ -195,7 +195,10 @@ Re-run with @latest to refresh:
|
|
|
195
195
|
options: [
|
|
196
196
|
{ value: "tcp", label: "TCP (default, no broker required)" },
|
|
197
197
|
{ value: "redis", label: "Redis" },
|
|
198
|
-
{ value: "nats", label: "NATS" }
|
|
198
|
+
{ value: "nats", label: "NATS" },
|
|
199
|
+
{ value: "mqtt", label: "MQTT" },
|
|
200
|
+
{ value: "rmq", label: "RabbitMQ" },
|
|
201
|
+
{ value: "kafka", label: "Kafka" }
|
|
199
202
|
],
|
|
200
203
|
initialValue: "tcp"
|
|
201
204
|
});
|
|
@@ -265,6 +268,24 @@ async function copyTree(src, dest) {
|
|
|
265
268
|
else if (entry.isFile()) await copyFile(s, d);
|
|
266
269
|
}
|
|
267
270
|
}
|
|
271
|
+
var TRANSPORT_ENV_TOKEN = {
|
|
272
|
+
redis: "REDIS",
|
|
273
|
+
nats: "NATS",
|
|
274
|
+
mqtt: "MQTT",
|
|
275
|
+
rmq: "RMQ",
|
|
276
|
+
kafka: "KAFKA"
|
|
277
|
+
};
|
|
278
|
+
var TRANSPORT_DEPS = {
|
|
279
|
+
nats: { nats: "^2.29.3" },
|
|
280
|
+
mqtt: { mqtt: "^5.15.1" },
|
|
281
|
+
rmq: { amqplib: "^2.0.1", "amqp-connection-manager": "^5.0.0" },
|
|
282
|
+
kafka: { kafkajs: "^2.2.4" }
|
|
283
|
+
};
|
|
284
|
+
function uncommentTransportEnv(text2, prefix, transport) {
|
|
285
|
+
const token = TRANSPORT_ENV_TOKEN[transport];
|
|
286
|
+
if (!token) return text2;
|
|
287
|
+
return text2.replace(new RegExp(`^# (${prefix}_${token}_[A-Z0-9_]*=)`, "gm"), "$1");
|
|
288
|
+
}
|
|
268
289
|
async function rewriteRootPackageJson(targetDir, opts) {
|
|
269
290
|
const pkgPath = join2(targetDir, "package.json");
|
|
270
291
|
const raw = await readFile2(pkgPath, "utf8");
|
|
@@ -273,9 +294,10 @@ async function rewriteRootPackageJson(targetDir, opts) {
|
|
|
273
294
|
pkg["version"] = "0.0.1";
|
|
274
295
|
pkg["private"] = true;
|
|
275
296
|
delete pkg.description;
|
|
276
|
-
|
|
297
|
+
const transportDeps = TRANSPORT_DEPS[opts.transport];
|
|
298
|
+
if (transportDeps) {
|
|
277
299
|
const deps = pkg["dependencies"] ??= {};
|
|
278
|
-
deps
|
|
300
|
+
Object.assign(deps, transportDeps);
|
|
279
301
|
}
|
|
280
302
|
if (opts.packageManager !== "yarn") {
|
|
281
303
|
delete pkg.packageManager;
|
|
@@ -302,9 +324,7 @@ async function writeAuthEnv(targetDir, opts) {
|
|
|
302
324
|
const envExample = join2(targetDir, "apps/microservices/auth/.env.example");
|
|
303
325
|
const env = await readFile2(envExample, "utf8");
|
|
304
326
|
let next = env.replace(/^AUTH_PROVIDER=.*$/m, `AUTH_PROVIDER=${opts.authProvider}`).replace(/^AUTH_TRANSPORT=.*$/m, `AUTH_TRANSPORT=${opts.transport}`);
|
|
305
|
-
|
|
306
|
-
next = next.replace(/^# (AUTH_(?:REDIS|NATS)_URL=)/m, "$1");
|
|
307
|
-
}
|
|
327
|
+
next = uncommentTransportEnv(next, "AUTH", opts.transport);
|
|
308
328
|
await writeFile(join2(targetDir, "apps/microservices/auth/.env"), next);
|
|
309
329
|
}
|
|
310
330
|
async function writeUploadEnv(targetDir, opts) {
|
|
@@ -312,9 +332,7 @@ async function writeUploadEnv(targetDir, opts) {
|
|
|
312
332
|
const envExample = join2(targetDir, "apps/microservices/upload/.env.example");
|
|
313
333
|
const env = await readFile2(envExample, "utf8");
|
|
314
334
|
let next = env.replace(/^STORAGE_PROVIDER=.*$/m, `STORAGE_PROVIDER=${opts.upload}`).replace(/^UPLOAD_TRANSPORT=.*$/m, `UPLOAD_TRANSPORT=${opts.transport}`);
|
|
315
|
-
|
|
316
|
-
next = next.replace(/^# (UPLOAD_(?:REDIS|NATS)_URL=)/m, "$1");
|
|
317
|
-
}
|
|
335
|
+
next = uncommentTransportEnv(next, "UPLOAD", opts.transport);
|
|
318
336
|
await writeFile(join2(targetDir, "apps/microservices/upload/.env"), next);
|
|
319
337
|
}
|
|
320
338
|
async function writeNotesEnv(targetDir, opts) {
|
|
@@ -323,9 +341,7 @@ async function writeNotesEnv(targetDir, opts) {
|
|
|
323
341
|
try {
|
|
324
342
|
const env = await readFile2(envExample, "utf8");
|
|
325
343
|
let next = env.replace(/^NOTES_TRANSPORT=.*$/m, `NOTES_TRANSPORT=${opts.transport}`);
|
|
326
|
-
|
|
327
|
-
next = next.replace(/^# (NOTES_(?:REDIS|NATS)_URL=)/m, "$1");
|
|
328
|
-
}
|
|
344
|
+
next = uncommentTransportEnv(next, "NOTES", opts.transport);
|
|
329
345
|
await writeFile(join2(targetDir, "apps/microservices/notes/.env"), next);
|
|
330
346
|
} catch {
|
|
331
347
|
}
|
|
@@ -334,8 +350,8 @@ async function writeGatewayEnv(targetDir, opts) {
|
|
|
334
350
|
const envExample = join2(targetDir, "apps/api/.env.example");
|
|
335
351
|
const env = await readFile2(envExample, "utf8");
|
|
336
352
|
let next = env.replace(/^AUTH_TRANSPORT=.*$/m, `AUTH_TRANSPORT=${opts.transport}`).replace(/^UPLOAD_TRANSPORT=.*$/m, `UPLOAD_TRANSPORT=${opts.transport}`).replace(/^NOTES_TRANSPORT=.*$/m, `NOTES_TRANSPORT=${opts.transport}`).replace(/^PAYMENT_TRANSPORT=.*$/m, `PAYMENT_TRANSPORT=${opts.transport}`);
|
|
337
|
-
|
|
338
|
-
next = next
|
|
353
|
+
for (const prefix of ["AUTH", "UPLOAD", "NOTES", "PAYMENT"]) {
|
|
354
|
+
next = uncommentTransportEnv(next, prefix, opts.transport);
|
|
339
355
|
}
|
|
340
356
|
await writeFile(join2(targetDir, "apps/api/.env"), next);
|
|
341
357
|
}
|
|
@@ -373,9 +389,7 @@ async function writePaymentEnv(targetDir, opts) {
|
|
|
373
389
|
try {
|
|
374
390
|
const env = await readFile2(envExample, "utf8");
|
|
375
391
|
let next = env.replace(/^PAYMENT_PROVIDER=.*$/m, `PAYMENT_PROVIDER=${opts.payment}`).replace(/^PAYMENT_TRANSPORT=.*$/m, `PAYMENT_TRANSPORT=${opts.transport}`);
|
|
376
|
-
|
|
377
|
-
next = next.replace(/^# (PAYMENT_(?:REDIS|NATS)_URL=)/m, "$1");
|
|
378
|
-
}
|
|
392
|
+
next = uncommentTransportEnv(next, "PAYMENT", opts.transport);
|
|
379
393
|
await writeFile(join2(targetDir, "apps/microservices/payment/.env"), next);
|
|
380
394
|
} catch {
|
|
381
395
|
}
|
|
@@ -476,21 +490,16 @@ async function removeNotesStack(targetDir) {
|
|
|
476
490
|
const siderPath = join2(targetDir, "apps/client/src/components/layout/LayoutSider.tsx");
|
|
477
491
|
try {
|
|
478
492
|
const src = await readFile2(siderPath, "utf8");
|
|
479
|
-
const next = src.replace(", StickyNote", "").replace(/\n {8}<Link\n {10}to="\/_dashboard\/notes"[\s\S]*?<\/Link>/, "").replace(", FileTextOutlined", "").replace(
|
|
493
|
+
const next = src.replace(", StickyNote", "").replace(/\n {8}<Link\n {10}to="\/(?:_dashboard\/)?notes"[\s\S]*?<\/Link>/, "").replace(", FileTextOutlined", "").replace(
|
|
480
494
|
"const selectedKey = pathname.includes('/notes')\n ? 'notes'\n : pathname.includes('/profile')",
|
|
481
495
|
"const selectedKey = pathname.includes('/profile')"
|
|
482
496
|
).replace(
|
|
483
|
-
|
|
484
|
-
{
|
|
485
|
-
key: 'notes',
|
|
486
|
-
icon: <FileTextOutlined />,
|
|
487
|
-
label: <Link to="/_dashboard/notes">{t('notes.title')}</Link>,
|
|
488
|
-
},`,
|
|
497
|
+
/\n {4}\{\n {6}key: 'notes',\n {6}icon: <FileTextOutlined \/>,\n {6}label: <Link to="\/(?:_dashboard\/)?notes">\{t\('notes\.title'\)\}<\/Link>,\n {4}\},/,
|
|
489
498
|
""
|
|
490
499
|
).replace("import NoteOutlinedIcon from '@mui/icons-material/NoteOutlined';\n", "").replace(
|
|
491
|
-
/\n {8}<ListItemButton\n {10}component=\{Link\}\n {10}to="\/_dashboard\/notes"[\s\S]*?<\/ListItemButton>/,
|
|
500
|
+
/\n {8}<ListItemButton\n {10}component=\{Link\}\n {10}to="\/(?:_dashboard\/)?notes"[\s\S]*?<\/ListItemButton>/,
|
|
492
501
|
""
|
|
493
|
-
).replace(/\n\s*<Link to="\/_dashboard\/notes">[\s\S]*?<\/Link>/m, "");
|
|
502
|
+
).replace(/\n\s*<Link to="\/(?:_dashboard\/)?notes">[\s\S]*?<\/Link>/m, "");
|
|
494
503
|
await writeFile(siderPath, next);
|
|
495
504
|
} catch {
|
|
496
505
|
}
|
|
@@ -874,7 +883,7 @@ Apache-2.0
|
|
|
874
883
|
|
|
875
884
|
- **Branch strategy**: \`dev\` is default. Cut \`feature/<name>\` or \`bug/<name>\` from dev. PRs only target dev. Never push directly to main.
|
|
876
885
|
- **No code without approval**: Propose changes first, wait for go-ahead.
|
|
877
|
-
-
|
|
886
|
+
- **RULE \u2014 no crash on missing .env**: MS factories must catch config errors, print a boxed banner with ALL missing vars, and return a Fake strategy in dev. In prod (\`NODE_ENV=production\`) throw the same banner. The \`formatEnvBanner\` + \`missingEnv\` helpers from \`@icore/shared\` handle this.
|
|
878
887
|
- **Post-coding routine**: \`npx prettier --write <files>\` \u2192 \`${nx} lint <project>\` \u2192 \`${nx} build <project>\` \u2014 all green before committing.
|
|
879
888
|
- **Nx generators only**: never hand-write \`project.json\` / tsconfig stacks. Use \`${nx} g @nx/<plugin>:<schematic>\`.
|
|
880
889
|
|
package/dist/index.cjs
CHANGED
|
@@ -74,6 +74,24 @@ async function copyTree(src, dest) {
|
|
|
74
74
|
else if (entry.isFile()) await (0, import_promises.copyFile)(s, d);
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
|
+
var TRANSPORT_ENV_TOKEN = {
|
|
78
|
+
redis: "REDIS",
|
|
79
|
+
nats: "NATS",
|
|
80
|
+
mqtt: "MQTT",
|
|
81
|
+
rmq: "RMQ",
|
|
82
|
+
kafka: "KAFKA"
|
|
83
|
+
};
|
|
84
|
+
var TRANSPORT_DEPS = {
|
|
85
|
+
nats: { nats: "^2.29.3" },
|
|
86
|
+
mqtt: { mqtt: "^5.15.1" },
|
|
87
|
+
rmq: { amqplib: "^2.0.1", "amqp-connection-manager": "^5.0.0" },
|
|
88
|
+
kafka: { kafkajs: "^2.2.4" }
|
|
89
|
+
};
|
|
90
|
+
function uncommentTransportEnv(text2, prefix, transport) {
|
|
91
|
+
const token = TRANSPORT_ENV_TOKEN[transport];
|
|
92
|
+
if (!token) return text2;
|
|
93
|
+
return text2.replace(new RegExp(`^# (${prefix}_${token}_[A-Z0-9_]*=)`, "gm"), "$1");
|
|
94
|
+
}
|
|
77
95
|
async function rewriteRootPackageJson(targetDir, opts) {
|
|
78
96
|
const pkgPath = (0, import_node_path.join)(targetDir, "package.json");
|
|
79
97
|
const raw = await (0, import_promises.readFile)(pkgPath, "utf8");
|
|
@@ -82,9 +100,10 @@ async function rewriteRootPackageJson(targetDir, opts) {
|
|
|
82
100
|
pkg["version"] = "0.0.1";
|
|
83
101
|
pkg["private"] = true;
|
|
84
102
|
delete pkg.description;
|
|
85
|
-
|
|
103
|
+
const transportDeps = TRANSPORT_DEPS[opts.transport];
|
|
104
|
+
if (transportDeps) {
|
|
86
105
|
const deps = pkg["dependencies"] ??= {};
|
|
87
|
-
deps
|
|
106
|
+
Object.assign(deps, transportDeps);
|
|
88
107
|
}
|
|
89
108
|
if (opts.packageManager !== "yarn") {
|
|
90
109
|
delete pkg.packageManager;
|
|
@@ -111,9 +130,7 @@ async function writeAuthEnv(targetDir, opts) {
|
|
|
111
130
|
const envExample = (0, import_node_path.join)(targetDir, "apps/microservices/auth/.env.example");
|
|
112
131
|
const env = await (0, import_promises.readFile)(envExample, "utf8");
|
|
113
132
|
let next = env.replace(/^AUTH_PROVIDER=.*$/m, `AUTH_PROVIDER=${opts.authProvider}`).replace(/^AUTH_TRANSPORT=.*$/m, `AUTH_TRANSPORT=${opts.transport}`);
|
|
114
|
-
|
|
115
|
-
next = next.replace(/^# (AUTH_(?:REDIS|NATS)_URL=)/m, "$1");
|
|
116
|
-
}
|
|
133
|
+
next = uncommentTransportEnv(next, "AUTH", opts.transport);
|
|
117
134
|
await (0, import_promises.writeFile)((0, import_node_path.join)(targetDir, "apps/microservices/auth/.env"), next);
|
|
118
135
|
}
|
|
119
136
|
async function writeUploadEnv(targetDir, opts) {
|
|
@@ -121,9 +138,7 @@ async function writeUploadEnv(targetDir, opts) {
|
|
|
121
138
|
const envExample = (0, import_node_path.join)(targetDir, "apps/microservices/upload/.env.example");
|
|
122
139
|
const env = await (0, import_promises.readFile)(envExample, "utf8");
|
|
123
140
|
let next = env.replace(/^STORAGE_PROVIDER=.*$/m, `STORAGE_PROVIDER=${opts.upload}`).replace(/^UPLOAD_TRANSPORT=.*$/m, `UPLOAD_TRANSPORT=${opts.transport}`);
|
|
124
|
-
|
|
125
|
-
next = next.replace(/^# (UPLOAD_(?:REDIS|NATS)_URL=)/m, "$1");
|
|
126
|
-
}
|
|
141
|
+
next = uncommentTransportEnv(next, "UPLOAD", opts.transport);
|
|
127
142
|
await (0, import_promises.writeFile)((0, import_node_path.join)(targetDir, "apps/microservices/upload/.env"), next);
|
|
128
143
|
}
|
|
129
144
|
async function writeNotesEnv(targetDir, opts) {
|
|
@@ -132,9 +147,7 @@ async function writeNotesEnv(targetDir, opts) {
|
|
|
132
147
|
try {
|
|
133
148
|
const env = await (0, import_promises.readFile)(envExample, "utf8");
|
|
134
149
|
let next = env.replace(/^NOTES_TRANSPORT=.*$/m, `NOTES_TRANSPORT=${opts.transport}`);
|
|
135
|
-
|
|
136
|
-
next = next.replace(/^# (NOTES_(?:REDIS|NATS)_URL=)/m, "$1");
|
|
137
|
-
}
|
|
150
|
+
next = uncommentTransportEnv(next, "NOTES", opts.transport);
|
|
138
151
|
await (0, import_promises.writeFile)((0, import_node_path.join)(targetDir, "apps/microservices/notes/.env"), next);
|
|
139
152
|
} catch {
|
|
140
153
|
}
|
|
@@ -143,8 +156,8 @@ async function writeGatewayEnv(targetDir, opts) {
|
|
|
143
156
|
const envExample = (0, import_node_path.join)(targetDir, "apps/api/.env.example");
|
|
144
157
|
const env = await (0, import_promises.readFile)(envExample, "utf8");
|
|
145
158
|
let next = env.replace(/^AUTH_TRANSPORT=.*$/m, `AUTH_TRANSPORT=${opts.transport}`).replace(/^UPLOAD_TRANSPORT=.*$/m, `UPLOAD_TRANSPORT=${opts.transport}`).replace(/^NOTES_TRANSPORT=.*$/m, `NOTES_TRANSPORT=${opts.transport}`).replace(/^PAYMENT_TRANSPORT=.*$/m, `PAYMENT_TRANSPORT=${opts.transport}`);
|
|
146
|
-
|
|
147
|
-
next = next
|
|
159
|
+
for (const prefix of ["AUTH", "UPLOAD", "NOTES", "PAYMENT"]) {
|
|
160
|
+
next = uncommentTransportEnv(next, prefix, opts.transport);
|
|
148
161
|
}
|
|
149
162
|
await (0, import_promises.writeFile)((0, import_node_path.join)(targetDir, "apps/api/.env"), next);
|
|
150
163
|
}
|
|
@@ -182,9 +195,7 @@ async function writePaymentEnv(targetDir, opts) {
|
|
|
182
195
|
try {
|
|
183
196
|
const env = await (0, import_promises.readFile)(envExample, "utf8");
|
|
184
197
|
let next = env.replace(/^PAYMENT_PROVIDER=.*$/m, `PAYMENT_PROVIDER=${opts.payment}`).replace(/^PAYMENT_TRANSPORT=.*$/m, `PAYMENT_TRANSPORT=${opts.transport}`);
|
|
185
|
-
|
|
186
|
-
next = next.replace(/^# (PAYMENT_(?:REDIS|NATS)_URL=)/m, "$1");
|
|
187
|
-
}
|
|
198
|
+
next = uncommentTransportEnv(next, "PAYMENT", opts.transport);
|
|
188
199
|
await (0, import_promises.writeFile)((0, import_node_path.join)(targetDir, "apps/microservices/payment/.env"), next);
|
|
189
200
|
} catch {
|
|
190
201
|
}
|
|
@@ -285,21 +296,16 @@ async function removeNotesStack(targetDir) {
|
|
|
285
296
|
const siderPath = (0, import_node_path.join)(targetDir, "apps/client/src/components/layout/LayoutSider.tsx");
|
|
286
297
|
try {
|
|
287
298
|
const src = await (0, import_promises.readFile)(siderPath, "utf8");
|
|
288
|
-
const next = src.replace(", StickyNote", "").replace(/\n {8}<Link\n {10}to="\/_dashboard\/notes"[\s\S]*?<\/Link>/, "").replace(", FileTextOutlined", "").replace(
|
|
299
|
+
const next = src.replace(", StickyNote", "").replace(/\n {8}<Link\n {10}to="\/(?:_dashboard\/)?notes"[\s\S]*?<\/Link>/, "").replace(", FileTextOutlined", "").replace(
|
|
289
300
|
"const selectedKey = pathname.includes('/notes')\n ? 'notes'\n : pathname.includes('/profile')",
|
|
290
301
|
"const selectedKey = pathname.includes('/profile')"
|
|
291
302
|
).replace(
|
|
292
|
-
|
|
293
|
-
{
|
|
294
|
-
key: 'notes',
|
|
295
|
-
icon: <FileTextOutlined />,
|
|
296
|
-
label: <Link to="/_dashboard/notes">{t('notes.title')}</Link>,
|
|
297
|
-
},`,
|
|
303
|
+
/\n {4}\{\n {6}key: 'notes',\n {6}icon: <FileTextOutlined \/>,\n {6}label: <Link to="\/(?:_dashboard\/)?notes">\{t\('notes\.title'\)\}<\/Link>,\n {4}\},/,
|
|
298
304
|
""
|
|
299
305
|
).replace("import NoteOutlinedIcon from '@mui/icons-material/NoteOutlined';\n", "").replace(
|
|
300
|
-
/\n {8}<ListItemButton\n {10}component=\{Link\}\n {10}to="\/_dashboard\/notes"[\s\S]*?<\/ListItemButton>/,
|
|
306
|
+
/\n {8}<ListItemButton\n {10}component=\{Link\}\n {10}to="\/(?:_dashboard\/)?notes"[\s\S]*?<\/ListItemButton>/,
|
|
301
307
|
""
|
|
302
|
-
).replace(/\n\s*<Link to="\/_dashboard\/notes">[\s\S]*?<\/Link>/m, "");
|
|
308
|
+
).replace(/\n\s*<Link to="\/(?:_dashboard\/)?notes">[\s\S]*?<\/Link>/m, "");
|
|
303
309
|
await (0, import_promises.writeFile)(siderPath, next);
|
|
304
310
|
} catch {
|
|
305
311
|
}
|
|
@@ -683,7 +689,7 @@ Apache-2.0
|
|
|
683
689
|
|
|
684
690
|
- **Branch strategy**: \`dev\` is default. Cut \`feature/<name>\` or \`bug/<name>\` from dev. PRs only target dev. Never push directly to main.
|
|
685
691
|
- **No code without approval**: Propose changes first, wait for go-ahead.
|
|
686
|
-
-
|
|
692
|
+
- **RULE \u2014 no crash on missing .env**: MS factories must catch config errors, print a boxed banner with ALL missing vars, and return a Fake strategy in dev. In prod (\`NODE_ENV=production\`) throw the same banner. The \`formatEnvBanner\` + \`missingEnv\` helpers from \`@icore/shared\` handle this.
|
|
687
693
|
- **Post-coding routine**: \`npx prettier --write <files>\` \u2192 \`${nx} lint <project>\` \u2192 \`${nx} build <project>\` \u2014 all green before committing.
|
|
688
694
|
- **Nx generators only**: never hand-write \`project.json\` / tsconfig stacks. Use \`${nx} g @nx/<plugin>:<schematic>\`.
|
|
689
695
|
|
|
@@ -980,7 +986,10 @@ Re-run with @latest to refresh:
|
|
|
980
986
|
options: [
|
|
981
987
|
{ value: "tcp", label: "TCP (default, no broker required)" },
|
|
982
988
|
{ value: "redis", label: "Redis" },
|
|
983
|
-
{ value: "nats", label: "NATS" }
|
|
989
|
+
{ value: "nats", label: "NATS" },
|
|
990
|
+
{ value: "mqtt", label: "MQTT" },
|
|
991
|
+
{ value: "rmq", label: "RabbitMQ" },
|
|
992
|
+
{ value: "kafka", label: "Kafka" }
|
|
984
993
|
],
|
|
985
994
|
initialValue: "tcp"
|
|
986
995
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -5,7 +5,7 @@ type PaymentProvider = 'paypal' | 'none';
|
|
|
5
5
|
type JobsProvider = 'bullmq' | 'none';
|
|
6
6
|
type ExampleMode = 'notes' | 'none';
|
|
7
7
|
type UiLibrary = 'shadcn' | 'antd' | 'mui';
|
|
8
|
-
type MsTransport = 'tcp' | 'redis' | 'nats';
|
|
8
|
+
type MsTransport = 'tcp' | 'redis' | 'nats' | 'mqtt' | 'rmq' | 'kafka';
|
|
9
9
|
type PackageManager = 'yarn' | 'npm' | 'pnpm';
|
|
10
10
|
/**
|
|
11
11
|
* Returns the correct invocation for a package.json script.
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ type PaymentProvider = 'paypal' | 'none';
|
|
|
5
5
|
type JobsProvider = 'bullmq' | 'none';
|
|
6
6
|
type ExampleMode = 'notes' | 'none';
|
|
7
7
|
type UiLibrary = 'shadcn' | 'antd' | 'mui';
|
|
8
|
-
type MsTransport = 'tcp' | 'redis' | 'nats';
|
|
8
|
+
type MsTransport = 'tcp' | 'redis' | 'nats' | 'mqtt' | 'rmq' | 'kafka';
|
|
9
9
|
type PackageManager = 'yarn' | 'npm' | 'pnpm';
|
|
10
10
|
/**
|
|
11
11
|
* Returns the correct invocation for a package.json script.
|
package/dist/index.js
CHANGED
|
@@ -32,6 +32,24 @@ async function copyTree(src, dest) {
|
|
|
32
32
|
else if (entry.isFile()) await copyFile(s, d);
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
+
var TRANSPORT_ENV_TOKEN = {
|
|
36
|
+
redis: "REDIS",
|
|
37
|
+
nats: "NATS",
|
|
38
|
+
mqtt: "MQTT",
|
|
39
|
+
rmq: "RMQ",
|
|
40
|
+
kafka: "KAFKA"
|
|
41
|
+
};
|
|
42
|
+
var TRANSPORT_DEPS = {
|
|
43
|
+
nats: { nats: "^2.29.3" },
|
|
44
|
+
mqtt: { mqtt: "^5.15.1" },
|
|
45
|
+
rmq: { amqplib: "^2.0.1", "amqp-connection-manager": "^5.0.0" },
|
|
46
|
+
kafka: { kafkajs: "^2.2.4" }
|
|
47
|
+
};
|
|
48
|
+
function uncommentTransportEnv(text2, prefix, transport) {
|
|
49
|
+
const token = TRANSPORT_ENV_TOKEN[transport];
|
|
50
|
+
if (!token) return text2;
|
|
51
|
+
return text2.replace(new RegExp(`^# (${prefix}_${token}_[A-Z0-9_]*=)`, "gm"), "$1");
|
|
52
|
+
}
|
|
35
53
|
async function rewriteRootPackageJson(targetDir, opts) {
|
|
36
54
|
const pkgPath = join(targetDir, "package.json");
|
|
37
55
|
const raw = await readFile(pkgPath, "utf8");
|
|
@@ -40,9 +58,10 @@ async function rewriteRootPackageJson(targetDir, opts) {
|
|
|
40
58
|
pkg["version"] = "0.0.1";
|
|
41
59
|
pkg["private"] = true;
|
|
42
60
|
delete pkg.description;
|
|
43
|
-
|
|
61
|
+
const transportDeps = TRANSPORT_DEPS[opts.transport];
|
|
62
|
+
if (transportDeps) {
|
|
44
63
|
const deps = pkg["dependencies"] ??= {};
|
|
45
|
-
deps
|
|
64
|
+
Object.assign(deps, transportDeps);
|
|
46
65
|
}
|
|
47
66
|
if (opts.packageManager !== "yarn") {
|
|
48
67
|
delete pkg.packageManager;
|
|
@@ -69,9 +88,7 @@ async function writeAuthEnv(targetDir, opts) {
|
|
|
69
88
|
const envExample = join(targetDir, "apps/microservices/auth/.env.example");
|
|
70
89
|
const env = await readFile(envExample, "utf8");
|
|
71
90
|
let next = env.replace(/^AUTH_PROVIDER=.*$/m, `AUTH_PROVIDER=${opts.authProvider}`).replace(/^AUTH_TRANSPORT=.*$/m, `AUTH_TRANSPORT=${opts.transport}`);
|
|
72
|
-
|
|
73
|
-
next = next.replace(/^# (AUTH_(?:REDIS|NATS)_URL=)/m, "$1");
|
|
74
|
-
}
|
|
91
|
+
next = uncommentTransportEnv(next, "AUTH", opts.transport);
|
|
75
92
|
await writeFile(join(targetDir, "apps/microservices/auth/.env"), next);
|
|
76
93
|
}
|
|
77
94
|
async function writeUploadEnv(targetDir, opts) {
|
|
@@ -79,9 +96,7 @@ async function writeUploadEnv(targetDir, opts) {
|
|
|
79
96
|
const envExample = join(targetDir, "apps/microservices/upload/.env.example");
|
|
80
97
|
const env = await readFile(envExample, "utf8");
|
|
81
98
|
let next = env.replace(/^STORAGE_PROVIDER=.*$/m, `STORAGE_PROVIDER=${opts.upload}`).replace(/^UPLOAD_TRANSPORT=.*$/m, `UPLOAD_TRANSPORT=${opts.transport}`);
|
|
82
|
-
|
|
83
|
-
next = next.replace(/^# (UPLOAD_(?:REDIS|NATS)_URL=)/m, "$1");
|
|
84
|
-
}
|
|
99
|
+
next = uncommentTransportEnv(next, "UPLOAD", opts.transport);
|
|
85
100
|
await writeFile(join(targetDir, "apps/microservices/upload/.env"), next);
|
|
86
101
|
}
|
|
87
102
|
async function writeNotesEnv(targetDir, opts) {
|
|
@@ -90,9 +105,7 @@ async function writeNotesEnv(targetDir, opts) {
|
|
|
90
105
|
try {
|
|
91
106
|
const env = await readFile(envExample, "utf8");
|
|
92
107
|
let next = env.replace(/^NOTES_TRANSPORT=.*$/m, `NOTES_TRANSPORT=${opts.transport}`);
|
|
93
|
-
|
|
94
|
-
next = next.replace(/^# (NOTES_(?:REDIS|NATS)_URL=)/m, "$1");
|
|
95
|
-
}
|
|
108
|
+
next = uncommentTransportEnv(next, "NOTES", opts.transport);
|
|
96
109
|
await writeFile(join(targetDir, "apps/microservices/notes/.env"), next);
|
|
97
110
|
} catch {
|
|
98
111
|
}
|
|
@@ -101,8 +114,8 @@ async function writeGatewayEnv(targetDir, opts) {
|
|
|
101
114
|
const envExample = join(targetDir, "apps/api/.env.example");
|
|
102
115
|
const env = await readFile(envExample, "utf8");
|
|
103
116
|
let next = env.replace(/^AUTH_TRANSPORT=.*$/m, `AUTH_TRANSPORT=${opts.transport}`).replace(/^UPLOAD_TRANSPORT=.*$/m, `UPLOAD_TRANSPORT=${opts.transport}`).replace(/^NOTES_TRANSPORT=.*$/m, `NOTES_TRANSPORT=${opts.transport}`).replace(/^PAYMENT_TRANSPORT=.*$/m, `PAYMENT_TRANSPORT=${opts.transport}`);
|
|
104
|
-
|
|
105
|
-
next = next
|
|
117
|
+
for (const prefix of ["AUTH", "UPLOAD", "NOTES", "PAYMENT"]) {
|
|
118
|
+
next = uncommentTransportEnv(next, prefix, opts.transport);
|
|
106
119
|
}
|
|
107
120
|
await writeFile(join(targetDir, "apps/api/.env"), next);
|
|
108
121
|
}
|
|
@@ -140,9 +153,7 @@ async function writePaymentEnv(targetDir, opts) {
|
|
|
140
153
|
try {
|
|
141
154
|
const env = await readFile(envExample, "utf8");
|
|
142
155
|
let next = env.replace(/^PAYMENT_PROVIDER=.*$/m, `PAYMENT_PROVIDER=${opts.payment}`).replace(/^PAYMENT_TRANSPORT=.*$/m, `PAYMENT_TRANSPORT=${opts.transport}`);
|
|
143
|
-
|
|
144
|
-
next = next.replace(/^# (PAYMENT_(?:REDIS|NATS)_URL=)/m, "$1");
|
|
145
|
-
}
|
|
156
|
+
next = uncommentTransportEnv(next, "PAYMENT", opts.transport);
|
|
146
157
|
await writeFile(join(targetDir, "apps/microservices/payment/.env"), next);
|
|
147
158
|
} catch {
|
|
148
159
|
}
|
|
@@ -243,21 +254,16 @@ async function removeNotesStack(targetDir) {
|
|
|
243
254
|
const siderPath = join(targetDir, "apps/client/src/components/layout/LayoutSider.tsx");
|
|
244
255
|
try {
|
|
245
256
|
const src = await readFile(siderPath, "utf8");
|
|
246
|
-
const next = src.replace(", StickyNote", "").replace(/\n {8}<Link\n {10}to="\/_dashboard\/notes"[\s\S]*?<\/Link>/, "").replace(", FileTextOutlined", "").replace(
|
|
257
|
+
const next = src.replace(", StickyNote", "").replace(/\n {8}<Link\n {10}to="\/(?:_dashboard\/)?notes"[\s\S]*?<\/Link>/, "").replace(", FileTextOutlined", "").replace(
|
|
247
258
|
"const selectedKey = pathname.includes('/notes')\n ? 'notes'\n : pathname.includes('/profile')",
|
|
248
259
|
"const selectedKey = pathname.includes('/profile')"
|
|
249
260
|
).replace(
|
|
250
|
-
|
|
251
|
-
{
|
|
252
|
-
key: 'notes',
|
|
253
|
-
icon: <FileTextOutlined />,
|
|
254
|
-
label: <Link to="/_dashboard/notes">{t('notes.title')}</Link>,
|
|
255
|
-
},`,
|
|
261
|
+
/\n {4}\{\n {6}key: 'notes',\n {6}icon: <FileTextOutlined \/>,\n {6}label: <Link to="\/(?:_dashboard\/)?notes">\{t\('notes\.title'\)\}<\/Link>,\n {4}\},/,
|
|
256
262
|
""
|
|
257
263
|
).replace("import NoteOutlinedIcon from '@mui/icons-material/NoteOutlined';\n", "").replace(
|
|
258
|
-
/\n {8}<ListItemButton\n {10}component=\{Link\}\n {10}to="\/_dashboard\/notes"[\s\S]*?<\/ListItemButton>/,
|
|
264
|
+
/\n {8}<ListItemButton\n {10}component=\{Link\}\n {10}to="\/(?:_dashboard\/)?notes"[\s\S]*?<\/ListItemButton>/,
|
|
259
265
|
""
|
|
260
|
-
).replace(/\n\s*<Link to="\/_dashboard\/notes">[\s\S]*?<\/Link>/m, "");
|
|
266
|
+
).replace(/\n\s*<Link to="\/(?:_dashboard\/)?notes">[\s\S]*?<\/Link>/m, "");
|
|
261
267
|
await writeFile(siderPath, next);
|
|
262
268
|
} catch {
|
|
263
269
|
}
|
|
@@ -641,7 +647,7 @@ Apache-2.0
|
|
|
641
647
|
|
|
642
648
|
- **Branch strategy**: \`dev\` is default. Cut \`feature/<name>\` or \`bug/<name>\` from dev. PRs only target dev. Never push directly to main.
|
|
643
649
|
- **No code without approval**: Propose changes first, wait for go-ahead.
|
|
644
|
-
-
|
|
650
|
+
- **RULE \u2014 no crash on missing .env**: MS factories must catch config errors, print a boxed banner with ALL missing vars, and return a Fake strategy in dev. In prod (\`NODE_ENV=production\`) throw the same banner. The \`formatEnvBanner\` + \`missingEnv\` helpers from \`@icore/shared\` handle this.
|
|
645
651
|
- **Post-coding routine**: \`npx prettier --write <files>\` \u2192 \`${nx} lint <project>\` \u2192 \`${nx} build <project>\` \u2014 all green before committing.
|
|
646
652
|
- **Nx generators only**: never hand-write \`project.json\` / tsconfig stacks. Use \`${nx} g @nx/<plugin>:<schematic>\`.
|
|
647
653
|
|
|
@@ -938,7 +944,10 @@ Re-run with @latest to refresh:
|
|
|
938
944
|
options: [
|
|
939
945
|
{ value: "tcp", label: "TCP (default, no broker required)" },
|
|
940
946
|
{ value: "redis", label: "Redis" },
|
|
941
|
-
{ value: "nats", label: "NATS" }
|
|
947
|
+
{ value: "nats", label: "NATS" },
|
|
948
|
+
{ value: "mqtt", label: "MQTT" },
|
|
949
|
+
{ value: "rmq", label: "RabbitMQ" },
|
|
950
|
+
{ value: "kafka", label: "Kafka" }
|
|
942
951
|
],
|
|
943
952
|
initialValue: "tcp"
|
|
944
953
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@idevconn/create-icore",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Bootstrap a new project from the iCore scaffold (Nx + NestJS + React + Vite + shadcn/Tailwind, swappable auth + storage providers).",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "iDEVconn",
|
|
@@ -7,6 +7,11 @@ AUTH_HOST=127.0.0.1
|
|
|
7
7
|
AUTH_PORT=4001
|
|
8
8
|
# AUTH_REDIS_URL=redis://localhost:6379
|
|
9
9
|
# AUTH_NATS_URL=nats://localhost:4222
|
|
10
|
+
# AUTH_MQTT_URL=mqtt://localhost:1883
|
|
11
|
+
# AUTH_RMQ_URL=amqp://localhost:5672
|
|
12
|
+
# AUTH_RMQ_QUEUE=auth_queue
|
|
13
|
+
# AUTH_KAFKA_BROKERS=localhost:9092
|
|
14
|
+
# AUTH_KAFKA_CLIENT_ID=auth
|
|
10
15
|
|
|
11
16
|
# Upload MS transport — must match apps/microservices/upload/.env
|
|
12
17
|
UPLOAD_TRANSPORT=tcp
|
|
@@ -14,6 +19,11 @@ UPLOAD_HOST=127.0.0.1
|
|
|
14
19
|
UPLOAD_PORT=4002
|
|
15
20
|
# UPLOAD_REDIS_URL=redis://localhost:6379
|
|
16
21
|
# UPLOAD_NATS_URL=nats://localhost:4222
|
|
22
|
+
# UPLOAD_MQTT_URL=mqtt://localhost:1883
|
|
23
|
+
# UPLOAD_RMQ_URL=amqp://localhost:5672
|
|
24
|
+
# UPLOAD_RMQ_QUEUE=upload_queue
|
|
25
|
+
# UPLOAD_KAFKA_BROKERS=localhost:9092
|
|
26
|
+
# UPLOAD_KAFKA_CLIENT_ID=upload
|
|
17
27
|
|
|
18
28
|
# Notes MS transport — must match apps/microservices/notes/.env
|
|
19
29
|
NOTES_TRANSPORT=tcp
|
|
@@ -21,6 +31,11 @@ NOTES_HOST=127.0.0.1
|
|
|
21
31
|
NOTES_PORT=4004
|
|
22
32
|
# NOTES_REDIS_URL=redis://localhost:6379
|
|
23
33
|
# NOTES_NATS_URL=nats://localhost:4222
|
|
34
|
+
# NOTES_MQTT_URL=mqtt://localhost:1883
|
|
35
|
+
# NOTES_RMQ_URL=amqp://localhost:5672
|
|
36
|
+
# NOTES_RMQ_QUEUE=notes_queue
|
|
37
|
+
# NOTES_KAFKA_BROKERS=localhost:9092
|
|
38
|
+
# NOTES_KAFKA_CLIENT_ID=notes
|
|
24
39
|
|
|
25
40
|
# Payment MS transport — must match apps/microservices/payment/.env
|
|
26
41
|
PAYMENT_TRANSPORT=tcp
|
|
@@ -28,6 +43,11 @@ PAYMENT_HOST=127.0.0.1
|
|
|
28
43
|
PAYMENT_PORT=4003
|
|
29
44
|
# PAYMENT_REDIS_URL=redis://localhost:6379
|
|
30
45
|
# PAYMENT_NATS_URL=nats://localhost:4222
|
|
46
|
+
# PAYMENT_MQTT_URL=mqtt://localhost:1883
|
|
47
|
+
# PAYMENT_RMQ_URL=amqp://localhost:5672
|
|
48
|
+
# PAYMENT_RMQ_QUEUE=payment_queue
|
|
49
|
+
# PAYMENT_KAFKA_BROKERS=localhost:9092
|
|
50
|
+
# PAYMENT_KAFKA_CLIENT_ID=payment
|
|
31
51
|
|
|
32
52
|
# Per-request multipart file size cap (KB). Default 5120 (5 MB) when unset.
|
|
33
53
|
MAX_FILE_SIZE_KB=5120
|
|
@@ -4,6 +4,11 @@ AUTH_HOST=127.0.0.1
|
|
|
4
4
|
AUTH_PORT=4001
|
|
5
5
|
# AUTH_REDIS_URL=redis://localhost:6379
|
|
6
6
|
# AUTH_NATS_URL=nats://localhost:4222
|
|
7
|
+
# AUTH_MQTT_URL=mqtt://localhost:1883
|
|
8
|
+
# AUTH_RMQ_URL=amqp://localhost:5672
|
|
9
|
+
# AUTH_RMQ_QUEUE=auth_queue
|
|
10
|
+
# AUTH_KAFKA_BROKERS=localhost:9092
|
|
11
|
+
# AUTH_KAFKA_CLIENT_ID=auth
|
|
7
12
|
|
|
8
13
|
# Which concrete AuthStrategy to instantiate
|
|
9
14
|
AUTH_PROVIDER=supabase
|
|
@@ -4,6 +4,11 @@ NOTES_HOST=127.0.0.1
|
|
|
4
4
|
NOTES_PORT=4004
|
|
5
5
|
# NOTES_REDIS_URL=redis://localhost:6379
|
|
6
6
|
# NOTES_NATS_URL=nats://localhost:4222
|
|
7
|
+
# NOTES_MQTT_URL=mqtt://localhost:1883
|
|
8
|
+
# NOTES_RMQ_URL=amqp://localhost:5672
|
|
9
|
+
# NOTES_RMQ_QUEUE=notes_queue
|
|
10
|
+
# NOTES_KAFKA_BROKERS=localhost:9092
|
|
11
|
+
# NOTES_KAFKA_CLIENT_ID=notes
|
|
7
12
|
|
|
8
13
|
# Which DB to use — defaults to the root .env DB_PROVIDER if unset.
|
|
9
14
|
# Supabase Postgres or Firestore. Both honored by NotesController via DBStrategy.
|
|
@@ -4,6 +4,11 @@ PAYMENT_HOST=127.0.0.1
|
|
|
4
4
|
PAYMENT_PORT=4003
|
|
5
5
|
# PAYMENT_REDIS_URL=redis://localhost:6379
|
|
6
6
|
# PAYMENT_NATS_URL=nats://localhost:4222
|
|
7
|
+
# PAYMENT_MQTT_URL=mqtt://localhost:1883
|
|
8
|
+
# PAYMENT_RMQ_URL=amqp://localhost:5672
|
|
9
|
+
# PAYMENT_RMQ_QUEUE=payment_queue
|
|
10
|
+
# PAYMENT_KAFKA_BROKERS=localhost:9092
|
|
11
|
+
# PAYMENT_KAFKA_CLIENT_ID=payment
|
|
7
12
|
|
|
8
13
|
# Which concrete PaymentStrategy to instantiate
|
|
9
14
|
PAYMENT_PROVIDER=paypal
|
|
@@ -4,6 +4,11 @@ UPLOAD_HOST=127.0.0.1
|
|
|
4
4
|
UPLOAD_PORT=4002
|
|
5
5
|
# UPLOAD_REDIS_URL=redis://localhost:6379
|
|
6
6
|
# UPLOAD_NATS_URL=nats://localhost:4222
|
|
7
|
+
# UPLOAD_MQTT_URL=mqtt://localhost:1883
|
|
8
|
+
# UPLOAD_RMQ_URL=amqp://localhost:5672
|
|
9
|
+
# UPLOAD_RMQ_QUEUE=upload_queue
|
|
10
|
+
# UPLOAD_KAFKA_BROKERS=localhost:9092
|
|
11
|
+
# UPLOAD_KAFKA_CLIENT_ID=upload
|
|
7
12
|
|
|
8
13
|
# Which concrete StorageStrategy to instantiate
|
|
9
14
|
STORAGE_PROVIDER=supabase
|