@jskit-ai/users-core 0.1.47 → 0.1.49

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 (104) hide show
  1. package/package.descriptor.mjs +9 -46
  2. package/package.json +8 -19
  3. package/src/server/UsersCoreServiceProvider.js +0 -4
  4. package/src/server/common/registerCommonRepositories.js +0 -5
  5. package/src/server/common/services/authProfileSyncService.js +28 -7
  6. package/src/server/common/support/realtimeServiceEvents.js +1 -59
  7. package/src/server/profileSyncLifecycleContributorRegistry.js +56 -0
  8. package/src/server/registerUsersBootstrap.js +1 -3
  9. package/src/server/registerUsersCore.js +2 -14
  10. package/src/server/usersBootstrapContributor.js +10 -85
  11. package/src/shared/index.js +2 -99
  12. package/src/shared/settings.js +1 -119
  13. package/templates/migrations/users_core_generic_initial.cjs +0 -16
  14. package/test/authProfileSyncService.test.js +19 -10
  15. package/test/registerServiceRealtimeEvents.test.js +0 -94
  16. package/test/registerUsersCore.test.js +6 -19
  17. package/test/repositoryContracts.test.js +1 -11
  18. package/test/resourcesCanonical.test.js +1 -19
  19. package/test/settingsFieldRegistriesSingleton.test.js +0 -10
  20. package/test/usersBootstrapContributor.test.js +20 -38
  21. package/test/usersRouteRequestInputValidator.test.js +2 -43
  22. package/test/usersRouteResources.test.js +2 -20
  23. package/test-support/registerDefaultSettingsFields.js +0 -1
  24. package/src/server/UsersWorkspacesServiceProvider.js +0 -44
  25. package/src/server/common/contributors/workspaceActionContextContributor.js +0 -88
  26. package/src/server/common/contributors/workspaceAuthPolicyContextResolver.js +0 -34
  27. package/src/server/common/contributors/workspaceRouteVisibilityResolver.js +0 -78
  28. package/src/server/common/formatters/workspaceFormatter.js +0 -53
  29. package/src/server/common/repositories/workspaceInvitesRepository.js +0 -208
  30. package/src/server/common/repositories/workspaceMembershipsRepository.js +0 -190
  31. package/src/server/common/repositories/workspacesRepository.js +0 -202
  32. package/src/server/common/services/workspaceContextService.js +0 -281
  33. package/src/server/common/support/workspaceRoutePaths.js +0 -17
  34. package/src/server/common/validators/routeParamsValidator.js +0 -62
  35. package/src/server/consoleSettings/bootConsoleSettingsRoutes.js +0 -63
  36. package/src/server/consoleSettings/consoleService.js +0 -36
  37. package/src/server/consoleSettings/consoleSettingsActions.js +0 -55
  38. package/src/server/consoleSettings/consoleSettingsRepository.js +0 -115
  39. package/src/server/consoleSettings/consoleSettingsService.js +0 -40
  40. package/src/server/consoleSettings/registerConsoleSettings.js +0 -56
  41. package/src/server/registerWorkspaceBootstrap.js +0 -27
  42. package/src/server/registerWorkspaceCore.js +0 -73
  43. package/src/server/registerWorkspaceRepositories.js +0 -26
  44. package/src/server/support/resolveWorkspace.js +0 -16
  45. package/src/server/support/workspaceActionSurfaces.js +0 -135
  46. package/src/server/support/workspaceInvitationsPolicy.js +0 -45
  47. package/src/server/support/workspaceRouteInput.js +0 -22
  48. package/src/server/workspaceBootstrapContributor.js +0 -211
  49. package/src/server/workspaceDirectory/bootWorkspaceDirectoryRoutes.js +0 -133
  50. package/src/server/workspaceDirectory/registerWorkspaceDirectory.js +0 -19
  51. package/src/server/workspaceDirectory/workspaceDirectoryActions.js +0 -133
  52. package/src/server/workspaceMembers/bootWorkspaceMembers.js +0 -236
  53. package/src/server/workspaceMembers/registerWorkspaceMembers.js +0 -108
  54. package/src/server/workspaceMembers/workspaceMembersActions.js +0 -186
  55. package/src/server/workspaceMembers/workspaceMembersService.js +0 -222
  56. package/src/server/workspacePendingInvitations/bootWorkspacePendingInvitations.js +0 -62
  57. package/src/server/workspacePendingInvitations/registerWorkspacePendingInvitations.js +0 -119
  58. package/src/server/workspacePendingInvitations/workspacePendingInvitationsActions.js +0 -74
  59. package/src/server/workspacePendingInvitations/workspacePendingInvitationsService.js +0 -138
  60. package/src/server/workspaceSettings/bootWorkspaceSettings.js +0 -76
  61. package/src/server/workspaceSettings/registerWorkspaceSettings.js +0 -62
  62. package/src/server/workspaceSettings/workspaceSettingsActions.js +0 -72
  63. package/src/server/workspaceSettings/workspaceSettingsRepository.js +0 -154
  64. package/src/server/workspaceSettings/workspaceSettingsService.js +0 -66
  65. package/src/shared/resources/consoleSettingsFields.js +0 -54
  66. package/src/shared/resources/consoleSettingsResource.js +0 -119
  67. package/src/shared/resources/workspaceMembersResource.js +0 -354
  68. package/src/shared/resources/workspacePendingInvitationsResource.js +0 -82
  69. package/src/shared/resources/workspaceResource.js +0 -176
  70. package/src/shared/resources/workspaceSettingsFields.js +0 -59
  71. package/src/shared/resources/workspaceSettingsResource.js +0 -169
  72. package/src/shared/roles.js +0 -161
  73. package/src/shared/support/usersApiPaths.js +0 -43
  74. package/src/shared/support/usersVisibility.js +0 -42
  75. package/src/shared/support/workspacePathModel.js +0 -145
  76. package/src/shared/tenancyMode.js +0 -35
  77. package/src/shared/tenancyProfile.js +0 -73
  78. package/templates/migrations/users_core_console_owner.cjs +0 -37
  79. package/templates/packages/main/src/shared/resources/consoleSettingsFields.js +0 -11
  80. package/test/consoleService.test.js +0 -57
  81. package/test/consoleSettingsService.test.js +0 -86
  82. package/test/registerWorkspaceDirectory.test.js +0 -31
  83. package/test/registerWorkspaceSettings.test.js +0 -40
  84. package/test/roles.test.js +0 -159
  85. package/test/tenancyProfile.test.js +0 -67
  86. package/test/usersApiPaths.test.js +0 -49
  87. package/test/usersRouteValidators.test.js +0 -49
  88. package/test/usersVisibility.test.js +0 -27
  89. package/test/workspaceActionContextContributor.test.js +0 -344
  90. package/test/workspaceActionSurfaces.test.js +0 -105
  91. package/test/workspaceAuthPolicyContextResolver.test.js +0 -119
  92. package/test/workspaceBootstrapContributor.test.js +0 -154
  93. package/test/workspaceInvitationsPolicy.test.js +0 -71
  94. package/test/workspaceInvitesRepository.test.js +0 -111
  95. package/test/workspaceMembersService.test.js +0 -398
  96. package/test/workspacePathModel.test.js +0 -93
  97. package/test/workspacePendingInvitationsResource.test.js +0 -38
  98. package/test/workspacePendingInvitationsService.test.js +0 -151
  99. package/test/workspaceRouteVisibilityResolver.test.js +0 -83
  100. package/test/workspaceService.test.js +0 -546
  101. package/test/workspaceSettingsActions.test.js +0 -52
  102. package/test/workspaceSettingsRepository.test.js +0 -202
  103. package/test/workspaceSettingsResource.test.js +0 -169
  104. package/test/workspaceSettingsService.test.js +0 -140
@@ -1,56 +0,0 @@
1
- import { withActionDefaults } from "@jskit-ai/kernel/shared/actions";
2
- import { createService as createConsoleSettingsService } from "./consoleSettingsService.js";
3
- import { createService as createConsoleService } from "./consoleService.js";
4
- import { consoleSettingsActions } from "./consoleSettingsActions.js";
5
-
6
- function registerConsoleSettings(app) {
7
- if (!app || typeof app.singleton !== "function" || typeof app.service !== "function" || typeof app.actions !== "function") {
8
- throw new Error("registerConsoleSettings requires application singleton()/service()/actions().");
9
- }
10
-
11
- const hasConsoleService = typeof app.has === "function" ? app.has("consoleService") : false;
12
- if (!hasConsoleService) {
13
- app.singleton("consoleService", (scope) =>
14
- createConsoleService({
15
- consoleSettingsRepository: scope.make("consoleSettingsRepository")
16
- })
17
- );
18
- }
19
-
20
- app.service(
21
- "users.console.settings.service",
22
- (scope) =>
23
- createConsoleSettingsService({
24
- consoleSettingsRepository: scope.make("consoleSettingsRepository"),
25
- consoleService: scope.make("consoleService")
26
- }),
27
- {
28
- events: Object.freeze({
29
- updateSettings: Object.freeze([
30
- Object.freeze({
31
- type: "entity.changed",
32
- source: "console",
33
- entity: "settings",
34
- operation: "updated",
35
- entityId: 1,
36
- realtime: Object.freeze({
37
- event: "console.settings.changed",
38
- audience: "all_users"
39
- })
40
- })
41
- ])
42
- })
43
- }
44
- );
45
-
46
- app.actions(
47
- withActionDefaults(consoleSettingsActions, {
48
- domain: "console",
49
- dependencies: {
50
- consoleSettingsService: "users.console.settings.service"
51
- }
52
- })
53
- );
54
- }
55
-
56
- export { registerConsoleSettings };
@@ -1,27 +0,0 @@
1
- import { registerBootstrapPayloadContributor } from "@jskit-ai/kernel/server/runtime";
2
- import { resolveAppConfig } from "@jskit-ai/kernel/server/support";
3
- import { createWorkspaceBootstrapContributor } from "./workspaceBootstrapContributor.js";
4
-
5
-
6
- function registerWorkspaceBootstrap(app) {
7
- if (!app || typeof app.singleton !== "function") {
8
- throw new Error("registerWorkspaceBootstrap requires application singleton().");
9
- }
10
-
11
- registerBootstrapPayloadContributor(app, "workspaces.core.bootstrap.payloadContributor", (scope) => {
12
- const workspaceInvitationsEnabled = scope.make("users.workspace.invitations.enabled");
13
-
14
- return createWorkspaceBootstrapContributor({
15
- workspaceService: scope.make("users.workspace.service"),
16
- workspacePendingInvitationsService: workspaceInvitationsEnabled
17
- ? scope.make("users.workspace.pending-invitations.service")
18
- : null,
19
- workspaceInvitationsEnabled,
20
- usersRepository: scope.make("usersRepository"),
21
- appConfig: resolveAppConfig(scope),
22
- tenancyProfile: scope.make("users.tenancy.profile")
23
- });
24
- });
25
- }
26
-
27
- export { registerWorkspaceBootstrap };
@@ -1,73 +0,0 @@
1
- import {
2
- registerActionContextContributor
3
- } from "@jskit-ai/kernel/server/actions";
4
- import { registerRouteVisibilityResolver } from "@jskit-ai/kernel/server/http";
5
- import { resolveAppConfig } from "@jskit-ai/kernel/server/support";
6
- import { createService as createWorkspaceService } from "./common/services/workspaceContextService.js";
7
- import { createWorkspaceActionContextContributor } from "./common/contributors/workspaceActionContextContributor.js";
8
- import { createWorkspaceRouteVisibilityResolver } from "./common/contributors/workspaceRouteVisibilityResolver.js";
9
- import { createWorkspaceAuthPolicyContextResolver } from "./common/contributors/workspaceAuthPolicyContextResolver.js";
10
- import { TENANCY_MODE_WORKSPACES } from "../shared/tenancyProfile.js";
11
- import { resolveWorkspaceInvitationsPolicy } from "./support/workspaceInvitationsPolicy.js";
12
- import { resolveWorkspaceSurfaceIdsFromAppConfig } from "./support/workspaceActionSurfaces.js";
13
-
14
-
15
- function registerWorkspaceCore(app) {
16
- if (!app || typeof app.singleton !== "function") {
17
- throw new Error("registerWorkspaceCore requires application singleton().");
18
- }
19
-
20
- app.singleton("users.workspace.service", (scope) => {
21
- const appConfig = resolveAppConfig(scope);
22
- return createWorkspaceService({
23
- appConfig,
24
- workspacesRepository: scope.make("workspacesRepository"),
25
- workspaceMembershipsRepository: scope.make("workspaceMembershipsRepository"),
26
- workspaceSettingsRepository: scope.make("workspaceSettingsRepository")
27
- });
28
- });
29
- app.singleton("users.workspace.enabled", (scope) => {
30
- return scope.make("users.tenancy.profile").workspace.enabled === true;
31
- });
32
-
33
- app.singleton("users.workspace.self-create.enabled", (scope) => {
34
- return scope.make("users.tenancy.profile").workspace.allowSelfCreate === true;
35
- });
36
-
37
- app.singleton("users.workspace.tenancy.enabled", (scope) => {
38
- return scope.make("users.tenancy.profile").mode === TENANCY_MODE_WORKSPACES;
39
- });
40
-
41
- app.singleton("users.workspace.invitations.enabled", (scope) => {
42
- const appConfig = resolveAppConfig(scope);
43
- const tenancyProfile = scope.make("users.tenancy.profile");
44
- return resolveWorkspaceInvitationsPolicy({
45
- appConfig,
46
- tenancyProfile
47
- }).enabled;
48
- });
49
-
50
- registerActionContextContributor(app, "users.core.workspace.actionContextContributor", (scope) => {
51
- const appConfig = resolveAppConfig(scope);
52
- return createWorkspaceActionContextContributor({
53
- workspaceService: scope.make("users.workspace.service"),
54
- workspaceSurfaceIds: resolveWorkspaceSurfaceIdsFromAppConfig(appConfig)
55
- });
56
- });
57
-
58
- if (typeof app.has !== "function" || !app.has("auth.policy.contextResolver")) {
59
- app.singleton("auth.policy.contextResolver", (scope) =>
60
- createWorkspaceAuthPolicyContextResolver({
61
- workspaceService: scope.make("users.workspace.service")
62
- })
63
- );
64
- }
65
-
66
- registerRouteVisibilityResolver(app, "users.core.workspace.routeVisibilityResolver", (scope) =>
67
- createWorkspaceRouteVisibilityResolver({
68
- workspaceService: scope.make("users.workspace.service")
69
- })
70
- );
71
- }
72
-
73
- export { registerWorkspaceCore };
@@ -1,26 +0,0 @@
1
- import { createRepository as createWorkspacesRepository } from "./common/repositories/workspacesRepository.js";
2
- import { createRepository as createWorkspaceMembershipsRepository } from "./common/repositories/workspaceMembershipsRepository.js";
3
- import { createRepository as createWorkspaceInvitesRepository } from "./common/repositories/workspaceInvitesRepository.js";
4
-
5
- function registerWorkspaceRepositories(app) {
6
- if (!app || typeof app.singleton !== "function") {
7
- throw new Error("registerWorkspaceRepositories requires application singleton().");
8
- }
9
-
10
- app.singleton("workspacesRepository", (scope) => {
11
- const knex = scope.make("jskit.database.knex");
12
- return createWorkspacesRepository(knex);
13
- });
14
-
15
- app.singleton("workspaceMembershipsRepository", (scope) => {
16
- const knex = scope.make("jskit.database.knex");
17
- return createWorkspaceMembershipsRepository(knex);
18
- });
19
-
20
- app.singleton("workspaceInvitesRepository", (scope) => {
21
- const knex = scope.make("jskit.database.knex");
22
- return createWorkspaceInvitesRepository(knex);
23
- });
24
- }
25
-
26
- export { registerWorkspaceRepositories };
@@ -1,16 +0,0 @@
1
- import { normalizeObject } from "@jskit-ai/kernel/shared/support/normalize";
2
-
3
- function resolveRequest(context = {}) {
4
- const requestMeta = normalizeObject(context?.requestMeta);
5
- return normalizeObject(requestMeta.request);
6
- }
7
-
8
- function resolveWorkspace(context = {}, input = {}) {
9
- const payload = normalizeObject(input);
10
- const requestMeta = normalizeObject(context?.requestMeta);
11
- const resolvedWorkspaceContext = normalizeObject(requestMeta.resolvedWorkspaceContext);
12
-
13
- return payload.workspace || resolvedWorkspaceContext.workspace || context?.workspace || resolveRequest(context)?.workspace || null;
14
- }
15
-
16
- export { resolveWorkspace };
@@ -1,135 +0,0 @@
1
- import { normalizeSurfaceId } from "@jskit-ai/kernel/shared/surface/registry";
2
- import { isRecord, normalizeLowerText } from "@jskit-ai/kernel/shared/support/normalize";
3
- import { resolveDefaultWorkspaceSurfaceId } from "../../shared/support/workspacePathModel.js";
4
-
5
- const CONSOLE_OWNER_ACCESS_POLICY_ID = "console_owner";
6
-
7
- function normalizeSurfaceIds(surfaceIds = []) {
8
- const source = Array.isArray(surfaceIds) ? surfaceIds : [];
9
- const seen = new Set();
10
- const normalized = [];
11
-
12
- for (const candidate of source) {
13
- const surfaceId = normalizeSurfaceId(candidate);
14
- if (!surfaceId || seen.has(surfaceId)) {
15
- continue;
16
- }
17
- seen.add(surfaceId);
18
- normalized.push(surfaceId);
19
- }
20
-
21
- return normalized;
22
- }
23
-
24
- function resolveWorkspaceSurfaceIdsFromAppConfig(appConfig = {}) {
25
- return resolveSurfaceIdsFromAppConfig(appConfig, (definition) => definition.requiresWorkspace === true);
26
- }
27
-
28
- function resolveConsoleSurfaceIdsFromAppConfig(appConfig = {}) {
29
- return resolveSurfaceIdsFromAppConfig(appConfig, (definition) => {
30
- return (
31
- definition.requiresWorkspace !== true &&
32
- normalizeLowerText(definition.accessPolicyId) === CONSOLE_OWNER_ACCESS_POLICY_ID
33
- );
34
- });
35
- }
36
-
37
- function resolveSurfaceIdsFromAppConfig(appConfig = {}, predicate) {
38
- const source = isRecord(appConfig?.surfaceDefinitions) ? appConfig.surfaceDefinitions : {};
39
- const resolved = [];
40
-
41
- for (const [key, value] of Object.entries(source)) {
42
- const definition = isRecord(value) ? value : {};
43
- const surfaceId = normalizeSurfaceId(definition.id || key);
44
- if (!surfaceId) {
45
- continue;
46
- }
47
- if (definition.enabled === false) {
48
- continue;
49
- }
50
- if (typeof predicate === "function" && predicate(definition) === true) {
51
- resolved.push(surfaceId);
52
- }
53
- }
54
-
55
- return normalizeSurfaceIds(resolved);
56
- }
57
-
58
- function materializeWorkspaceActionSurfaces(actions = [], { workspaceSurfaceIds = [] } = {}) {
59
- const sourceActions = Array.isArray(actions) ? actions : [];
60
- const resolvedWorkspaceSurfaceIds = normalizeSurfaceIds(workspaceSurfaceIds);
61
- const materialized = [];
62
-
63
- for (const entry of sourceActions) {
64
- const action = isRecord(entry) ? entry : {};
65
- const surfacesFrom = String(action.surfacesFrom || "")
66
- .trim()
67
- .toLowerCase();
68
- if (surfacesFrom !== "workspace") {
69
- materialized.push(action);
70
- continue;
71
- }
72
-
73
- if (resolvedWorkspaceSurfaceIds.length < 1) {
74
- continue;
75
- }
76
-
77
- const { surfacesFrom: _ignored, ...rest } = action;
78
- materialized.push({
79
- ...rest,
80
- surfaces: [...resolvedWorkspaceSurfaceIds]
81
- });
82
- }
83
-
84
- return Object.freeze(materialized.map((entry) => Object.freeze({ ...entry })));
85
- }
86
-
87
- function registerUsersCoreActionSurfaceSources(app) {
88
- if (!app || typeof app.actionSurfaceSource !== "function") {
89
- return;
90
- }
91
-
92
- app.actionSurfaceSource("workspace", ({ scope }) => {
93
- const appConfig = scope?.has?.("appConfig") ? scope.make("appConfig") : {};
94
- return resolveWorkspaceSurfaceIdsFromAppConfig(appConfig);
95
- });
96
-
97
- app.actionSurfaceSource("console", ({ scope }) => {
98
- const appConfig = scope?.has?.("appConfig") ? scope.make("appConfig") : {};
99
- return resolveConsoleSurfaceIdsFromAppConfig(appConfig);
100
- });
101
- }
102
-
103
- function materializeWorkspaceActionSurfacesFromAppConfig(actions = [], { appConfig = {} } = {}) {
104
- const workspaceSurfaceIds = resolveWorkspaceSurfaceIdsFromAppConfig(appConfig);
105
- return materializeWorkspaceActionSurfaces(actions, { workspaceSurfaceIds });
106
- }
107
-
108
- function resolveDefaultWorkspaceRouteSurfaceIdFromAppConfig(appConfig = {}) {
109
- const workspaceSurfaceIds = resolveWorkspaceSurfaceIdsFromAppConfig(appConfig);
110
- const workspaceSurfaceSet = new Set(workspaceSurfaceIds);
111
-
112
- const resolvedSurfaceId = resolveDefaultWorkspaceSurfaceId({
113
- defaultSurfaceId: appConfig?.surfaceDefaultId,
114
- workspaceSurfaceIds,
115
- surfaceRequiresWorkspace(surfaceId) {
116
- return workspaceSurfaceSet.has(surfaceId);
117
- }
118
- });
119
-
120
- return (
121
- normalizeSurfaceId(resolvedSurfaceId) ||
122
- normalizeSurfaceId(workspaceSurfaceIds[0]) ||
123
- normalizeSurfaceId(appConfig?.surfaceDefaultId) ||
124
- ""
125
- );
126
- }
127
-
128
- export {
129
- resolveWorkspaceSurfaceIdsFromAppConfig,
130
- resolveConsoleSurfaceIdsFromAppConfig,
131
- resolveDefaultWorkspaceRouteSurfaceIdFromAppConfig,
132
- materializeWorkspaceActionSurfaces,
133
- materializeWorkspaceActionSurfacesFromAppConfig,
134
- registerUsersCoreActionSurfaceSources
135
- };
@@ -1,45 +0,0 @@
1
- import {
2
- TENANCY_MODE_NONE,
3
- TENANCY_MODE_PERSONAL,
4
- normalizeTenancyMode
5
- } from "../../shared/tenancyMode.js";
6
-
7
- function normalizeWorkspaceInvitationsConfig(appConfig = {}) {
8
- const source = appConfig && typeof appConfig === "object" && !Array.isArray(appConfig)
9
- ? appConfig.workspaceInvitations
10
- : null;
11
- const normalizedSource = source && typeof source === "object" && !Array.isArray(source)
12
- ? source
13
- : {};
14
-
15
- return Object.freeze({
16
- enabled: normalizedSource.enabled !== false,
17
- allowInPersonalMode: normalizedSource.allowInPersonalMode !== false
18
- });
19
- }
20
-
21
- function resolveWorkspaceInvitationsPolicy({
22
- appConfig = {},
23
- tenancyProfile = null
24
- } = {}) {
25
- const config = normalizeWorkspaceInvitationsConfig(appConfig);
26
- const normalizedTenancyProfile = tenancyProfile && typeof tenancyProfile === "object"
27
- ? tenancyProfile
28
- : {};
29
- const tenancyMode = normalizeTenancyMode(normalizedTenancyProfile.mode || appConfig?.tenancyMode);
30
- const workspaceEnabled = normalizedTenancyProfile?.workspace?.enabled === true || tenancyMode !== TENANCY_MODE_NONE;
31
- const enabledForTenancyMode = tenancyMode !== TENANCY_MODE_PERSONAL || config.allowInPersonalMode === true;
32
- const enabled = config.enabled === true && workspaceEnabled && enabledForTenancyMode;
33
-
34
- return Object.freeze({
35
- enabled,
36
- workspaceEnabled,
37
- allowInPersonalMode: config.allowInPersonalMode,
38
- tenancyMode
39
- });
40
- }
41
-
42
- export {
43
- normalizeWorkspaceInvitationsConfig,
44
- resolveWorkspaceInvitationsPolicy
45
- };
@@ -1,22 +0,0 @@
1
- import { normalizeText } from "@jskit-ai/kernel/shared/support/normalize";
2
-
3
- function readWorkspaceSlugFromRouteParams(params = {}) {
4
- const workspaceSlug = normalizeText(params?.workspaceSlug).toLowerCase();
5
- return workspaceSlug || "";
6
- }
7
-
8
- function buildWorkspaceInputFromRouteParams(params = {}) {
9
- const workspaceSlug = readWorkspaceSlugFromRouteParams(params);
10
- if (!workspaceSlug) {
11
- return {};
12
- }
13
-
14
- return {
15
- workspaceSlug
16
- };
17
- }
18
-
19
- export {
20
- readWorkspaceSlugFromRouteParams,
21
- buildWorkspaceInputFromRouteParams
22
- };
@@ -1,211 +0,0 @@
1
- import { requireServiceMethod } from "@jskit-ai/kernel/shared/actions/actionContributorHelpers";
2
- import { normalizeRecordId } from "@jskit-ai/kernel/shared/support/normalize";
3
- import { normalizeLowerText } from "@jskit-ai/kernel/shared/actions/textNormalization";
4
- import {
5
- TENANCY_MODE_NONE,
6
- resolveTenancyProfile
7
- } from "../shared/tenancyProfile.js";
8
- import { workspacePendingInvitationsResource } from "../shared/resources/workspacePendingInvitationsResource.js";
9
- import {
10
- mapMembershipSummary,
11
- mapWorkspaceSettingsPublic,
12
- mapWorkspaceSummary
13
- } from "./common/formatters/workspaceFormatter.js";
14
-
15
- const REQUESTED_WORKSPACE_STATUS_RESOLVED = "resolved";
16
- const REQUESTED_WORKSPACE_STATUS_NOT_FOUND = "not_found";
17
- const REQUESTED_WORKSPACE_STATUS_FORBIDDEN = "forbidden";
18
- const REQUESTED_WORKSPACE_STATUS_UNAUTHENTICATED = "unauthenticated";
19
-
20
- function normalizePendingInvites(invites) {
21
- return workspacePendingInvitationsResource.operations.list.outputValidator.normalize({
22
- pendingInvites: invites
23
- }).pendingInvites;
24
- }
25
-
26
- function normalizeQueryPayload(value = {}) {
27
- if (!value || typeof value !== "object" || Array.isArray(value)) {
28
- return {};
29
- }
30
- return value;
31
- }
32
-
33
- function resolveBootstrapWorkspaceSlug({ query = {}, request = null } = {}) {
34
- const normalizedQuery = normalizeQueryPayload(query);
35
- if (Object.hasOwn(normalizedQuery, "workspaceSlug")) {
36
- return normalizeLowerText(normalizedQuery.workspaceSlug);
37
- }
38
-
39
- const normalizedInputQuery = normalizeQueryPayload(request?.input?.query);
40
- if (Object.hasOwn(normalizedInputQuery, "workspaceSlug")) {
41
- return normalizeLowerText(normalizedInputQuery.workspaceSlug);
42
- }
43
-
44
- const normalizedRequestQuery = normalizeQueryPayload(request?.query);
45
- if (Object.hasOwn(normalizedRequestQuery, "workspaceSlug")) {
46
- return normalizeLowerText(normalizedRequestQuery.workspaceSlug);
47
- }
48
-
49
- return "";
50
- }
51
-
52
- function normalizeRequestedWorkspaceStatus(value = "") {
53
- const normalizedValue = normalizeLowerText(value);
54
- if (
55
- normalizedValue === REQUESTED_WORKSPACE_STATUS_RESOLVED ||
56
- normalizedValue === REQUESTED_WORKSPACE_STATUS_NOT_FOUND ||
57
- normalizedValue === REQUESTED_WORKSPACE_STATUS_FORBIDDEN ||
58
- normalizedValue === REQUESTED_WORKSPACE_STATUS_UNAUTHENTICATED
59
- ) {
60
- return normalizedValue;
61
- }
62
- return "";
63
- }
64
-
65
- function createRequestedWorkspacePayload(workspaceSlug = "", status = "") {
66
- const normalizedWorkspaceSlug = normalizeLowerText(workspaceSlug);
67
- const normalizedStatus = normalizeRequestedWorkspaceStatus(status);
68
- if (!normalizedWorkspaceSlug || !normalizedStatus) {
69
- return null;
70
- }
71
- return {
72
- slug: normalizedWorkspaceSlug,
73
- status: normalizedStatus
74
- };
75
- }
76
-
77
- function resolveRequestedWorkspaceStatusFromError(error) {
78
- const statusCode = Number(error?.statusCode || error?.status || 0);
79
- if (statusCode === 404) {
80
- return REQUESTED_WORKSPACE_STATUS_NOT_FOUND;
81
- }
82
- if (statusCode === 403) {
83
- return REQUESTED_WORKSPACE_STATUS_FORBIDDEN;
84
- }
85
- if (statusCode === 401) {
86
- return REQUESTED_WORKSPACE_STATUS_UNAUTHENTICATED;
87
- }
88
- return "";
89
- }
90
-
91
- function resolveBootstrapTenancyProfile(tenancyProfile = null, appConfig = {}) {
92
- const fallback = resolveTenancyProfile(appConfig);
93
- return Object.freeze({
94
- mode: fallback.mode,
95
- workspace: Object.freeze({
96
- enabled: fallback.workspace.enabled === true,
97
- autoProvision: fallback.workspace.autoProvision === true,
98
- allowSelfCreate: fallback.workspace.allowSelfCreate === true,
99
- slugPolicy: fallback.workspace.slugPolicy
100
- })
101
- });
102
- }
103
-
104
- function createWorkspaceBootstrapContributor({
105
- workspaceService,
106
- workspacePendingInvitationsService,
107
- usersRepository,
108
- workspaceInvitationsEnabled = false,
109
- appConfig = {},
110
- tenancyProfile = null
111
- } = {}) {
112
- const contributorId = "users.workspace.bootstrap";
113
- const resolvedTenancyProfile = resolveBootstrapTenancyProfile(tenancyProfile, appConfig);
114
-
115
- requireServiceMethod(workspaceService, "listWorkspacesForUser", contributorId, {
116
- serviceLabel: "workspaceService"
117
- });
118
- requireServiceMethod(workspaceService, "resolveWorkspaceContextForUserBySlug", contributorId, {
119
- serviceLabel: "workspaceService"
120
- });
121
- if (workspaceInvitationsEnabled) {
122
- requireServiceMethod(workspacePendingInvitationsService, "listPendingInvitesForUser", contributorId, {
123
- serviceLabel: "workspacePendingInvitationsService"
124
- });
125
- }
126
- requireServiceMethod(usersRepository, "findById", contributorId, {
127
- serviceLabel: "usersRepository"
128
- });
129
-
130
- return Object.freeze({
131
- contributorId,
132
- async contribute({ request = null, query = {}, payload = {} } = {}) {
133
- const normalizedUserId = normalizeRecordId(
134
- payload?.session?.authenticated === true ? payload?.session?.userId : null,
135
- { fallback: null }
136
- );
137
- const normalizedWorkspaceSlug = resolveBootstrapWorkspaceSlug({ query, request });
138
- if (!normalizedUserId) {
139
- if (!normalizedWorkspaceSlug || resolvedTenancyProfile.mode === TENANCY_MODE_NONE) {
140
- return {};
141
- }
142
-
143
- return {
144
- requestedWorkspace: createRequestedWorkspacePayload(
145
- normalizedWorkspaceSlug,
146
- REQUESTED_WORKSPACE_STATUS_UNAUTHENTICATED
147
- )
148
- };
149
- }
150
-
151
- const latestProfile = await usersRepository.findById(normalizedUserId);
152
- if (!latestProfile) {
153
- return {};
154
- }
155
-
156
- const pendingInvites =
157
- workspaceInvitationsEnabled
158
- ? normalizePendingInvites(
159
- await workspacePendingInvitationsService.listPendingInvitesForUser(latestProfile, {
160
- context: {
161
- actor: latestProfile
162
- }
163
- })
164
- )
165
- : [];
166
- const workspaces = await workspaceService.listWorkspacesForUser(latestProfile, { request });
167
- let workspaceContext = null;
168
- let requestedWorkspace = null;
169
- if (normalizedWorkspaceSlug && resolvedTenancyProfile.mode !== TENANCY_MODE_NONE) {
170
- try {
171
- workspaceContext = await workspaceService.resolveWorkspaceContextForUserBySlug(
172
- latestProfile,
173
- normalizedWorkspaceSlug,
174
- { request }
175
- );
176
- requestedWorkspace = createRequestedWorkspacePayload(
177
- normalizedWorkspaceSlug,
178
- REQUESTED_WORKSPACE_STATUS_RESOLVED
179
- );
180
- } catch (error) {
181
- const requestedWorkspaceStatus = resolveRequestedWorkspaceStatusFromError(error);
182
- if (!requestedWorkspaceStatus) {
183
- throw error;
184
- }
185
- requestedWorkspace = createRequestedWorkspacePayload(normalizedWorkspaceSlug, requestedWorkspaceStatus);
186
- }
187
- }
188
-
189
- return {
190
- workspaces: [...workspaces],
191
- pendingInvites,
192
- activeWorkspace: workspaceContext
193
- ? mapWorkspaceSummary(workspaceContext.workspace, {
194
- roleSid: workspaceContext.membership?.roleSid,
195
- status: workspaceContext.membership?.status
196
- })
197
- : null,
198
- membership: mapMembershipSummary(workspaceContext?.membership, workspaceContext?.workspace),
199
- requestedWorkspace,
200
- permissions: workspaceContext ? [...workspaceContext.permissions] : [],
201
- workspaceSettings: workspaceContext
202
- ? mapWorkspaceSettingsPublic(workspaceContext.workspaceSettings, {
203
- workspaceInvitationsEnabled
204
- })
205
- : null
206
- };
207
- }
208
- });
209
- }
210
-
211
- export { createWorkspaceBootstrapContributor };