@jskit-ai/users-web 0.1.52 → 0.1.54

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 (73) hide show
  1. package/package.descriptor.mjs +14 -96
  2. package/package.json +16 -11
  3. package/src/client/account-settings/sections.js +74 -0
  4. package/src/client/composables/account-settings/accountSettingsRuntimeHelpers.js +2 -38
  5. package/src/client/composables/crud/crudLookupFieldRuntime.js +2 -2
  6. package/src/client/composables/internal/crudListParentTitleSupport.js +1 -1
  7. package/src/client/composables/internal/useOperationScope.js +12 -12
  8. package/src/client/composables/records/useAddEdit.js +2 -2
  9. package/src/client/composables/records/useList.js +3 -3
  10. package/src/client/composables/records/useView.js +2 -2
  11. package/src/client/composables/support/scopeHelpers.js +19 -19
  12. package/src/client/composables/useAccess.js +3 -3
  13. package/src/client/composables/useAccountSettingsRuntime.js +8 -156
  14. package/src/client/composables/useCommand.js +2 -2
  15. package/src/client/composables/useCrudListParentTitle.js +2 -2
  16. package/src/client/composables/usePaths.js +50 -38
  17. package/src/client/composables/useScopeRuntime.js +55 -27
  18. package/src/client/composables/useSurfaceRouteContext.js +1 -7
  19. package/src/client/index.js +0 -1
  20. package/src/client/lib/bootstrap.js +0 -63
  21. package/src/client/lib/httpClient.js +2 -59
  22. package/src/client/lib/theme.js +12 -189
  23. package/src/client/providers/UsersWebClientProvider.js +2 -25
  24. package/src/client/providers/bootUsersWebClientProvider.js +28 -0
  25. package/src/shared/toolsOutletContracts.js +1 -8
  26. package/templates/src/components/account/settings/AccountSettingsClientElement.vue +33 -21
  27. package/test/accountSettingsSections.test.js +79 -0
  28. package/test/exportsContract.test.js +2 -2
  29. package/test/scopeHelpers.test.js +6 -6
  30. package/test/settingsPlacementContract.test.js +4 -49
  31. package/test/theme.test.js +0 -56
  32. package/src/client/components/ConsoleSettingsClientElement.vue +0 -24
  33. package/src/client/components/MembersAdminClientElement.vue +0 -400
  34. package/src/client/components/UsersProfileSurfaceSwitchMenuItem.vue +0 -39
  35. package/src/client/components/UsersWorkspaceMembersMenuItem.vue +0 -36
  36. package/src/client/components/UsersWorkspacePermissionMenuItem.vue +0 -90
  37. package/src/client/components/UsersWorkspaceSelector.vue +0 -248
  38. package/src/client/components/UsersWorkspaceSettingsMenuItem.vue +0 -39
  39. package/src/client/components/UsersWorkspaceToolsWidget.vue +0 -12
  40. package/src/client/components/WorkspaceMembersClientElement.vue +0 -655
  41. package/src/client/components/WorkspaceProfileClientElement.vue +0 -116
  42. package/src/client/components/WorkspaceSettingsClientElement.vue +0 -102
  43. package/src/client/components/WorkspaceSettingsFieldsClientElement.vue +0 -265
  44. package/src/client/components/WorkspacesClientElement.vue +0 -509
  45. package/src/client/composables/account-settings/accountSettingsInvitesRuntime.js +0 -88
  46. package/src/client/composables/useBootstrapQuery.js +0 -52
  47. package/src/client/composables/useWorkspaceRouteContext.js +0 -28
  48. package/src/client/composables/useWorkspaceSurfaceId.js +0 -43
  49. package/src/client/lib/menuIcons.js +0 -210
  50. package/src/client/lib/profileSurfaceMenuLinks.js +0 -142
  51. package/src/client/lib/surfaceAccessPolicy.js +0 -350
  52. package/src/client/lib/workspaceLinkResolver.js +0 -207
  53. package/src/client/lib/workspaceSurfaceContext.js +0 -82
  54. package/src/client/lib/workspaceSurfacePaths.js +0 -163
  55. package/src/client/providers/UsersWorkspacesClientProvider.js +0 -24
  56. package/src/client/runtime/bootstrapPlacementRouteGuards.js +0 -371
  57. package/src/client/runtime/bootstrapPlacementRuntime.js +0 -463
  58. package/src/client/runtime/bootstrapPlacementRuntimeConstants.js +0 -28
  59. package/src/client/runtime/bootstrapPlacementRuntimeHelpers.js +0 -147
  60. package/src/client/support/menuLinkTarget.js +0 -93
  61. package/src/client/support/realtimeWorkspace.js +0 -21
  62. package/src/client/support/runtimeNormalization.js +0 -27
  63. package/src/client/support/workspaceQueryKeys.js +0 -15
  64. package/templates/src/components/account/settings/AccountSettingsInvitesSection.vue +0 -77
  65. package/templates/src/pages/console/settings/index.vue +0 -8
  66. package/templates/src/pages/console/settings.vue +0 -32
  67. package/test/bootstrapPlacementRuntime.test.js +0 -1095
  68. package/test/menuIcons.test.js +0 -35
  69. package/test/menuLinkTarget.test.js +0 -116
  70. package/test/profileSurfaceMenuLinks.test.js +0 -207
  71. package/test/surfaceAccessPolicy.test.js +0 -129
  72. package/test/workspaceLinkResolver.test.js +0 -61
  73. package/test/workspaceSurfacePaths.test.js +0 -39
@@ -1,463 +0,0 @@
1
- import {
2
- findWorkspaceBySlug,
3
- normalizeWorkspaceList,
4
- resolvePlacementUserFromBootstrapPayload
5
- } from "../lib/bootstrap.js";
6
- import { normalizePermissionList } from "../lib/permissions.js";
7
- import {
8
- persistBootstrapThemePreference,
9
- resolveBootstrapThemeName,
10
- setVuetifyPrimaryColorOverride,
11
- resolveVuetifyThemeController,
12
- setVuetifyThemeName
13
- } from "../lib/theme.js";
14
- import { createBootstrapPlacementRouteGuards } from "./bootstrapPlacementRouteGuards.js";
15
- import {
16
- WORKSPACE_BOOTSTRAP_STATUS_ERROR,
17
- WORKSPACE_BOOTSTRAP_STATUS_FORBIDDEN,
18
- WORKSPACE_BOOTSTRAP_STATUS_NOT_FOUND,
19
- WORKSPACE_BOOTSTRAP_STATUS_RESOLVED,
20
- WORKSPACE_BOOTSTRAP_STATUS_UNAUTHENTICATED
21
- } from "./bootstrapPlacementRuntimeConstants.js";
22
- import {
23
- countPendingInvites,
24
- createProviderLogger,
25
- fetchBootstrapPayload,
26
- normalizeWorkspaceBootstrapStatus,
27
- normalizeWorkspaceSlugKey,
28
- resolveAuthSignature,
29
- resolveRequestedWorkspaceBootstrapStatus,
30
- resolveRouteState
31
- } from "./bootstrapPlacementRuntimeHelpers.js";
32
- import { resolveErrorStatusCode } from "../support/runtimeNormalization.js";
33
-
34
- function createBootstrapPlacementRuntime({ app, logger = null, fetchBootstrap = fetchBootstrapPayload } = {}) {
35
- if (!app || typeof app.has !== "function" || typeof app.make !== "function") {
36
- throw new Error("createBootstrapPlacementRuntime requires application has()/make().");
37
- }
38
- if (!app.has("runtime.web-placement.client")) {
39
- throw new Error("createBootstrapPlacementRuntime requires shell-web placement runtime.");
40
- }
41
- if (typeof fetchBootstrap !== "function") {
42
- throw new TypeError("createBootstrapPlacementRuntime requires fetchBootstrap(workspaceSlug).");
43
- }
44
-
45
- const runtimeLogger = logger || createProviderLogger(app);
46
- const placementRuntime = app.make("runtime.web-placement.client");
47
- const router = app.has("jskit.client.router") ? app.make("jskit.client.router") : null;
48
- let vuetifyThemeController = resolveVuetifyThemeController(
49
- app.has("jskit.client.vue.app") ? app.make("jskit.client.vue.app") : null
50
- );
51
- const socket = app.has("runtime.realtime.client.socket") ? app.make("runtime.realtime.client.socket") : null;
52
- const cleanup = [];
53
- let refreshQueue = Promise.resolve();
54
- let shutdownRequested = false;
55
- let authSignature = resolveAuthSignature(placementRuntime.getContext());
56
- let lastRouteWorkspaceSlug = resolveRouteState(placementRuntime, router).workspaceSlug;
57
- const workspaceBootstrapStatusBySlug = new Map();
58
- const workspaceBootstrapStatusListeners = new Set();
59
- const root = typeof globalThis === "object" && globalThis ? globalThis : null;
60
-
61
- const routeGuards = createBootstrapPlacementRouteGuards({
62
- placementRuntime,
63
- router,
64
- root,
65
- getWorkspaceBootstrapStatus: (workspaceSlug) => getWorkspaceBootstrapStatus(workspaceSlug)
66
- });
67
-
68
- cleanup.push(() => {
69
- routeGuards.shutdown();
70
- });
71
-
72
- function setWorkspaceBootstrapStatus(workspaceSlug = "", status = "", source = "users-web.bootstrap-placement") {
73
- const workspaceSlugKey = normalizeWorkspaceSlugKey(workspaceSlug);
74
- const normalizedStatus = normalizeWorkspaceBootstrapStatus(status);
75
- if (!workspaceSlugKey || !normalizedStatus) {
76
- return;
77
- }
78
-
79
- const previousStatus = workspaceBootstrapStatusBySlug.get(workspaceSlugKey) || "";
80
- workspaceBootstrapStatusBySlug.set(workspaceSlugKey, normalizedStatus);
81
- if (previousStatus === normalizedStatus) {
82
- return;
83
- }
84
-
85
- placementRuntime.setContext(
86
- {
87
- workspaceBootstrapStatuses: Object.freeze(Object.fromEntries(workspaceBootstrapStatusBySlug))
88
- },
89
- {
90
- source
91
- }
92
- );
93
-
94
- const payload = Object.freeze({
95
- workspaceSlug: workspaceSlugKey,
96
- status: normalizedStatus,
97
- source: String(source || "users-web.bootstrap-placement").trim() || "users-web.bootstrap-placement"
98
- });
99
- for (const listener of workspaceBootstrapStatusListeners) {
100
- try {
101
- listener(payload);
102
- } catch {}
103
- }
104
- routeGuards.enforceWorkspaceRouteForStatusUpdate(payload);
105
- }
106
-
107
- function getWorkspaceBootstrapStatus(workspaceSlug = "") {
108
- const workspaceSlugKey = normalizeWorkspaceSlugKey(workspaceSlug);
109
- if (!workspaceSlugKey) {
110
- return "";
111
- }
112
- return String(workspaceBootstrapStatusBySlug.get(workspaceSlugKey) || "");
113
- }
114
-
115
- function subscribeWorkspaceBootstrapStatus(listener) {
116
- if (typeof listener !== "function") {
117
- return () => {};
118
- }
119
- workspaceBootstrapStatusListeners.add(listener);
120
- return () => {
121
- workspaceBootstrapStatusListeners.delete(listener);
122
- };
123
- }
124
-
125
- function writePlacementContext(payload = {}, state = {}, source = "users-web.bootstrap-placement") {
126
- const availableWorkspaces = normalizeWorkspaceList(payload?.workspaces);
127
- const currentWorkspace = findWorkspaceBySlug(availableWorkspaces, state.workspaceSlug);
128
- const workspaceSettings =
129
- payload?.workspaceSettings && typeof payload.workspaceSettings === "object"
130
- ? payload.workspaceSettings
131
- : null;
132
- const permissions = normalizePermissionList(payload?.permissions);
133
- const user = resolvePlacementUserFromBootstrapPayload(payload, state.context?.user);
134
- const workspaceInvitesEnabled = payload?.app?.features?.workspaceInvites === true;
135
- const pendingInvitesCount = workspaceInvitesEnabled ? countPendingInvites(payload?.pendingInvites) : 0;
136
-
137
- placementRuntime.setContext(
138
- {
139
- workspace: currentWorkspace,
140
- workspaceSettings,
141
- workspaces: availableWorkspaces,
142
- permissions,
143
- user,
144
- surfaceAccess: payload?.surfaceAccess && typeof payload.surfaceAccess === "object" ? payload.surfaceAccess : {},
145
- pendingInvitesCount,
146
- workspaceInvitesEnabled
147
- },
148
- {
149
- source
150
- }
151
- );
152
- routeGuards.enforceSurfaceAccessForCurrentRoute();
153
- applyWorkspaceColorFromPlacementContext("write");
154
- }
155
-
156
- function clearPlacementContext(source = "users-web.bootstrap-placement") {
157
- placementRuntime.setContext(
158
- {
159
- workspace: null,
160
- workspaceSettings: null,
161
- workspaces: [],
162
- permissions: [],
163
- user: null,
164
- surfaceAccess: {},
165
- pendingInvitesCount: 0,
166
- workspaceInvitesEnabled: false
167
- },
168
- {
169
- source
170
- }
171
- );
172
- routeGuards.enforceSurfaceAccessForCurrentRoute();
173
- applyWorkspaceColorFromPlacementContext("clear");
174
- }
175
-
176
- function getVuetifyThemeController() {
177
- if (vuetifyThemeController) {
178
- return vuetifyThemeController;
179
- }
180
- if (!app.has("jskit.client.vue.app")) {
181
- return null;
182
- }
183
-
184
- vuetifyThemeController = resolveVuetifyThemeController(app.make("jskit.client.vue.app"));
185
- return vuetifyThemeController;
186
- }
187
-
188
- function applyThemeFromBootstrapPayload(payload = {}, reason = "manual") {
189
- const themeController = getVuetifyThemeController();
190
- if (!themeController) {
191
- return;
192
- }
193
-
194
- try {
195
- const nextThemeName = resolveBootstrapThemeName(payload);
196
- setVuetifyThemeName(themeController, nextThemeName);
197
- persistBootstrapThemePreference(payload);
198
- } catch (error) {
199
- runtimeLogger.warn(
200
- {
201
- reason,
202
- error: String(error?.message || error || "unknown error")
203
- },
204
- "users-web bootstrap theme apply failed."
205
- );
206
- }
207
- }
208
-
209
- function resolveWorkspaceThemeForCurrentRoute() {
210
- const routeState = resolveRouteState(placementRuntime, router);
211
- if (!routeState.workspaceSlug) {
212
- return null;
213
- }
214
-
215
- const context = placementRuntime.getContext();
216
- const workspaceSettings =
217
- context?.workspaceSettings && typeof context.workspaceSettings === "object"
218
- ? context.workspaceSettings
219
- : null;
220
- if (workspaceSettings) {
221
- return workspaceSettings;
222
- }
223
-
224
- const workspace = context?.workspace && typeof context.workspace === "object" ? context.workspace : null;
225
- if (!workspace) {
226
- return null;
227
- }
228
- const workspaceSlug = normalizeWorkspaceSlugKey(workspace.slug);
229
- if (!workspaceSlug || workspaceSlug !== normalizeWorkspaceSlugKey(routeState.workspaceSlug)) {
230
- return null;
231
- }
232
-
233
- return workspace;
234
- }
235
-
236
- function applyWorkspaceColorFromPlacementContext(reason = "manual") {
237
- const themeController = getVuetifyThemeController();
238
- if (!themeController) {
239
- return;
240
- }
241
- try {
242
- const workspaceTheme = resolveWorkspaceThemeForCurrentRoute();
243
- setVuetifyPrimaryColorOverride(themeController, workspaceTheme);
244
- } catch (error) {
245
- runtimeLogger.warn(
246
- {
247
- reason,
248
- error: String(error?.message || error || "unknown error")
249
- },
250
- "users-web bootstrap workspace color apply failed."
251
- );
252
- }
253
- }
254
-
255
- async function refresh(reason = "manual") {
256
- if (shutdownRequested) {
257
- return;
258
- }
259
-
260
- const stateAtStart = resolveRouteState(placementRuntime, router);
261
- const source = `users-web.bootstrap-placement.${String(reason || "manual").trim() || "manual"}`;
262
- try {
263
- const payload = await fetchBootstrap(stateAtStart.workspaceSlug);
264
- const stateAtApply = resolveRouteState(placementRuntime, router);
265
- if (stateAtStart.path !== stateAtApply.path || stateAtStart.workspaceSlug !== stateAtApply.workspaceSlug) {
266
- return;
267
- }
268
-
269
- writePlacementContext(payload, stateAtStart, source);
270
- applyThemeFromBootstrapPayload(payload, reason);
271
- applyWorkspaceColorFromPlacementContext(reason);
272
- if (stateAtStart.workspaceSlug) {
273
- const sessionAuthenticated = payload?.session?.authenticated === true;
274
- if (!sessionAuthenticated) {
275
- setWorkspaceBootstrapStatus(stateAtStart.workspaceSlug, WORKSPACE_BOOTSTRAP_STATUS_UNAUTHENTICATED, source);
276
- return;
277
- }
278
-
279
- const requestedWorkspaceStatus = resolveRequestedWorkspaceBootstrapStatus(payload, stateAtStart.workspaceSlug);
280
- if (requestedWorkspaceStatus) {
281
- setWorkspaceBootstrapStatus(stateAtStart.workspaceSlug, requestedWorkspaceStatus, source);
282
- return;
283
- }
284
-
285
- const availableWorkspaces = normalizeWorkspaceList(payload?.workspaces);
286
- const currentWorkspace = findWorkspaceBySlug(availableWorkspaces, stateAtStart.workspaceSlug);
287
- setWorkspaceBootstrapStatus(
288
- stateAtStart.workspaceSlug,
289
- currentWorkspace ? WORKSPACE_BOOTSTRAP_STATUS_RESOLVED : WORKSPACE_BOOTSTRAP_STATUS_FORBIDDEN,
290
- source
291
- );
292
- }
293
- } catch (error) {
294
- const statusCode = resolveErrorStatusCode(error);
295
- const stateAtApply = resolveRouteState(placementRuntime, router);
296
- const sameWorkspaceRoute =
297
- stateAtStart.path === stateAtApply.path && stateAtStart.workspaceSlug === stateAtApply.workspaceSlug;
298
-
299
- if (statusCode === 401) {
300
- if (stateAtStart.workspaceSlug) {
301
- setWorkspaceBootstrapStatus(stateAtStart.workspaceSlug, WORKSPACE_BOOTSTRAP_STATUS_UNAUTHENTICATED, source);
302
- }
303
- clearPlacementContext(source);
304
- applyThemeFromBootstrapPayload(
305
- {
306
- session: {
307
- authenticated: false
308
- }
309
- },
310
- reason
311
- );
312
- return;
313
- }
314
- if (statusCode === 403) {
315
- if (stateAtStart.workspaceSlug) {
316
- setWorkspaceBootstrapStatus(stateAtStart.workspaceSlug, WORKSPACE_BOOTSTRAP_STATUS_FORBIDDEN, source);
317
- }
318
- if (sameWorkspaceRoute) {
319
- clearPlacementContext(source);
320
- }
321
- return;
322
- }
323
- if (statusCode === 404) {
324
- if (stateAtStart.workspaceSlug) {
325
- setWorkspaceBootstrapStatus(stateAtStart.workspaceSlug, WORKSPACE_BOOTSTRAP_STATUS_NOT_FOUND, source);
326
- }
327
- if (sameWorkspaceRoute) {
328
- clearPlacementContext(source);
329
- }
330
- return;
331
- }
332
-
333
- if (stateAtStart.workspaceSlug) {
334
- setWorkspaceBootstrapStatus(stateAtStart.workspaceSlug, WORKSPACE_BOOTSTRAP_STATUS_ERROR, source);
335
- }
336
-
337
- runtimeLogger.warn(
338
- {
339
- reason,
340
- error: String(error?.message || error || "unknown error")
341
- },
342
- "users-web bootstrap placement refresh failed."
343
- );
344
- }
345
- }
346
-
347
- function queueRefresh(reason = "manual") {
348
- refreshQueue = refreshQueue
349
- .then(() => refresh(reason))
350
- .catch((error) => {
351
- runtimeLogger.warn(
352
- {
353
- reason,
354
- error: String(error?.message || error || "unknown error")
355
- },
356
- "users-web bootstrap placement queued refresh failed."
357
- );
358
- });
359
- return refreshQueue;
360
- }
361
-
362
- async function initialize() {
363
- routeGuards.installWorkspaceGuardEvaluator();
364
-
365
- const contextAtInit = placementRuntime.getContext();
366
- if (contextAtInit?.auth?.authenticated !== true) {
367
- applyThemeFromBootstrapPayload({
368
- session: {
369
- authenticated: false
370
- }
371
- }, "init");
372
- }
373
- applyWorkspaceColorFromPlacementContext("init");
374
-
375
- if (typeof placementRuntime.subscribe === "function") {
376
- const unsubscribePlacement = placementRuntime.subscribe((event = {}) => {
377
- if (event.type !== "context.updated") {
378
- return;
379
- }
380
-
381
- const nextContext = placementRuntime.getContext();
382
- applyWorkspaceColorFromPlacementContext("context");
383
- const nextSignature = resolveAuthSignature(nextContext);
384
- if (nextSignature === authSignature) {
385
- return;
386
- }
387
-
388
- authSignature = nextSignature;
389
- if (nextContext?.auth?.authenticated !== true) {
390
- applyThemeFromBootstrapPayload({
391
- session: {
392
- authenticated: false
393
- }
394
- }, "auth");
395
- }
396
- void queueRefresh("auth");
397
- });
398
- cleanup.push(() => {
399
- if (typeof unsubscribePlacement === "function") {
400
- unsubscribePlacement();
401
- }
402
- });
403
- }
404
-
405
- await queueRefresh("init");
406
-
407
- if (router && typeof router.afterEach === "function") {
408
- const removeAfterEach = router.afterEach(() => {
409
- const nextWorkspaceSlug = resolveRouteState(placementRuntime, router).workspaceSlug;
410
- if (nextWorkspaceSlug === lastRouteWorkspaceSlug) {
411
- return;
412
- }
413
- lastRouteWorkspaceSlug = nextWorkspaceSlug;
414
- void queueRefresh("route");
415
- });
416
- cleanup.push(() => {
417
- if (typeof removeAfterEach === "function") {
418
- removeAfterEach();
419
- }
420
- });
421
- }
422
-
423
- if (socket && typeof socket.on === "function") {
424
- const handleBootstrapChanged = () => {
425
- void queueRefresh("realtime");
426
- };
427
- socket.on("users.bootstrap.changed", handleBootstrapChanged);
428
- cleanup.push(() => {
429
- if (typeof socket.off === "function") {
430
- socket.off("users.bootstrap.changed", handleBootstrapChanged);
431
- }
432
- });
433
- }
434
- }
435
-
436
- function shutdown() {
437
- shutdownRequested = true;
438
- for (const release of cleanup.splice(0, cleanup.length)) {
439
- if (typeof release === "function") {
440
- try {
441
- release();
442
- } catch {}
443
- }
444
- }
445
- }
446
-
447
- return Object.freeze({
448
- initialize,
449
- shutdown,
450
- refresh: queueRefresh,
451
- getWorkspaceBootstrapStatus,
452
- subscribeWorkspaceBootstrapStatus
453
- });
454
- }
455
-
456
- export {
457
- WORKSPACE_BOOTSTRAP_STATUS_RESOLVED,
458
- WORKSPACE_BOOTSTRAP_STATUS_NOT_FOUND,
459
- WORKSPACE_BOOTSTRAP_STATUS_FORBIDDEN,
460
- WORKSPACE_BOOTSTRAP_STATUS_UNAUTHENTICATED,
461
- WORKSPACE_BOOTSTRAP_STATUS_ERROR,
462
- createBootstrapPlacementRuntime
463
- };
@@ -1,28 +0,0 @@
1
- const WORKSPACE_BOOTSTRAP_STATUS_RESOLVED = "resolved";
2
- const WORKSPACE_BOOTSTRAP_STATUS_NOT_FOUND = "not_found";
3
- const WORKSPACE_BOOTSTRAP_STATUS_FORBIDDEN = "forbidden";
4
- const WORKSPACE_BOOTSTRAP_STATUS_UNAUTHENTICATED = "unauthenticated";
5
- const WORKSPACE_BOOTSTRAP_STATUS_ERROR = "error";
6
- const SHELL_GUARD_EVALUATOR_KEY = "__JSKIT_WEB_SHELL_GUARD_EVALUATOR__";
7
- const WORKSPACE_NOT_FOUND_GUARD_REASON = "workspace-not-found";
8
- const WORKSPACE_FORBIDDEN_GUARD_REASON = "workspace-forbidden";
9
-
10
- const WORKSPACE_BOOTSTRAP_STATUSES = new Set([
11
- WORKSPACE_BOOTSTRAP_STATUS_RESOLVED,
12
- WORKSPACE_BOOTSTRAP_STATUS_NOT_FOUND,
13
- WORKSPACE_BOOTSTRAP_STATUS_FORBIDDEN,
14
- WORKSPACE_BOOTSTRAP_STATUS_UNAUTHENTICATED,
15
- WORKSPACE_BOOTSTRAP_STATUS_ERROR
16
- ]);
17
-
18
- export {
19
- SHELL_GUARD_EVALUATOR_KEY,
20
- WORKSPACE_BOOTSTRAP_STATUSES,
21
- WORKSPACE_BOOTSTRAP_STATUS_ERROR,
22
- WORKSPACE_BOOTSTRAP_STATUS_FORBIDDEN,
23
- WORKSPACE_BOOTSTRAP_STATUS_NOT_FOUND,
24
- WORKSPACE_BOOTSTRAP_STATUS_RESOLVED,
25
- WORKSPACE_BOOTSTRAP_STATUS_UNAUTHENTICATED,
26
- WORKSPACE_FORBIDDEN_GUARD_REASON,
27
- WORKSPACE_NOT_FOUND_GUARD_REASON
28
- };
@@ -1,147 +0,0 @@
1
- import {
2
- createProviderLogger as createSharedProviderLogger
3
- } from "@jskit-ai/kernel/shared/support/providerLogger";
4
- import {
5
- resolveRuntimePathname,
6
- resolveSurfaceIdFromPlacementPathname
7
- } from "@jskit-ai/shell-web/client/placement";
8
- import { parseWorkspacePathname } from "@jskit-ai/users-core/shared/support/workspacePathModel";
9
- import { extractWorkspaceSlugFromSurfacePathname } from "../lib/workspaceSurfacePaths.js";
10
- import { usersWebHttpClient } from "../lib/httpClient.js";
11
- import { buildBootstrapApiPath } from "../lib/bootstrap.js";
12
- import {
13
- normalizeWorkspaceBootstrapStatusValue
14
- } from "../support/runtimeNormalization.js";
15
- import { WORKSPACE_BOOTSTRAP_STATUSES } from "./bootstrapPlacementRuntimeConstants.js";
16
-
17
- function createProviderLogger(app) {
18
- return createSharedProviderLogger(app);
19
- }
20
-
21
- function resolveRouteState(placementRuntime, router) {
22
- const context = placementRuntime.getContext();
23
- const path = resolveRuntimePathname(router?.currentRoute?.value?.path);
24
- const surfaceId = String(resolveSurfaceIdFromPlacementPathname(context, path) || "")
25
- .trim()
26
- .toLowerCase();
27
- const workspaceSlugFromSurface = String(extractWorkspaceSlugFromSurfacePathname(context, surfaceId, path) || "").trim();
28
- const workspaceSlug =
29
- workspaceSlugFromSurface ||
30
- String(parseWorkspacePathname(path)?.workspaceSlug || "").trim();
31
-
32
- return Object.freeze({
33
- context,
34
- path,
35
- workspaceSlug
36
- });
37
- }
38
-
39
- function normalizeSearch(search = "") {
40
- const normalizedSearch = String(search || "").trim();
41
- if (!normalizedSearch) {
42
- return "";
43
- }
44
- return normalizedSearch.startsWith("?") ? normalizedSearch : `?${normalizedSearch}`;
45
- }
46
-
47
- function resolveSearchFromFullPath(fullPath = "") {
48
- const normalizedFullPath = String(fullPath || "").trim();
49
- const queryStart = normalizedFullPath.indexOf("?");
50
- if (queryStart < 0) {
51
- return "";
52
- }
53
- const hashStart = normalizedFullPath.indexOf("#", queryStart);
54
- const search = hashStart < 0 ? normalizedFullPath.slice(queryStart) : normalizedFullPath.slice(queryStart, hashStart);
55
- return normalizeSearch(search);
56
- }
57
-
58
- function isGuardDenied(outcome) {
59
- if (outcome === false) {
60
- return true;
61
- }
62
- if (outcome == null || outcome === true || typeof outcome !== "object" || Array.isArray(outcome)) {
63
- return false;
64
- }
65
- return outcome.allow === false;
66
- }
67
-
68
- function normalizeWorkspaceSlugKey(workspaceSlug = "") {
69
- return String(workspaceSlug || "")
70
- .trim()
71
- .toLowerCase();
72
- }
73
-
74
- function normalizeWorkspaceBootstrapStatus(status = "") {
75
- return normalizeWorkspaceBootstrapStatusValue(status, WORKSPACE_BOOTSTRAP_STATUSES);
76
- }
77
-
78
- function resolveRequestedWorkspaceBootstrapStatus(payload = {}, workspaceSlug = "") {
79
- const normalizedWorkspaceSlug = normalizeWorkspaceSlugKey(workspaceSlug);
80
- if (!normalizedWorkspaceSlug) {
81
- return "";
82
- }
83
-
84
- const requestedWorkspace =
85
- payload?.requestedWorkspace && typeof payload.requestedWorkspace === "object" ? payload.requestedWorkspace : null;
86
- if (!requestedWorkspace) {
87
- return "";
88
- }
89
-
90
- const requestedWorkspaceSlug = normalizeWorkspaceSlugKey(requestedWorkspace.slug);
91
- if (!requestedWorkspaceSlug || requestedWorkspaceSlug !== normalizedWorkspaceSlug) {
92
- return "";
93
- }
94
-
95
- return normalizeWorkspaceBootstrapStatus(requestedWorkspace.status);
96
- }
97
-
98
- function resolveAuthSignature(context = {}) {
99
- const auth = context?.auth && typeof context.auth === "object" ? context.auth : {};
100
- const authenticated = auth.authenticated === true ? "1" : "0";
101
- const oauthDefaultProvider = String(auth.oauthDefaultProvider || "")
102
- .trim()
103
- .toLowerCase();
104
- const oauthProviders = Array.isArray(auth.oauthProviders)
105
- ? auth.oauthProviders
106
- .map((entry) => String(entry?.id || "").trim().toLowerCase())
107
- .filter(Boolean)
108
- .join(",")
109
- : "";
110
-
111
- return `${authenticated}|${oauthDefaultProvider}|${oauthProviders}`;
112
- }
113
-
114
- function countPendingInvites(entries = []) {
115
- if (!Array.isArray(entries)) {
116
- return 0;
117
- }
118
-
119
- let total = 0;
120
- for (const entry of entries) {
121
- if (!entry || typeof entry !== "object") {
122
- continue;
123
- }
124
- total += 1;
125
- }
126
- return total;
127
- }
128
-
129
- async function fetchBootstrapPayload(workspaceSlug = "") {
130
- return usersWebHttpClient.request(buildBootstrapApiPath(workspaceSlug), {
131
- method: "GET"
132
- });
133
- }
134
-
135
- export {
136
- countPendingInvites,
137
- createProviderLogger,
138
- fetchBootstrapPayload,
139
- isGuardDenied,
140
- normalizeSearch,
141
- normalizeWorkspaceBootstrapStatus,
142
- normalizeWorkspaceSlugKey,
143
- resolveAuthSignature,
144
- resolveRequestedWorkspaceBootstrapStatus,
145
- resolveRouteState,
146
- resolveSearchFromFullPath
147
- };