@jskit-ai/workspaces-core 0.1.30 → 0.1.32

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.
Files changed (61) hide show
  1. package/package.descriptor.mjs +11 -22
  2. package/package.json +11 -9
  3. package/src/server/WorkspacesCoreServiceProvider.js +22 -2
  4. package/src/server/common/repositories/workspaceInvitesRepository.js +233 -78
  5. package/src/server/common/repositories/workspaceMembershipsRepository.js +177 -86
  6. package/src/server/common/repositories/workspacesRepository.js +179 -86
  7. package/src/server/common/services/workspaceContextService.js +26 -24
  8. package/src/server/common/validators/routeParamsValidator.js +36 -53
  9. package/src/server/registerWorkspaceCore.js +6 -7
  10. package/src/server/registerWorkspaceRepositories.js +7 -3
  11. package/src/server/support/workspaceServerScopeSupport.js +1 -1
  12. package/src/server/workspaceBootstrapContributor.js +5 -14
  13. package/src/server/workspaceDirectory/bootWorkspaceDirectoryRoutes.js +54 -27
  14. package/src/server/workspaceDirectory/workspaceDirectoryActions.js +30 -24
  15. package/src/server/workspaceMembers/bootWorkspaceMembers.js +70 -32
  16. package/src/server/workspaceMembers/workspaceMembersActions.js +61 -27
  17. package/src/server/workspaceMembers/workspaceMembersService.js +43 -7
  18. package/src/server/workspacePendingInvitations/bootWorkspacePendingInvitations.js +28 -13
  19. package/src/server/workspacePendingInvitations/workspacePendingInvitationsActions.js +13 -15
  20. package/src/server/workspacePendingInvitations/workspacePendingInvitationsService.js +33 -10
  21. package/src/server/workspaceSettings/bootWorkspaceSettings.js +32 -13
  22. package/src/server/workspaceSettings/registerWorkspaceSettings.js +5 -1
  23. package/src/server/workspaceSettings/workspaceSettingsActions.js +18 -12
  24. package/src/server/workspaceSettings/workspaceSettingsRepository.js +104 -91
  25. package/src/server/workspaceSettings/workspaceSettingsService.js +5 -6
  26. package/src/shared/jsonApiTransports.js +79 -0
  27. package/src/shared/resources/workspaceInvitesResource.js +158 -0
  28. package/src/shared/resources/workspaceMembersResource.js +176 -311
  29. package/src/shared/resources/workspaceMembershipsResource.js +96 -0
  30. package/src/shared/resources/workspacePendingInvitationsResource.js +25 -72
  31. package/src/shared/resources/workspaceResource.js +113 -144
  32. package/src/shared/resources/workspaceRoleCatalogSchema.js +31 -0
  33. package/src/shared/resources/workspaceSettingsResource.js +276 -148
  34. package/test/repositoryContracts.test.js +16 -4
  35. package/test/resourcesCanonical.test.js +39 -16
  36. package/test/routeParamsValidator.test.js +37 -19
  37. package/test/usersRouteResources.test.js +27 -17
  38. package/test/workspaceActionContextContributor.test.js +1 -1
  39. package/test/workspaceInternalCrudResources.test.js +98 -0
  40. package/test/workspaceInvitesRepository.test.js +196 -148
  41. package/test/workspaceMembersResource.test.js +35 -0
  42. package/test/workspaceMembershipsRepository.test.js +155 -115
  43. package/test/workspacePendingInvitationsResource.test.js +18 -23
  44. package/test/workspacePendingInvitationsService.test.js +2 -1
  45. package/test/workspaceServerScopeSupport.test.js +21 -3
  46. package/test/workspaceSettingsActions.test.js +5 -7
  47. package/test/workspaceSettingsInternalResource.test.js +8 -0
  48. package/test/workspaceSettingsRepository.test.js +158 -123
  49. package/test/workspaceSettingsResource.test.js +51 -62
  50. package/test/workspaceSettingsService.test.js +0 -1
  51. package/test/workspacesRepository.test.js +318 -174
  52. package/test/workspacesRouteRequestInputValidator.test.js +25 -11
  53. package/src/server/common/resources/workspaceInvitesResource.js +0 -207
  54. package/src/server/common/resources/workspaceMembershipsResource.js +0 -154
  55. package/src/server/common/resources/workspacesResource.js +0 -170
  56. package/src/server/common/validators/authenticatedUserValidator.js +0 -43
  57. package/src/shared/resources/resolveGlobalArrayRegistry.js +0 -6
  58. package/src/shared/resources/workspaceSettingsFields.js +0 -65
  59. package/templates/packages/main/src/shared/resources/workspaceSettingsFields.js +0 -197
  60. package/test/settingsFieldRegistriesSingleton.test.js +0 -14
  61. package/test-support/registerDefaultSettingsFields.js +0 -1
@@ -5,7 +5,6 @@ import {
5
5
  TENANCY_MODE_NONE,
6
6
  resolveTenancyProfile
7
7
  } from "../shared/tenancyProfile.js";
8
- import { workspacePendingInvitationsResource } from "../shared/resources/workspacePendingInvitationsResource.js";
9
8
  import {
10
9
  mapMembershipSummary,
11
10
  mapWorkspaceSettingsPublic,
@@ -17,12 +16,6 @@ const REQUESTED_WORKSPACE_STATUS_NOT_FOUND = "not_found";
17
16
  const REQUESTED_WORKSPACE_STATUS_FORBIDDEN = "forbidden";
18
17
  const REQUESTED_WORKSPACE_STATUS_UNAUTHENTICATED = "unauthenticated";
19
18
 
20
- function normalizePendingInvites(invites) {
21
- return workspacePendingInvitationsResource.operations.list.outputValidator.normalize({
22
- pendingInvites: invites
23
- }).pendingInvites;
24
- }
25
-
26
19
  function normalizeQueryPayload(value = {}) {
27
20
  if (!value || typeof value !== "object" || Array.isArray(value)) {
28
21
  return {};
@@ -168,13 +161,11 @@ function createWorkspaceBootstrapContributor({
168
161
 
169
162
  const pendingInvites =
170
163
  workspaceInvitationsEnabled
171
- ? normalizePendingInvites(
172
- await workspacePendingInvitationsService.listPendingInvitesForUser(latestProfile, {
173
- context: {
174
- actor: latestProfile
175
- }
176
- })
177
- )
164
+ ? await workspacePendingInvitationsService.listPendingInvitesForUser(latestProfile, {
165
+ context: {
166
+ actor: latestProfile
167
+ }
168
+ })
178
169
  : [];
179
170
  const workspaces = await workspaceService.listWorkspacesForUser(latestProfile, { request });
180
171
  let workspaceContext = null;
@@ -1,9 +1,30 @@
1
- import { withStandardErrorResponses } from "@jskit-ai/http-runtime/shared/validators/errorResponses";
2
- import { workspaceResource } from "../../shared/resources/workspaceResource.js";
1
+ import { createJsonApiResourceRouteContract } from "@jskit-ai/http-runtime/shared/validators/jsonApiRouteTransport";
2
+ import {
3
+ workspaceListItemOutputValidator,
4
+ workspaceResource
5
+ } from "../../shared/resources/workspaceResource.js";
6
+ import {
7
+ WORKSPACES_COLLECTION_TRANSPORT,
8
+ WORKSPACES_TRANSPORT
9
+ } from "../../shared/jsonApiTransports.js";
3
10
  import { resolveWorkspaceRoutePath } from "../common/support/workspaceRoutePaths.js";
4
11
  import { workspaceSlugParamsValidator } from "../common/validators/routeParamsValidator.js";
5
12
  import { resolveDefaultWorkspaceRouteSurfaceIdFromAppConfig } from "../support/workspaceActionSurfaces.js";
6
13
 
14
+ function resolveWorkspaceRecordId(record = {}, context = {}) {
15
+ const workspaceId = record?.workspace?.id ?? record?.id;
16
+ if (workspaceId != null && String(workspaceId).trim()) {
17
+ return workspaceId;
18
+ }
19
+
20
+ const workspaceSlug = context?.request?.params?.workspaceSlug;
21
+ if (workspaceSlug != null && String(workspaceSlug).trim()) {
22
+ return workspaceSlug;
23
+ }
24
+
25
+ throw new Error("Workspace JSON:API response requires workspace id.");
26
+ }
27
+
7
28
  function bootWorkspaceDirectoryRoutes(app) {
8
29
  if (!app || typeof app.make !== "function" || typeof app.has !== "function") {
9
30
  throw new Error("bootWorkspaceDirectoryRoutes requires application make()/has().");
@@ -22,18 +43,18 @@ function bootWorkspaceDirectoryRoutes(app) {
22
43
  "/api/workspaces",
23
44
  {
24
45
  auth: "required",
25
- meta: {
26
- tags: ["workspace"],
27
- summary: "Create a workspace for the authenticated user"
28
- },
29
- bodyValidator: workspaceResource.operations.create.bodyValidator,
30
- responseValidators: withStandardErrorResponses(
31
- {
32
- 200: workspaceResource.operations.create.outputValidator
33
- },
34
- { includeValidation400: true }
35
- )
46
+ meta: {
47
+ tags: ["workspace"],
48
+ summary: "Create a workspace for the authenticated user"
36
49
  },
50
+ ...createJsonApiResourceRouteContract({
51
+ ...WORKSPACES_TRANSPORT,
52
+ body: workspaceResource.operations.create.body,
53
+ output: workspaceResource.operations.create.output,
54
+ outputKind: "record",
55
+ includeValidation400: true
56
+ })
57
+ },
37
58
  async function (request, reply) {
38
59
  const body = request.input.body || {};
39
60
  const response = await request.executeAction({
@@ -57,8 +78,10 @@ function bootWorkspaceDirectoryRoutes(app) {
57
78
  tags: ["workspace"],
58
79
  summary: "List workspaces visible to authenticated user"
59
80
  },
60
- responseValidators: withStandardErrorResponses({
61
- 200: workspaceResource.operations.list.outputValidator
81
+ ...createJsonApiResourceRouteContract({
82
+ ...WORKSPACES_COLLECTION_TRANSPORT,
83
+ output: workspaceListItemOutputValidator,
84
+ outputKind: "collection"
62
85
  })
63
86
  },
64
87
  async function (request, reply) {
@@ -81,9 +104,12 @@ function bootWorkspaceDirectoryRoutes(app) {
81
104
  tags: ["workspace"],
82
105
  summary: "Get workspace profile by workspace slug"
83
106
  },
84
- paramsValidator: workspaceSlugParamsValidator,
85
- responseValidators: withStandardErrorResponses({
86
- 200: workspaceResource.operations.view.outputValidator
107
+ params: workspaceSlugParamsValidator,
108
+ ...createJsonApiResourceRouteContract({
109
+ ...WORKSPACES_TRANSPORT,
110
+ output: workspaceResource.operations.view.output,
111
+ outputKind: "record",
112
+ getRecordId: resolveWorkspaceRecordId
87
113
  })
88
114
  },
89
115
  async function (request, reply) {
@@ -108,21 +134,22 @@ function bootWorkspaceDirectoryRoutes(app) {
108
134
  tags: ["workspace"],
109
135
  summary: "Update workspace profile by workspace slug"
110
136
  },
111
- paramsValidator: workspaceSlugParamsValidator,
112
- bodyValidator: workspaceResource.operations.patch.bodyValidator,
113
- responseValidators: withStandardErrorResponses(
114
- {
115
- 200: workspaceResource.operations.patch.outputValidator
116
- },
117
- { includeValidation400: true }
118
- )
137
+ params: workspaceSlugParamsValidator,
138
+ ...createJsonApiResourceRouteContract({
139
+ ...WORKSPACES_TRANSPORT,
140
+ body: workspaceResource.operations.patch.body,
141
+ output: workspaceResource.operations.patch.output,
142
+ outputKind: "record",
143
+ getRecordId: resolveWorkspaceRecordId,
144
+ includeValidation400: true
145
+ })
119
146
  },
120
147
  async function (request, reply) {
121
148
  const response = await request.executeAction({
122
149
  actionId: "workspace.workspaces.update",
123
150
  input: {
124
151
  workspaceSlug: request.input.params.workspaceSlug,
125
- patch: request.input.body
152
+ ...(request.input.body || {})
126
153
  }
127
154
  });
128
155
  reply.code(200).send(response);
@@ -1,11 +1,21 @@
1
1
  import {
2
- EMPTY_INPUT_VALIDATOR,
2
+ emptyInputValidator,
3
3
  resolveRequest
4
4
  } from "@jskit-ai/kernel/shared/actions/actionContributorHelpers";
5
+ import { returnJsonApiData } from "@jskit-ai/http-runtime/shared";
6
+ import { composeSchemaDefinitions } from "@jskit-ai/kernel/shared/validators";
5
7
  import { workspaceResource } from "../../shared/resources/workspaceResource.js";
6
8
  import { workspaceSlugParamsValidator } from "../common/validators/routeParamsValidator.js";
7
9
  import { resolveActionUser } from "../common/support/resolveActionUser.js";
8
10
 
11
+ const workspaceUpdateInputValidator = composeSchemaDefinitions([
12
+ workspaceSlugParamsValidator,
13
+ workspaceResource.operations.patch.body
14
+ ], {
15
+ mode: "patch",
16
+ context: "workspaceDirectoryActions.workspaceUpdateInputValidator"
17
+ });
18
+
9
19
  const workspaceDirectoryActions = Object.freeze([
10
20
  {
11
21
  id: "workspace.workspaces.create",
@@ -16,8 +26,8 @@ const workspaceDirectoryActions = Object.freeze([
16
26
  permission: {
17
27
  require: "authenticated"
18
28
  },
19
- inputValidator: workspaceResource.operations.create.bodyValidator,
20
- outputValidator: workspaceResource.operations.create.outputValidator,
29
+ input: workspaceResource.operations.create.body,
30
+ output: null,
21
31
  idempotency: "none",
22
32
  audit: {
23
33
  actionName: "workspace.workspaces.create"
@@ -29,10 +39,10 @@ const workspaceDirectoryActions = Object.freeze([
29
39
  }
30
40
  },
31
41
  async execute(input, context, deps) {
32
- return deps.workspaceService.createWorkspaceForAuthenticatedUser(resolveActionUser(context, input), input, {
42
+ return returnJsonApiData(await deps.workspaceService.createWorkspaceForAuthenticatedUser(resolveActionUser(context, input), input, {
33
43
  request: resolveRequest(context),
34
44
  context
35
- });
45
+ }));
36
46
  }
37
47
  },
38
48
  {
@@ -44,21 +54,21 @@ const workspaceDirectoryActions = Object.freeze([
44
54
  permission: {
45
55
  require: "authenticated"
46
56
  },
47
- inputValidator: EMPTY_INPUT_VALIDATOR,
48
- outputValidator: workspaceResource.operations.list.outputValidator,
57
+ input: emptyInputValidator,
58
+ output: null,
49
59
  idempotency: "none",
50
60
  audit: {
51
61
  actionName: "workspace.workspaces.list"
52
62
  },
53
63
  observability: {},
54
64
  async execute(input, context, deps) {
55
- return {
65
+ return returnJsonApiData({
56
66
  items: await deps.workspaceService.listWorkspacesForAuthenticatedUser(resolveActionUser(context, input), {
57
67
  request: resolveRequest(context),
58
68
  context
59
69
  }),
60
70
  nextCursor: null
61
- };
71
+ });
62
72
  }
63
73
  },
64
74
  {
@@ -71,22 +81,22 @@ const workspaceDirectoryActions = Object.freeze([
71
81
  require: "any",
72
82
  permissions: ["workspace.settings.view", "workspace.settings.update"]
73
83
  },
74
- inputValidator: workspaceSlugParamsValidator,
75
- outputValidator: workspaceResource.operations.view.outputValidator,
84
+ input: workspaceSlugParamsValidator,
85
+ output: null,
76
86
  idempotency: "none",
77
87
  audit: {
78
88
  actionName: "workspace.workspaces.read"
79
89
  },
80
90
  observability: {},
81
91
  async execute(input, context, deps) {
82
- return deps.workspaceService.getWorkspaceForAuthenticatedUser(
92
+ return returnJsonApiData(await deps.workspaceService.getWorkspaceForAuthenticatedUser(
83
93
  resolveActionUser(context, input),
84
94
  input.workspaceSlug,
85
95
  {
86
96
  request: resolveRequest(context),
87
97
  context
88
98
  }
89
- );
99
+ ));
90
100
  }
91
101
  },
92
102
  {
@@ -99,13 +109,8 @@ const workspaceDirectoryActions = Object.freeze([
99
109
  require: "all",
100
110
  permissions: ["workspace.settings.update"]
101
111
  },
102
- inputValidator: [
103
- workspaceSlugParamsValidator,
104
- {
105
- patch: workspaceResource.operations.patch.bodyValidator
106
- }
107
- ],
108
- outputValidator: workspaceResource.operations.patch.outputValidator,
112
+ input: workspaceUpdateInputValidator,
113
+ output: null,
109
114
  idempotency: "optional",
110
115
  audit: {
111
116
  actionName: "workspace.workspaces.update"
@@ -117,15 +122,16 @@ const workspaceDirectoryActions = Object.freeze([
117
122
  }
118
123
  },
119
124
  async execute(input, context, deps) {
120
- return deps.workspaceService.updateWorkspaceForAuthenticatedUser(
125
+ const { workspaceSlug, ...patch } = input;
126
+ return returnJsonApiData(await deps.workspaceService.updateWorkspaceForAuthenticatedUser(
121
127
  resolveActionUser(context, input),
122
- input.workspaceSlug,
123
- input.patch,
128
+ workspaceSlug,
129
+ patch,
124
130
  {
125
131
  request: resolveRequest(context),
126
132
  context
127
133
  }
128
- );
134
+ ));
129
135
  }
130
136
  }
131
137
  ]);
@@ -1,4 +1,11 @@
1
- import { withStandardErrorResponses } from "@jskit-ai/http-runtime/shared/validators/errorResponses";
1
+ import { createJsonApiResourceRouteContract } from "@jskit-ai/http-runtime/shared/validators/jsonApiRouteTransport";
2
+ import {
3
+ WORKSPACE_INVITES_TRANSPORT,
4
+ WORKSPACE_INVITE_CREATE_TRANSPORT,
5
+ WORKSPACE_MEMBERS_TRANSPORT,
6
+ WORKSPACE_MEMBER_ROLE_UPDATE_TRANSPORT,
7
+ WORKSPACE_ROLE_CATALOG_TRANSPORT
8
+ } from "../../shared/jsonApiTransports.js";
2
9
  import { workspaceMembersResource } from "../../shared/resources/workspaceMembersResource.js";
3
10
  import { resolveWorkspaceRoutePath } from "../common/support/workspaceRoutePaths.js";
4
11
  import {
@@ -7,6 +14,20 @@ import {
7
14
  } from "../common/validators/routeParamsValidator.js";
8
15
  import { resolveDefaultWorkspaceRouteSurfaceIdFromAppConfig } from "../support/workspaceActionSurfaces.js";
9
16
 
17
+ function resolveWorkspaceAggregateRecordId(record = {}, context = {}) {
18
+ const workspaceId = record?.workspace?.id;
19
+ if (workspaceId != null && String(workspaceId).trim()) {
20
+ return workspaceId;
21
+ }
22
+
23
+ const workspaceSlug = context?.request?.params?.workspaceSlug;
24
+ if (workspaceSlug != null && String(workspaceSlug).trim()) {
25
+ return workspaceSlug;
26
+ }
27
+
28
+ throw new Error("Workspace JSON:API response requires workspace id.");
29
+ }
30
+
10
31
  function bootWorkspaceMembers(app) {
11
32
  if (!app || typeof app.make !== "function") {
12
33
  throw new Error("bootWorkspaceMembers requires application make().");
@@ -32,9 +53,12 @@ function bootWorkspaceMembers(app) {
32
53
  tags: ["workspace"],
33
54
  summary: "Get workspace role catalog by workspace slug"
34
55
  },
35
- paramsValidator: workspaceSlugParamsValidator,
36
- responseValidators: withStandardErrorResponses({
37
- 200: workspaceMembersResource.operations.rolesList.outputValidator
56
+ params: workspaceSlugParamsValidator,
57
+ ...createJsonApiResourceRouteContract({
58
+ ...WORKSPACE_ROLE_CATALOG_TRANSPORT,
59
+ output: workspaceMembersResource.operations.rolesList.output,
60
+ outputKind: "record",
61
+ getRecordId: resolveWorkspaceAggregateRecordId
38
62
  })
39
63
  },
40
64
  async function (request, reply) {
@@ -60,9 +84,12 @@ function bootWorkspaceMembers(app) {
60
84
  tags: ["workspace"],
61
85
  summary: "List members by workspace slug"
62
86
  },
63
- paramsValidator: workspaceSlugParamsValidator,
64
- responseValidators: withStandardErrorResponses({
65
- 200: workspaceMembersResource.operations.membersList.outputValidator
87
+ params: workspaceSlugParamsValidator,
88
+ ...createJsonApiResourceRouteContract({
89
+ ...WORKSPACE_MEMBERS_TRANSPORT,
90
+ output: workspaceMembersResource.operations.membersList.output,
91
+ outputKind: "record",
92
+ getRecordId: resolveWorkspaceAggregateRecordId
66
93
  })
67
94
  },
68
95
  async function (request, reply) {
@@ -88,14 +115,15 @@ function bootWorkspaceMembers(app) {
88
115
  tags: ["workspace"],
89
116
  summary: "Update workspace member role by workspace slug"
90
117
  },
91
- paramsValidator: routeParamsValidator,
92
- bodyValidator: workspaceMembersResource.operations.updateMemberRole.bodyValidator,
93
- responseValidators: withStandardErrorResponses(
94
- {
95
- 200: workspaceMembersResource.operations.updateMemberRole.outputValidator
96
- },
97
- { includeValidation400: true }
98
- )
118
+ params: routeParamsValidator,
119
+ ...createJsonApiResourceRouteContract({
120
+ ...WORKSPACE_MEMBER_ROLE_UPDATE_TRANSPORT,
121
+ body: workspaceMembersResource.operations.updateMemberRole.body,
122
+ output: workspaceMembersResource.operations.updateMemberRole.output,
123
+ outputKind: "record",
124
+ getRecordId: resolveWorkspaceAggregateRecordId,
125
+ includeValidation400: true
126
+ })
99
127
  },
100
128
  async function (request, reply) {
101
129
  const response = await request.executeAction({
@@ -122,9 +150,12 @@ function bootWorkspaceMembers(app) {
122
150
  tags: ["workspace"],
123
151
  summary: "Remove workspace member by workspace slug"
124
152
  },
125
- paramsValidator: routeParamsValidator,
126
- responseValidators: withStandardErrorResponses({
127
- 200: workspaceMembersResource.operations.removeMember.outputValidator
153
+ params: routeParamsValidator,
154
+ ...createJsonApiResourceRouteContract({
155
+ ...WORKSPACE_MEMBERS_TRANSPORT,
156
+ output: workspaceMembersResource.operations.removeMember.output,
157
+ outputKind: "record",
158
+ getRecordId: resolveWorkspaceAggregateRecordId
128
159
  })
129
160
  },
130
161
  async function (request, reply) {
@@ -152,9 +183,12 @@ function bootWorkspaceMembers(app) {
152
183
  tags: ["workspace"],
153
184
  summary: "List workspace invites by workspace slug"
154
185
  },
155
- paramsValidator: workspaceSlugParamsValidator,
156
- responseValidators: withStandardErrorResponses({
157
- 200: workspaceMembersResource.operations.invitesList.outputValidator
186
+ params: workspaceSlugParamsValidator,
187
+ ...createJsonApiResourceRouteContract({
188
+ ...WORKSPACE_INVITES_TRANSPORT,
189
+ output: workspaceMembersResource.operations.invitesList.output,
190
+ outputKind: "record",
191
+ getRecordId: resolveWorkspaceAggregateRecordId
158
192
  })
159
193
  },
160
194
  async function (request, reply) {
@@ -180,14 +214,15 @@ function bootWorkspaceMembers(app) {
180
214
  tags: ["workspace"],
181
215
  summary: "Create workspace invite by workspace slug"
182
216
  },
183
- paramsValidator: workspaceSlugParamsValidator,
184
- bodyValidator: workspaceMembersResource.operations.createInvite.bodyValidator,
185
- responseValidators: withStandardErrorResponses(
186
- {
187
- 200: workspaceMembersResource.operations.createInvite.outputValidator
188
- },
189
- { includeValidation400: true }
190
- )
217
+ params: workspaceSlugParamsValidator,
218
+ ...createJsonApiResourceRouteContract({
219
+ ...WORKSPACE_INVITE_CREATE_TRANSPORT,
220
+ body: workspaceMembersResource.operations.createInvite.body,
221
+ output: workspaceMembersResource.operations.createInvite.output,
222
+ outputKind: "record",
223
+ getRecordId: resolveWorkspaceAggregateRecordId,
224
+ includeValidation400: true
225
+ })
191
226
  },
192
227
  async function (request, reply) {
193
228
  const response = await request.executeAction({
@@ -214,9 +249,12 @@ function bootWorkspaceMembers(app) {
214
249
  tags: ["workspace"],
215
250
  summary: "Revoke workspace invite by workspace slug"
216
251
  },
217
- paramsValidator: routeParamsValidator,
218
- responseValidators: withStandardErrorResponses({
219
- 200: workspaceMembersResource.operations.revokeInvite.outputValidator
252
+ params: routeParamsValidator,
253
+ ...createJsonApiResourceRouteContract({
254
+ ...WORKSPACE_INVITES_TRANSPORT,
255
+ output: workspaceMembersResource.operations.revokeInvite.output,
256
+ outputKind: "record",
257
+ getRecordId: resolveWorkspaceAggregateRecordId
220
258
  })
221
259
  },
222
260
  async function (request, reply) {
@@ -1,8 +1,42 @@
1
+ import { composeSchemaDefinitions } from "@jskit-ai/kernel/shared/validators";
2
+ import { returnJsonApiData } from "@jskit-ai/http-runtime/shared";
1
3
  import { resolveWorkspace } from "../support/resolveWorkspace.js";
2
4
  import { resolveActionUser } from "../common/support/resolveActionUser.js";
3
5
  import { workspaceMembersResource } from "../../shared/resources/workspaceMembersResource.js";
4
6
  import { workspaceSlugParamsValidator } from "../common/validators/routeParamsValidator.js";
5
7
 
8
+ const updateMemberRoleActionInput = composeSchemaDefinitions([
9
+ workspaceSlugParamsValidator,
10
+ workspaceMembersResource.operations.updateMemberRole.input
11
+ ], {
12
+ mode: workspaceMembersResource.operations.updateMemberRole.input.mode,
13
+ context: "workspaceMembersActions.updateMemberRoleActionInput"
14
+ });
15
+
16
+ const removeMemberActionInput = composeSchemaDefinitions([
17
+ workspaceSlugParamsValidator,
18
+ workspaceMembersResource.operations.removeMember.input
19
+ ], {
20
+ mode: workspaceMembersResource.operations.removeMember.input.mode,
21
+ context: "workspaceMembersActions.removeMemberActionInput"
22
+ });
23
+
24
+ const createInviteActionInput = composeSchemaDefinitions([
25
+ workspaceSlugParamsValidator,
26
+ workspaceMembersResource.operations.createInvite.body
27
+ ], {
28
+ mode: workspaceMembersResource.operations.createInvite.body.mode,
29
+ context: "workspaceMembersActions.createInviteActionInput"
30
+ });
31
+
32
+ const revokeInviteActionInput = composeSchemaDefinitions([
33
+ workspaceSlugParamsValidator,
34
+ workspaceMembersResource.operations.revokeInvite.input
35
+ ], {
36
+ mode: workspaceMembersResource.operations.revokeInvite.input.mode,
37
+ context: "workspaceMembersActions.revokeInviteActionInput"
38
+ });
39
+
6
40
  const workspaceMembersActions = Object.freeze([
7
41
  {
8
42
  id: "workspace.roles.list",
@@ -14,15 +48,15 @@ const workspaceMembersActions = Object.freeze([
14
48
  require: "all",
15
49
  permissions: ["workspace.roles.view"]
16
50
  },
17
- inputValidator: workspaceSlugParamsValidator,
18
- outputValidator: workspaceMembersResource.operations.rolesList.outputValidator,
51
+ input: workspaceSlugParamsValidator,
52
+ output: null,
19
53
  idempotency: "none",
20
54
  audit: {
21
55
  actionName: "workspace.roles.list"
22
56
  },
23
57
  observability: {},
24
58
  async execute(_input, context, deps) {
25
- return deps.workspaceMembersService.listRoles({ context });
59
+ return returnJsonApiData(await deps.workspaceMembersService.listRoles({ context }));
26
60
  }
27
61
  },
28
62
  {
@@ -35,17 +69,17 @@ const workspaceMembersActions = Object.freeze([
35
69
  require: "all",
36
70
  permissions: ["workspace.members.view"]
37
71
  },
38
- inputValidator: workspaceSlugParamsValidator,
39
- outputValidator: workspaceMembersResource.operations.membersList.outputValidator,
72
+ input: workspaceSlugParamsValidator,
73
+ output: null,
40
74
  idempotency: "none",
41
75
  audit: {
42
76
  actionName: "workspace.members.list"
43
77
  },
44
78
  observability: {},
45
79
  async execute(input, context, deps) {
46
- return deps.workspaceMembersService.listMembers(resolveWorkspace(context, input), {
80
+ return returnJsonApiData(await deps.workspaceMembersService.listMembers(resolveWorkspace(context, input), {
47
81
  context
48
- });
82
+ }));
49
83
  }
50
84
  },
51
85
  {
@@ -58,20 +92,20 @@ const workspaceMembersActions = Object.freeze([
58
92
  require: "all",
59
93
  permissions: ["workspace.members.manage"]
60
94
  },
61
- inputValidator: [workspaceSlugParamsValidator, workspaceMembersResource.operations.updateMemberRole.inputValidator],
62
- outputValidator: workspaceMembersResource.operations.updateMemberRole.outputValidator,
95
+ input: updateMemberRoleActionInput,
96
+ output: null,
63
97
  idempotency: "optional",
64
98
  audit: {
65
99
  actionName: "workspace.member.role.update"
66
100
  },
67
101
  observability: {},
68
102
  async execute(input, context, deps) {
69
- return deps.workspaceMembersService.updateMemberRole(resolveWorkspace(context, input), {
103
+ return returnJsonApiData(await deps.workspaceMembersService.updateMemberRole(resolveWorkspace(context, input), {
70
104
  memberUserId: input.memberUserId,
71
105
  roleSid: input.roleSid
72
106
  }, {
73
107
  context
74
- });
108
+ }));
75
109
  }
76
110
  },
77
111
  {
@@ -84,19 +118,19 @@ const workspaceMembersActions = Object.freeze([
84
118
  require: "all",
85
119
  permissions: ["workspace.members.manage"]
86
120
  },
87
- inputValidator: [workspaceSlugParamsValidator, workspaceMembersResource.operations.removeMember.inputValidator],
88
- outputValidator: workspaceMembersResource.operations.removeMember.outputValidator,
121
+ input: removeMemberActionInput,
122
+ output: null,
89
123
  idempotency: "optional",
90
124
  audit: {
91
125
  actionName: "workspace.member.remove"
92
126
  },
93
127
  observability: {},
94
128
  async execute(input, context, deps) {
95
- return deps.workspaceMembersService.removeMember(resolveWorkspace(context, input), {
129
+ return returnJsonApiData(await deps.workspaceMembersService.removeMember(resolveWorkspace(context, input), {
96
130
  memberUserId: input.memberUserId
97
131
  }, {
98
132
  context
99
- });
133
+ }));
100
134
  }
101
135
  },
102
136
  {
@@ -109,17 +143,17 @@ const workspaceMembersActions = Object.freeze([
109
143
  require: "all",
110
144
  permissions: ["workspace.members.view"]
111
145
  },
112
- inputValidator: workspaceSlugParamsValidator,
113
- outputValidator: workspaceMembersResource.operations.invitesList.outputValidator,
146
+ input: workspaceSlugParamsValidator,
147
+ output: null,
114
148
  idempotency: "none",
115
149
  audit: {
116
150
  actionName: "workspace.invites.list"
117
151
  },
118
152
  observability: {},
119
153
  async execute(input, context, deps) {
120
- return deps.workspaceMembersService.listInvites(resolveWorkspace(context, input), {
154
+ return returnJsonApiData(await deps.workspaceMembersService.listInvites(resolveWorkspace(context, input), {
121
155
  context
122
- });
156
+ }));
123
157
  }
124
158
  },
125
159
  {
@@ -132,8 +166,8 @@ const workspaceMembersActions = Object.freeze([
132
166
  require: "all",
133
167
  permissions: ["workspace.members.invite"]
134
168
  },
135
- inputValidator: [workspaceSlugParamsValidator, workspaceMembersResource.operations.createInvite.bodyValidator],
136
- outputValidator: workspaceMembersResource.operations.createInvite.outputValidator,
169
+ input: createInviteActionInput,
170
+ output: null,
137
171
  idempotency: "optional",
138
172
  audit: {
139
173
  actionName: "workspace.invite.create"
@@ -145,7 +179,7 @@ const workspaceMembersActions = Object.freeze([
145
179
  }
146
180
  },
147
181
  async execute(input, context, deps) {
148
- return deps.workspaceMembersService.createInvite(
182
+ return returnJsonApiData(await deps.workspaceMembersService.createInvite(
149
183
  resolveWorkspace(context, input),
150
184
  resolveActionUser(context, input),
151
185
  {
@@ -155,7 +189,7 @@ const workspaceMembersActions = Object.freeze([
155
189
  {
156
190
  context
157
191
  }
158
- );
192
+ ));
159
193
  }
160
194
  },
161
195
  {
@@ -168,17 +202,17 @@ const workspaceMembersActions = Object.freeze([
168
202
  require: "all",
169
203
  permissions: ["workspace.invites.revoke"]
170
204
  },
171
- inputValidator: [workspaceSlugParamsValidator, workspaceMembersResource.operations.revokeInvite.inputValidator],
172
- outputValidator: workspaceMembersResource.operations.revokeInvite.outputValidator,
205
+ input: revokeInviteActionInput,
206
+ output: null,
173
207
  idempotency: "optional",
174
208
  audit: {
175
209
  actionName: "workspace.invite.revoke"
176
210
  },
177
211
  observability: {},
178
212
  async execute(input, context, deps) {
179
- return deps.workspaceMembersService.revokeInvite(resolveWorkspace(context, input), input.inviteId, {
213
+ return returnJsonApiData(await deps.workspaceMembersService.revokeInvite(resolveWorkspace(context, input), input.inviteId, {
180
214
  context
181
- });
215
+ }));
182
216
  }
183
217
  }
184
218
  ]);