@jskit-ai/users-core 0.1.42 → 0.1.44
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.descriptor.mjs +6 -6
- package/package.json +6 -6
- package/src/server/accountProfile/avatarStorageService.js +3 -3
- package/src/server/common/contributors/workspaceRouteVisibilityResolver.js +12 -13
- package/src/server/common/formatters/workspaceFormatter.js +3 -2
- package/src/server/common/repositories/repositoryUtils.js +12 -3
- package/src/server/common/repositories/userSettingsRepository.js +35 -11
- package/src/server/common/repositories/usersRepository.js +44 -27
- package/src/server/common/repositories/workspaceInvitesRepository.js +49 -13
- package/src/server/common/repositories/workspaceMembershipsRepository.js +55 -22
- package/src/server/common/repositories/workspacesRepository.js +41 -11
- package/src/server/common/services/accountContextService.js +3 -2
- package/src/server/common/services/authProfileSyncService.js +7 -5
- package/src/server/common/services/workspaceContextService.js +4 -1
- package/src/server/common/support/realtimeServiceEvents.js +4 -3
- package/src/server/common/validators/authenticatedUserValidator.js +5 -4
- package/src/server/consoleSettings/consoleService.js +3 -3
- package/src/server/consoleSettings/consoleSettingsRepository.js +10 -6
- package/src/server/usersBootstrapContributor.js +7 -3
- package/src/server/workspaceBootstrapContributor.js +5 -1
- package/src/server/workspaceMembers/registerWorkspaceMembers.js +6 -4
- package/src/server/workspaceMembers/workspaceMembersService.js +23 -11
- package/src/server/workspacePendingInvitations/registerWorkspacePendingInvitations.js +5 -4
- package/src/server/workspacePendingInvitations/workspacePendingInvitationsService.js +3 -2
- package/src/server/workspaceSettings/workspaceSettingsRepository.js +29 -10
- package/src/server/workspaceSettings/workspaceSettingsService.js +3 -2
- package/src/shared/resources/workspaceMembersResource.js +25 -21
- package/src/shared/resources/workspacePendingInvitationsResource.js +7 -12
- package/src/shared/resources/workspaceResource.js +13 -9
- package/src/shared/resources/workspaceSettingsResource.js +7 -5
- package/templates/migrations/users_core_console_owner.cjs +1 -1
- package/templates/migrations/users_core_generic_initial.cjs +4 -4
- package/templates/migrations/users_core_profile_username.cjs +1 -1
- package/test/authProfileSyncService.test.js +7 -4
- package/test/avatarStorageService.test.js +3 -3
- package/test/consoleService.test.js +9 -9
- package/test/registerServiceRealtimeEvents.test.js +9 -9
- package/test/repositoryContracts.test.js +40 -0
- package/test/usersBootstrapContributor.test.js +4 -4
- package/test/workspaceBootstrapContributor.test.js +1 -1
- package/test/workspaceInvitesRepository.test.js +3 -3
- package/test/workspaceMembersService.test.js +34 -34
- package/test/workspacePendingInvitationsResource.test.js +4 -4
- package/test/workspacePendingInvitationsService.test.js +11 -11
- package/test/workspaceRouteVisibilityResolver.test.js +6 -6
- package/test/workspaceService.test.js +33 -33
- package/test/workspaceSettingsRepository.test.js +7 -6
- package/test/workspaceSettingsResource.test.js +2 -2
- package/src/server/common/README.md +0 -20
- package/src/server/common/contributors/README.md +0 -11
- package/src/server/common/formatters/README.md +0 -11
- package/src/server/common/repositories/README.md +0 -24
- package/src/server/common/routes/README.md +0 -11
- package/src/server/common/services/README.md +0 -12
- package/src/server/common/validators/README.md +0 -11
|
@@ -28,10 +28,10 @@ function createWorkspaceServiceFixture({
|
|
|
28
28
|
userWorkspaceRows = null,
|
|
29
29
|
membershipResolver = null,
|
|
30
30
|
personalWorkspace = {
|
|
31
|
-
id: 1,
|
|
31
|
+
id: "1",
|
|
32
32
|
slug: "tonymobily3",
|
|
33
33
|
name: "TonyMobily3",
|
|
34
|
-
ownerUserId: 7,
|
|
34
|
+
ownerUserId: "7",
|
|
35
35
|
isPersonal: true,
|
|
36
36
|
avatarUrl: ""
|
|
37
37
|
}
|
|
@@ -93,7 +93,7 @@ function createWorkspaceServiceFixture({
|
|
|
93
93
|
}
|
|
94
94
|
return [
|
|
95
95
|
{
|
|
96
|
-
id: 1,
|
|
96
|
+
id: "1",
|
|
97
97
|
slug: "tonymobily3",
|
|
98
98
|
name: "TonyMobily3",
|
|
99
99
|
avatarUrl: "",
|
|
@@ -101,7 +101,7 @@ function createWorkspaceServiceFixture({
|
|
|
101
101
|
membershipStatus: "active"
|
|
102
102
|
},
|
|
103
103
|
{
|
|
104
|
-
id: 2,
|
|
104
|
+
id: "2",
|
|
105
105
|
slug: "pending-workspace",
|
|
106
106
|
name: "Pending Workspace",
|
|
107
107
|
avatarUrl: "",
|
|
@@ -113,12 +113,12 @@ function createWorkspaceServiceFixture({
|
|
|
113
113
|
async insert(payload) {
|
|
114
114
|
calls.insert += 1;
|
|
115
115
|
insertedPayloads.push(payload);
|
|
116
|
-
const workspaceId = nextWorkspaceId
|
|
116
|
+
const workspaceId = String(nextWorkspaceId++);
|
|
117
117
|
const inserted = {
|
|
118
118
|
id: workspaceId,
|
|
119
119
|
slug: String(payload.slug || ""),
|
|
120
120
|
name: String(payload.name || ""),
|
|
121
|
-
ownerUserId:
|
|
121
|
+
ownerUserId: String(payload.ownerUserId || ""),
|
|
122
122
|
isPersonal: payload.isPersonal === true,
|
|
123
123
|
avatarUrl: String(payload.avatarUrl || "")
|
|
124
124
|
};
|
|
@@ -127,9 +127,9 @@ function createWorkspaceServiceFixture({
|
|
|
127
127
|
},
|
|
128
128
|
async updateById(workspaceId, patch) {
|
|
129
129
|
calls.updateById += 1;
|
|
130
|
-
const targetId =
|
|
130
|
+
const targetId = String(workspaceId || "").trim();
|
|
131
131
|
for (const [slug, workspace] of workspaceBySlug.entries()) {
|
|
132
|
-
if (
|
|
132
|
+
if (String(workspace.id || "").trim() !== targetId) {
|
|
133
133
|
continue;
|
|
134
134
|
}
|
|
135
135
|
const updated = {
|
|
@@ -185,7 +185,7 @@ test("workspaceService no longer exposes bootstrap payload assembly", () => {
|
|
|
185
185
|
test("workspaceService.listWorkspacesForUser returns only accessible workspaces", async () => {
|
|
186
186
|
const { service, calls } = createWorkspaceServiceFixture();
|
|
187
187
|
const workspaces = await service.listWorkspacesForUser({
|
|
188
|
-
id: 7,
|
|
188
|
+
id: "7",
|
|
189
189
|
email: "chiaramobily@gmail.com",
|
|
190
190
|
displayName: "Chiara"
|
|
191
191
|
});
|
|
@@ -204,7 +204,7 @@ test("workspaceService.listWorkspacesForUser no longer provisions personal works
|
|
|
204
204
|
});
|
|
205
205
|
|
|
206
206
|
await service.listWorkspacesForUser({
|
|
207
|
-
id: 7,
|
|
207
|
+
id: "7",
|
|
208
208
|
email: "chiaramobily@gmail.com",
|
|
209
209
|
displayName: "Chiara"
|
|
210
210
|
});
|
|
@@ -218,7 +218,7 @@ test("workspaceService.listWorkspacesForUser returns all active memberships in p
|
|
|
218
218
|
tenancyMode: "personal",
|
|
219
219
|
userWorkspaceRows: [
|
|
220
220
|
{
|
|
221
|
-
id: 1,
|
|
221
|
+
id: "1",
|
|
222
222
|
slug: "chiaramobily",
|
|
223
223
|
name: "Chiara Personal",
|
|
224
224
|
avatarUrl: "",
|
|
@@ -226,7 +226,7 @@ test("workspaceService.listWorkspacesForUser returns all active memberships in p
|
|
|
226
226
|
membershipStatus: "active"
|
|
227
227
|
},
|
|
228
228
|
{
|
|
229
|
-
id: 2,
|
|
229
|
+
id: "2",
|
|
230
230
|
slug: "tonymobily",
|
|
231
231
|
name: "Tony Workspace",
|
|
232
232
|
avatarUrl: "",
|
|
@@ -234,7 +234,7 @@ test("workspaceService.listWorkspacesForUser returns all active memberships in p
|
|
|
234
234
|
membershipStatus: "active"
|
|
235
235
|
},
|
|
236
236
|
{
|
|
237
|
-
id: 3,
|
|
237
|
+
id: "3",
|
|
238
238
|
slug: "pending-workspace",
|
|
239
239
|
name: "Pending Workspace",
|
|
240
240
|
avatarUrl: "",
|
|
@@ -245,7 +245,7 @@ test("workspaceService.listWorkspacesForUser returns all active memberships in p
|
|
|
245
245
|
});
|
|
246
246
|
|
|
247
247
|
const workspaces = await service.listWorkspacesForUser({
|
|
248
|
-
id: 7,
|
|
248
|
+
id: "7",
|
|
249
249
|
email: "chiaramobily@gmail.com",
|
|
250
250
|
displayName: "Chiara"
|
|
251
251
|
});
|
|
@@ -265,7 +265,7 @@ test("workspaceService.provisionWorkspaceForNewUser provisions personal workspac
|
|
|
265
265
|
});
|
|
266
266
|
|
|
267
267
|
const workspace = await service.provisionWorkspaceForNewUser({
|
|
268
|
-
id: 7,
|
|
268
|
+
id: "7",
|
|
269
269
|
email: "chiaramobily@gmail.com",
|
|
270
270
|
displayName: "Chiara"
|
|
271
271
|
});
|
|
@@ -283,7 +283,7 @@ test("workspaceService.provisionWorkspaceForNewUser is a no-op outside personal
|
|
|
283
283
|
});
|
|
284
284
|
|
|
285
285
|
const result = await service.provisionWorkspaceForNewUser({
|
|
286
|
-
id: 7,
|
|
286
|
+
id: "7",
|
|
287
287
|
email: "chiaramobily@gmail.com",
|
|
288
288
|
displayName: "Chiara"
|
|
289
289
|
});
|
|
@@ -304,7 +304,7 @@ test("workspaceService.createWorkspaceForAuthenticatedUser creates non-personal
|
|
|
304
304
|
|
|
305
305
|
const workspace = await service.createWorkspaceForAuthenticatedUser(
|
|
306
306
|
{
|
|
307
|
-
id: 7,
|
|
307
|
+
id: "7",
|
|
308
308
|
email: "chiaramobily@gmail.com",
|
|
309
309
|
displayName: "Chiara"
|
|
310
310
|
},
|
|
@@ -318,7 +318,7 @@ test("workspaceService.createWorkspaceForAuthenticatedUser creates non-personal
|
|
|
318
318
|
assert.equal(calls.insert, 1);
|
|
319
319
|
assert.equal(calls.ensureOwnerMembership, 1);
|
|
320
320
|
assert.equal(insertedPayloads[0].isPersonal, false);
|
|
321
|
-
assert.equal(insertedPayloads[0].ownerUserId, 7);
|
|
321
|
+
assert.equal(insertedPayloads[0].ownerUserId, "7");
|
|
322
322
|
});
|
|
323
323
|
|
|
324
324
|
test("workspaceService.createWorkspaceForAuthenticatedUser rejects creation when self-create policy is disabled", async () => {
|
|
@@ -330,7 +330,7 @@ test("workspaceService.createWorkspaceForAuthenticatedUser rejects creation when
|
|
|
330
330
|
() =>
|
|
331
331
|
service.createWorkspaceForAuthenticatedUser(
|
|
332
332
|
{
|
|
333
|
-
id: 7,
|
|
333
|
+
id: "7",
|
|
334
334
|
email: "chiaramobily@gmail.com",
|
|
335
335
|
displayName: "Chiara"
|
|
336
336
|
},
|
|
@@ -352,7 +352,7 @@ test("workspaceService.resolveWorkspaceContextForUserBySlug returns workspace-no
|
|
|
352
352
|
() =>
|
|
353
353
|
service.resolveWorkspaceContextForUserBySlug(
|
|
354
354
|
{
|
|
355
|
-
id: 7,
|
|
355
|
+
id: "7",
|
|
356
356
|
email: "chiaramobily@gmail.com",
|
|
357
357
|
displayName: "Chiara"
|
|
358
358
|
},
|
|
@@ -366,19 +366,19 @@ test("workspaceService.resolveWorkspaceContextForUserBySlug allows personal tena
|
|
|
366
366
|
const { service } = createWorkspaceServiceFixture({
|
|
367
367
|
tenancyMode: "personal",
|
|
368
368
|
personalWorkspace: {
|
|
369
|
-
id: 1,
|
|
369
|
+
id: "1",
|
|
370
370
|
slug: "my-personal",
|
|
371
371
|
name: "My Personal",
|
|
372
|
-
ownerUserId: 7,
|
|
372
|
+
ownerUserId: "7",
|
|
373
373
|
isPersonal: true,
|
|
374
374
|
avatarUrl: ""
|
|
375
375
|
},
|
|
376
376
|
additionalWorkspaces: [
|
|
377
377
|
{
|
|
378
|
-
id: 42,
|
|
378
|
+
id: "42",
|
|
379
379
|
slug: "team-alpha",
|
|
380
380
|
name: "Team Alpha",
|
|
381
|
-
ownerUserId: 99,
|
|
381
|
+
ownerUserId: "99",
|
|
382
382
|
isPersonal: false,
|
|
383
383
|
avatarUrl: ""
|
|
384
384
|
}
|
|
@@ -387,7 +387,7 @@ test("workspaceService.resolveWorkspaceContextForUserBySlug allows personal tena
|
|
|
387
387
|
|
|
388
388
|
const context = await service.resolveWorkspaceContextForUserBySlug(
|
|
389
389
|
{
|
|
390
|
-
id: 7,
|
|
390
|
+
id: "7",
|
|
391
391
|
email: "chiaramobily@gmail.com",
|
|
392
392
|
displayName: "Chiara"
|
|
393
393
|
},
|
|
@@ -414,10 +414,10 @@ test("workspaceService.resolveWorkspaceContextForUserBySlug grants owner access
|
|
|
414
414
|
return null;
|
|
415
415
|
}
|
|
416
416
|
return {
|
|
417
|
-
id: 1,
|
|
417
|
+
id: "1",
|
|
418
418
|
slug: "tonymobily",
|
|
419
419
|
name: "TonyMobily",
|
|
420
|
-
ownerUserId: 7,
|
|
420
|
+
ownerUserId: "7",
|
|
421
421
|
isPersonal: true,
|
|
422
422
|
avatarUrl: ""
|
|
423
423
|
};
|
|
@@ -458,7 +458,7 @@ test("workspaceService.resolveWorkspaceContextForUserBySlug grants owner access
|
|
|
458
458
|
|
|
459
459
|
const context = await service.resolveWorkspaceContextForUserBySlug(
|
|
460
460
|
{
|
|
461
|
-
id: 7,
|
|
461
|
+
id: "7",
|
|
462
462
|
email: "chiaramobily@gmail.com",
|
|
463
463
|
displayName: "Chiara"
|
|
464
464
|
},
|
|
@@ -487,7 +487,7 @@ test("workspaceService.resolveWorkspaceContextForUserBySlug resolves permissions
|
|
|
487
487
|
|
|
488
488
|
const context = await service.resolveWorkspaceContextForUserBySlug(
|
|
489
489
|
{
|
|
490
|
-
id: 7,
|
|
490
|
+
id: "7",
|
|
491
491
|
email: "chiaramobily@gmail.com",
|
|
492
492
|
displayName: "Chiara"
|
|
493
493
|
},
|
|
@@ -501,10 +501,10 @@ test("workspaceService.getWorkspaceForAuthenticatedUser resolves workspace from
|
|
|
501
501
|
const { service } = createWorkspaceServiceFixture({
|
|
502
502
|
additionalWorkspaces: [
|
|
503
503
|
{
|
|
504
|
-
id: 42,
|
|
504
|
+
id: "42",
|
|
505
505
|
slug: "team-alpha",
|
|
506
506
|
name: "Team Alpha",
|
|
507
|
-
ownerUserId: 99,
|
|
507
|
+
ownerUserId: "99",
|
|
508
508
|
isPersonal: false,
|
|
509
509
|
avatarUrl: ""
|
|
510
510
|
}
|
|
@@ -513,7 +513,7 @@ test("workspaceService.getWorkspaceForAuthenticatedUser resolves workspace from
|
|
|
513
513
|
|
|
514
514
|
const workspace = await service.getWorkspaceForAuthenticatedUser(
|
|
515
515
|
{
|
|
516
|
-
id: 7,
|
|
516
|
+
id: "7",
|
|
517
517
|
email: "chiaramobily@gmail.com",
|
|
518
518
|
displayName: "Chiara"
|
|
519
519
|
},
|
|
@@ -529,7 +529,7 @@ test("workspaceService.updateWorkspaceForAuthenticatedUser updates workspace pro
|
|
|
529
529
|
|
|
530
530
|
const workspace = await service.updateWorkspaceForAuthenticatedUser(
|
|
531
531
|
{
|
|
532
|
-
id: 7,
|
|
532
|
+
id: "7",
|
|
533
533
|
email: "chiaramobily@gmail.com",
|
|
534
534
|
displayName: "Chiara"
|
|
535
535
|
},
|
|
@@ -110,10 +110,10 @@ test("workspaceSettingsRepository.findByWorkspaceId maps the stored row", async
|
|
|
110
110
|
defaultInvitesEnabled: createDefaultWorkspaceSettings()
|
|
111
111
|
});
|
|
112
112
|
|
|
113
|
-
const record = await repository.findByWorkspaceId(1);
|
|
113
|
+
const record = await repository.findByWorkspaceId("1");
|
|
114
114
|
|
|
115
115
|
assert.deepEqual(record, {
|
|
116
|
-
workspaceId: 1,
|
|
116
|
+
workspaceId: "1",
|
|
117
117
|
lightPrimaryColor: DEFAULT_WORKSPACE_THEME.light.color,
|
|
118
118
|
lightSecondaryColor: DEFAULT_WORKSPACE_THEME.light.secondaryColor,
|
|
119
119
|
lightSurfaceColor: DEFAULT_WORKSPACE_THEME.light.surfaceColor,
|
|
@@ -134,7 +134,7 @@ test("workspaceSettingsRepository.updateSettingsByWorkspaceId updates invitesEna
|
|
|
134
134
|
defaultInvitesEnabled: createDefaultWorkspaceSettings()
|
|
135
135
|
});
|
|
136
136
|
|
|
137
|
-
const updated = await repository.updateSettingsByWorkspaceId(1, {
|
|
137
|
+
const updated = await repository.updateSettingsByWorkspaceId("1", {
|
|
138
138
|
invitesEnabled: false
|
|
139
139
|
});
|
|
140
140
|
|
|
@@ -149,9 +149,9 @@ test("workspaceSettingsRepository.ensureForWorkspaceId inserts the injected defa
|
|
|
149
149
|
defaultInvitesEnabled: false
|
|
150
150
|
});
|
|
151
151
|
|
|
152
|
-
const record = await repository.ensureForWorkspaceId(5);
|
|
152
|
+
const record = await repository.ensureForWorkspaceId("5");
|
|
153
153
|
|
|
154
|
-
assert.equal(state.insertedRow.workspace_id, 5);
|
|
154
|
+
assert.equal(state.insertedRow.workspace_id, "5");
|
|
155
155
|
assert.equal(state.insertedRow.light_primary_color, DEFAULT_WORKSPACE_THEME.light.color);
|
|
156
156
|
assert.equal(state.insertedRow.light_secondary_color, DEFAULT_WORKSPACE_THEME.light.secondaryColor);
|
|
157
157
|
assert.equal(state.insertedRow.light_surface_color, DEFAULT_WORKSPACE_THEME.light.surfaceColor);
|
|
@@ -176,6 +176,7 @@ test("workspaceSettingsRepository.ensureForWorkspaceId inserts the injected defa
|
|
|
176
176
|
assert.equal(record.darkSurfaceColor, DEFAULT_WORKSPACE_THEME.dark.surfaceColor);
|
|
177
177
|
assert.equal(record.darkSurfaceVariantColor, DEFAULT_WORKSPACE_THEME.dark.surfaceVariantColor);
|
|
178
178
|
assert.equal(record.invitesEnabled, false);
|
|
179
|
+
assert.equal(record.workspaceId, "5");
|
|
179
180
|
});
|
|
180
181
|
|
|
181
182
|
test("workspaceSettingsRepository.updateSettingsByWorkspaceId updates workspace settings columns", async () => {
|
|
@@ -184,7 +185,7 @@ test("workspaceSettingsRepository.updateSettingsByWorkspaceId updates workspace
|
|
|
184
185
|
defaultInvitesEnabled: true
|
|
185
186
|
});
|
|
186
187
|
|
|
187
|
-
const updated = await repository.updateSettingsByWorkspaceId(1, {
|
|
188
|
+
const updated = await repository.updateSettingsByWorkspaceId("1", {
|
|
188
189
|
lightPrimaryColor: "#123abc"
|
|
189
190
|
});
|
|
190
191
|
|
|
@@ -118,9 +118,9 @@ test("workspace settings output normalizes raw service payloads", () => {
|
|
|
118
118
|
|
|
119
119
|
assert.deepEqual(normalized, {
|
|
120
120
|
workspace: {
|
|
121
|
-
id: 7,
|
|
121
|
+
id: "7",
|
|
122
122
|
slug: "mercury",
|
|
123
|
-
ownerUserId: 9
|
|
123
|
+
ownerUserId: "9"
|
|
124
124
|
},
|
|
125
125
|
settings: {
|
|
126
126
|
lightPrimaryColor: "#0F6B54",
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
# Server Common
|
|
2
|
-
|
|
3
|
-
This directory contains server-only runtime pieces reused by multiple slices in `users-core`.
|
|
4
|
-
|
|
5
|
-
Use these folders:
|
|
6
|
-
- `repositories/`: shared repositories and repository-only helpers.
|
|
7
|
-
- `services/`: shared domain services consumed by multiple slices.
|
|
8
|
-
- `contributors/`: shared action-context/bootstrap contributors.
|
|
9
|
-
- `validators/`: shared request/response validators used by multiple adapters.
|
|
10
|
-
- `formatters/`: shared payload formatters/projections for transport output.
|
|
11
|
-
- `routes/`: shared route schema maps used by more than one route adapter.
|
|
12
|
-
|
|
13
|
-
Keep these files here:
|
|
14
|
-
- `registerCommonRepositories.js`: shared repository bindings.
|
|
15
|
-
- `registerSharedApi.js`: shared API metadata registration.
|
|
16
|
-
|
|
17
|
-
Do not put these in `common/`:
|
|
18
|
-
- feature-only actions/services/repositories/controllers
|
|
19
|
-
- one-off route payload shapes used by a single feature
|
|
20
|
-
- UI/client code
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# `contributors/`
|
|
2
|
-
|
|
3
|
-
Put shared runtime contributors here (for action context or bootstrap payload composition).
|
|
4
|
-
|
|
5
|
-
Allowed:
|
|
6
|
-
- contributors reused by multiple slices/actions
|
|
7
|
-
- contributor logic that delegates domain work to services
|
|
8
|
-
|
|
9
|
-
Not allowed:
|
|
10
|
-
- feature-specific contributors used by one slice only
|
|
11
|
-
- direct repository access when a service already owns that domain
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# `repositories/`
|
|
2
|
-
|
|
3
|
-
Use this directory for persistence code shared by more than one server slice.
|
|
4
|
-
|
|
5
|
-
What belongs here:
|
|
6
|
-
- repository helpers that are part of persistence logic
|
|
7
|
-
- shared repositories used by multiple features/slices
|
|
8
|
-
|
|
9
|
-
Examples:
|
|
10
|
-
- SQL/date/JSON helper functions reused by several repositories
|
|
11
|
-
- `workspaceMembershipsRepository`
|
|
12
|
-
- `workspaceInvitesRepository`
|
|
13
|
-
|
|
14
|
-
Do not put these here:
|
|
15
|
-
- repositories used by only one feature
|
|
16
|
-
- business logic
|
|
17
|
-
- action definitions
|
|
18
|
-
- transport validation
|
|
19
|
-
- feature-specific response mapping
|
|
20
|
-
|
|
21
|
-
Rule:
|
|
22
|
-
- if a helper is reused by multiple repository files, it can live here
|
|
23
|
-
- if a repository is reused by multiple slices, keep it here
|
|
24
|
-
- if a repository is owned by one slice only, keep it in that slice folder
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# `routes/`
|
|
2
|
-
|
|
3
|
-
Put shared route schema maps here when multiple route adapters consume them.
|
|
4
|
-
|
|
5
|
-
Allowed:
|
|
6
|
-
- shared route request/response schema groupings
|
|
7
|
-
- references to shared resources/commands
|
|
8
|
-
|
|
9
|
-
Not allowed:
|
|
10
|
-
- route registration/handlers
|
|
11
|
-
- business logic
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# `services/`
|
|
2
|
-
|
|
3
|
-
Put shared server services here when they are used by more than one slice.
|
|
4
|
-
|
|
5
|
-
Allowed:
|
|
6
|
-
- cross-slice service logic with clear inputs/outputs
|
|
7
|
-
- no HTTP route validator handling
|
|
8
|
-
|
|
9
|
-
Not allowed:
|
|
10
|
-
- feature-only services
|
|
11
|
-
- route adapters/controllers
|
|
12
|
-
- response schema declarations
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# `validators/`
|
|
2
|
-
|
|
3
|
-
Put shared validators here when they are reused by multiple server slices/adapters.
|
|
4
|
-
|
|
5
|
-
Allowed:
|
|
6
|
-
- validator objects (`schema` + `normalize`)
|
|
7
|
-
- transport-level reusable validators
|
|
8
|
-
|
|
9
|
-
Not allowed:
|
|
10
|
-
- feature-only validators used by one slice
|
|
11
|
-
- business/domain decision logic
|