@jskit-ai/workspaces-core 0.1.31 → 0.1.33
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 +11 -22
- package/package.json +11 -9
- package/src/server/WorkspacesCoreServiceProvider.js +22 -2
- package/src/server/common/repositories/workspaceInvitesRepository.js +233 -78
- package/src/server/common/repositories/workspaceMembershipsRepository.js +177 -86
- package/src/server/common/repositories/workspacesRepository.js +179 -86
- package/src/server/common/services/workspaceContextService.js +28 -26
- package/src/server/common/validators/routeParamsValidator.js +36 -53
- package/src/server/registerWorkspaceCore.js +9 -10
- package/src/server/registerWorkspaceRepositories.js +7 -3
- package/src/server/support/workspaceServerScopeSupport.js +1 -1
- package/src/server/workspaceBootstrapContributor.js +5 -14
- package/src/server/workspaceDirectory/bootWorkspaceDirectoryRoutes.js +54 -27
- package/src/server/workspaceDirectory/workspaceDirectoryActions.js +30 -24
- package/src/server/workspaceMembers/bootWorkspaceMembers.js +70 -32
- package/src/server/workspaceMembers/workspaceMembersActions.js +61 -27
- package/src/server/workspaceMembers/workspaceMembersService.js +43 -7
- package/src/server/workspacePendingInvitations/bootWorkspacePendingInvitations.js +28 -13
- package/src/server/workspacePendingInvitations/workspacePendingInvitationsActions.js +13 -15
- package/src/server/workspacePendingInvitations/workspacePendingInvitationsService.js +33 -10
- package/src/server/workspaceSettings/bootWorkspaceSettings.js +32 -13
- package/src/server/workspaceSettings/registerWorkspaceSettings.js +5 -1
- package/src/server/workspaceSettings/workspaceSettingsActions.js +18 -12
- package/src/server/workspaceSettings/workspaceSettingsRepository.js +104 -91
- package/src/server/workspaceSettings/workspaceSettingsService.js +5 -6
- package/src/shared/jsonApiTransports.js +79 -0
- package/src/shared/resources/workspaceInvitesResource.js +158 -0
- package/src/shared/resources/workspaceMembersResource.js +176 -311
- package/src/shared/resources/workspaceMembershipsResource.js +96 -0
- package/src/shared/resources/workspacePendingInvitationsResource.js +25 -72
- package/src/shared/resources/workspaceResource.js +113 -144
- package/src/shared/resources/workspaceRoleCatalogSchema.js +31 -0
- package/src/shared/resources/workspaceSettingsResource.js +276 -148
- package/test/repositoryContracts.test.js +16 -4
- package/test/resourcesCanonical.test.js +39 -16
- package/test/routeParamsValidator.test.js +37 -19
- package/test/usersRouteResources.test.js +27 -17
- package/test/workspaceActionContextContributor.test.js +1 -1
- package/test/workspaceInternalCrudResources.test.js +98 -0
- package/test/workspaceInvitesRepository.test.js +196 -148
- package/test/workspaceMembersResource.test.js +35 -0
- package/test/workspaceMembershipsRepository.test.js +155 -115
- package/test/workspacePendingInvitationsResource.test.js +18 -23
- package/test/workspacePendingInvitationsService.test.js +2 -1
- package/test/workspaceServerScopeSupport.test.js +77 -3
- package/test/workspaceService.test.js +26 -5
- package/test/workspaceSettingsActions.test.js +5 -7
- package/test/workspaceSettingsInternalResource.test.js +8 -0
- package/test/workspaceSettingsRepository.test.js +158 -123
- package/test/workspaceSettingsResource.test.js +51 -62
- package/test/workspaceSettingsService.test.js +0 -1
- package/test/workspacesRepository.test.js +318 -174
- package/test/workspacesRouteRequestInputValidator.test.js +25 -11
- package/src/server/common/resources/workspaceInvitesResource.js +0 -207
- package/src/server/common/resources/workspaceMembershipsResource.js +0 -154
- package/src/server/common/resources/workspacesResource.js +0 -170
- package/src/server/common/validators/authenticatedUserValidator.js +0 -43
- package/src/shared/resources/resolveGlobalArrayRegistry.js +0 -6
- package/src/shared/resources/workspaceSettingsFields.js +0 -65
- package/templates/packages/main/src/shared/resources/workspaceSettingsFields.js +0 -197
- package/test/settingsFieldRegistriesSingleton.test.js +0 -14
- package/test-support/registerDefaultSettingsFields.js +0 -1
|
@@ -1,147 +1,160 @@
|
|
|
1
1
|
import {
|
|
2
|
-
normalizeDbRecordId,
|
|
3
2
|
normalizeRecordId,
|
|
4
|
-
toIsoString,
|
|
5
3
|
nowDb,
|
|
6
4
|
isDuplicateEntryError,
|
|
7
5
|
createWithTransaction
|
|
8
6
|
} from "../common/repositories/repositoryUtils.js";
|
|
9
|
-
import { normalizeObjectInput } from "@jskit-ai/kernel/shared/validators/inputNormalization";
|
|
10
|
-
import { pickOwnProperties } from "@jskit-ai/kernel/shared/support";
|
|
11
7
|
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
8
|
+
createJsonApiInputRecord,
|
|
9
|
+
createJsonRestContext,
|
|
10
|
+
simplifyJsonApiDocument
|
|
11
|
+
} from "@jskit-ai/json-rest-api-core/server/jsonRestApiHost";
|
|
12
|
+
import { resolveWorkspaceThemePalettes } from "../../shared/settings.js";
|
|
13
|
+
|
|
14
|
+
const RESOURCE_TYPE = "workspaceSettings";
|
|
15
|
+
const WORKSPACE_SETTINGS_PATCH_FIELDS = Object.freeze([
|
|
16
|
+
"lightPrimaryColor",
|
|
17
|
+
"lightSecondaryColor",
|
|
18
|
+
"lightSurfaceColor",
|
|
19
|
+
"lightSurfaceVariantColor",
|
|
20
|
+
"darkPrimaryColor",
|
|
21
|
+
"darkSecondaryColor",
|
|
22
|
+
"darkSurfaceColor",
|
|
23
|
+
"darkSurfaceVariantColor",
|
|
24
|
+
"invitesEnabled"
|
|
25
|
+
]);
|
|
26
|
+
|
|
27
|
+
function pickPatchFields(source = {}) {
|
|
28
|
+
const patch = {};
|
|
29
|
+
|
|
30
|
+
for (const fieldName of WORKSPACE_SETTINGS_PATCH_FIELDS) {
|
|
31
|
+
if (Object.hasOwn(source, fieldName)) {
|
|
32
|
+
patch[fieldName] = source[fieldName];
|
|
33
|
+
}
|
|
30
34
|
}
|
|
31
|
-
|
|
35
|
+
|
|
36
|
+
return patch;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function createDefaultWorkspaceSettingsCreatePayload(workspaceId) {
|
|
40
|
+
const palettes = resolveWorkspaceThemePalettes({});
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
id: workspaceId,
|
|
44
|
+
lightPrimaryColor: palettes.light.color,
|
|
45
|
+
lightSecondaryColor: palettes.light.secondaryColor,
|
|
46
|
+
lightSurfaceColor: palettes.light.surfaceColor,
|
|
47
|
+
lightSurfaceVariantColor: palettes.light.surfaceVariantColor,
|
|
48
|
+
darkPrimaryColor: palettes.dark.color,
|
|
49
|
+
darkSecondaryColor: palettes.dark.secondaryColor,
|
|
50
|
+
darkSurfaceColor: palettes.dark.surfaceColor,
|
|
51
|
+
darkSurfaceVariantColor: palettes.dark.surfaceVariantColor,
|
|
52
|
+
invitesEnabled: true
|
|
53
|
+
};
|
|
32
54
|
}
|
|
33
55
|
|
|
34
|
-
function createRepository(
|
|
56
|
+
function createRepository({ api, knex } = {}) {
|
|
57
|
+
if (!api?.resources?.workspaceSettings) {
|
|
58
|
+
throw new TypeError("workspaceSettingsRepository requires json-rest-api workspaceSettings resource.");
|
|
59
|
+
}
|
|
35
60
|
if (typeof knex !== "function") {
|
|
36
61
|
throw new TypeError("workspaceSettingsRepository requires knex.");
|
|
37
62
|
}
|
|
38
63
|
const withTransaction = createWithTransaction(knex);
|
|
39
64
|
|
|
40
|
-
function
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
});
|
|
55
|
-
settings[field.key] = field.normalizeOutput(rawValue, {
|
|
56
|
-
defaultInvitesEnabled
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
settings.createdAt = toIsoString(row.created_at);
|
|
61
|
-
settings.updatedAt = toIsoString(row.updated_at);
|
|
62
|
-
return settings;
|
|
65
|
+
async function queryFirst(filters = {}, options = {}) {
|
|
66
|
+
const result = await api.resources.workspaceSettings.query(
|
|
67
|
+
{
|
|
68
|
+
queryParams: {
|
|
69
|
+
filters
|
|
70
|
+
},
|
|
71
|
+
transaction: options?.trx || null,
|
|
72
|
+
simplified: false
|
|
73
|
+
},
|
|
74
|
+
createJsonRestContext(options?.context || null)
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
const rows = simplifyJsonApiDocument(result);
|
|
78
|
+
return Array.isArray(rows) ? rows[0] || null : null;
|
|
63
79
|
}
|
|
64
80
|
|
|
65
81
|
async function findByWorkspaceId(workspaceId, options = {}) {
|
|
66
|
-
const client = options?.trx || knex;
|
|
67
82
|
const normalizedWorkspaceId = normalizeRecordId(workspaceId, { fallback: null });
|
|
68
83
|
if (!normalizedWorkspaceId) {
|
|
69
84
|
return null;
|
|
70
85
|
}
|
|
71
86
|
|
|
72
|
-
|
|
73
|
-
return mapRow(row);
|
|
87
|
+
return queryFirst({ id: normalizedWorkspaceId }, options);
|
|
74
88
|
}
|
|
75
89
|
|
|
76
90
|
async function ensureForWorkspaceId(workspaceId, options = {}) {
|
|
77
|
-
const client = options?.trx || knex;
|
|
78
91
|
const normalizedWorkspaceId = normalizeRecordId(workspaceId, { fallback: null });
|
|
79
92
|
if (!normalizedWorkspaceId) {
|
|
80
93
|
throw new TypeError("workspaceSettingsRepository.ensureForWorkspaceId requires a valid workspace id.");
|
|
81
94
|
}
|
|
82
95
|
|
|
83
|
-
const
|
|
84
|
-
defaultInvitesEnabled
|
|
85
|
-
});
|
|
86
|
-
const existing = await findByWorkspaceId(normalizedWorkspaceId, { trx: client });
|
|
96
|
+
const existing = await findByWorkspaceId(normalizedWorkspaceId, options);
|
|
87
97
|
if (existing) {
|
|
88
98
|
return existing;
|
|
89
99
|
}
|
|
90
100
|
|
|
91
101
|
try {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
102
|
+
await api.resources.workspaceSettings.post(
|
|
103
|
+
{
|
|
104
|
+
inputRecord: createJsonApiInputRecord(
|
|
105
|
+
RESOURCE_TYPE,
|
|
106
|
+
createDefaultWorkspaceSettingsCreatePayload(normalizedWorkspaceId),
|
|
107
|
+
{
|
|
108
|
+
id: normalizedWorkspaceId
|
|
109
|
+
}
|
|
110
|
+
),
|
|
111
|
+
transaction: options?.trx || null,
|
|
112
|
+
simplified: false
|
|
113
|
+
},
|
|
114
|
+
createJsonRestContext(options?.context || null)
|
|
115
|
+
);
|
|
101
116
|
} catch (error) {
|
|
102
117
|
if (!isDuplicateEntryError(error)) {
|
|
103
118
|
throw error;
|
|
104
119
|
}
|
|
105
120
|
}
|
|
106
121
|
|
|
107
|
-
return findByWorkspaceId(normalizedWorkspaceId,
|
|
122
|
+
return findByWorkspaceId(normalizedWorkspaceId, options);
|
|
108
123
|
}
|
|
109
124
|
|
|
110
125
|
async function updateSettingsByWorkspaceId(workspaceId, patch = {}, options = {}) {
|
|
111
|
-
const client = options?.trx || knex;
|
|
112
126
|
const normalizedWorkspaceId = normalizeRecordId(workspaceId, { fallback: null });
|
|
113
127
|
if (!normalizedWorkspaceId) {
|
|
114
128
|
throw new TypeError("workspaceSettingsRepository.updateSettingsByWorkspaceId requires a valid workspace id.");
|
|
115
129
|
}
|
|
116
130
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
});
|
|
121
|
-
const source = normalizeObjectInput(patch);
|
|
122
|
-
const settingsPatch = pickOwnProperties(source, resolveWorkspaceSettingsFieldKeys());
|
|
131
|
+
await ensureForWorkspaceId(normalizedWorkspaceId, options);
|
|
132
|
+
const source = patch && typeof patch === "object" && !Array.isArray(patch) ? patch : {};
|
|
133
|
+
const updatePayload = pickPatchFields(source);
|
|
123
134
|
|
|
124
|
-
if (Object.keys(
|
|
125
|
-
return
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const dbPatch = {
|
|
129
|
-
updated_at: nowDb()
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
for (const field of workspaceSettingsFields) {
|
|
133
|
-
if (!Object.hasOwn(settingsPatch, field.key)) {
|
|
134
|
-
continue;
|
|
135
|
-
}
|
|
136
|
-
dbPatch[field.repository.column] = field.normalizeInput(settingsPatch[field.key], {
|
|
137
|
-
payload: source
|
|
138
|
-
});
|
|
135
|
+
if (Object.keys(updatePayload).length < 1) {
|
|
136
|
+
return findByWorkspaceId(normalizedWorkspaceId, options);
|
|
139
137
|
}
|
|
140
138
|
|
|
141
|
-
await
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
139
|
+
await api.resources.workspaceSettings.patch(
|
|
140
|
+
{
|
|
141
|
+
inputRecord: createJsonApiInputRecord(
|
|
142
|
+
RESOURCE_TYPE,
|
|
143
|
+
{
|
|
144
|
+
...updatePayload,
|
|
145
|
+
updatedAt: nowDb()
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
id: normalizedWorkspaceId
|
|
149
|
+
}
|
|
150
|
+
),
|
|
151
|
+
transaction: options?.trx || null,
|
|
152
|
+
simplified: false
|
|
153
|
+
},
|
|
154
|
+
createJsonRestContext(options?.context || null)
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
return findByWorkspaceId(normalizedWorkspaceId, options);
|
|
145
158
|
}
|
|
146
159
|
|
|
147
160
|
return Object.freeze({
|
|
@@ -2,9 +2,8 @@ import { normalizeRecordId } from "@jskit-ai/kernel/shared/support/normalize";
|
|
|
2
2
|
import { normalizeObjectInput } from "@jskit-ai/kernel/shared/validators/inputNormalization";
|
|
3
3
|
import { pickOwnProperties } from "@jskit-ai/kernel/shared/support";
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
} from "../../shared/resources/workspaceSettingsFields.js";
|
|
5
|
+
WORKSPACE_SETTINGS_FIELD_KEYS
|
|
6
|
+
} from "../../shared/resources/workspaceSettingsResource.js";
|
|
8
7
|
import { createWorkspaceRoleCatalog, cloneWorkspaceRoleCatalog } from "../../shared/roles.js";
|
|
9
8
|
|
|
10
9
|
function createService({
|
|
@@ -24,8 +23,8 @@ function createService({
|
|
|
24
23
|
workspace
|
|
25
24
|
});
|
|
26
25
|
const settings = {};
|
|
27
|
-
for (const
|
|
28
|
-
settings[
|
|
26
|
+
for (const fieldKey of WORKSPACE_SETTINGS_FIELD_KEYS) {
|
|
27
|
+
settings[fieldKey] = settingsRecord[fieldKey];
|
|
29
28
|
}
|
|
30
29
|
const invitesEnabled = invitesAvailable && settings.invitesEnabled !== false;
|
|
31
30
|
settings.invitesEnabled = invitesEnabled;
|
|
@@ -45,7 +44,7 @@ function createService({
|
|
|
45
44
|
|
|
46
45
|
async function updateWorkspaceSettings(workspace, payload = {}, options = {}) {
|
|
47
46
|
const source = normalizeObjectInput(payload);
|
|
48
|
-
const settingsPatch = pickOwnProperties(source,
|
|
47
|
+
const settingsPatch = pickOwnProperties(source, WORKSPACE_SETTINGS_FIELD_KEYS);
|
|
49
48
|
|
|
50
49
|
if (Object.keys(settingsPatch).length > 0) {
|
|
51
50
|
await workspaceSettingsRepository.updateSettingsByWorkspaceId(workspace.id, settingsPatch, {
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { deepFreeze } from "@jskit-ai/kernel/shared/support/deepFreeze";
|
|
2
|
+
|
|
3
|
+
const WORKSPACES_TRANSPORT = deepFreeze({
|
|
4
|
+
kind: "jsonapi-resource",
|
|
5
|
+
requestType: "workspaces",
|
|
6
|
+
responseType: "workspaces",
|
|
7
|
+
responseKind: "record"
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
const WORKSPACES_COLLECTION_TRANSPORT = deepFreeze({
|
|
11
|
+
kind: "jsonapi-resource",
|
|
12
|
+
responseType: "workspaces",
|
|
13
|
+
responseKind: "collection"
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const WORKSPACE_SETTINGS_TRANSPORT = deepFreeze({
|
|
17
|
+
kind: "jsonapi-resource",
|
|
18
|
+
requestType: "workspace-settings",
|
|
19
|
+
responseType: "workspace-settings",
|
|
20
|
+
responseKind: "record"
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const WORKSPACE_ROLE_CATALOG_TRANSPORT = deepFreeze({
|
|
24
|
+
kind: "jsonapi-resource",
|
|
25
|
+
responseType: "workspace-role-catalogs",
|
|
26
|
+
responseKind: "record"
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const WORKSPACE_MEMBERS_TRANSPORT = deepFreeze({
|
|
30
|
+
kind: "jsonapi-resource",
|
|
31
|
+
responseType: "workspace-members",
|
|
32
|
+
responseKind: "record"
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const WORKSPACE_MEMBER_ROLE_UPDATE_TRANSPORT = deepFreeze({
|
|
36
|
+
kind: "jsonapi-resource",
|
|
37
|
+
requestType: "workspace-member-role-updates",
|
|
38
|
+
responseType: "workspace-members",
|
|
39
|
+
responseKind: "record"
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const WORKSPACE_INVITES_TRANSPORT = deepFreeze({
|
|
43
|
+
kind: "jsonapi-resource",
|
|
44
|
+
responseType: "workspace-invites",
|
|
45
|
+
responseKind: "record"
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const WORKSPACE_INVITE_CREATE_TRANSPORT = deepFreeze({
|
|
49
|
+
kind: "jsonapi-resource",
|
|
50
|
+
requestType: "workspace-invite-creations",
|
|
51
|
+
responseType: "workspace-invites",
|
|
52
|
+
responseKind: "record"
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const WORKSPACE_INVITE_REDEEM_TRANSPORT = deepFreeze({
|
|
56
|
+
kind: "jsonapi-resource",
|
|
57
|
+
requestType: "workspace-invitation-decisions",
|
|
58
|
+
responseType: "workspace-invitation-decisions",
|
|
59
|
+
responseKind: "record"
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const WORKSPACE_PENDING_INVITATIONS_TRANSPORT = deepFreeze({
|
|
63
|
+
kind: "jsonapi-resource",
|
|
64
|
+
responseType: "workspace-pending-invitations",
|
|
65
|
+
responseKind: "record"
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
export {
|
|
69
|
+
WORKSPACES_TRANSPORT,
|
|
70
|
+
WORKSPACES_COLLECTION_TRANSPORT,
|
|
71
|
+
WORKSPACE_SETTINGS_TRANSPORT,
|
|
72
|
+
WORKSPACE_ROLE_CATALOG_TRANSPORT,
|
|
73
|
+
WORKSPACE_MEMBERS_TRANSPORT,
|
|
74
|
+
WORKSPACE_MEMBER_ROLE_UPDATE_TRANSPORT,
|
|
75
|
+
WORKSPACE_INVITES_TRANSPORT,
|
|
76
|
+
WORKSPACE_INVITE_CREATE_TRANSPORT,
|
|
77
|
+
WORKSPACE_INVITE_REDEEM_TRANSPORT,
|
|
78
|
+
WORKSPACE_PENDING_INVITATIONS_TRANSPORT
|
|
79
|
+
};
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { normalizeLowerText, normalizeText } from "@jskit-ai/kernel/shared/support/normalize";
|
|
2
|
+
import { defineCrudResource } from "@jskit-ai/resource-crud-core/shared/crudResource";
|
|
3
|
+
|
|
4
|
+
const workspaceInvitesResource = defineCrudResource({
|
|
5
|
+
namespace: "workspaceInvites",
|
|
6
|
+
tableName: "workspace_invites",
|
|
7
|
+
searchSchema: {
|
|
8
|
+
id: { type: "id", actualField: "id" }
|
|
9
|
+
},
|
|
10
|
+
schema: {
|
|
11
|
+
workspaceId: {
|
|
12
|
+
type: "id",
|
|
13
|
+
required: true,
|
|
14
|
+
search: true,
|
|
15
|
+
belongsTo: "workspaces",
|
|
16
|
+
as: "workspace",
|
|
17
|
+
operations: {
|
|
18
|
+
output: { required: true },
|
|
19
|
+
create: { required: true }
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
email: {
|
|
23
|
+
type: "string",
|
|
24
|
+
required: true,
|
|
25
|
+
max: 255,
|
|
26
|
+
search: true,
|
|
27
|
+
setter: (value) => normalizeLowerText(value),
|
|
28
|
+
operations: {
|
|
29
|
+
output: { required: true },
|
|
30
|
+
create: { required: true }
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
roleSid: {
|
|
34
|
+
type: "string",
|
|
35
|
+
required: true,
|
|
36
|
+
max: 64,
|
|
37
|
+
defaultTo: "member",
|
|
38
|
+
search: true,
|
|
39
|
+
storage: { column: "role_sid" },
|
|
40
|
+
setter: (value) => normalizeLowerText(value),
|
|
41
|
+
operations: {
|
|
42
|
+
output: { required: true },
|
|
43
|
+
create: { required: true },
|
|
44
|
+
patch: { required: false }
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
status: {
|
|
48
|
+
type: "string",
|
|
49
|
+
required: true,
|
|
50
|
+
max: 64,
|
|
51
|
+
defaultTo: "pending",
|
|
52
|
+
search: true,
|
|
53
|
+
setter: (value) => normalizeLowerText(value),
|
|
54
|
+
operations: {
|
|
55
|
+
output: { required: true },
|
|
56
|
+
create: { required: true },
|
|
57
|
+
patch: { required: false }
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
tokenHash: {
|
|
61
|
+
type: "string",
|
|
62
|
+
required: true,
|
|
63
|
+
max: 255,
|
|
64
|
+
search: true,
|
|
65
|
+
storage: { column: "token_hash" },
|
|
66
|
+
setter: (value) => normalizeText(value),
|
|
67
|
+
operations: {
|
|
68
|
+
output: { required: true },
|
|
69
|
+
create: { required: true }
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
invitedByUserId: {
|
|
73
|
+
type: "id",
|
|
74
|
+
nullable: true,
|
|
75
|
+
belongsTo: "userProfiles",
|
|
76
|
+
as: "invitedByUser",
|
|
77
|
+
storage: { column: "invited_by_user_id" },
|
|
78
|
+
operations: {
|
|
79
|
+
output: { required: false },
|
|
80
|
+
create: { required: false }
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
expiresAt: {
|
|
84
|
+
type: "dateTime",
|
|
85
|
+
nullable: true,
|
|
86
|
+
storage: {
|
|
87
|
+
column: "expires_at",
|
|
88
|
+
writeSerializer: "datetime-utc"
|
|
89
|
+
},
|
|
90
|
+
operations: {
|
|
91
|
+
output: { required: true },
|
|
92
|
+
create: { required: false },
|
|
93
|
+
patch: { required: false }
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
acceptedAt: {
|
|
97
|
+
type: "dateTime",
|
|
98
|
+
nullable: true,
|
|
99
|
+
storage: {
|
|
100
|
+
column: "accepted_at",
|
|
101
|
+
writeSerializer: "datetime-utc"
|
|
102
|
+
},
|
|
103
|
+
operations: {
|
|
104
|
+
output: { required: true },
|
|
105
|
+
create: { required: false },
|
|
106
|
+
patch: { required: false }
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
revokedAt: {
|
|
110
|
+
type: "dateTime",
|
|
111
|
+
nullable: true,
|
|
112
|
+
storage: {
|
|
113
|
+
column: "revoked_at",
|
|
114
|
+
writeSerializer: "datetime-utc"
|
|
115
|
+
},
|
|
116
|
+
operations: {
|
|
117
|
+
output: { required: true },
|
|
118
|
+
create: { required: false },
|
|
119
|
+
patch: { required: false }
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
createdAt: {
|
|
123
|
+
type: "dateTime",
|
|
124
|
+
default: "now()",
|
|
125
|
+
storage: {
|
|
126
|
+
column: "created_at",
|
|
127
|
+
writeSerializer: "datetime-utc"
|
|
128
|
+
},
|
|
129
|
+
operations: {
|
|
130
|
+
output: { required: true },
|
|
131
|
+
create: { required: false }
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
updatedAt: {
|
|
135
|
+
type: "dateTime",
|
|
136
|
+
default: "now()",
|
|
137
|
+
storage: {
|
|
138
|
+
column: "updated_at",
|
|
139
|
+
writeSerializer: "datetime-utc"
|
|
140
|
+
},
|
|
141
|
+
operations: {
|
|
142
|
+
output: { required: true },
|
|
143
|
+
create: { required: false },
|
|
144
|
+
patch: { required: false }
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
messages: {
|
|
149
|
+
validation: "Fix invalid values and try again.",
|
|
150
|
+
saveSuccess: "Record saved.",
|
|
151
|
+
saveError: "Unable to save record.",
|
|
152
|
+
deleteSuccess: "Record deleted.",
|
|
153
|
+
deleteError: "Unable to delete record."
|
|
154
|
+
},
|
|
155
|
+
crudOperations: ["list", "view", "create", "patch"]
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
export { workspaceInvitesResource };
|