@jskit-ai/workspaces-web 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.
- package/package.descriptor.mjs +3 -3
- package/package.json +11 -7
- package/src/client/account-settings/useAccountSettingsInvitesSectionRuntime.js +2 -0
- package/src/client/components/WorkspaceMembersClientElement.vue +16 -0
- package/src/client/components/WorkspaceProfileClientElement.vue +3 -7
- package/src/client/components/WorkspaceSettingsFieldsClientElement.vue +3 -7
- package/src/client/components/WorkspacesClientElement.vue +6 -0
- package/src/client/providers/WorkspacesWebClientProvider.js +19 -2
- package/src/client/runtime/bootstrapPlacementRuntime.js +191 -136
- package/src/client/support/workspaceScopeSupport.js +4 -11
- package/test/bootstrapPlacementRuntime.test.js +340 -440
- package/test/profileSurfaceMenuLinks.test.js +34 -0
- package/test/workspaceScopeSupport.test.js +28 -39
|
@@ -2,7 +2,6 @@ import {
|
|
|
2
2
|
findWorkspaceBySlug,
|
|
3
3
|
normalizeWorkspaceList
|
|
4
4
|
} from "../lib/bootstrap.js";
|
|
5
|
-
import { resolvePlacementUserFromBootstrapPayload } from "@jskit-ai/users-web/client/lib/bootstrap";
|
|
6
5
|
import { normalizePermissionList } from "../lib/permissions.js";
|
|
7
6
|
import {
|
|
8
7
|
persistBootstrapThemePreference,
|
|
@@ -22,25 +21,20 @@ import {
|
|
|
22
21
|
import {
|
|
23
22
|
countPendingInvites,
|
|
24
23
|
createProviderLogger,
|
|
25
|
-
fetchBootstrapPayload,
|
|
26
24
|
normalizeWorkspaceBootstrapStatus,
|
|
27
25
|
normalizeWorkspaceSlugKey,
|
|
28
|
-
resolveAuthSignature,
|
|
29
26
|
resolveRequestedWorkspaceBootstrapStatus,
|
|
30
27
|
resolveRouteState
|
|
31
28
|
} from "./bootstrapPlacementRuntimeHelpers.js";
|
|
32
29
|
import { resolveErrorStatusCode } from "../support/runtimeNormalization.js";
|
|
33
30
|
|
|
34
|
-
function createBootstrapPlacementRuntime({ app, logger = null
|
|
31
|
+
function createBootstrapPlacementRuntime({ app, logger = null } = {}) {
|
|
35
32
|
if (!app || typeof app.has !== "function" || typeof app.make !== "function") {
|
|
36
33
|
throw new Error("createBootstrapPlacementRuntime requires application has()/make().");
|
|
37
34
|
}
|
|
38
35
|
if (!app.has("runtime.web-placement.client")) {
|
|
39
36
|
throw new Error("createBootstrapPlacementRuntime requires shell-web placement runtime.");
|
|
40
37
|
}
|
|
41
|
-
if (typeof fetchBootstrap !== "function") {
|
|
42
|
-
throw new TypeError("createBootstrapPlacementRuntime requires fetchBootstrap(workspaceSlug).");
|
|
43
|
-
}
|
|
44
38
|
|
|
45
39
|
const runtimeLogger = logger || createProviderLogger(app);
|
|
46
40
|
const placementRuntime = app.make("runtime.web-placement.client");
|
|
@@ -50,10 +44,9 @@ function createBootstrapPlacementRuntime({ app, logger = null, fetchBootstrap =
|
|
|
50
44
|
);
|
|
51
45
|
const socket = app.has("runtime.realtime.client.socket") ? app.make("runtime.realtime.client.socket") : null;
|
|
52
46
|
const cleanup = [];
|
|
53
|
-
let refreshQueue = Promise.resolve();
|
|
54
47
|
let shutdownRequested = false;
|
|
55
|
-
let authSignature = resolveAuthSignature(placementRuntime.getContext());
|
|
56
48
|
let lastRouteWorkspaceSlug = resolveRouteState(placementRuntime, router).workspaceSlug;
|
|
49
|
+
let initialized = false;
|
|
57
50
|
const workspaceBootstrapStatusBySlug = new Map();
|
|
58
51
|
const workspaceBootstrapStatusListeners = new Set();
|
|
59
52
|
const root = typeof globalThis === "object" && globalThis ? globalThis : null;
|
|
@@ -69,6 +62,23 @@ function createBootstrapPlacementRuntime({ app, logger = null, fetchBootstrap =
|
|
|
69
62
|
routeGuards.shutdown();
|
|
70
63
|
});
|
|
71
64
|
|
|
65
|
+
function normalizeBootstrapSource(source = "") {
|
|
66
|
+
return String(source || "workspaces-web.bootstrap-placement").trim() || "workspaces-web.bootstrap-placement";
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function shouldApplyWorkspaceColorForContextUpdate(event = {}) {
|
|
70
|
+
if (event?.type !== "context.updated") {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const source = String(event?.source || "").trim().toLowerCase();
|
|
75
|
+
if (!source) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return source.startsWith("workspaces-web.") && !source.startsWith("workspaces-web.bootstrap-placement");
|
|
80
|
+
}
|
|
81
|
+
|
|
72
82
|
function setWorkspaceBootstrapStatus(workspaceSlug = "", status = "", source = "workspaces-web.bootstrap-placement") {
|
|
73
83
|
const workspaceSlugKey = normalizeWorkspaceSlugKey(workspaceSlug);
|
|
74
84
|
const normalizedStatus = normalizeWorkspaceBootstrapStatus(status);
|
|
@@ -94,7 +104,7 @@ function createBootstrapPlacementRuntime({ app, logger = null, fetchBootstrap =
|
|
|
94
104
|
const payload = Object.freeze({
|
|
95
105
|
workspaceSlug: workspaceSlugKey,
|
|
96
106
|
status: normalizedStatus,
|
|
97
|
-
source:
|
|
107
|
+
source: normalizeBootstrapSource(source)
|
|
98
108
|
});
|
|
99
109
|
for (const listener of workspaceBootstrapStatusListeners) {
|
|
100
110
|
try {
|
|
@@ -122,7 +132,7 @@ function createBootstrapPlacementRuntime({ app, logger = null, fetchBootstrap =
|
|
|
122
132
|
};
|
|
123
133
|
}
|
|
124
134
|
|
|
125
|
-
function
|
|
135
|
+
function writeWorkspacePlacementContext(payload = {}, state = {}, source = "workspaces-web.bootstrap-placement") {
|
|
126
136
|
const availableWorkspaces = normalizeWorkspaceList(payload?.workspaces);
|
|
127
137
|
const currentWorkspace = findWorkspaceBySlug(availableWorkspaces, state.workspaceSlug);
|
|
128
138
|
const workspaceSettings =
|
|
@@ -130,7 +140,6 @@ function createBootstrapPlacementRuntime({ app, logger = null, fetchBootstrap =
|
|
|
130
140
|
? payload.workspaceSettings
|
|
131
141
|
: null;
|
|
132
142
|
const permissions = normalizePermissionList(payload?.permissions);
|
|
133
|
-
const user = resolvePlacementUserFromBootstrapPayload(payload, state.context?.user);
|
|
134
143
|
const workspaceInvitesEnabled = payload?.app?.features?.workspaceInvites === true;
|
|
135
144
|
const pendingInvitesCount = workspaceInvitesEnabled ? countPendingInvites(payload?.pendingInvites) : 0;
|
|
136
145
|
|
|
@@ -140,8 +149,6 @@ function createBootstrapPlacementRuntime({ app, logger = null, fetchBootstrap =
|
|
|
140
149
|
workspaceSettings,
|
|
141
150
|
workspaces: availableWorkspaces,
|
|
142
151
|
permissions,
|
|
143
|
-
user,
|
|
144
|
-
surfaceAccess: payload?.surfaceAccess && typeof payload.surfaceAccess === "object" ? payload.surfaceAccess : {},
|
|
145
152
|
pendingInvitesCount,
|
|
146
153
|
workspaceInvitesEnabled
|
|
147
154
|
},
|
|
@@ -150,18 +157,15 @@ function createBootstrapPlacementRuntime({ app, logger = null, fetchBootstrap =
|
|
|
150
157
|
}
|
|
151
158
|
);
|
|
152
159
|
routeGuards.enforceSurfaceAccessForCurrentRoute();
|
|
153
|
-
applyWorkspaceColorFromPlacementContext("write");
|
|
154
160
|
}
|
|
155
161
|
|
|
156
|
-
function
|
|
162
|
+
function clearWorkspacePlacementContext(source = "workspaces-web.bootstrap-placement") {
|
|
157
163
|
placementRuntime.setContext(
|
|
158
164
|
{
|
|
159
165
|
workspace: null,
|
|
160
166
|
workspaceSettings: null,
|
|
161
167
|
workspaces: [],
|
|
162
168
|
permissions: [],
|
|
163
|
-
user: null,
|
|
164
|
-
surfaceAccess: {},
|
|
165
169
|
pendingInvitesCount: 0,
|
|
166
170
|
workspaceInvitesEnabled: false
|
|
167
171
|
},
|
|
@@ -252,148 +256,195 @@ function createBootstrapPlacementRuntime({ app, logger = null, fetchBootstrap =
|
|
|
252
256
|
}
|
|
253
257
|
}
|
|
254
258
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
259
|
+
function applyUnauthenticatedTheme(reason = "manual") {
|
|
260
|
+
applyThemeFromBootstrapPayload(
|
|
261
|
+
{
|
|
262
|
+
session: {
|
|
263
|
+
authenticated: false
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
reason
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function normalizeBootstrapRequestContext(request = {}) {
|
|
271
|
+
const meta = request?.meta && typeof request.meta === "object" ? request.meta : {};
|
|
272
|
+
const query = request?.query && typeof request.query === "object" ? request.query : {};
|
|
273
|
+
return Object.freeze({
|
|
274
|
+
path: String(meta.path || "").trim(),
|
|
275
|
+
workspaceSlug: normalizeWorkspaceSlugKey(meta.workspaceSlug || query.workspaceSlug)
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function isCurrentRequestTarget(request = {}) {
|
|
280
|
+
const requested = normalizeBootstrapRequestContext(request);
|
|
281
|
+
const currentState = resolveRouteState(placementRuntime, router);
|
|
282
|
+
if (requested.path && requested.path !== currentState.path) {
|
|
283
|
+
return false;
|
|
258
284
|
}
|
|
285
|
+
return requested.workspaceSlug === normalizeWorkspaceSlugKey(currentState.workspaceSlug);
|
|
286
|
+
}
|
|
259
287
|
|
|
260
|
-
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
288
|
+
function resolveBootstrapRequest() {
|
|
289
|
+
const state = resolveRouteState(placementRuntime, router);
|
|
290
|
+
const workspaceSlug = normalizeWorkspaceSlugKey(state.workspaceSlug);
|
|
291
|
+
return Object.freeze({
|
|
292
|
+
query: workspaceSlug ? Object.freeze({ workspaceSlug }) : Object.freeze({}),
|
|
293
|
+
meta: Object.freeze({
|
|
294
|
+
path: state.path,
|
|
295
|
+
workspaceSlug
|
|
296
|
+
})
|
|
297
|
+
});
|
|
298
|
+
}
|
|
268
299
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
const sessionAuthenticated = payload?.session?.authenticated === true;
|
|
274
|
-
if (!sessionAuthenticated) {
|
|
275
|
-
setWorkspaceBootstrapStatus(stateAtStart.workspaceSlug, WORKSPACE_BOOTSTRAP_STATUS_UNAUTHENTICATED, source);
|
|
276
|
-
return;
|
|
277
|
-
}
|
|
300
|
+
async function applyBootstrapPayload({ payload = {}, reason = "manual", source = "", request = {} } = {}) {
|
|
301
|
+
if (!isCurrentRequestTarget(request)) {
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
278
304
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
305
|
+
const stateAtApply = resolveRouteState(placementRuntime, router);
|
|
306
|
+
const normalizedSource = normalizeBootstrapSource(source);
|
|
307
|
+
writeWorkspacePlacementContext(payload, stateAtApply, normalizedSource);
|
|
308
|
+
applyThemeFromBootstrapPayload(payload, reason);
|
|
309
|
+
applyWorkspaceColorFromPlacementContext(reason);
|
|
310
|
+
if (!stateAtApply.workspaceSlug) {
|
|
311
|
+
return payload;
|
|
312
|
+
}
|
|
284
313
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
314
|
+
const sessionAuthenticated = payload?.session?.authenticated === true;
|
|
315
|
+
if (!sessionAuthenticated) {
|
|
316
|
+
setWorkspaceBootstrapStatus(stateAtApply.workspaceSlug, WORKSPACE_BOOTSTRAP_STATUS_UNAUTHENTICATED, normalizedSource);
|
|
317
|
+
return payload;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const requestedWorkspaceStatus = resolveRequestedWorkspaceBootstrapStatus(payload, stateAtApply.workspaceSlug);
|
|
321
|
+
if (requestedWorkspaceStatus) {
|
|
322
|
+
setWorkspaceBootstrapStatus(stateAtApply.workspaceSlug, requestedWorkspaceStatus, normalizedSource);
|
|
323
|
+
return payload;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const availableWorkspaces = normalizeWorkspaceList(payload?.workspaces);
|
|
327
|
+
const currentWorkspace = findWorkspaceBySlug(availableWorkspaces, stateAtApply.workspaceSlug);
|
|
328
|
+
setWorkspaceBootstrapStatus(
|
|
329
|
+
stateAtApply.workspaceSlug,
|
|
330
|
+
currentWorkspace ? WORKSPACE_BOOTSTRAP_STATUS_RESOLVED : WORKSPACE_BOOTSTRAP_STATUS_FORBIDDEN,
|
|
331
|
+
normalizedSource
|
|
332
|
+
);
|
|
333
|
+
return payload;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
async function handleBootstrapError({ error, reason = "manual", source = "", request = {} } = {}) {
|
|
337
|
+
if (!isCurrentRequestTarget(request)) {
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
const normalizedSource = normalizeBootstrapSource(source);
|
|
342
|
+
const requested = normalizeBootstrapRequestContext(request);
|
|
343
|
+
const stateAtApply = resolveRouteState(placementRuntime, router);
|
|
344
|
+
const statusCode = resolveErrorStatusCode(error);
|
|
345
|
+
|
|
346
|
+
if (statusCode === 401) {
|
|
347
|
+
if (requested.workspaceSlug) {
|
|
348
|
+
setWorkspaceBootstrapStatus(requested.workspaceSlug, WORKSPACE_BOOTSTRAP_STATUS_UNAUTHENTICATED, normalizedSource);
|
|
313
349
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
350
|
+
clearWorkspacePlacementContext(normalizedSource);
|
|
351
|
+
applyUnauthenticatedTheme(reason);
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
if (statusCode === 403) {
|
|
356
|
+
if (requested.workspaceSlug) {
|
|
357
|
+
setWorkspaceBootstrapStatus(requested.workspaceSlug, WORKSPACE_BOOTSTRAP_STATUS_FORBIDDEN, normalizedSource);
|
|
322
358
|
}
|
|
323
|
-
if (
|
|
324
|
-
|
|
325
|
-
setWorkspaceBootstrapStatus(stateAtStart.workspaceSlug, WORKSPACE_BOOTSTRAP_STATUS_NOT_FOUND, source);
|
|
326
|
-
}
|
|
327
|
-
if (sameWorkspaceRoute) {
|
|
328
|
-
clearPlacementContext(source);
|
|
329
|
-
}
|
|
330
|
-
return;
|
|
359
|
+
if (requested.path === stateAtApply.path) {
|
|
360
|
+
clearWorkspacePlacementContext(normalizedSource);
|
|
331
361
|
}
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
332
364
|
|
|
333
|
-
|
|
334
|
-
|
|
365
|
+
if (statusCode === 404) {
|
|
366
|
+
if (requested.workspaceSlug) {
|
|
367
|
+
setWorkspaceBootstrapStatus(requested.workspaceSlug, WORKSPACE_BOOTSTRAP_STATUS_NOT_FOUND, normalizedSource);
|
|
335
368
|
}
|
|
369
|
+
if (requested.path === stateAtApply.path) {
|
|
370
|
+
clearWorkspacePlacementContext(normalizedSource);
|
|
371
|
+
}
|
|
372
|
+
return null;
|
|
373
|
+
}
|
|
336
374
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
reason,
|
|
340
|
-
error: String(error?.message || error || "unknown error")
|
|
341
|
-
},
|
|
342
|
-
"workspaces-web bootstrap placement refresh failed."
|
|
343
|
-
);
|
|
375
|
+
if (requested.workspaceSlug) {
|
|
376
|
+
setWorkspaceBootstrapStatus(requested.workspaceSlug, WORKSPACE_BOOTSTRAP_STATUS_ERROR, normalizedSource);
|
|
344
377
|
}
|
|
378
|
+
|
|
379
|
+
runtimeLogger.warn(
|
|
380
|
+
{
|
|
381
|
+
reason,
|
|
382
|
+
error: String(error?.message || error || "unknown error")
|
|
383
|
+
},
|
|
384
|
+
"workspaces-web bootstrap placement refresh failed."
|
|
385
|
+
);
|
|
386
|
+
return null;
|
|
345
387
|
}
|
|
346
388
|
|
|
347
|
-
function
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
389
|
+
function resolveBootstrapRuntime() {
|
|
390
|
+
if (!app.has("runtime.web-bootstrap.client")) {
|
|
391
|
+
throw new Error("createBootstrapPlacementRuntime requires shell-web bootstrap runtime.");
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const bootstrapRuntime = app.make("runtime.web-bootstrap.client");
|
|
395
|
+
if (!bootstrapRuntime || typeof bootstrapRuntime.refresh !== "function") {
|
|
396
|
+
throw new Error("createBootstrapPlacementRuntime requires runtime.web-bootstrap.client.refresh().");
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
return bootstrapRuntime;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
function refresh(reason = "manual") {
|
|
403
|
+
if (shutdownRequested) {
|
|
404
|
+
return Promise.resolve(null);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
return resolveBootstrapRuntime().refresh(reason);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
function enforceCurrentWorkspaceStatus() {
|
|
411
|
+
const state = resolveRouteState(placementRuntime, router);
|
|
412
|
+
if (!state.workspaceSlug) {
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
const status = getWorkspaceBootstrapStatus(state.workspaceSlug);
|
|
417
|
+
if (!status) {
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
routeGuards.enforceWorkspaceRouteForStatusUpdate({
|
|
422
|
+
workspaceSlug: state.workspaceSlug,
|
|
423
|
+
status
|
|
424
|
+
});
|
|
360
425
|
}
|
|
361
426
|
|
|
362
427
|
async function initialize() {
|
|
428
|
+
if (initialized) {
|
|
429
|
+
return null;
|
|
430
|
+
}
|
|
431
|
+
initialized = true;
|
|
363
432
|
routeGuards.installWorkspaceGuardEvaluator();
|
|
364
433
|
|
|
365
434
|
const contextAtInit = placementRuntime.getContext();
|
|
366
435
|
if (contextAtInit?.auth?.authenticated !== true) {
|
|
367
|
-
|
|
368
|
-
session: {
|
|
369
|
-
authenticated: false
|
|
370
|
-
}
|
|
371
|
-
}, "init");
|
|
436
|
+
applyUnauthenticatedTheme("init");
|
|
372
437
|
}
|
|
373
438
|
applyWorkspaceColorFromPlacementContext("init");
|
|
439
|
+
routeGuards.enforceSurfaceAccessForCurrentRoute();
|
|
440
|
+
enforceCurrentWorkspaceStatus();
|
|
374
441
|
|
|
375
442
|
if (typeof placementRuntime.subscribe === "function") {
|
|
376
443
|
const unsubscribePlacement = placementRuntime.subscribe((event = {}) => {
|
|
377
|
-
if (event
|
|
444
|
+
if (!shouldApplyWorkspaceColorForContextUpdate(event)) {
|
|
378
445
|
return;
|
|
379
446
|
}
|
|
380
|
-
|
|
381
|
-
const nextContext = placementRuntime.getContext();
|
|
382
447
|
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
448
|
});
|
|
398
449
|
cleanup.push(() => {
|
|
399
450
|
if (typeof unsubscribePlacement === "function") {
|
|
@@ -402,16 +453,17 @@ function createBootstrapPlacementRuntime({ app, logger = null, fetchBootstrap =
|
|
|
402
453
|
});
|
|
403
454
|
}
|
|
404
455
|
|
|
405
|
-
await queueRefresh("init");
|
|
406
|
-
|
|
407
456
|
if (router && typeof router.afterEach === "function") {
|
|
408
457
|
const removeAfterEach = router.afterEach(() => {
|
|
458
|
+
routeGuards.enforceSurfaceAccessForCurrentRoute();
|
|
459
|
+
applyWorkspaceColorFromPlacementContext("route");
|
|
460
|
+
enforceCurrentWorkspaceStatus();
|
|
409
461
|
const nextWorkspaceSlug = resolveRouteState(placementRuntime, router).workspaceSlug;
|
|
410
462
|
if (nextWorkspaceSlug === lastRouteWorkspaceSlug) {
|
|
411
463
|
return;
|
|
412
464
|
}
|
|
413
465
|
lastRouteWorkspaceSlug = nextWorkspaceSlug;
|
|
414
|
-
void
|
|
466
|
+
void refresh("route");
|
|
415
467
|
});
|
|
416
468
|
cleanup.push(() => {
|
|
417
469
|
if (typeof removeAfterEach === "function") {
|
|
@@ -422,7 +474,7 @@ function createBootstrapPlacementRuntime({ app, logger = null, fetchBootstrap =
|
|
|
422
474
|
|
|
423
475
|
if (socket && typeof socket.on === "function") {
|
|
424
476
|
const handleBootstrapChanged = () => {
|
|
425
|
-
void
|
|
477
|
+
void refresh("realtime");
|
|
426
478
|
};
|
|
427
479
|
socket.on("users.bootstrap.changed", handleBootstrapChanged);
|
|
428
480
|
cleanup.push(() => {
|
|
@@ -447,7 +499,10 @@ function createBootstrapPlacementRuntime({ app, logger = null, fetchBootstrap =
|
|
|
447
499
|
return Object.freeze({
|
|
448
500
|
initialize,
|
|
449
501
|
shutdown,
|
|
450
|
-
refresh
|
|
502
|
+
refresh,
|
|
503
|
+
resolveBootstrapRequest,
|
|
504
|
+
applyBootstrapPayload,
|
|
505
|
+
handleBootstrapError,
|
|
451
506
|
getWorkspaceBootstrapStatus,
|
|
452
507
|
subscribeWorkspaceBootstrapStatus
|
|
453
508
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { unref } from "vue";
|
|
1
2
|
import { getClientAppConfig } from "@jskit-ai/kernel/client";
|
|
2
3
|
import { normalizeText } from "@jskit-ai/kernel/shared/support/normalize";
|
|
3
4
|
import {
|
|
@@ -6,18 +7,10 @@ import {
|
|
|
6
7
|
|
|
7
8
|
const WORKSPACES_WEB_SCOPE_SUPPORT_INJECTION_KEY = "jskit.workspaces.web.scope-support";
|
|
8
9
|
|
|
9
|
-
function unwrapRefValue(value) {
|
|
10
|
-
if (value && typeof value === "object" && Object.hasOwn(value, "value")) {
|
|
11
|
-
return value.value;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
return value;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
10
|
function readWorkspaceRouteScope(routeContext = {}) {
|
|
18
|
-
const placementContext =
|
|
19
|
-
const currentSurfaceId = normalizeText(
|
|
20
|
-
const routePath = normalizeText(
|
|
11
|
+
const placementContext = unref(routeContext?.placementContext);
|
|
12
|
+
const currentSurfaceId = normalizeText(unref(routeContext?.currentSurfaceId)).toLowerCase();
|
|
13
|
+
const routePath = normalizeText(unref(routeContext?.routePath));
|
|
21
14
|
const workspaceSlug = extractWorkspaceSlugFromSurfacePathname(
|
|
22
15
|
placementContext,
|
|
23
16
|
currentSurfaceId,
|