create-forgeon 0.3.16 → 0.3.18
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/package.json +1 -1
- package/src/cli/add-options.test.mjs +5 -2
- package/src/cli/options.test.mjs +1 -0
- package/src/cli/prompt-select.test.mjs +1 -0
- package/src/core/docs.test.mjs +1 -0
- package/src/core/scaffold.test.mjs +1 -0
- package/src/core/validate.test.mjs +1 -0
- package/src/modules/accounts.mjs +416 -0
- package/src/modules/db-prisma.mjs +5 -9
- package/src/modules/dependencies.test.mjs +71 -29
- package/src/modules/executor.mjs +3 -2
- package/src/modules/executor.test.mjs +521 -477
- package/src/modules/files-access.mjs +9 -7
- package/src/modules/files-image.mjs +9 -7
- package/src/modules/files-local.mjs +15 -6
- package/src/modules/files-quotas.mjs +8 -6
- package/src/modules/files-s3.mjs +17 -6
- package/src/modules/files.mjs +21 -21
- package/src/modules/idempotency.test.mjs +13 -7
- package/src/modules/probes.test.mjs +4 -2
- package/src/modules/queue.mjs +9 -6
- package/src/modules/rate-limit.mjs +14 -10
- package/src/modules/rbac.mjs +12 -11
- package/src/modules/registry.mjs +22 -35
- package/src/modules/scheduler.mjs +9 -6
- package/src/modules/shared/files-runtime-wiring.mjs +81 -0
- package/src/modules/shared/patch-utils.mjs +29 -1
- package/src/modules/sync-integrations.mjs +102 -422
- package/src/modules/sync-integrations.test.mjs +32 -111
- package/src/run-add-module.test.mjs +1 -0
- package/templates/base/scripts/forgeon-sync-integrations.mjs +65 -325
- package/templates/module-fragments/{jwt-auth → accounts}/00_title.md +2 -1
- package/templates/module-fragments/{jwt-auth → accounts}/10_overview.md +5 -5
- package/templates/module-fragments/accounts/20_scope.md +29 -0
- package/templates/module-fragments/accounts/90_status_implemented.md +8 -0
- package/templates/module-fragments/accounts/90_status_planned.md +7 -0
- package/templates/module-fragments/rbac/30_what_it_adds.md +3 -2
- package/templates/module-fragments/rbac/40_how_it_works.md +2 -1
- package/templates/module-fragments/rbac/50_how_to_use.md +2 -1
- package/templates/module-fragments/swagger/20_scope.md +2 -1
- package/templates/module-presets/accounts/apps/api/prisma/migrations/0002_accounts_core/migration.sql +97 -0
- package/templates/module-presets/accounts/apps/api/src/accounts/forgeon-accounts-db-prisma.module.ts +17 -0
- package/templates/module-presets/accounts/apps/api/src/accounts/prisma-accounts-persistence.store.ts +332 -0
- package/templates/module-presets/{jwt-auth/packages/auth-api → accounts/packages/accounts-api}/package.json +5 -5
- package/templates/module-presets/accounts/packages/accounts-api/src/accounts-email.port.ts +13 -0
- package/templates/module-presets/accounts/packages/accounts-api/src/accounts-persistence.port.ts +67 -0
- package/templates/module-presets/accounts/packages/accounts-api/src/accounts-rbac.port.ts +14 -0
- package/templates/module-presets/{jwt-auth/packages/auth-api → accounts/packages/accounts-api}/src/auth-config.loader.ts +7 -7
- package/templates/module-presets/{jwt-auth/packages/auth-api → accounts/packages/accounts-api}/src/auth-config.service.ts +7 -7
- package/templates/module-presets/accounts/packages/accounts-api/src/auth-core.service.ts +318 -0
- package/templates/module-presets/{jwt-auth/packages/auth-api → accounts/packages/accounts-api}/src/auth-env.schema.ts +4 -4
- package/templates/module-presets/accounts/packages/accounts-api/src/auth-jwt.service.ts +58 -0
- package/templates/module-presets/accounts/packages/accounts-api/src/auth-password.service.ts +21 -0
- package/templates/module-presets/accounts/packages/accounts-api/src/auth.controller.ts +93 -0
- package/templates/module-presets/accounts/packages/accounts-api/src/auth.service.ts +48 -0
- package/templates/module-presets/accounts/packages/accounts-api/src/auth.types.ts +17 -0
- package/templates/module-presets/accounts/packages/accounts-api/src/dto/change-password.dto.ts +13 -0
- package/templates/module-presets/accounts/packages/accounts-api/src/dto/confirm-password-reset.dto.ts +12 -0
- package/templates/module-presets/accounts/packages/accounts-api/src/dto/index.ts +10 -0
- package/templates/module-presets/{jwt-auth/packages/auth-api → accounts/packages/accounts-api}/src/dto/login.dto.ts +1 -1
- package/templates/module-presets/{jwt-auth/packages/auth-api → accounts/packages/accounts-api}/src/dto/refresh.dto.ts +1 -1
- package/templates/module-presets/accounts/packages/accounts-api/src/dto/register.dto.ts +23 -0
- package/templates/module-presets/accounts/packages/accounts-api/src/dto/request-password-reset.dto.ts +7 -0
- package/templates/module-presets/accounts/packages/accounts-api/src/dto/update-user-profile.dto.ts +16 -0
- package/templates/module-presets/accounts/packages/accounts-api/src/dto/update-user-settings.dto.ts +16 -0
- package/templates/module-presets/accounts/packages/accounts-api/src/dto/update-user.dto.ts +8 -0
- package/templates/module-presets/accounts/packages/accounts-api/src/dto/verify-email.dto.ts +8 -0
- package/templates/module-presets/accounts/packages/accounts-api/src/forgeon-accounts.module.ts +82 -0
- package/templates/module-presets/accounts/packages/accounts-api/src/index.ts +24 -0
- package/templates/module-presets/{jwt-auth/packages/auth-api → accounts/packages/accounts-api}/src/jwt.strategy.ts +3 -3
- package/templates/module-presets/accounts/packages/accounts-api/src/owner-access.guard.ts +39 -0
- package/templates/module-presets/accounts/packages/accounts-api/src/users-config.ts +13 -0
- package/templates/module-presets/accounts/packages/accounts-api/src/users.controller.ts +65 -0
- package/templates/module-presets/accounts/packages/accounts-api/src/users.service.ts +87 -0
- package/templates/module-presets/accounts/packages/accounts-api/src/users.types.ts +65 -0
- package/templates/module-presets/{jwt-auth/packages/auth-contracts → accounts/packages/accounts-contracts}/package.json +1 -1
- package/templates/module-presets/accounts/packages/accounts-contracts/src/index.ts +119 -0
- package/templates/module-presets/db-prisma/apps/api/prisma/seed.ts +40 -19
- package/templates/module-presets/files/apps/api/src/files/forgeon-files-db-prisma.module.ts +17 -0
- package/templates/module-presets/files/apps/api/src/files/prisma-files-persistence.store.ts +164 -0
- package/templates/module-presets/files/packages/files/package.json +1 -2
- package/templates/module-presets/files/packages/files/src/files.ports.ts +107 -0
- package/templates/module-presets/files/packages/files/src/files.service.ts +81 -395
- package/templates/module-presets/files/packages/files/src/forgeon-files.module.ts +126 -2
- package/templates/module-presets/files/packages/files/src/index.ts +2 -1
- package/templates/module-presets/files-local/packages/files-local/src/forgeon-files-local-storage.module.ts +18 -0
- package/templates/module-presets/files-local/packages/files-local/src/index.ts +2 -0
- package/templates/module-presets/files-local/packages/files-local/src/local-files-storage.adapter.ts +53 -0
- package/templates/module-presets/files-s3/packages/files-s3/src/forgeon-files-s3-storage.module.ts +18 -0
- package/templates/module-presets/files-s3/packages/files-s3/src/index.ts +2 -0
- package/templates/module-presets/files-s3/packages/files-s3/src/s3-files-storage.adapter.ts +130 -0
- package/src/modules/jwt-auth.mjs +0 -271
- package/templates/module-fragments/jwt-auth/20_scope.md +0 -19
- package/templates/module-fragments/jwt-auth/90_status_implemented.md +0 -8
- package/templates/module-fragments/jwt-auth/90_status_planned.md +0 -3
- package/templates/module-presets/jwt-auth/apps/api/prisma/migrations/0002_auth_refresh_token_hash/migration.sql +0 -3
- package/templates/module-presets/jwt-auth/apps/api/src/auth/prisma-auth-refresh-token.store.ts +0 -36
- package/templates/module-presets/jwt-auth/packages/auth-api/src/auth-refresh-token.store.ts +0 -23
- package/templates/module-presets/jwt-auth/packages/auth-api/src/auth.controller.ts +0 -71
- package/templates/module-presets/jwt-auth/packages/auth-api/src/auth.service.ts +0 -175
- package/templates/module-presets/jwt-auth/packages/auth-api/src/auth.types.ts +0 -6
- package/templates/module-presets/jwt-auth/packages/auth-api/src/dto/index.ts +0 -2
- package/templates/module-presets/jwt-auth/packages/auth-api/src/forgeon-auth.module.ts +0 -47
- package/templates/module-presets/jwt-auth/packages/auth-api/src/index.ts +0 -12
- package/templates/module-presets/jwt-auth/packages/auth-contracts/src/index.ts +0 -47
- /package/templates/module-presets/{jwt-auth/packages/auth-api/src/jwt-auth.guard.ts → accounts/packages/accounts-api/src/access-token.guard.ts} +0 -0
- /package/templates/module-presets/{jwt-auth/packages/auth-api → accounts/packages/accounts-api}/src/auth-config.module.ts +0 -0
- /package/templates/module-presets/{jwt-auth/packages/auth-api → accounts/packages/accounts-api}/tsconfig.json +0 -0
- /package/templates/module-presets/{jwt-auth/packages/auth-contracts → accounts/packages/accounts-contracts}/tsconfig.json +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
1
|
+
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { copyRecursive, writeJson } from '../utils/fs.mjs';
|
|
4
4
|
import {
|
|
@@ -65,10 +65,10 @@ function patchAppModule(targetRoot) {
|
|
|
65
65
|
content = ensureLineAfter(content, ' ForgeonFilesModule,', ' ForgeonFilesAccessModule,');
|
|
66
66
|
} else if (content.includes(' ForgeonI18nModule.register({')) {
|
|
67
67
|
content = ensureLineBefore(content, ' ForgeonI18nModule.register({', ' ForgeonFilesAccessModule,');
|
|
68
|
-
} else if (content.includes('
|
|
69
|
-
content = ensureLineBefore(content, '
|
|
70
|
-
} else if (content.includes('
|
|
71
|
-
content = ensureLineBefore(content, '
|
|
68
|
+
} else if (content.includes(' ForgeonAccountsModule.register({')) {
|
|
69
|
+
content = ensureLineBefore(content, ' ForgeonAccountsModule.register({', ' ForgeonFilesAccessModule,');
|
|
70
|
+
} else if (content.includes(' ForgeonAccountsModule.register(),')) {
|
|
71
|
+
content = ensureLineBefore(content, ' ForgeonAccountsModule.register(),', ' ForgeonFilesAccessModule,');
|
|
72
72
|
} else if (content.includes(' DbPrismaModule,')) {
|
|
73
73
|
content = ensureLineAfter(content, ' DbPrismaModule,', ' ForgeonFilesAccessModule,');
|
|
74
74
|
} else if (content.includes(' ForgeonLoggerModule,')) {
|
|
@@ -274,7 +274,7 @@ function patchApiDockerfile(targetRoot) {
|
|
|
274
274
|
'COPY packages/files/package.json packages/files/package.json',
|
|
275
275
|
'COPY packages/files-local/package.json packages/files-local/package.json',
|
|
276
276
|
'COPY packages/files-s3/package.json packages/files-s3/package.json',
|
|
277
|
-
'COPY packages/
|
|
277
|
+
'COPY packages/accounts-api/package.json packages/accounts-api/package.json',
|
|
278
278
|
'COPY packages/rbac/package.json packages/rbac/package.json',
|
|
279
279
|
'COPY packages/rate-limit/package.json packages/rate-limit/package.json',
|
|
280
280
|
'COPY packages/logger/package.json packages/logger/package.json',
|
|
@@ -294,7 +294,7 @@ function patchApiDockerfile(targetRoot) {
|
|
|
294
294
|
'COPY packages/files packages/files',
|
|
295
295
|
'COPY packages/files-local packages/files-local',
|
|
296
296
|
'COPY packages/files-s3 packages/files-s3',
|
|
297
|
-
'COPY packages/
|
|
297
|
+
'COPY packages/accounts-api packages/accounts-api',
|
|
298
298
|
'COPY packages/rbac packages/rbac',
|
|
299
299
|
'COPY packages/rate-limit packages/rate-limit',
|
|
300
300
|
'COPY packages/logger packages/logger',
|
|
@@ -373,3 +373,5 @@ export function applyFilesAccessModule({ packageRoot, targetRoot }) {
|
|
|
373
373
|
patchApiDockerfile(targetRoot);
|
|
374
374
|
patchReadme(targetRoot);
|
|
375
375
|
}
|
|
376
|
+
|
|
377
|
+
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
1
|
+
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { copyRecursive, writeJson } from '../utils/fs.mjs';
|
|
4
4
|
import {
|
|
@@ -95,10 +95,10 @@ function patchAppModule(targetRoot) {
|
|
|
95
95
|
if (!content.includes(' ForgeonFilesImageModule,')) {
|
|
96
96
|
if (content.includes(' ForgeonI18nModule.register({')) {
|
|
97
97
|
content = ensureLineBefore(content, ' ForgeonI18nModule.register({', ' ForgeonFilesImageModule,');
|
|
98
|
-
} else if (content.includes('
|
|
99
|
-
content = ensureLineBefore(content, '
|
|
100
|
-
} else if (content.includes('
|
|
101
|
-
content = ensureLineBefore(content, '
|
|
98
|
+
} else if (content.includes(' ForgeonAccountsModule.register({')) {
|
|
99
|
+
content = ensureLineBefore(content, ' ForgeonAccountsModule.register({', ' ForgeonFilesImageModule,');
|
|
100
|
+
} else if (content.includes(' ForgeonAccountsModule.register(),')) {
|
|
101
|
+
content = ensureLineBefore(content, ' ForgeonAccountsModule.register(),', ' ForgeonFilesImageModule,');
|
|
102
102
|
} else if (content.includes(' ForgeonFilesModule,')) {
|
|
103
103
|
content = ensureLineAfter(content, ' ForgeonFilesModule,', ' ForgeonFilesImageModule,');
|
|
104
104
|
} else if (content.includes(' DbPrismaModule,')) {
|
|
@@ -342,7 +342,7 @@ function patchApiDockerfile(targetRoot) {
|
|
|
342
342
|
'COPY packages/files/package.json packages/files/package.json',
|
|
343
343
|
'COPY packages/files-local/package.json packages/files-local/package.json',
|
|
344
344
|
'COPY packages/files-s3/package.json packages/files-s3/package.json',
|
|
345
|
-
'COPY packages/
|
|
345
|
+
'COPY packages/accounts-api/package.json packages/accounts-api/package.json',
|
|
346
346
|
'COPY packages/rbac/package.json packages/rbac/package.json',
|
|
347
347
|
'COPY packages/rate-limit/package.json packages/rate-limit/package.json',
|
|
348
348
|
'COPY packages/logger/package.json packages/logger/package.json',
|
|
@@ -364,7 +364,7 @@ function patchApiDockerfile(targetRoot) {
|
|
|
364
364
|
'COPY packages/files packages/files',
|
|
365
365
|
'COPY packages/files-local packages/files-local',
|
|
366
366
|
'COPY packages/files-s3 packages/files-s3',
|
|
367
|
-
'COPY packages/
|
|
367
|
+
'COPY packages/accounts-api packages/accounts-api',
|
|
368
368
|
'COPY packages/rbac packages/rbac',
|
|
369
369
|
'COPY packages/rate-limit packages/rate-limit',
|
|
370
370
|
'COPY packages/logger packages/logger',
|
|
@@ -508,3 +508,5 @@ export function applyFilesImageModule({ packageRoot, targetRoot }) {
|
|
|
508
508
|
'FILES_IMAGE_ALLOWED_MIME_TYPES=image/jpeg,image/png,image/webp',
|
|
509
509
|
]);
|
|
510
510
|
}
|
|
511
|
+
|
|
512
|
+
|
|
@@ -9,8 +9,10 @@ import {
|
|
|
9
9
|
ensureLineBefore,
|
|
10
10
|
ensureLoadItem,
|
|
11
11
|
ensureValidatorSchema,
|
|
12
|
+
ensureNamedImportSpecifier,
|
|
12
13
|
upsertEnvLines,
|
|
13
14
|
} from './shared/patch-utils.mjs';
|
|
15
|
+
import { resolveFilesStorageRuntimeModule, upsertFilesModuleRegistration } from './shared/files-runtime-wiring.mjs';
|
|
14
16
|
|
|
15
17
|
function copyFromPreset(packageRoot, targetRoot, relativePath) {
|
|
16
18
|
const source = path.join(packageRoot, 'templates', 'module-presets', 'files-local', relativePath);
|
|
@@ -40,16 +42,18 @@ function patchAppModule(targetRoot) {
|
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
let content = fs.readFileSync(filePath, 'utf8').replace(/\r\n/g, '\n');
|
|
43
|
-
content =
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
);
|
|
45
|
+
content = ensureNamedImportSpecifier(content, '@forgeon/files-local', 'filesLocalConfig');
|
|
46
|
+
content = ensureNamedImportSpecifier(content, '@forgeon/files-local', 'filesLocalEnvSchemaZod');
|
|
47
|
+
content = ensureNamedImportSpecifier(content, '@forgeon/files-local', 'FilesLocalConfigModule');
|
|
48
|
+
content = ensureNamedImportSpecifier(content, '@forgeon/files-local', 'ForgeonFilesLocalStorageModule');
|
|
47
49
|
content = ensureLoadItem(content, 'filesLocalConfig');
|
|
48
50
|
content = ensureValidatorSchema(content, 'filesLocalEnvSchemaZod');
|
|
49
51
|
|
|
50
52
|
if (!content.includes(' FilesLocalConfigModule,')) {
|
|
51
53
|
if (content.includes(' ForgeonFilesModule,')) {
|
|
52
54
|
content = ensureLineAfter(content, ' ForgeonFilesModule,', ' FilesLocalConfigModule,');
|
|
55
|
+
} else if (content.includes(' ForgeonFilesModule.register({')) {
|
|
56
|
+
content = ensureLineBefore(content, ' ForgeonFilesModule.register({', ' FilesLocalConfigModule,');
|
|
53
57
|
} else if (content.includes(' ForgeonI18nModule.register({')) {
|
|
54
58
|
content = ensureLineBefore(content, ' ForgeonI18nModule.register({', ' FilesLocalConfigModule,');
|
|
55
59
|
} else if (content.includes(' DbPrismaModule,')) {
|
|
@@ -61,6 +65,10 @@ function patchAppModule(targetRoot) {
|
|
|
61
65
|
}
|
|
62
66
|
}
|
|
63
67
|
|
|
68
|
+
if (content.includes('ForgeonFilesModule')) {
|
|
69
|
+
content = upsertFilesModuleRegistration(content, resolveFilesStorageRuntimeModule(targetRoot));
|
|
70
|
+
}
|
|
71
|
+
|
|
64
72
|
fs.writeFileSync(filePath, `${content.trimEnd()}\n`, 'utf8');
|
|
65
73
|
}
|
|
66
74
|
|
|
@@ -74,7 +82,7 @@ function patchApiDockerfile(targetRoot) {
|
|
|
74
82
|
|
|
75
83
|
const packageAnchors = [
|
|
76
84
|
'COPY packages/files/package.json packages/files/package.json',
|
|
77
|
-
'COPY packages/
|
|
85
|
+
'COPY packages/accounts-api/package.json packages/accounts-api/package.json',
|
|
78
86
|
'COPY packages/rbac/package.json packages/rbac/package.json',
|
|
79
87
|
'COPY packages/rate-limit/package.json packages/rate-limit/package.json',
|
|
80
88
|
'COPY packages/logger/package.json packages/logger/package.json',
|
|
@@ -92,7 +100,7 @@ function patchApiDockerfile(targetRoot) {
|
|
|
92
100
|
|
|
93
101
|
const sourceAnchors = [
|
|
94
102
|
'COPY packages/files packages/files',
|
|
95
|
-
'COPY packages/
|
|
103
|
+
'COPY packages/accounts-api packages/accounts-api',
|
|
96
104
|
'COPY packages/rbac packages/rbac',
|
|
97
105
|
'COPY packages/rate-limit packages/rate-limit',
|
|
98
106
|
'COPY packages/logger packages/logger',
|
|
@@ -219,3 +227,4 @@ export function applyFilesLocalModule({ packageRoot, targetRoot }) {
|
|
|
219
227
|
'FILES_LOCAL_ROOT=storage/uploads',
|
|
220
228
|
]);
|
|
221
229
|
}
|
|
230
|
+
|
|
@@ -75,10 +75,10 @@ function patchAppModule(targetRoot) {
|
|
|
75
75
|
content = ensureLineAfter(content, ' ForgeonFilesModule,', ' ForgeonFilesQuotasModule,');
|
|
76
76
|
} else if (content.includes(' ForgeonI18nModule.register({')) {
|
|
77
77
|
content = ensureLineBefore(content, ' ForgeonI18nModule.register({', ' ForgeonFilesQuotasModule,');
|
|
78
|
-
} else if (content.includes('
|
|
79
|
-
content = ensureLineBefore(content, '
|
|
80
|
-
} else if (content.includes('
|
|
81
|
-
content = ensureLineBefore(content, '
|
|
78
|
+
} else if (content.includes(' ForgeonAccountsModule.register({')) {
|
|
79
|
+
content = ensureLineBefore(content, ' ForgeonAccountsModule.register({', ' ForgeonFilesQuotasModule,');
|
|
80
|
+
} else if (content.includes(' ForgeonAccountsModule.register(),')) {
|
|
81
|
+
content = ensureLineBefore(content, ' ForgeonAccountsModule.register(),', ' ForgeonFilesQuotasModule,');
|
|
82
82
|
} else if (content.includes(' DbPrismaModule,')) {
|
|
83
83
|
content = ensureLineAfter(content, ' DbPrismaModule,', ' ForgeonFilesQuotasModule,');
|
|
84
84
|
} else if (content.includes(' ForgeonLoggerModule,')) {
|
|
@@ -241,7 +241,7 @@ function patchApiDockerfile(targetRoot) {
|
|
|
241
241
|
'COPY packages/files/package.json packages/files/package.json',
|
|
242
242
|
'COPY packages/files-local/package.json packages/files-local/package.json',
|
|
243
243
|
'COPY packages/files-s3/package.json packages/files-s3/package.json',
|
|
244
|
-
'COPY packages/
|
|
244
|
+
'COPY packages/accounts-api/package.json packages/accounts-api/package.json',
|
|
245
245
|
'COPY packages/rbac/package.json packages/rbac/package.json',
|
|
246
246
|
'COPY packages/rate-limit/package.json packages/rate-limit/package.json',
|
|
247
247
|
'COPY packages/logger/package.json packages/logger/package.json',
|
|
@@ -262,7 +262,7 @@ function patchApiDockerfile(targetRoot) {
|
|
|
262
262
|
'COPY packages/files packages/files',
|
|
263
263
|
'COPY packages/files-local packages/files-local',
|
|
264
264
|
'COPY packages/files-s3 packages/files-s3',
|
|
265
|
-
'COPY packages/
|
|
265
|
+
'COPY packages/accounts-api packages/accounts-api',
|
|
266
266
|
'COPY packages/rbac packages/rbac',
|
|
267
267
|
'COPY packages/rate-limit packages/rate-limit',
|
|
268
268
|
'COPY packages/logger packages/logger',
|
|
@@ -380,3 +380,5 @@ export function applyFilesQuotasModule({ packageRoot, targetRoot }) {
|
|
|
380
380
|
]);
|
|
381
381
|
}
|
|
382
382
|
|
|
383
|
+
|
|
384
|
+
|
package/src/modules/files-s3.mjs
CHANGED
|
@@ -9,8 +9,10 @@ import {
|
|
|
9
9
|
ensureLineBefore,
|
|
10
10
|
ensureLoadItem,
|
|
11
11
|
ensureValidatorSchema,
|
|
12
|
+
ensureNamedImportSpecifier,
|
|
12
13
|
upsertEnvLines,
|
|
13
14
|
} from './shared/patch-utils.mjs';
|
|
15
|
+
import { resolveFilesStorageRuntimeModule, upsertFilesModuleRegistration } from './shared/files-runtime-wiring.mjs';
|
|
14
16
|
|
|
15
17
|
function copyFromPreset(packageRoot, targetRoot, relativePath) {
|
|
16
18
|
const source = path.join(packageRoot, 'templates', 'module-presets', 'files-s3', relativePath);
|
|
@@ -40,16 +42,18 @@ function patchAppModule(targetRoot) {
|
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
let content = fs.readFileSync(filePath, 'utf8').replace(/\r\n/g, '\n');
|
|
43
|
-
content =
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
);
|
|
45
|
+
content = ensureNamedImportSpecifier(content, '@forgeon/files-s3', 'filesS3Config');
|
|
46
|
+
content = ensureNamedImportSpecifier(content, '@forgeon/files-s3', 'filesS3EnvSchemaZod');
|
|
47
|
+
content = ensureNamedImportSpecifier(content, '@forgeon/files-s3', 'FilesS3ConfigModule');
|
|
48
|
+
content = ensureNamedImportSpecifier(content, '@forgeon/files-s3', 'ForgeonFilesS3StorageModule');
|
|
47
49
|
content = ensureLoadItem(content, 'filesS3Config');
|
|
48
50
|
content = ensureValidatorSchema(content, 'filesS3EnvSchemaZod');
|
|
49
51
|
|
|
50
52
|
if (!content.includes(' FilesS3ConfigModule,')) {
|
|
51
53
|
if (content.includes(' ForgeonFilesModule,')) {
|
|
52
54
|
content = ensureLineAfter(content, ' ForgeonFilesModule,', ' FilesS3ConfigModule,');
|
|
55
|
+
} else if (content.includes(' ForgeonFilesModule.register({')) {
|
|
56
|
+
content = ensureLineBefore(content, ' ForgeonFilesModule.register({', ' FilesS3ConfigModule,');
|
|
53
57
|
} else if (content.includes(' ForgeonI18nModule.register({')) {
|
|
54
58
|
content = ensureLineBefore(content, ' ForgeonI18nModule.register({', ' FilesS3ConfigModule,');
|
|
55
59
|
} else if (content.includes(' DbPrismaModule,')) {
|
|
@@ -61,6 +65,10 @@ function patchAppModule(targetRoot) {
|
|
|
61
65
|
}
|
|
62
66
|
}
|
|
63
67
|
|
|
68
|
+
if (content.includes('ForgeonFilesModule')) {
|
|
69
|
+
content = upsertFilesModuleRegistration(content, resolveFilesStorageRuntimeModule(targetRoot));
|
|
70
|
+
}
|
|
71
|
+
|
|
64
72
|
fs.writeFileSync(filePath, `${content.trimEnd()}\n`, 'utf8');
|
|
65
73
|
}
|
|
66
74
|
|
|
@@ -75,7 +83,7 @@ function patchApiDockerfile(targetRoot) {
|
|
|
75
83
|
const packageAnchors = [
|
|
76
84
|
'COPY packages/files/package.json packages/files/package.json',
|
|
77
85
|
'COPY packages/files-local/package.json packages/files-local/package.json',
|
|
78
|
-
'COPY packages/
|
|
86
|
+
'COPY packages/accounts-api/package.json packages/accounts-api/package.json',
|
|
79
87
|
'COPY packages/rbac/package.json packages/rbac/package.json',
|
|
80
88
|
'COPY packages/rate-limit/package.json packages/rate-limit/package.json',
|
|
81
89
|
'COPY packages/logger/package.json packages/logger/package.json',
|
|
@@ -94,7 +102,7 @@ function patchApiDockerfile(targetRoot) {
|
|
|
94
102
|
const sourceAnchors = [
|
|
95
103
|
'COPY packages/files packages/files',
|
|
96
104
|
'COPY packages/files-local packages/files-local',
|
|
97
|
-
'COPY packages/
|
|
105
|
+
'COPY packages/accounts-api packages/accounts-api',
|
|
98
106
|
'COPY packages/rbac packages/rbac',
|
|
99
107
|
'COPY packages/rate-limit packages/rate-limit',
|
|
100
108
|
'COPY packages/logger packages/logger',
|
|
@@ -263,4 +271,7 @@ export function applyFilesS3Module({ packageRoot, targetRoot }) {
|
|
|
263
271
|
|
|
264
272
|
setEnvValue(path.join(targetRoot, 'apps', 'api', '.env.example'), 'FILES_STORAGE_DRIVER', 's3');
|
|
265
273
|
setEnvValue(path.join(targetRoot, 'infra', 'docker', '.env.example'), 'FILES_STORAGE_DRIVER', 's3');
|
|
274
|
+
|
|
275
|
+
patchAppModule(targetRoot);
|
|
266
276
|
}
|
|
277
|
+
|
package/src/modules/files.mjs
CHANGED
|
@@ -11,9 +11,11 @@ import {
|
|
|
11
11
|
ensureLoadItem,
|
|
12
12
|
ensureNestCommonImport,
|
|
13
13
|
ensureValidatorSchema,
|
|
14
|
+
ensureNamedImportSpecifier,
|
|
14
15
|
upsertEnvLines,
|
|
15
16
|
} from './shared/patch-utils.mjs';
|
|
16
17
|
import { ensureWebProbeDefinition, resolveProbeTargets } from './shared/probes.mjs';
|
|
18
|
+
import { resolveFilesStorageRuntimeModule, upsertFilesModuleRegistration } from './shared/files-runtime-wiring.mjs';
|
|
17
19
|
|
|
18
20
|
function copyFromPreset(packageRoot, targetRoot, relativePath) {
|
|
19
21
|
const source = path.join(packageRoot, 'templates', 'module-presets', 'files', relativePath);
|
|
@@ -168,27 +170,22 @@ function patchAppModule(targetRoot) {
|
|
|
168
170
|
content,
|
|
169
171
|
"import { filesConfig, filesEnvSchema, ForgeonFilesModule } from '@forgeon/files';",
|
|
170
172
|
);
|
|
171
|
-
content =
|
|
172
|
-
|
|
173
|
+
content = ensureImportLine(
|
|
174
|
+
content,
|
|
175
|
+
"import { ForgeonFilesDbPrismaModule } from './files/forgeon-files-db-prisma.module';",
|
|
176
|
+
);
|
|
173
177
|
|
|
174
|
-
if (
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
} else if (content.includes(' ForgeonAuthModule.register(),')) {
|
|
180
|
-
content = ensureLineBefore(content, ' ForgeonAuthModule.register(),', ' ForgeonFilesModule,');
|
|
181
|
-
} else if (content.includes(' DbPrismaModule,')) {
|
|
182
|
-
content = ensureLineAfter(content, ' DbPrismaModule,', ' ForgeonFilesModule,');
|
|
183
|
-
} else if (content.includes(' ForgeonLoggerModule,')) {
|
|
184
|
-
content = ensureLineAfter(content, ' ForgeonLoggerModule,', ' ForgeonFilesModule,');
|
|
185
|
-
} else if (content.includes(' ForgeonSwaggerModule,')) {
|
|
186
|
-
content = ensureLineAfter(content, ' ForgeonSwaggerModule,', ' ForgeonFilesModule,');
|
|
187
|
-
} else {
|
|
188
|
-
content = ensureLineAfter(content, ' CoreErrorsModule,', ' ForgeonFilesModule,');
|
|
189
|
-
}
|
|
178
|
+
if (fs.existsSync(path.join(targetRoot, 'packages', 'files-local', 'package.json'))) {
|
|
179
|
+
content = ensureNamedImportSpecifier(content, '@forgeon/files-local', 'ForgeonFilesLocalStorageModule');
|
|
180
|
+
}
|
|
181
|
+
if (fs.existsSync(path.join(targetRoot, 'packages', 'files-s3', 'package.json'))) {
|
|
182
|
+
content = ensureNamedImportSpecifier(content, '@forgeon/files-s3', 'ForgeonFilesS3StorageModule');
|
|
190
183
|
}
|
|
191
184
|
|
|
185
|
+
content = ensureLoadItem(content, 'filesConfig');
|
|
186
|
+
content = ensureValidatorSchema(content, 'filesEnvSchema');
|
|
187
|
+
content = upsertFilesModuleRegistration(content, resolveFilesStorageRuntimeModule(targetRoot));
|
|
188
|
+
|
|
192
189
|
fs.writeFileSync(filePath, `${content.trimEnd()}\n`, 'utf8');
|
|
193
190
|
}
|
|
194
191
|
|
|
@@ -201,7 +198,7 @@ function patchApiDockerfile(targetRoot) {
|
|
|
201
198
|
let content = fs.readFileSync(dockerfilePath, 'utf8').replace(/\r\n/g, '\n');
|
|
202
199
|
|
|
203
200
|
const packageAnchors = [
|
|
204
|
-
'COPY packages/
|
|
201
|
+
'COPY packages/accounts-api/package.json packages/accounts-api/package.json',
|
|
205
202
|
'COPY packages/rbac/package.json packages/rbac/package.json',
|
|
206
203
|
'COPY packages/rate-limit/package.json packages/rate-limit/package.json',
|
|
207
204
|
'COPY packages/logger/package.json packages/logger/package.json',
|
|
@@ -214,7 +211,7 @@ function patchApiDockerfile(targetRoot) {
|
|
|
214
211
|
content = ensureLineAfter(content, packageAnchor, 'COPY packages/files/package.json packages/files/package.json');
|
|
215
212
|
|
|
216
213
|
const sourceAnchors = [
|
|
217
|
-
'COPY packages/
|
|
214
|
+
'COPY packages/accounts-api packages/accounts-api',
|
|
218
215
|
'COPY packages/rbac packages/rbac',
|
|
219
216
|
'COPY packages/rate-limit packages/rate-limit',
|
|
220
217
|
'COPY packages/logger packages/logger',
|
|
@@ -344,7 +341,7 @@ function patchCompose(targetRoot) {
|
|
|
344
341
|
let content = fs.readFileSync(composePath, 'utf8').replace(/\r\n/g, '\n');
|
|
345
342
|
if (!content.includes('FILES_ENABLED: ${FILES_ENABLED}')) {
|
|
346
343
|
const anchors = [
|
|
347
|
-
/^(\s+
|
|
344
|
+
/^(\s+AUTH_ARGON2_PARALLELISM:.*)$/m,
|
|
348
345
|
/^(\s+THROTTLE_TRUST_PROXY:.*)$/m,
|
|
349
346
|
/^(\s+LOGGER_LEVEL:.*)$/m,
|
|
350
347
|
/^(\s+SWAGGER_ENABLED:.*)$/m,
|
|
@@ -428,6 +425,7 @@ Key env:
|
|
|
428
425
|
|
|
429
426
|
export function applyFilesModule({ packageRoot, targetRoot }) {
|
|
430
427
|
copyFromPreset(packageRoot, targetRoot, path.join('packages', 'files'));
|
|
428
|
+
copyFromPreset(packageRoot, targetRoot, path.join('apps', 'api', 'src', 'files'));
|
|
431
429
|
const probeTargets = resolveProbeTargets({ targetRoot, moduleId: 'files' });
|
|
432
430
|
|
|
433
431
|
|
|
@@ -456,3 +454,5 @@ export function applyFilesModule({ packageRoot, targetRoot }) {
|
|
|
456
454
|
'FILES_ALLOWED_MIME_PREFIXES=image/,application/pdf,text/',
|
|
457
455
|
]);
|
|
458
456
|
}
|
|
457
|
+
|
|
458
|
+
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { describe, it } from 'node:test';
|
|
1
|
+
import { describe, it } from 'node:test';
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
3
|
import fs from 'node:fs';
|
|
4
4
|
import os from 'node:os';
|
|
@@ -81,19 +81,25 @@ describe('addModule idempotency', () => {
|
|
|
81
81
|
},
|
|
82
82
|
},
|
|
83
83
|
{
|
|
84
|
-
name: '
|
|
85
|
-
moduleId: '
|
|
86
|
-
dbPrismaEnabled:
|
|
84
|
+
name: 'accounts',
|
|
85
|
+
moduleId: 'accounts',
|
|
86
|
+
dbPrismaEnabled: true,
|
|
87
87
|
setup: [],
|
|
88
88
|
verify(projectRoot) {
|
|
89
|
-
assert.equal(fs.existsSync(path.join(projectRoot, 'packages', '
|
|
89
|
+
assert.equal(fs.existsSync(path.join(projectRoot, 'packages', 'accounts-api', 'package.json')), true);
|
|
90
|
+
assert.equal(
|
|
91
|
+
fs.existsSync(
|
|
92
|
+
path.join(projectRoot, 'apps', 'api', 'src', 'accounts', 'prisma-accounts-persistence.store.ts'),
|
|
93
|
+
),
|
|
94
|
+
true,
|
|
95
|
+
);
|
|
90
96
|
assert.match(
|
|
91
97
|
readFile(path.join(projectRoot, 'apps', 'api', 'src', 'health', 'health.controller.ts')),
|
|
92
98
|
/@Get\('auth'\)/,
|
|
93
99
|
);
|
|
94
|
-
assert.
|
|
100
|
+
assert.match(
|
|
95
101
|
readFile(path.join(projectRoot, 'apps', 'api', 'src', 'app.module.ts')),
|
|
96
|
-
/
|
|
102
|
+
/ForgeonAccountsModule\.register\(/,
|
|
97
103
|
);
|
|
98
104
|
},
|
|
99
105
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import { describe, it } from 'node:test';
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
3
|
import fs from 'node:fs';
|
|
4
4
|
import os from 'node:os';
|
|
@@ -188,7 +188,7 @@ describe('probe wiring', () => {
|
|
|
188
188
|
addModule({ moduleId: 'queue', targetRoot: projectRoot, packageRoot });
|
|
189
189
|
addModule({ moduleId: 'scheduler', targetRoot: projectRoot, packageRoot });
|
|
190
190
|
addModule({ moduleId: 'db-prisma', targetRoot: projectRoot, packageRoot });
|
|
191
|
-
addModule({ moduleId: '
|
|
191
|
+
addModule({ moduleId: 'accounts', targetRoot: projectRoot, packageRoot });
|
|
192
192
|
addModule({ moduleId: 'rate-limit', targetRoot: projectRoot, packageRoot });
|
|
193
193
|
|
|
194
194
|
assert.deepEqual(readManagedProbeIds(projectRoot), ['db', 'auth', 'rate-limit', 'queue', 'scheduler']);
|
|
@@ -200,3 +200,5 @@ describe('probe wiring', () => {
|
|
|
200
200
|
|
|
201
201
|
|
|
202
202
|
|
|
203
|
+
|
|
204
|
+
|
package/src/modules/queue.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
1
|
+
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { copyRecursive, writeJson } from '../utils/fs.mjs';
|
|
4
4
|
import {
|
|
@@ -40,8 +40,8 @@ function patchAppModule(targetRoot) {
|
|
|
40
40
|
moduleLine: ' ForgeonQueueModule,',
|
|
41
41
|
beforeAnchors: [
|
|
42
42
|
' ForgeonI18nModule.register({',
|
|
43
|
-
'
|
|
44
|
-
'
|
|
43
|
+
' ForgeonAccountsModule.register({',
|
|
44
|
+
' ForgeonAccountsModule.register(),',
|
|
45
45
|
],
|
|
46
46
|
afterAnchors: [
|
|
47
47
|
' DbPrismaModule,',
|
|
@@ -89,7 +89,7 @@ function patchApiDockerfile(targetRoot) {
|
|
|
89
89
|
'COPY packages/files-s3/package.json packages/files-s3/package.json',
|
|
90
90
|
'COPY packages/files-local/package.json packages/files-local/package.json',
|
|
91
91
|
'COPY packages/files/package.json packages/files/package.json',
|
|
92
|
-
'COPY packages/
|
|
92
|
+
'COPY packages/accounts-api/package.json packages/accounts-api/package.json',
|
|
93
93
|
'COPY packages/rbac/package.json packages/rbac/package.json',
|
|
94
94
|
'COPY packages/rate-limit/package.json packages/rate-limit/package.json',
|
|
95
95
|
'COPY packages/logger/package.json packages/logger/package.json',
|
|
@@ -108,7 +108,7 @@ function patchApiDockerfile(targetRoot) {
|
|
|
108
108
|
'COPY packages/files-s3 packages/files-s3',
|
|
109
109
|
'COPY packages/files-local packages/files-local',
|
|
110
110
|
'COPY packages/files packages/files',
|
|
111
|
-
'COPY packages/
|
|
111
|
+
'COPY packages/accounts-api packages/accounts-api',
|
|
112
112
|
'COPY packages/rbac packages/rbac',
|
|
113
113
|
'COPY packages/rate-limit packages/rate-limit',
|
|
114
114
|
'COPY packages/logger packages/logger',
|
|
@@ -224,7 +224,7 @@ function patchCompose(targetRoot) {
|
|
|
224
224
|
/^(\s+FILES_S3_MAX_ATTEMPTS:.*)$/m,
|
|
225
225
|
/^(\s+FILES_LOCAL_ROOT:.*)$/m,
|
|
226
226
|
/^(\s+FILES_PUBLIC_BASE_PATH:.*)$/m,
|
|
227
|
-
/^(\s+
|
|
227
|
+
/^(\s+AUTH_ARGON2_PARALLELISM:.*)$/m,
|
|
228
228
|
/^(\s+THROTTLE_TRUST_PROXY:.*)$/m,
|
|
229
229
|
/^(\s+LOGGER_REQUEST_ID_HEADER:.*)$/m,
|
|
230
230
|
/^(\s+SWAGGER_DOCS_PATH:.*)$/m,
|
|
@@ -323,3 +323,6 @@ export function applyQueueModule({ packageRoot, targetRoot }) {
|
|
|
323
323
|
'QUEUE_DEFAULT_BACKOFF_MS=1000',
|
|
324
324
|
]);
|
|
325
325
|
}
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
1
|
+
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { copyRecursive, writeJson } from '../utils/fs.mjs';
|
|
4
4
|
import {
|
|
@@ -50,11 +50,11 @@ function patchAppModule(targetRoot) {
|
|
|
50
50
|
"import { ForgeonRateLimitModule, rateLimitConfig, rateLimitEnvSchema } from '@forgeon/rate-limit';",
|
|
51
51
|
);
|
|
52
52
|
} else if (
|
|
53
|
-
content.includes("import { authConfig, authEnvSchema,
|
|
53
|
+
content.includes("import { authConfig, authEnvSchema, ForgeonAccountsModule, UsersModule } from '@forgeon/accounts-api';")
|
|
54
54
|
) {
|
|
55
55
|
content = ensureLineAfter(
|
|
56
56
|
content,
|
|
57
|
-
"import { authConfig, authEnvSchema,
|
|
57
|
+
"import { authConfig, authEnvSchema, ForgeonAccountsModule, UsersModule } from '@forgeon/accounts-api';",
|
|
58
58
|
"import { ForgeonRateLimitModule, rateLimitConfig, rateLimitEnvSchema } from '@forgeon/rate-limit';",
|
|
59
59
|
);
|
|
60
60
|
} else if (
|
|
@@ -96,10 +96,10 @@ function patchAppModule(targetRoot) {
|
|
|
96
96
|
if (!content.includes(' ForgeonRateLimitModule,')) {
|
|
97
97
|
if (content.includes(' ForgeonI18nModule.register({')) {
|
|
98
98
|
content = ensureLineBefore(content, ' ForgeonI18nModule.register({', ' ForgeonRateLimitModule,');
|
|
99
|
-
} else if (content.includes('
|
|
100
|
-
content = ensureLineBefore(content, '
|
|
101
|
-
} else if (content.includes('
|
|
102
|
-
content = ensureLineBefore(content, '
|
|
99
|
+
} else if (content.includes(' ForgeonAccountsModule.register({')) {
|
|
100
|
+
content = ensureLineBefore(content, ' ForgeonAccountsModule.register({', ' ForgeonRateLimitModule,');
|
|
101
|
+
} else if (content.includes(' ForgeonAccountsModule.register(),')) {
|
|
102
|
+
content = ensureLineBefore(content, ' ForgeonAccountsModule.register(),', ' ForgeonRateLimitModule,');
|
|
103
103
|
} else if (content.includes(' DbPrismaModule,')) {
|
|
104
104
|
content = ensureLineAfter(content, ' DbPrismaModule,', ' ForgeonRateLimitModule,');
|
|
105
105
|
} else if (content.includes(' ForgeonLoggerModule,')) {
|
|
@@ -166,7 +166,7 @@ function patchApiDockerfile(targetRoot) {
|
|
|
166
166
|
|
|
167
167
|
let content = fs.readFileSync(dockerfilePath, 'utf8').replace(/\r\n/g, '\n');
|
|
168
168
|
const packageAnchors = [
|
|
169
|
-
'COPY packages/
|
|
169
|
+
'COPY packages/accounts-api/package.json packages/accounts-api/package.json',
|
|
170
170
|
'COPY packages/logger/package.json packages/logger/package.json',
|
|
171
171
|
'COPY packages/swagger/package.json packages/swagger/package.json',
|
|
172
172
|
'COPY packages/i18n/package.json packages/i18n/package.json',
|
|
@@ -181,7 +181,7 @@ function patchApiDockerfile(targetRoot) {
|
|
|
181
181
|
);
|
|
182
182
|
|
|
183
183
|
const sourceAnchors = [
|
|
184
|
-
'COPY packages/
|
|
184
|
+
'COPY packages/accounts-api packages/accounts-api',
|
|
185
185
|
'COPY packages/logger packages/logger',
|
|
186
186
|
'COPY packages/swagger packages/swagger',
|
|
187
187
|
'COPY packages/i18n packages/i18n',
|
|
@@ -209,7 +209,7 @@ function patchCompose(targetRoot) {
|
|
|
209
209
|
let content = fs.readFileSync(composePath, 'utf8').replace(/\r\n/g, '\n');
|
|
210
210
|
if (!content.includes('THROTTLE_ENABLED: ${THROTTLE_ENABLED}')) {
|
|
211
211
|
const anchors = [
|
|
212
|
-
/^(\s+
|
|
212
|
+
/^(\s+AUTH_ARGON2_PARALLELISM:.*)$/m,
|
|
213
213
|
/^(\s+JWT_ACCESS_SECRET:.*)$/m,
|
|
214
214
|
/^(\s+LOGGER_LEVEL:.*)$/m,
|
|
215
215
|
/^(\s+SWAGGER_ENABLED:.*)$/m,
|
|
@@ -303,3 +303,7 @@ export function applyRateLimitModule({ packageRoot, targetRoot }) {
|
|
|
303
303
|
'THROTTLE_TRUST_PROXY=false',
|
|
304
304
|
]);
|
|
305
305
|
}
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
|
package/src/modules/rbac.mjs
CHANGED
|
@@ -48,11 +48,11 @@ function patchAppModule(targetRoot) {
|
|
|
48
48
|
"import { ForgeonRbacModule } from '@forgeon/rbac';",
|
|
49
49
|
);
|
|
50
50
|
} else if (
|
|
51
|
-
content.includes("import { authConfig, authEnvSchema,
|
|
51
|
+
content.includes("import { authConfig, authEnvSchema, ForgeonAccountsModule, UsersModule } from '@forgeon/accounts-api';")
|
|
52
52
|
) {
|
|
53
53
|
content = ensureLineAfter(
|
|
54
54
|
content,
|
|
55
|
-
"import { authConfig, authEnvSchema,
|
|
55
|
+
"import { authConfig, authEnvSchema, ForgeonAccountsModule, UsersModule } from '@forgeon/accounts-api';",
|
|
56
56
|
"import { ForgeonRbacModule } from '@forgeon/rbac';",
|
|
57
57
|
);
|
|
58
58
|
} else if (
|
|
@@ -99,10 +99,8 @@ function patchAppModule(targetRoot) {
|
|
|
99
99
|
if (!content.includes(' ForgeonRbacModule,')) {
|
|
100
100
|
if (content.includes(' ForgeonI18nModule.register({')) {
|
|
101
101
|
content = ensureLineBefore(content, ' ForgeonI18nModule.register({', ' ForgeonRbacModule,');
|
|
102
|
-
} else if (content.includes('
|
|
103
|
-
content = ensureLineBefore(content, '
|
|
104
|
-
} else if (content.includes(' ForgeonAuthModule.register(),')) {
|
|
105
|
-
content = ensureLineBefore(content, ' ForgeonAuthModule.register(),', ' ForgeonRbacModule,');
|
|
102
|
+
} else if (content.includes(' ForgeonAccountsModule.register({')) {
|
|
103
|
+
content = ensureLineBefore(content, ' ForgeonAccountsModule.register({', ' ForgeonRbacModule,');
|
|
106
104
|
} else if (content.includes(' ForgeonRateLimitModule,')) {
|
|
107
105
|
content = ensureLineAfter(content, ' ForgeonRateLimitModule,', ' ForgeonRbacModule,');
|
|
108
106
|
} else if (content.includes(' DbPrismaModule,')) {
|
|
@@ -192,7 +190,7 @@ function patchApiDockerfile(targetRoot) {
|
|
|
192
190
|
|
|
193
191
|
let content = fs.readFileSync(dockerfilePath, 'utf8').replace(/\r\n/g, '\n');
|
|
194
192
|
const packageAnchors = [
|
|
195
|
-
'COPY packages/
|
|
193
|
+
'COPY packages/accounts-api/package.json packages/accounts-api/package.json',
|
|
196
194
|
'COPY packages/rate-limit/package.json packages/rate-limit/package.json',
|
|
197
195
|
'COPY packages/logger/package.json packages/logger/package.json',
|
|
198
196
|
'COPY packages/swagger/package.json packages/swagger/package.json',
|
|
@@ -204,7 +202,7 @@ function patchApiDockerfile(targetRoot) {
|
|
|
204
202
|
content = ensureLineAfter(content, packageAnchor, 'COPY packages/rbac/package.json packages/rbac/package.json');
|
|
205
203
|
|
|
206
204
|
const sourceAnchors = [
|
|
207
|
-
'COPY packages/
|
|
205
|
+
'COPY packages/accounts-api packages/accounts-api',
|
|
208
206
|
'COPY packages/rate-limit packages/rate-limit',
|
|
209
207
|
'COPY packages/logger packages/logger',
|
|
210
208
|
'COPY packages/swagger packages/swagger',
|
|
@@ -240,7 +238,7 @@ function patchReadme(targetRoot) {
|
|
|
240
238
|
|
|
241
239
|
The rbac add-module provides a minimal authorization layer for role and permission checks.
|
|
242
240
|
|
|
243
|
-
It installs independently. \`
|
|
241
|
+
It installs independently. \`accounts\` is optional and only prepares auth claims compatibility through integration sync.
|
|
244
242
|
|
|
245
243
|
What it adds:
|
|
246
244
|
- \`@Roles(...)\` and \`@Permissions(...)\` decorators
|
|
@@ -260,8 +258,8 @@ How to verify:
|
|
|
260
258
|
- the same route without that header should return \`403\`
|
|
261
259
|
|
|
262
260
|
Optional integration:
|
|
263
|
-
- if \`
|
|
264
|
-
- that
|
|
261
|
+
- if \`accounts\` is installed too, run \`pnpm forgeon:sync-integrations\`
|
|
262
|
+
- that prepares accounts auth claims types for optional RBAC compatibility without changing the base accounts schema
|
|
265
263
|
|
|
266
264
|
Current scope:
|
|
267
265
|
- no policy engine
|
|
@@ -288,3 +286,6 @@ export function applyRbacModule({ packageRoot, targetRoot }) {
|
|
|
288
286
|
patchApiDockerfile(targetRoot);
|
|
289
287
|
patchReadme(targetRoot);
|
|
290
288
|
}
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
|