@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.
- package/package.descriptor.mjs +14 -96
- package/package.json +16 -11
- package/src/client/account-settings/sections.js +74 -0
- package/src/client/composables/account-settings/accountSettingsRuntimeHelpers.js +2 -38
- package/src/client/composables/crud/crudLookupFieldRuntime.js +2 -2
- package/src/client/composables/internal/crudListParentTitleSupport.js +1 -1
- package/src/client/composables/internal/useOperationScope.js +12 -12
- package/src/client/composables/records/useAddEdit.js +2 -2
- package/src/client/composables/records/useList.js +3 -3
- package/src/client/composables/records/useView.js +2 -2
- package/src/client/composables/support/scopeHelpers.js +19 -19
- package/src/client/composables/useAccess.js +3 -3
- package/src/client/composables/useAccountSettingsRuntime.js +8 -156
- package/src/client/composables/useCommand.js +2 -2
- package/src/client/composables/useCrudListParentTitle.js +2 -2
- package/src/client/composables/usePaths.js +50 -38
- package/src/client/composables/useScopeRuntime.js +55 -27
- package/src/client/composables/useSurfaceRouteContext.js +1 -7
- package/src/client/index.js +0 -1
- package/src/client/lib/bootstrap.js +0 -63
- package/src/client/lib/httpClient.js +2 -59
- package/src/client/lib/theme.js +12 -189
- package/src/client/providers/UsersWebClientProvider.js +2 -25
- package/src/client/providers/bootUsersWebClientProvider.js +28 -0
- package/src/shared/toolsOutletContracts.js +1 -8
- package/templates/src/components/account/settings/AccountSettingsClientElement.vue +33 -21
- package/test/accountSettingsSections.test.js +79 -0
- package/test/exportsContract.test.js +2 -2
- package/test/scopeHelpers.test.js +6 -6
- package/test/settingsPlacementContract.test.js +4 -49
- package/test/theme.test.js +0 -56
- package/src/client/components/ConsoleSettingsClientElement.vue +0 -24
- package/src/client/components/MembersAdminClientElement.vue +0 -400
- package/src/client/components/UsersProfileSurfaceSwitchMenuItem.vue +0 -39
- package/src/client/components/UsersWorkspaceMembersMenuItem.vue +0 -36
- package/src/client/components/UsersWorkspacePermissionMenuItem.vue +0 -90
- package/src/client/components/UsersWorkspaceSelector.vue +0 -248
- package/src/client/components/UsersWorkspaceSettingsMenuItem.vue +0 -39
- package/src/client/components/UsersWorkspaceToolsWidget.vue +0 -12
- package/src/client/components/WorkspaceMembersClientElement.vue +0 -655
- package/src/client/components/WorkspaceProfileClientElement.vue +0 -116
- package/src/client/components/WorkspaceSettingsClientElement.vue +0 -102
- package/src/client/components/WorkspaceSettingsFieldsClientElement.vue +0 -265
- package/src/client/components/WorkspacesClientElement.vue +0 -509
- package/src/client/composables/account-settings/accountSettingsInvitesRuntime.js +0 -88
- package/src/client/composables/useBootstrapQuery.js +0 -52
- package/src/client/composables/useWorkspaceRouteContext.js +0 -28
- package/src/client/composables/useWorkspaceSurfaceId.js +0 -43
- package/src/client/lib/menuIcons.js +0 -210
- package/src/client/lib/profileSurfaceMenuLinks.js +0 -142
- package/src/client/lib/surfaceAccessPolicy.js +0 -350
- package/src/client/lib/workspaceLinkResolver.js +0 -207
- package/src/client/lib/workspaceSurfaceContext.js +0 -82
- package/src/client/lib/workspaceSurfacePaths.js +0 -163
- package/src/client/providers/UsersWorkspacesClientProvider.js +0 -24
- package/src/client/runtime/bootstrapPlacementRouteGuards.js +0 -371
- package/src/client/runtime/bootstrapPlacementRuntime.js +0 -463
- package/src/client/runtime/bootstrapPlacementRuntimeConstants.js +0 -28
- package/src/client/runtime/bootstrapPlacementRuntimeHelpers.js +0 -147
- package/src/client/support/menuLinkTarget.js +0 -93
- package/src/client/support/realtimeWorkspace.js +0 -21
- package/src/client/support/runtimeNormalization.js +0 -27
- package/src/client/support/workspaceQueryKeys.js +0 -15
- package/templates/src/components/account/settings/AccountSettingsInvitesSection.vue +0 -77
- package/templates/src/pages/console/settings/index.vue +0 -8
- package/templates/src/pages/console/settings.vue +0 -32
- package/test/bootstrapPlacementRuntime.test.js +0 -1095
- package/test/menuIcons.test.js +0 -35
- package/test/menuLinkTarget.test.js +0 -116
- package/test/profileSurfaceMenuLinks.test.js +0 -207
- package/test/surfaceAccessPolicy.test.js +0 -129
- package/test/workspaceLinkResolver.test.js +0 -61
- package/test/workspaceSurfacePaths.test.js +0 -39
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
normalizeSurfaceId
|
|
3
|
-
} from "@jskit-ai/kernel/shared/surface";
|
|
4
|
-
import {
|
|
5
|
-
normalizePathname,
|
|
6
|
-
normalizeSurfaceSegmentFromRouteBase,
|
|
7
|
-
parseWorkspacePathname,
|
|
8
|
-
resolveDefaultWorkspaceSurfaceId,
|
|
9
|
-
resolveWorkspaceSurfaceIdFromSuffixSegments
|
|
10
|
-
} from "@jskit-ai/users-core/shared/support/workspacePathModel";
|
|
11
|
-
import {
|
|
12
|
-
readPlacementSurfaceConfig,
|
|
13
|
-
resolveSurfaceDefinitionFromPlacementContext,
|
|
14
|
-
resolveSurfacePathFromPlacementContext,
|
|
15
|
-
resolveSurfaceRootPathFromPlacementContext
|
|
16
|
-
} from "@jskit-ai/shell-web/client/placement";
|
|
17
|
-
import {
|
|
18
|
-
listWorkspaceSurfaceIdsFromSurfaceConfig,
|
|
19
|
-
surfaceRequiresWorkspaceFromPlacementContext
|
|
20
|
-
} from "./workspaceSurfaceContext.js";
|
|
21
|
-
|
|
22
|
-
const ACCOUNT_SURFACE_ID = "account";
|
|
23
|
-
const ACCOUNT_SETTINGS_SUFFIX = "/";
|
|
24
|
-
const ACCOUNT_SETTINGS_FALLBACK_PATH = "/account";
|
|
25
|
-
|
|
26
|
-
function normalizeWorkspaceSuffix(suffix) {
|
|
27
|
-
const rawSuffix = String(suffix || "/").trim();
|
|
28
|
-
if (!rawSuffix || rawSuffix === "/") {
|
|
29
|
-
return "/";
|
|
30
|
-
}
|
|
31
|
-
return rawSuffix.startsWith("/") ? rawSuffix : `/${rawSuffix}`;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function resolveWorkspaceSurfaceIdFromSurfaceConfig(surfaceConfig, pathname = "") {
|
|
35
|
-
const parsedWorkspacePath = parseWorkspacePathname(pathname, {
|
|
36
|
-
workspaceBasePath: "/w"
|
|
37
|
-
});
|
|
38
|
-
if (!parsedWorkspacePath) {
|
|
39
|
-
return "";
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const workspaceSurfaceIds = listWorkspaceSurfaceIdsFromSurfaceConfig(surfaceConfig);
|
|
43
|
-
const defaultWorkspaceSurfaceId = resolveDefaultWorkspaceSurfaceId({
|
|
44
|
-
defaultSurfaceId: surfaceConfig?.defaultSurfaceId,
|
|
45
|
-
workspaceSurfaceIds,
|
|
46
|
-
surfaceRequiresWorkspace: (surfaceId) => Boolean(surfaceConfig?.surfacesById?.[surfaceId]?.requiresWorkspace)
|
|
47
|
-
});
|
|
48
|
-
if (parsedWorkspacePath.suffixSegments.length < 1) {
|
|
49
|
-
return defaultWorkspaceSurfaceId || normalizeSurfaceId(surfaceConfig?.defaultSurfaceId);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const workspaceSurfaces = workspaceSurfaceIds
|
|
53
|
-
.map((surfaceId) => normalizeSurfaceId(surfaceId))
|
|
54
|
-
.map((surfaceId) => {
|
|
55
|
-
if (!surfaceId) {
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
const definition = surfaceConfig.surfacesById?.[surfaceId];
|
|
59
|
-
return {
|
|
60
|
-
id: surfaceId,
|
|
61
|
-
routeBase: definition?.routeBase
|
|
62
|
-
};
|
|
63
|
-
})
|
|
64
|
-
.filter(Boolean);
|
|
65
|
-
|
|
66
|
-
return (
|
|
67
|
-
resolveWorkspaceSurfaceIdFromSuffixSegments({
|
|
68
|
-
suffixSegments: parsedWorkspacePath.suffixSegments,
|
|
69
|
-
defaultWorkspaceSurfaceId,
|
|
70
|
-
workspaceSurfaces
|
|
71
|
-
}) ||
|
|
72
|
-
defaultWorkspaceSurfaceId ||
|
|
73
|
-
normalizeSurfaceId(surfaceConfig?.defaultSurfaceId)
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function resolveWorkspaceSurfaceIdFromPlacementPathname(contextValue = null, pathname = "") {
|
|
78
|
-
const surfaceConfig = readPlacementSurfaceConfig(contextValue);
|
|
79
|
-
const normalizedPathname =
|
|
80
|
-
normalizePathname(pathname) ||
|
|
81
|
-
(typeof window === "object" && window?.location?.pathname ? normalizePathname(window.location.pathname) : "/");
|
|
82
|
-
|
|
83
|
-
return resolveWorkspaceSurfaceIdFromSurfaceConfig(surfaceConfig, normalizedPathname);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function resolveAccountSettingsPathFromPlacementContext(contextValue = null) {
|
|
87
|
-
const accountSurfaceDefinition = resolveSurfaceDefinitionFromPlacementContext(contextValue, ACCOUNT_SURFACE_ID);
|
|
88
|
-
if (!accountSurfaceDefinition) {
|
|
89
|
-
return ACCOUNT_SETTINGS_FALLBACK_PATH;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return resolveSurfacePathFromPlacementContext(contextValue, ACCOUNT_SURFACE_ID, ACCOUNT_SETTINGS_SUFFIX);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function resolveSurfaceWorkspacePathFromPlacementContext(contextValue = null, surfaceId = "", workspaceSlug = "", suffix = "/") {
|
|
96
|
-
const normalizedWorkspaceSlug = String(workspaceSlug || "").trim();
|
|
97
|
-
const normalizedSurfaceId = normalizeSurfaceId(surfaceId);
|
|
98
|
-
if (!normalizedWorkspaceSlug) {
|
|
99
|
-
return "";
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const surfaceConfig = readPlacementSurfaceConfig(contextValue);
|
|
103
|
-
const surfaceDefinition = surfaceConfig.surfacesById[normalizedSurfaceId] || null;
|
|
104
|
-
const normalizedSuffix = normalizeWorkspaceSuffix(suffix);
|
|
105
|
-
|
|
106
|
-
if (surfaceDefinition && !surfaceDefinition.requiresWorkspace) {
|
|
107
|
-
if (normalizedSuffix === "/") {
|
|
108
|
-
return resolveSurfaceRootPathFromPlacementContext(contextValue, normalizedSurfaceId);
|
|
109
|
-
}
|
|
110
|
-
return resolveSurfacePathFromPlacementContext(contextValue, normalizedSurfaceId, normalizedSuffix);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
let workspaceRootPath = `/w/${normalizedWorkspaceSlug}`;
|
|
114
|
-
const workspaceSurfaceIds = listWorkspaceSurfaceIdsFromSurfaceConfig(surfaceConfig);
|
|
115
|
-
const defaultWorkspaceSurfaceId = resolveDefaultWorkspaceSurfaceId({
|
|
116
|
-
defaultSurfaceId: surfaceConfig?.defaultSurfaceId,
|
|
117
|
-
workspaceSurfaceIds,
|
|
118
|
-
surfaceRequiresWorkspace: (candidateSurfaceId) => Boolean(surfaceConfig?.surfacesById?.[candidateSurfaceId]?.requiresWorkspace)
|
|
119
|
-
});
|
|
120
|
-
if (normalizedSurfaceId && normalizedSurfaceId !== defaultWorkspaceSurfaceId) {
|
|
121
|
-
const surfaceSegment = normalizeSurfaceSegmentFromRouteBase(surfaceDefinition?.routeBase) || normalizedSurfaceId;
|
|
122
|
-
if (surfaceSegment) {
|
|
123
|
-
workspaceRootPath = `${workspaceRootPath}/${surfaceSegment}`;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (normalizedSuffix === "/") {
|
|
128
|
-
return normalizePathname(workspaceRootPath);
|
|
129
|
-
}
|
|
130
|
-
return normalizePathname(`${workspaceRootPath}${normalizedSuffix}`);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function extractWorkspaceSlugFromSurfacePathname(contextValue = null, surfaceId = "", pathname = "") {
|
|
134
|
-
const normalizedPathname = normalizePathname(
|
|
135
|
-
pathname || (typeof window === "object" && window?.location?.pathname ? window.location.pathname : "/")
|
|
136
|
-
);
|
|
137
|
-
const normalizedSurfaceId = normalizeSurfaceId(surfaceId);
|
|
138
|
-
if (!normalizedSurfaceId) {
|
|
139
|
-
return "";
|
|
140
|
-
}
|
|
141
|
-
if (!surfaceRequiresWorkspaceFromPlacementContext(contextValue, normalizedSurfaceId)) {
|
|
142
|
-
return "";
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const parsedWorkspacePath = parseWorkspacePathname(normalizedPathname);
|
|
146
|
-
if (!parsedWorkspacePath) {
|
|
147
|
-
return "";
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const resolvedSurfaceId = resolveWorkspaceSurfaceIdFromPlacementPathname(contextValue, normalizedPathname);
|
|
151
|
-
if (resolvedSurfaceId !== normalizedSurfaceId) {
|
|
152
|
-
return "";
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return parsedWorkspacePath.workspaceSlug;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
export {
|
|
159
|
-
resolveAccountSettingsPathFromPlacementContext,
|
|
160
|
-
resolveWorkspaceSurfaceIdFromPlacementPathname,
|
|
161
|
-
resolveSurfaceWorkspacePathFromPlacementContext,
|
|
162
|
-
extractWorkspaceSlugFromSurfacePathname
|
|
163
|
-
};
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import UsersWorkspaceSelector from "../components/UsersWorkspaceSelector.vue";
|
|
2
|
-
import UsersWorkspaceToolsWidget from "../components/UsersWorkspaceToolsWidget.vue";
|
|
3
|
-
import UsersWorkspaceSettingsMenuItem from "../components/UsersWorkspaceSettingsMenuItem.vue";
|
|
4
|
-
import UsersWorkspaceMembersMenuItem from "../components/UsersWorkspaceMembersMenuItem.vue";
|
|
5
|
-
import MembersAdminClientElement from "../components/MembersAdminClientElement.vue";
|
|
6
|
-
|
|
7
|
-
class UsersWorkspacesClientProvider {
|
|
8
|
-
static id = "workspaces.web.client";
|
|
9
|
-
static dependsOn = ["users.web.client"];
|
|
10
|
-
|
|
11
|
-
register(app) {
|
|
12
|
-
if (!app || typeof app.singleton !== "function") {
|
|
13
|
-
throw new Error("UsersWorkspacesClientProvider requires application singleton().");
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
app.singleton("users.web.workspace.selector", () => UsersWorkspaceSelector);
|
|
17
|
-
app.singleton("users.web.workspace.tools.widget", () => UsersWorkspaceToolsWidget);
|
|
18
|
-
app.singleton("users.web.workspace-settings.menu-item", () => UsersWorkspaceSettingsMenuItem);
|
|
19
|
-
app.singleton("users.web.workspace-members.menu-item", () => UsersWorkspaceMembersMenuItem);
|
|
20
|
-
app.singleton("users.web.members-admin.element", () => MembersAdminClientElement);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export { UsersWorkspacesClientProvider };
|
|
@@ -1,371 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
resolveSurfaceDefinitionFromPlacementContext,
|
|
3
|
-
resolveSurfaceIdFromPlacementPathname,
|
|
4
|
-
resolveSurfaceRootPathFromPlacementContext,
|
|
5
|
-
resolveRuntimePathname
|
|
6
|
-
} from "@jskit-ai/shell-web/client/placement";
|
|
7
|
-
import {
|
|
8
|
-
extractWorkspaceSlugFromSurfacePathname,
|
|
9
|
-
resolveSurfaceWorkspacePathFromPlacementContext
|
|
10
|
-
} from "../lib/workspaceSurfacePaths.js";
|
|
11
|
-
import { evaluateSurfaceAccess } from "../lib/surfaceAccessPolicy.js";
|
|
12
|
-
import {
|
|
13
|
-
SHELL_GUARD_EVALUATOR_KEY,
|
|
14
|
-
WORKSPACE_BOOTSTRAP_STATUS_FORBIDDEN,
|
|
15
|
-
WORKSPACE_BOOTSTRAP_STATUS_NOT_FOUND,
|
|
16
|
-
WORKSPACE_FORBIDDEN_GUARD_REASON,
|
|
17
|
-
WORKSPACE_NOT_FOUND_GUARD_REASON
|
|
18
|
-
} from "./bootstrapPlacementRuntimeConstants.js";
|
|
19
|
-
import {
|
|
20
|
-
isGuardDenied,
|
|
21
|
-
normalizeSearch,
|
|
22
|
-
normalizeWorkspaceBootstrapStatus,
|
|
23
|
-
normalizeWorkspaceSlugKey,
|
|
24
|
-
resolveSearchFromFullPath
|
|
25
|
-
} from "./bootstrapPlacementRuntimeHelpers.js";
|
|
26
|
-
|
|
27
|
-
function createBootstrapPlacementRouteGuards({
|
|
28
|
-
placementRuntime,
|
|
29
|
-
router = null,
|
|
30
|
-
root = null,
|
|
31
|
-
getWorkspaceBootstrapStatus = () => ""
|
|
32
|
-
} = {}) {
|
|
33
|
-
const cleanup = [];
|
|
34
|
-
let delegatedGuardEvaluator = null;
|
|
35
|
-
let workspaceGuardEvaluatorInstalled = false;
|
|
36
|
-
|
|
37
|
-
function resolveNormalizedSurfaceState(pathname = "/", search = "") {
|
|
38
|
-
const context = placementRuntime.getContext();
|
|
39
|
-
const normalizedPathname = resolveRuntimePathname(pathname);
|
|
40
|
-
const normalizedSearch = normalizeSearch(search);
|
|
41
|
-
const surfaceId = String(resolveSurfaceIdFromPlacementPathname(context, normalizedPathname) || "")
|
|
42
|
-
.trim()
|
|
43
|
-
.toLowerCase();
|
|
44
|
-
if (!surfaceId) {
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const surfaceDefinition = resolveSurfaceDefinitionFromPlacementContext(context, surfaceId);
|
|
49
|
-
if (!surfaceDefinition) {
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return Object.freeze({
|
|
54
|
-
context,
|
|
55
|
-
normalizedPathname,
|
|
56
|
-
normalizedSearch,
|
|
57
|
-
surfaceId,
|
|
58
|
-
surfaceDefinition
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function resolveWorkspaceRouteState(pathname = "/", search = "") {
|
|
63
|
-
const surfaceState = resolveNormalizedSurfaceState(pathname, search);
|
|
64
|
-
if (!surfaceState || surfaceState.surfaceDefinition.requiresWorkspace !== true) {
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const workspaceSlug = normalizeWorkspaceSlugKey(
|
|
69
|
-
extractWorkspaceSlugFromSurfacePathname(surfaceState.context, surfaceState.surfaceId, surfaceState.normalizedPathname)
|
|
70
|
-
);
|
|
71
|
-
if (!workspaceSlug) {
|
|
72
|
-
return null;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return Object.freeze({
|
|
76
|
-
pathname: surfaceState.normalizedPathname,
|
|
77
|
-
search: surfaceState.normalizedSearch,
|
|
78
|
-
surfaceId: surfaceState.surfaceId,
|
|
79
|
-
workspaceSlug,
|
|
80
|
-
workspaceRootPath: resolveRuntimePathname(
|
|
81
|
-
resolveSurfaceWorkspacePathFromPlacementContext(surfaceState.context, surfaceState.surfaceId, workspaceSlug, "/")
|
|
82
|
-
),
|
|
83
|
-
workspaceBootstrapStatus: String(getWorkspaceBootstrapStatus(workspaceSlug) || "")
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function resolveSurfaceRouteState(pathname = "/", search = "") {
|
|
88
|
-
const surfaceState = resolveNormalizedSurfaceState(pathname, search);
|
|
89
|
-
if (!surfaceState || surfaceState.surfaceDefinition.enabled === false) {
|
|
90
|
-
return null;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const workspaceSlug =
|
|
94
|
-
surfaceState.surfaceDefinition.requiresWorkspace === true
|
|
95
|
-
? normalizeWorkspaceSlugKey(
|
|
96
|
-
extractWorkspaceSlugFromSurfacePathname(
|
|
97
|
-
surfaceState.context,
|
|
98
|
-
surfaceState.surfaceId,
|
|
99
|
-
surfaceState.normalizedPathname
|
|
100
|
-
)
|
|
101
|
-
)
|
|
102
|
-
: "";
|
|
103
|
-
return Object.freeze({
|
|
104
|
-
pathname: surfaceState.normalizedPathname,
|
|
105
|
-
search: surfaceState.normalizedSearch,
|
|
106
|
-
surfaceId: surfaceState.surfaceId,
|
|
107
|
-
workspaceSlug,
|
|
108
|
-
workspaceBootstrapStatus: workspaceSlug ? String(getWorkspaceBootstrapStatus(workspaceSlug) || "") : ""
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function resolveDefaultSurfaceFallbackPath(surfaceState = null) {
|
|
113
|
-
const context = placementRuntime.getContext();
|
|
114
|
-
const defaultSurfaceId = String(context?.surfaceConfig?.defaultSurfaceId || "")
|
|
115
|
-
.trim()
|
|
116
|
-
.toLowerCase();
|
|
117
|
-
const fallbackSurfaceId = defaultSurfaceId || surfaceState?.surfaceId || "";
|
|
118
|
-
if (!fallbackSurfaceId) {
|
|
119
|
-
return "/";
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const fallbackSurfaceDefinition = resolveSurfaceDefinitionFromPlacementContext(context, fallbackSurfaceId);
|
|
123
|
-
if (fallbackSurfaceDefinition?.requiresWorkspace === true) {
|
|
124
|
-
const fallbackWorkspaceSlug =
|
|
125
|
-
normalizeWorkspaceSlugKey(surfaceState?.workspaceSlug) || normalizeWorkspaceSlugKey(context?.workspace?.slug);
|
|
126
|
-
if (!fallbackWorkspaceSlug) {
|
|
127
|
-
return "/";
|
|
128
|
-
}
|
|
129
|
-
return resolveRuntimePathname(
|
|
130
|
-
resolveSurfaceWorkspacePathFromPlacementContext(context, fallbackSurfaceId, fallbackWorkspaceSlug, "/")
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const fallbackPath = resolveRuntimePathname(resolveSurfaceRootPathFromPlacementContext(context, fallbackSurfaceId));
|
|
135
|
-
if (fallbackPath.includes(":")) {
|
|
136
|
-
return "/";
|
|
137
|
-
}
|
|
138
|
-
return fallbackPath || "/";
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function resolveWorkspaceGuardDecision(pathname = "/", search = "") {
|
|
142
|
-
const workspaceState = resolveWorkspaceRouteState(pathname, search);
|
|
143
|
-
if (!workspaceState) {
|
|
144
|
-
return null;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if (workspaceState.workspaceBootstrapStatus === WORKSPACE_BOOTSTRAP_STATUS_NOT_FOUND) {
|
|
148
|
-
if (workspaceState.workspaceRootPath && workspaceState.workspaceRootPath !== workspaceState.pathname) {
|
|
149
|
-
return {
|
|
150
|
-
allow: false,
|
|
151
|
-
redirectTo: workspaceState.workspaceRootPath,
|
|
152
|
-
reason: WORKSPACE_NOT_FOUND_GUARD_REASON
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
return null;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (workspaceState.workspaceBootstrapStatus === WORKSPACE_BOOTSTRAP_STATUS_FORBIDDEN) {
|
|
159
|
-
if (workspaceState.workspaceRootPath && workspaceState.workspaceRootPath !== workspaceState.pathname) {
|
|
160
|
-
return {
|
|
161
|
-
allow: false,
|
|
162
|
-
redirectTo: workspaceState.workspaceRootPath,
|
|
163
|
-
reason: WORKSPACE_FORBIDDEN_GUARD_REASON
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
return null;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
return null;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
function resolveSurfaceAccessGuardDecision(pathname = "/", search = "", { allowOnUnknown = true } = {}) {
|
|
173
|
-
const surfaceState = resolveSurfaceRouteState(pathname, search);
|
|
174
|
-
if (!surfaceState) {
|
|
175
|
-
return null;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if (
|
|
179
|
-
surfaceState.workspaceBootstrapStatus === WORKSPACE_BOOTSTRAP_STATUS_NOT_FOUND ||
|
|
180
|
-
surfaceState.workspaceBootstrapStatus === WORKSPACE_BOOTSTRAP_STATUS_FORBIDDEN
|
|
181
|
-
) {
|
|
182
|
-
return null;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const accessDecision = evaluateSurfaceAccess({
|
|
186
|
-
context: placementRuntime.getContext(),
|
|
187
|
-
surfaceId: surfaceState.surfaceId,
|
|
188
|
-
workspaceSlug: surfaceState.workspaceSlug,
|
|
189
|
-
allowOnUnknown
|
|
190
|
-
});
|
|
191
|
-
if (accessDecision.allowed || accessDecision.pending) {
|
|
192
|
-
return null;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
const redirectTarget = resolveDefaultSurfaceFallbackPath(surfaceState);
|
|
196
|
-
const redirectTo = redirectTarget && redirectTarget !== surfaceState.pathname ? redirectTarget : "";
|
|
197
|
-
|
|
198
|
-
return {
|
|
199
|
-
allow: false,
|
|
200
|
-
redirectTo,
|
|
201
|
-
reason: accessDecision.reason || "surface-access-denied"
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
async function replaceRouteIfNeeded(targetPath = "") {
|
|
206
|
-
if (!router || typeof router.replace !== "function") {
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
const normalizedTargetPath = String(targetPath || "").trim();
|
|
211
|
-
if (!normalizedTargetPath) {
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
const currentRoute = router.currentRoute?.value || {};
|
|
216
|
-
const currentFullPath = String(currentRoute.fullPath || "").trim();
|
|
217
|
-
const currentPath = resolveRuntimePathname(currentRoute.path || "/");
|
|
218
|
-
const currentComparablePath = currentFullPath || currentPath;
|
|
219
|
-
if (currentComparablePath === normalizedTargetPath) {
|
|
220
|
-
return;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
try {
|
|
224
|
-
await router.replace(normalizedTargetPath);
|
|
225
|
-
} catch {}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
function enforceWorkspaceRouteForStatusUpdate({ workspaceSlug = "", status = "" } = {}) {
|
|
229
|
-
const normalizedWorkspaceSlug = normalizeWorkspaceSlugKey(workspaceSlug);
|
|
230
|
-
const normalizedStatus = normalizeWorkspaceBootstrapStatus(status);
|
|
231
|
-
if (!normalizedWorkspaceSlug || !normalizedStatus || !router) {
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
const currentRoute = router.currentRoute?.value || {};
|
|
236
|
-
const currentPath = resolveRuntimePathname(currentRoute.path || "/");
|
|
237
|
-
const currentSearch = resolveSearchFromFullPath(currentRoute.fullPath || "");
|
|
238
|
-
const workspaceState = resolveWorkspaceRouteState(currentPath, currentSearch);
|
|
239
|
-
if (!workspaceState || workspaceState.workspaceSlug !== normalizedWorkspaceSlug) {
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
if (normalizedStatus === WORKSPACE_BOOTSTRAP_STATUS_NOT_FOUND) {
|
|
244
|
-
if (workspaceState.workspaceRootPath && workspaceState.workspaceRootPath !== workspaceState.pathname) {
|
|
245
|
-
void replaceRouteIfNeeded(workspaceState.workspaceRootPath);
|
|
246
|
-
}
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
if (normalizedStatus === WORKSPACE_BOOTSTRAP_STATUS_FORBIDDEN) {
|
|
251
|
-
if (workspaceState.workspaceRootPath && workspaceState.workspaceRootPath !== workspaceState.pathname) {
|
|
252
|
-
void replaceRouteIfNeeded(workspaceState.workspaceRootPath);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
function enforceSurfaceAccessForCurrentRoute() {
|
|
258
|
-
if (!router) {
|
|
259
|
-
return;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
const currentRoute = router.currentRoute?.value || {};
|
|
263
|
-
const currentPath = resolveRuntimePathname(currentRoute.path || "/");
|
|
264
|
-
const currentSearch = resolveSearchFromFullPath(currentRoute.fullPath || "");
|
|
265
|
-
const surfaceDecision = resolveSurfaceAccessGuardDecision(currentPath, currentSearch, {
|
|
266
|
-
allowOnUnknown: false
|
|
267
|
-
});
|
|
268
|
-
if (!surfaceDecision || !surfaceDecision.redirectTo) {
|
|
269
|
-
return;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
void replaceRouteIfNeeded(surfaceDecision.redirectTo);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
function installWorkspaceGuardEvaluator() {
|
|
276
|
-
if (!root || workspaceGuardEvaluatorInstalled) {
|
|
277
|
-
return;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
if (typeof delegatedGuardEvaluator !== "function") {
|
|
281
|
-
const currentEvaluator = root[SHELL_GUARD_EVALUATOR_KEY];
|
|
282
|
-
delegatedGuardEvaluator = typeof currentEvaluator === "function" ? currentEvaluator : null;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
const previousDescriptor = Object.getOwnPropertyDescriptor(root, SHELL_GUARD_EVALUATOR_KEY);
|
|
286
|
-
const previousOwnProperty = previousDescriptor || null;
|
|
287
|
-
let released = false;
|
|
288
|
-
|
|
289
|
-
const workspaceGuardEvaluator = ({ guard, phase, context } = {}) => {
|
|
290
|
-
const baseOutcome =
|
|
291
|
-
typeof delegatedGuardEvaluator === "function"
|
|
292
|
-
? delegatedGuardEvaluator({
|
|
293
|
-
guard,
|
|
294
|
-
phase,
|
|
295
|
-
context
|
|
296
|
-
})
|
|
297
|
-
: true;
|
|
298
|
-
if (isGuardDenied(baseOutcome)) {
|
|
299
|
-
return baseOutcome;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
const pathname = resolveRuntimePathname(context?.location?.pathname || context?.to?.path || "/");
|
|
303
|
-
const search = normalizeSearch(context?.location?.search || resolveSearchFromFullPath(context?.to?.fullPath || ""));
|
|
304
|
-
const workspaceDecision = resolveWorkspaceGuardDecision(pathname, search);
|
|
305
|
-
if (workspaceDecision) {
|
|
306
|
-
return workspaceDecision;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
const surfaceDecision = resolveSurfaceAccessGuardDecision(pathname, search, {
|
|
310
|
-
allowOnUnknown: true
|
|
311
|
-
});
|
|
312
|
-
if (surfaceDecision) {
|
|
313
|
-
return surfaceDecision;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
return baseOutcome;
|
|
317
|
-
};
|
|
318
|
-
|
|
319
|
-
Object.defineProperty(root, SHELL_GUARD_EVALUATOR_KEY, {
|
|
320
|
-
configurable: true,
|
|
321
|
-
enumerable: true,
|
|
322
|
-
get() {
|
|
323
|
-
return workspaceGuardEvaluator;
|
|
324
|
-
},
|
|
325
|
-
set(nextEvaluator) {
|
|
326
|
-
if (nextEvaluator === workspaceGuardEvaluator) {
|
|
327
|
-
return;
|
|
328
|
-
}
|
|
329
|
-
delegatedGuardEvaluator = typeof nextEvaluator === "function" ? nextEvaluator : null;
|
|
330
|
-
}
|
|
331
|
-
});
|
|
332
|
-
workspaceGuardEvaluatorInstalled = true;
|
|
333
|
-
|
|
334
|
-
cleanup.push(() => {
|
|
335
|
-
if (released || !root) {
|
|
336
|
-
return;
|
|
337
|
-
}
|
|
338
|
-
released = true;
|
|
339
|
-
|
|
340
|
-
try {
|
|
341
|
-
if (previousOwnProperty) {
|
|
342
|
-
Object.defineProperty(root, SHELL_GUARD_EVALUATOR_KEY, previousOwnProperty);
|
|
343
|
-
} else {
|
|
344
|
-
delete root[SHELL_GUARD_EVALUATOR_KEY];
|
|
345
|
-
}
|
|
346
|
-
} catch {}
|
|
347
|
-
delegatedGuardEvaluator = null;
|
|
348
|
-
workspaceGuardEvaluatorInstalled = false;
|
|
349
|
-
});
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
function shutdown() {
|
|
353
|
-
for (const release of cleanup.splice(0, cleanup.length)) {
|
|
354
|
-
if (typeof release !== "function") {
|
|
355
|
-
continue;
|
|
356
|
-
}
|
|
357
|
-
try {
|
|
358
|
-
release();
|
|
359
|
-
} catch {}
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
return Object.freeze({
|
|
364
|
-
enforceSurfaceAccessForCurrentRoute,
|
|
365
|
-
enforceWorkspaceRouteForStatusUpdate,
|
|
366
|
-
installWorkspaceGuardEvaluator,
|
|
367
|
-
shutdown
|
|
368
|
-
});
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
export { createBootstrapPlacementRouteGuards };
|