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
|
@@ -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
|
+
});
|