create-forgeon 0.3.16 → 0.3.17
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/dependencies.test.mjs +71 -29
- package/src/modules/executor.mjs +3 -2
- package/src/modules/executor.test.mjs +512 -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/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
|
@@ -31,29 +31,29 @@ describe('sync integrations', () => {
|
|
|
31
31
|
const modulesDir = path.dirname(fileURLToPath(import.meta.url));
|
|
32
32
|
const packageRoot = path.resolve(modulesDir, '..', '..');
|
|
33
33
|
|
|
34
|
-
it('does not expose
|
|
35
|
-
const tempRoot = makeTempDir('forgeon-sync-no-
|
|
36
|
-
const projectRoot = path.join(tempRoot, 'demo-sync-no-
|
|
34
|
+
it('does not expose accounts-rbac integration when rbac is missing', () => {
|
|
35
|
+
const tempRoot = makeTempDir('forgeon-sync-no-rbac-');
|
|
36
|
+
const projectRoot = path.join(tempRoot, 'demo-sync-no-rbac');
|
|
37
37
|
|
|
38
38
|
try {
|
|
39
39
|
scaffoldBaseProject({
|
|
40
40
|
packageRoot,
|
|
41
41
|
targetRoot: projectRoot,
|
|
42
|
-
projectName: 'demo-sync-no-
|
|
42
|
+
projectName: 'demo-sync-no-rbac',
|
|
43
43
|
});
|
|
44
44
|
|
|
45
|
-
addModule({ moduleId: '
|
|
45
|
+
addModule({ moduleId: 'db-prisma', targetRoot: projectRoot, packageRoot });
|
|
46
|
+
addModule({ moduleId: 'accounts', targetRoot: projectRoot, packageRoot });
|
|
46
47
|
|
|
47
48
|
const scan = scanIntegrations({
|
|
48
49
|
targetRoot: projectRoot,
|
|
49
|
-
relatedModuleId: '
|
|
50
|
+
relatedModuleId: 'accounts',
|
|
50
51
|
});
|
|
51
|
-
assert.equal(scan.groups.some((group) => group.id === '
|
|
52
|
+
assert.equal(scan.groups.some((group) => group.id === 'accounts-rbac'), false);
|
|
52
53
|
|
|
53
54
|
const syncResult = syncIntegrations({
|
|
54
55
|
targetRoot: projectRoot,
|
|
55
|
-
|
|
56
|
-
groupIds: ['auth-persistence'],
|
|
56
|
+
groupIds: ['accounts-rbac'],
|
|
57
57
|
});
|
|
58
58
|
assert.deepEqual(syncResult.summary, []);
|
|
59
59
|
assert.deepEqual(syncResult.changedFiles, []);
|
|
@@ -62,48 +62,7 @@ describe('sync integrations', () => {
|
|
|
62
62
|
}
|
|
63
63
|
});
|
|
64
64
|
|
|
65
|
-
it('treats
|
|
66
|
-
const tempRoot = makeTempDir('forgeon-sync-db-noop-');
|
|
67
|
-
const projectRoot = path.join(tempRoot, 'demo-sync-db-noop');
|
|
68
|
-
|
|
69
|
-
try {
|
|
70
|
-
scaffoldBaseProject({
|
|
71
|
-
packageRoot,
|
|
72
|
-
targetRoot: projectRoot,
|
|
73
|
-
projectName: 'demo-sync-db-noop',
|
|
74
|
-
dbPrismaEnabled: true,
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
addModule({ moduleId: 'jwt-auth', targetRoot: projectRoot, packageRoot });
|
|
78
|
-
|
|
79
|
-
const firstSync = syncIntegrations({
|
|
80
|
-
targetRoot: projectRoot,
|
|
81
|
-
packageRoot,
|
|
82
|
-
groupIds: ['auth-persistence'],
|
|
83
|
-
});
|
|
84
|
-
assert.equal(firstSync.summary.length, 1);
|
|
85
|
-
assert.equal(firstSync.summary[0].id, 'auth-persistence');
|
|
86
|
-
assert.equal(firstSync.summary[0].result.applied, true);
|
|
87
|
-
|
|
88
|
-
const secondScan = scanIntegrations({
|
|
89
|
-
targetRoot: projectRoot,
|
|
90
|
-
relatedModuleId: 'jwt-auth',
|
|
91
|
-
});
|
|
92
|
-
assert.equal(secondScan.groups.some((group) => group.id === 'auth-persistence'), false);
|
|
93
|
-
|
|
94
|
-
const secondSync = syncIntegrations({
|
|
95
|
-
targetRoot: projectRoot,
|
|
96
|
-
packageRoot,
|
|
97
|
-
groupIds: ['auth-persistence'],
|
|
98
|
-
});
|
|
99
|
-
assert.deepEqual(secondSync.summary, []);
|
|
100
|
-
assert.deepEqual(secondSync.changedFiles, []);
|
|
101
|
-
} finally {
|
|
102
|
-
fs.rmSync(tempRoot, { recursive: true, force: true });
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it('treats auth claims sync as a no-op after it has already been applied', () => {
|
|
65
|
+
it('treats accounts-rbac sync as a no-op after it has already been applied', () => {
|
|
107
66
|
const tempRoot = makeTempDir('forgeon-sync-rbac-noop-');
|
|
108
67
|
const projectRoot = path.join(tempRoot, 'demo-sync-rbac-noop');
|
|
109
68
|
|
|
@@ -114,28 +73,27 @@ describe('sync integrations', () => {
|
|
|
114
73
|
projectName: 'demo-sync-rbac-noop',
|
|
115
74
|
});
|
|
116
75
|
|
|
76
|
+
addModule({ moduleId: 'db-prisma', targetRoot: projectRoot, packageRoot });
|
|
117
77
|
addModule({ moduleId: 'rbac', targetRoot: projectRoot, packageRoot });
|
|
118
|
-
addModule({ moduleId: '
|
|
78
|
+
addModule({ moduleId: 'accounts', targetRoot: projectRoot, packageRoot });
|
|
119
79
|
|
|
120
80
|
const firstSync = syncIntegrations({
|
|
121
81
|
targetRoot: projectRoot,
|
|
122
|
-
|
|
123
|
-
groupIds: ['auth-rbac-claims'],
|
|
82
|
+
groupIds: ['accounts-rbac'],
|
|
124
83
|
});
|
|
125
84
|
assert.equal(firstSync.summary.length, 1);
|
|
126
|
-
assert.equal(firstSync.summary[0].id, '
|
|
85
|
+
assert.equal(firstSync.summary[0].id, 'accounts-rbac');
|
|
127
86
|
assert.equal(firstSync.summary[0].result.applied, true);
|
|
128
87
|
|
|
129
88
|
const secondScan = scanIntegrations({
|
|
130
89
|
targetRoot: projectRoot,
|
|
131
|
-
relatedModuleId: '
|
|
90
|
+
relatedModuleId: 'accounts',
|
|
132
91
|
});
|
|
133
|
-
assert.equal(secondScan.groups.some((group) => group.id === '
|
|
92
|
+
assert.equal(secondScan.groups.some((group) => group.id === 'accounts-rbac'), false);
|
|
134
93
|
|
|
135
94
|
const secondSync = syncIntegrations({
|
|
136
95
|
targetRoot: projectRoot,
|
|
137
|
-
|
|
138
|
-
groupIds: ['auth-rbac-claims'],
|
|
96
|
+
groupIds: ['accounts-rbac'],
|
|
139
97
|
});
|
|
140
98
|
assert.deepEqual(secondSync.summary, []);
|
|
141
99
|
assert.deepEqual(secondSync.changedFiles, []);
|
|
@@ -143,45 +101,8 @@ describe('sync integrations', () => {
|
|
|
143
101
|
fs.rmSync(tempRoot, { recursive: true, force: true });
|
|
144
102
|
}
|
|
145
103
|
});
|
|
146
|
-
it('uses persistence markers instead of README prose when auth persistence sync runs', () => {
|
|
147
|
-
const tempRoot = makeTempDir('forgeon-sync-db-markers-');
|
|
148
|
-
const projectRoot = path.join(tempRoot, 'demo-sync-db-markers');
|
|
149
|
-
|
|
150
|
-
try {
|
|
151
|
-
scaffoldBaseProject({
|
|
152
|
-
packageRoot,
|
|
153
|
-
targetRoot: projectRoot,
|
|
154
|
-
projectName: 'demo-sync-db-markers',
|
|
155
|
-
dbPrismaEnabled: true,
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
addModule({ moduleId: 'jwt-auth', targetRoot: projectRoot, packageRoot });
|
|
159
|
-
|
|
160
|
-
const readmePath = path.join(projectRoot, 'README.md');
|
|
161
|
-
const customizedReadme = fs
|
|
162
|
-
.readFileSync(readmePath, 'utf8')
|
|
163
|
-
.replace('refresh token persistence: disabled by default', 'refresh token persistence: custom local note');
|
|
164
|
-
fs.writeFileSync(readmePath, customizedReadme, 'utf8');
|
|
165
|
-
|
|
166
|
-
const syncResult = syncIntegrations({
|
|
167
|
-
targetRoot: projectRoot,
|
|
168
|
-
packageRoot,
|
|
169
|
-
groupIds: ['auth-persistence'],
|
|
170
|
-
});
|
|
171
|
-
assert.equal(syncResult.summary.length, 1);
|
|
172
|
-
assert.equal(syncResult.summary[0].result.applied, true);
|
|
173
|
-
|
|
174
|
-
const readme = fs.readFileSync(readmePath, 'utf8');
|
|
175
|
-
assert.match(readme, /forgeon:jwt-auth:persistence:start/);
|
|
176
|
-
assert.match(readme, /refresh token persistence: enabled through the `db-adapter` capability/);
|
|
177
|
-
assert.match(readme, /0002_auth_refresh_token_hash/);
|
|
178
|
-
assert.doesNotMatch(readme, /custom local note/);
|
|
179
|
-
} finally {
|
|
180
|
-
fs.rmSync(tempRoot, { recursive: true, force: true });
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
104
|
|
|
184
|
-
it('
|
|
105
|
+
it('updates claim types and README markers when accounts-rbac sync runs', () => {
|
|
185
106
|
const tempRoot = makeTempDir('forgeon-sync-rbac-markers-');
|
|
186
107
|
const projectRoot = path.join(tempRoot, 'demo-sync-rbac-markers');
|
|
187
108
|
|
|
@@ -192,29 +113,29 @@ describe('sync integrations', () => {
|
|
|
192
113
|
projectName: 'demo-sync-rbac-markers',
|
|
193
114
|
});
|
|
194
115
|
|
|
116
|
+
addModule({ moduleId: 'db-prisma', targetRoot: projectRoot, packageRoot });
|
|
195
117
|
addModule({ moduleId: 'rbac', targetRoot: projectRoot, packageRoot });
|
|
196
|
-
addModule({ moduleId: '
|
|
197
|
-
|
|
198
|
-
const readmePath = path.join(projectRoot, 'README.md');
|
|
199
|
-
const customizedReadme = fs
|
|
200
|
-
.readFileSync(readmePath, 'utf8')
|
|
201
|
-
.replace('Default demo credentials:', 'Demo credentials:');
|
|
202
|
-
fs.writeFileSync(readmePath, customizedReadme, 'utf8');
|
|
118
|
+
addModule({ moduleId: 'accounts', targetRoot: projectRoot, packageRoot });
|
|
203
119
|
|
|
204
120
|
const syncResult = syncIntegrations({
|
|
205
121
|
targetRoot: projectRoot,
|
|
206
|
-
|
|
207
|
-
groupIds: ['auth-rbac-claims'],
|
|
122
|
+
groupIds: ['accounts-rbac'],
|
|
208
123
|
});
|
|
209
124
|
assert.equal(syncResult.summary.length, 1);
|
|
210
125
|
assert.equal(syncResult.summary[0].result.applied, true);
|
|
211
126
|
|
|
212
|
-
const readme = fs.readFileSync(
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
127
|
+
const readme = fs.readFileSync(path.join(projectRoot, 'README.md'), 'utf8');
|
|
128
|
+
const contracts = fs.readFileSync(path.join(projectRoot, 'packages', 'accounts-contracts', 'src', 'index.ts'), 'utf8');
|
|
129
|
+
const authTypes = fs.readFileSync(path.join(projectRoot, 'packages', 'accounts-api', 'src', 'auth.types.ts'), 'utf8');
|
|
130
|
+
|
|
131
|
+
assert.match(readme, /forgeon:accounts:rbac:start/);
|
|
132
|
+
assert.match(readme, /base accounts schema remains free of roles and permissions/);
|
|
133
|
+
assert.match(contracts, /roles\?: string\[\];/);
|
|
134
|
+
assert.match(contracts, /permissions\?: string\[\];/);
|
|
135
|
+
assert.match(authTypes, /roles\?: string\[\];/);
|
|
136
|
+
assert.match(authTypes, /permissions\?: string\[\];/);
|
|
216
137
|
} finally {
|
|
217
138
|
fs.rmSync(tempRoot, { recursive: true, force: true });
|
|
218
139
|
}
|
|
219
140
|
});
|
|
220
|
-
});
|
|
141
|
+
});
|