@jskit-ai/users-web 0.1.53 → 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 (70) hide show
  1. package/package.descriptor.mjs +15 -53
  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 -11
  31. package/test/theme.test.js +0 -56
  32. package/src/client/components/MembersAdminClientElement.vue +0 -400
  33. package/src/client/components/UsersProfileSurfaceSwitchMenuItem.vue +0 -39
  34. package/src/client/components/UsersWorkspaceMembersMenuItem.vue +0 -36
  35. package/src/client/components/UsersWorkspacePermissionMenuItem.vue +0 -90
  36. package/src/client/components/UsersWorkspaceSelector.vue +0 -248
  37. package/src/client/components/UsersWorkspaceSettingsMenuItem.vue +0 -39
  38. package/src/client/components/UsersWorkspaceToolsWidget.vue +0 -12
  39. package/src/client/components/WorkspaceMembersClientElement.vue +0 -655
  40. package/src/client/components/WorkspaceProfileClientElement.vue +0 -116
  41. package/src/client/components/WorkspaceSettingsClientElement.vue +0 -102
  42. package/src/client/components/WorkspaceSettingsFieldsClientElement.vue +0 -265
  43. package/src/client/components/WorkspacesClientElement.vue +0 -509
  44. package/src/client/composables/account-settings/accountSettingsInvitesRuntime.js +0 -88
  45. package/src/client/composables/useBootstrapQuery.js +0 -52
  46. package/src/client/composables/useWorkspaceRouteContext.js +0 -28
  47. package/src/client/composables/useWorkspaceSurfaceId.js +0 -43
  48. package/src/client/lib/menuIcons.js +0 -201
  49. package/src/client/lib/profileSurfaceMenuLinks.js +0 -142
  50. package/src/client/lib/surfaceAccessPolicy.js +0 -350
  51. package/src/client/lib/workspaceLinkResolver.js +0 -207
  52. package/src/client/lib/workspaceSurfaceContext.js +0 -82
  53. package/src/client/lib/workspaceSurfacePaths.js +0 -163
  54. package/src/client/providers/UsersWorkspacesClientProvider.js +0 -24
  55. package/src/client/runtime/bootstrapPlacementRouteGuards.js +0 -371
  56. package/src/client/runtime/bootstrapPlacementRuntime.js +0 -463
  57. package/src/client/runtime/bootstrapPlacementRuntimeConstants.js +0 -28
  58. package/src/client/runtime/bootstrapPlacementRuntimeHelpers.js +0 -147
  59. package/src/client/support/menuLinkTarget.js +0 -93
  60. package/src/client/support/realtimeWorkspace.js +0 -21
  61. package/src/client/support/runtimeNormalization.js +0 -27
  62. package/src/client/support/workspaceQueryKeys.js +0 -15
  63. package/templates/src/components/account/settings/AccountSettingsInvitesSection.vue +0 -77
  64. package/test/bootstrapPlacementRuntime.test.js +0 -1095
  65. package/test/menuIcons.test.js +0 -34
  66. package/test/menuLinkTarget.test.js +0 -116
  67. package/test/profileSurfaceMenuLinks.test.js +0 -208
  68. package/test/surfaceAccessPolicy.test.js +0 -129
  69. package/test/workspaceLinkResolver.test.js +0 -61
  70. package/test/workspaceSurfacePaths.test.js +0 -39
@@ -1,12 +1,9 @@
1
- import {
2
- HOME_TOOLS_OUTLET,
3
- WORKSPACE_TOOLS_OUTLET
4
- } from "./src/shared/toolsOutletContracts.js";
1
+ import { HOME_TOOLS_OUTLET } from "./src/shared/toolsOutletContracts.js";
5
2
 
6
3
  export default Object.freeze({
7
4
  packageVersion: 1,
8
5
  packageId: "@jskit-ai/users-web",
9
- version: "0.1.53",
6
+ version: "0.1.54",
10
7
  kind: "runtime",
11
8
  description: "Users web module: account/profile UI plus shared users web widgets.",
12
9
  dependsOn: [
@@ -79,24 +76,22 @@ export default Object.freeze({
79
76
  },
80
77
  {
81
78
  subpath: "./client/composables/usePaths",
82
- summary: "Exports surface/workspace path resolver composable."
79
+ summary: "Exports surface route path resolver composable."
83
80
  },
84
81
  {
85
82
  subpath: "./client/composables/useAccountSettingsRuntime",
86
83
  summary: "Exports account settings runtime composable for app-owned settings UI."
87
84
  },
88
85
  {
89
- subpath: "./client/composables/useWorkspaceRouteContext",
90
- summary: "Exports workspace route context composable."
91
- },
86
+ subpath: "./client/account-settings/sections",
87
+ summary: "Exports account settings section extension seam helpers."
88
+ }
92
89
  ],
93
90
  containerTokens: {
94
91
  server: [],
95
92
  client: [
96
- "users.web.profile.menu.surface-switch-item",
97
93
  "users.web.home.tools.widget",
98
- "users.web.profile.element",
99
- "users.web.bootstrap-placement.runtime"
94
+ "users.web.profile.element"
100
95
  ]
101
96
  }
102
97
  },
@@ -108,24 +103,9 @@ export default Object.freeze({
108
103
  defaultLinkComponentToken: HOME_TOOLS_OUTLET.defaultLinkComponentToken,
109
104
  surfaces: ["home"],
110
105
  source: "src/client/components/UsersHomeToolsWidget.vue"
111
- },
112
- {
113
- target: WORKSPACE_TOOLS_OUTLET.target,
114
- defaultLinkComponentToken: WORKSPACE_TOOLS_OUTLET.defaultLinkComponentToken,
115
- surfaces: ["admin"],
116
- source: "src/client/components/UsersWorkspaceToolsWidget.vue"
117
- },
106
+ }
118
107
  ],
119
108
  contributions: [
120
- {
121
- id: "users.profile.menu.surface-switch",
122
- target: "auth-profile-menu:primary-menu",
123
- surfaces: ["*"],
124
- order: 100,
125
- componentToken: "users.web.profile.menu.surface-switch-item",
126
- when: "auth.authenticated === true",
127
- source: "mutations.text#users-web-profile-surface-switch-placement"
128
- },
129
109
  {
130
110
  id: "users.profile.menu.settings",
131
111
  target: "auth-profile-menu:primary-menu",
@@ -162,12 +142,12 @@ export default Object.freeze({
162
142
  runtime: {
163
143
  "@tanstack/vue-query": "5.92.12",
164
144
  "@mdi/js": "^7.4.47",
165
- "@jskit-ai/http-runtime": "0.1.37",
166
- "@jskit-ai/realtime": "0.1.37",
167
- "@jskit-ai/kernel": "0.1.38",
168
- "@jskit-ai/shell-web": "0.1.37",
169
- "@jskit-ai/uploads-image-web": "0.1.16",
170
- "@jskit-ai/users-core": "0.1.48",
145
+ "@jskit-ai/http-runtime": "0.1.38",
146
+ "@jskit-ai/realtime": "0.1.38",
147
+ "@jskit-ai/kernel": "0.1.39",
148
+ "@jskit-ai/shell-web": "0.1.38",
149
+ "@jskit-ai/uploads-image-web": "0.1.17",
150
+ "@jskit-ai/users-core": "0.1.49",
171
151
  vuetify: "^4.0.0"
172
152
  },
173
153
  dev: {}
@@ -215,13 +195,6 @@ export default Object.freeze({
215
195
  reason: "Install app-owned account settings notifications section scaffold.",
216
196
  category: "users-web",
217
197
  id: "users-web-component-account-settings-notifications"
218
- },
219
- {
220
- from: "templates/src/components/account/settings/AccountSettingsInvitesSection.vue",
221
- to: "src/components/account/settings/AccountSettingsInvitesSection.vue",
222
- reason: "Install app-owned account settings invites section scaffold.",
223
- category: "users-web",
224
- id: "users-web-component-account-settings-invites"
225
198
  }
226
199
  ],
227
200
  text: [
@@ -236,17 +209,6 @@ export default Object.freeze({
236
209
  category: "users-web",
237
210
  id: "users-web-surface-config-account"
238
211
  },
239
- {
240
- op: "append-text",
241
- file: "src/placement.js",
242
- position: "bottom",
243
- skipIfContains: "id: \"users.profile.menu.surface-switch\"",
244
- value:
245
- "\naddPlacement({\n id: \"users.profile.menu.surface-switch\",\n target: \"auth-profile-menu:primary-menu\",\n surfaces: [\"*\"],\n order: 100,\n componentToken: \"users.web.profile.menu.surface-switch-item\",\n when: ({ auth }) => Boolean(auth?.authenticated)\n});\n",
246
- reason: "Append users-web profile surface switch placement into app-owned placement registry.",
247
- category: "users-web",
248
- id: "users-web-profile-surface-switch-placement"
249
- },
250
212
  {
251
213
  op: "append-text",
252
214
  file: "src/placement.js",
@@ -264,7 +226,7 @@ export default Object.freeze({
264
226
  position: "bottom",
265
227
  skipIfContains: "id: \"users.home.tools.widget\"",
266
228
  value:
267
- "\naddPlacement({\n id: \"users.home.tools.widget\",\n target: \"shell-layout:top-right\",\n surfaces: [\"home\"],\n order: 900,\n componentToken: \"users.web.home.tools.widget\",\n when: ({ auth }) => Boolean(auth?.authenticated)\n});\n\naddPlacement({\n id: \"users.home.menu.settings\",\n target: \"home-tools:primary-menu\",\n surfaces: [\"home\"],\n order: 100,\n componentToken: \"local.main.ui.surface-aware-menu-link-item\",\n props: {\n label: \"Settings\",\n surface: \"home\",\n workspaceSuffix: \"/settings\",\n nonWorkspaceSuffix: \"/settings\"\n },\n when: ({ auth }) => Boolean(auth?.authenticated)\n});\n",
229
+ "\naddPlacement({\n id: \"users.home.tools.widget\",\n target: \"shell-layout:top-right\",\n surfaces: [\"home\"],\n order: 900,\n componentToken: \"users.web.home.tools.widget\",\n when: ({ auth }) => Boolean(auth?.authenticated)\n});\n\naddPlacement({\n id: \"users.home.menu.settings\",\n target: \"home-tools:primary-menu\",\n surfaces: [\"home\"],\n order: 100,\n componentToken: \"local.main.ui.surface-aware-menu-link-item\",\n props: {\n label: \"Settings\",\n surface: \"home\",\n scopedSuffix: \"/settings\",\n unscopedSuffix: \"/settings\"\n },\n when: ({ auth }) => Boolean(auth?.authenticated)\n});\n",
268
230
  reason: "Append users-web home tools widget and settings menu placements into app-owned placement registry.",
269
231
  category: "users-web",
270
232
  id: "users-web-home-tools-placement"
package/package.json CHANGED
@@ -1,37 +1,42 @@
1
1
  {
2
2
  "name": "@jskit-ai/users-web",
3
- "version": "0.1.53",
3
+ "version": "0.1.54",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "test": "node --test"
7
7
  },
8
8
  "exports": {
9
9
  "./client": "./src/client/index.js",
10
- "./client/providers/UsersWorkspacesClientProvider": "./src/client/providers/UsersWorkspacesClientProvider.js",
11
- "./client/components/WorkspaceMembersClientElement": "./src/client/components/WorkspaceMembersClientElement.vue",
10
+ "./client/account-settings/sections": "./src/client/account-settings/sections.js",
12
11
  "./client/composables/useAddEdit": "./src/client/composables/records/useAddEdit.js",
12
+ "./client/composables/useAccess": "./src/client/composables/useAccess.js",
13
+ "./client/composables/useCommand": "./src/client/composables/useCommand.js",
13
14
  "./client/composables/useCrudAddEdit": "./src/client/composables/records/useCrudAddEdit.js",
14
15
  "./client/composables/crudLookupFieldRuntime": "./src/client/composables/crud/crudLookupFieldRuntime.js",
15
16
  "./client/composables/useList": "./src/client/composables/records/useList.js",
16
17
  "./client/composables/useCrudList": "./src/client/composables/records/useCrudList.js",
17
18
  "./client/composables/useCrudListParentTitle": "./src/client/composables/useCrudListParentTitle.js",
19
+ "./client/composables/useRealtimeQueryInvalidation": "./src/client/composables/useRealtimeQueryInvalidation.js",
20
+ "./client/composables/useSurfaceRouteContext": "./src/client/composables/useSurfaceRouteContext.js",
18
21
  "./client/composables/useView": "./src/client/composables/records/useView.js",
19
22
  "./client/composables/useCrudView": "./src/client/composables/records/useCrudView.js",
20
23
  "./client/composables/usePagedCollection": "./src/client/composables/usePagedCollection.js",
21
24
  "./client/composables/useAccountSettingsRuntime": "./src/client/composables/useAccountSettingsRuntime.js",
22
25
  "./client/composables/usePaths": "./src/client/composables/usePaths.js",
23
- "./client/composables/useWorkspaceRouteContext": "./src/client/composables/useWorkspaceRouteContext.js",
24
- "./client/support/menuLinkTarget": "./src/client/support/menuLinkTarget.js"
26
+ "./client/composables/runtime/useUiFeedback": "./src/client/composables/runtime/useUiFeedback.js",
27
+ "./client/lib/bootstrap": "./src/client/lib/bootstrap.js",
28
+ "./client/lib/permissions": "./src/client/lib/permissions.js",
29
+ "./client/support/contractGuards": "./src/client/support/contractGuards.js"
25
30
  },
26
31
  "dependencies": {
27
32
  "@tanstack/vue-query": "5.92.12",
28
33
  "@mdi/js": "^7.4.47",
29
- "@jskit-ai/http-runtime": "0.1.37",
30
- "@jskit-ai/kernel": "0.1.38",
31
- "@jskit-ai/realtime": "0.1.37",
32
- "@jskit-ai/shell-web": "0.1.37",
33
- "@jskit-ai/uploads-image-web": "0.1.16",
34
- "@jskit-ai/users-core": "0.1.48",
34
+ "@jskit-ai/http-runtime": "0.1.38",
35
+ "@jskit-ai/kernel": "0.1.39",
36
+ "@jskit-ai/realtime": "0.1.38",
37
+ "@jskit-ai/shell-web": "0.1.38",
38
+ "@jskit-ai/uploads-image-web": "0.1.17",
39
+ "@jskit-ai/users-core": "0.1.49",
35
40
  "vuetify": "^4.0.0"
36
41
  }
37
42
  }
@@ -0,0 +1,74 @@
1
+ import { inject } from "vue";
2
+
3
+ const ACCOUNT_SETTINGS_SECTIONS_INJECTION_KEY = Symbol("users-web.account-settings.sections");
4
+ const ACCOUNT_SETTINGS_SECTION_REGISTRY_TAG = "users.web.account-settings.sections";
5
+ const EMPTY_ACCOUNT_SETTINGS_SECTIONS = Object.freeze([]);
6
+ const RESERVED_ACCOUNT_SETTINGS_SECTION_VALUES = Object.freeze([
7
+ "profile",
8
+ "preferences",
9
+ "notifications"
10
+ ]);
11
+
12
+ function normalizeAccountSettingsSectionEntry(entry = null) {
13
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
14
+ return null;
15
+ }
16
+
17
+ const value = String(entry.value || "").trim().toLowerCase();
18
+ const title = String(entry.title || "").trim();
19
+ const component = entry.component;
20
+ if (!value || !title || !component) {
21
+ return null;
22
+ }
23
+
24
+ return Object.freeze({
25
+ value,
26
+ title,
27
+ component,
28
+ order: Number.isFinite(Number(entry.order)) ? Number(entry.order) : 500,
29
+ usesSharedRuntime: entry.usesSharedRuntime === true
30
+ });
31
+ }
32
+
33
+ function sortAccountSettingsSections(entries = []) {
34
+ return Object.freeze(
35
+ [...entries].sort((left, right) => {
36
+ const orderDelta = left.order - right.order;
37
+ if (orderDelta !== 0) {
38
+ return orderDelta;
39
+ }
40
+ return left.value.localeCompare(right.value);
41
+ })
42
+ );
43
+ }
44
+
45
+ function resolveAccountSettingsSections(entries = []) {
46
+ const seen = new Set(RESERVED_ACCOUNT_SETTINGS_SECTION_VALUES);
47
+ const normalized = [];
48
+
49
+ for (const entry of Array.isArray(entries) ? entries : []) {
50
+ const resolved = normalizeAccountSettingsSectionEntry(entry);
51
+ if (!resolved || seen.has(resolved.value)) {
52
+ continue;
53
+ }
54
+ seen.add(resolved.value);
55
+ normalized.push(resolved);
56
+ }
57
+
58
+ return sortAccountSettingsSections(normalized);
59
+ }
60
+
61
+ function useAccountSettingsSections() {
62
+ return inject(ACCOUNT_SETTINGS_SECTIONS_INJECTION_KEY, EMPTY_ACCOUNT_SETTINGS_SECTIONS);
63
+ }
64
+
65
+ export {
66
+ ACCOUNT_SETTINGS_SECTIONS_INJECTION_KEY,
67
+ ACCOUNT_SETTINGS_SECTION_REGISTRY_TAG,
68
+ EMPTY_ACCOUNT_SETTINGS_SECTIONS,
69
+ RESERVED_ACCOUNT_SETTINGS_SECTION_VALUES,
70
+ normalizeAccountSettingsSectionEntry,
71
+ resolveAccountSettingsSections,
72
+ sortAccountSettingsSections,
73
+ useAccountSettingsSections
74
+ };
@@ -1,10 +1,9 @@
1
1
  import { ACCOUNT_SETTINGS_DEFAULTS } from "./accountSettingsRuntimeConstants.js";
2
2
  import {
3
+ isRecord,
3
4
  normalizeReturnToPath as normalizeSharedReturnToPath,
4
5
  resolveAllowedOriginsFromPlacementContext
5
6
  } from "@jskit-ai/kernel/shared/support";
6
- import { normalizeRecordId } from "@jskit-ai/kernel/shared/support/normalize";
7
- import { normalizeRecord } from "../../support/runtimeNormalization.js";
8
7
 
9
8
  function normalizeReturnToPath(value, { fallback = "/", accountSettingsPath = "/account", allowedOrigins = [] } = {}) {
10
9
  return normalizeSharedReturnToPath(value, {
@@ -20,41 +19,7 @@ function resolveAllowedReturnToOrigins(contextValue = null) {
20
19
  }
21
20
 
22
21
  function normalizeSettingsPayload(value) {
23
- return normalizeRecord(value);
24
- }
25
-
26
- function normalizePendingInvite(entry) {
27
- if (!entry || typeof entry !== "object") {
28
- return null;
29
- }
30
-
31
- const id = normalizeRecordId(entry.id, { fallback: null });
32
- const workspaceId = normalizeRecordId(entry.workspaceId, { fallback: null });
33
- if (!id || !workspaceId) {
34
- return null;
35
- }
36
-
37
- const workspaceSlug = String(entry.workspaceSlug || "").trim();
38
- if (!workspaceSlug) {
39
- return null;
40
- }
41
-
42
- const token = String(entry.token || "").trim();
43
- if (!token) {
44
- return null;
45
- }
46
-
47
- return {
48
- id,
49
- token,
50
- workspaceId,
51
- workspaceSlug,
52
- workspaceName: String(entry.workspaceName || workspaceSlug).trim() || workspaceSlug,
53
- workspaceAvatarUrl: String(entry.workspaceAvatarUrl || "").trim(),
54
- roleSid: String(entry.roleSid || "member").trim().toLowerCase() || "member",
55
- status: String(entry.status || "pending").trim().toLowerCase() || "pending",
56
- expiresAt: String(entry.expiresAt || "").trim()
57
- };
22
+ return isRecord(value) ? value : {};
58
23
  }
59
24
 
60
25
  function normalizeAvatarSize(value) {
@@ -70,7 +35,6 @@ function normalizeAvatarSize(value) {
70
35
  export {
71
36
  resolveAllowedReturnToOrigins,
72
37
  normalizeAvatarSize,
73
- normalizePendingInvite,
74
38
  normalizeReturnToPath,
75
39
  normalizeSettingsPayload
76
40
  };
@@ -119,11 +119,11 @@ function createCrudLookupFieldRuntime({
119
119
  adapter: adapter || undefined,
120
120
  ...(relationSurfaceId ? { surfaceId: relationSurfaceId } : {}),
121
121
  apiSuffix: apiPath,
122
- queryKeyFactory: (surfaceId = "", workspaceSlug = "") => [
122
+ queryKeyFactory: (surfaceId = "", scopeParamValue = "") => [
123
123
  ...normalizedQueryKeyPrefix,
124
124
  key,
125
125
  String(surfaceId || ""),
126
- String(workspaceSlug || "")
126
+ String(scopeParamValue || "")
127
127
  ],
128
128
  search: {
129
129
  enabled: true,
@@ -83,7 +83,7 @@ function resolveCrudListParentDescriptor({ resource = {}, route = null, recordId
83
83
 
84
84
  const normalizedRecordIdParam = normalizeText(recordIdParam) || "recordId";
85
85
  for (const routeParamKey of [...orderedRouteParamNames].reverse()) {
86
- if (routeParamKey === "workspaceSlug" || routeParamKey === normalizedRecordIdParam) {
86
+ if (routeParamKey === normalizedRecordIdParam) {
87
87
  continue;
88
88
  }
89
89
 
@@ -1,5 +1,5 @@
1
1
  import { computed, unref } from "vue";
2
- import { USERS_ROUTE_VISIBILITY_WORKSPACE } from "@jskit-ai/users-core/shared/support/usersVisibility";
2
+ import { ROUTE_VISIBILITY_WORKSPACE } from "@jskit-ai/kernel/shared/support/visibility";
3
3
  import { useScopeRuntime } from "../useScopeRuntime.js";
4
4
  import { useOperationRealtime } from "../useRealtimeQueryInvalidation.js";
5
5
  import {
@@ -33,7 +33,7 @@ function hasAnyPermissions(permissionSets = {}) {
33
33
  }
34
34
 
35
35
  function useOperationScope({
36
- ownershipFilter = USERS_ROUTE_VISIBILITY_WORKSPACE,
36
+ ownershipFilter = ROUTE_VISIBILITY_WORKSPACE,
37
37
  surfaceId = "",
38
38
  access = "auto",
39
39
  placementSource = "users-web.operation",
@@ -54,8 +54,8 @@ function useOperationScope({
54
54
  });
55
55
  const normalizedOwnershipFilter = scopeRuntime.normalizedOwnershipFilter;
56
56
  const routeContext = scopeRuntime.routeContext;
57
- const workspaceSlugFromRoute = scopeRuntime.workspaceSlugFromRoute;
58
- const hasRouteWorkspaceSlug = scopeRuntime.hasRouteWorkspaceSlug;
57
+ const scopeParamValue = scopeRuntime.scopeParamValue;
58
+ const hasRequiredRouteScope = scopeRuntime.hasRequiredRouteScope;
59
59
  const accessRuntime = scopeRuntime.access;
60
60
 
61
61
  const apiPath = computed(() =>
@@ -67,7 +67,7 @@ function useOperationScope({
67
67
  const queryEnabled = computed(() =>
68
68
  resolveEnabled(readEnabled, {
69
69
  surfaceId: routeContext.currentSurfaceId.value,
70
- workspaceSlug: workspaceSlugFromRoute.value,
70
+ scopeParamValue: scopeParamValue.value,
71
71
  ownershipFilter: normalizedOwnershipFilter,
72
72
  model
73
73
  })
@@ -76,20 +76,20 @@ function useOperationScope({
76
76
  const queryKey = computed(() =>
77
77
  resolveQueryKey(queryKeyFactory, {
78
78
  surfaceId: routeContext.currentSurfaceId.value,
79
- workspaceSlug: workspaceSlugFromRoute.value,
79
+ scopeParamValue: scopeParamValue.value,
80
80
  ownershipFilter: normalizedOwnershipFilter
81
81
  })
82
82
  );
83
83
  const realtimeBinding = useOperationRealtime({
84
84
  realtime,
85
85
  queryKey: typeof queryKeyFactory === "function" ? queryKey : null,
86
- enabled: computed(() => hasRouteWorkspaceSlug.value && Boolean(apiPath.value))
86
+ enabled: computed(() => hasRequiredRouteScope.value && Boolean(apiPath.value))
87
87
  });
88
88
 
89
89
  function queryCanRun(accessGate = true) {
90
90
  return computed(() =>
91
91
  queryEnabled.value &&
92
- hasRouteWorkspaceSlug.value &&
92
+ hasRequiredRouteScope.value &&
93
93
  Boolean(apiPath.value) &&
94
94
  Boolean(unref(accessGate))
95
95
  );
@@ -102,8 +102,8 @@ function useOperationScope({
102
102
 
103
103
  function loadError(baseError = "") {
104
104
  return computed(() => {
105
- if (scopeRuntime.workspaceRouteError.value) {
106
- return scopeRuntime.workspaceRouteError.value;
105
+ if (scopeRuntime.routeScopeError.value) {
106
+ return scopeRuntime.routeScopeError.value;
107
107
  }
108
108
 
109
109
  const bootstrapError = String(accessRuntime.bootstrapError.value || "").trim();
@@ -127,8 +127,8 @@ function useOperationScope({
127
127
  scopeRuntime,
128
128
  routeContext,
129
129
  normalizedOwnershipFilter,
130
- workspaceSlugFromRoute,
131
- hasRouteWorkspaceSlug,
130
+ scopeParamValue,
131
+ hasRequiredRouteScope,
132
132
  access: accessRuntime,
133
133
  apiPath,
134
134
  queryEnabled,
@@ -1,6 +1,6 @@
1
1
  import { computed, proxyRefs } from "vue";
2
2
  import { useRoute } from "vue-router";
3
- import { USERS_ROUTE_VISIBILITY_WORKSPACE } from "@jskit-ai/users-core/shared/support/usersVisibility";
3
+ import { ROUTE_VISIBILITY_WORKSPACE } from "@jskit-ai/kernel/shared/support/visibility";
4
4
  import { useAddEditCore } from "../runtime/useAddEditCore.js";
5
5
  import { useEndpointResource } from "../runtime/useEndpointResource.js";
6
6
  import { resolveOperationAdapter } from "../runtime/operationAdapters.js";
@@ -17,7 +17,7 @@ import {
17
17
  import { resolveRouteParamNamesInOrder } from "../support/routeTemplateHelpers.js";
18
18
 
19
19
  function useAddEdit({
20
- ownershipFilter = USERS_ROUTE_VISIBILITY_WORKSPACE,
20
+ ownershipFilter = ROUTE_VISIBILITY_WORKSPACE,
21
21
  surfaceId = "",
22
22
  access = "auto",
23
23
  resource = null,
@@ -2,7 +2,7 @@ import { computed, onScopeDispose, proxyRefs, ref, watch } from "vue";
2
2
  import { useRouter } from "vue-router";
3
3
  import { appendQueryString } from "@jskit-ai/kernel/shared/support";
4
4
  import { normalizeText } from "@jskit-ai/kernel/shared/support/normalize";
5
- import { USERS_ROUTE_VISIBILITY_WORKSPACE } from "@jskit-ai/users-core/shared/support/usersVisibility";
5
+ import { ROUTE_VISIBILITY_WORKSPACE } from "@jskit-ai/kernel/shared/support/visibility";
6
6
  import { useListCore } from "../runtime/useListCore.js";
7
7
  import { resolveOperationAdapter } from "../runtime/operationAdapters.js";
8
8
  import { setupOperationErrorReporting } from "../runtime/operationUiHelpers.js";
@@ -31,7 +31,7 @@ import {
31
31
  const EMPTY_ROUTE_SYNC_QUERY_PARAM_BLACKLIST = Object.freeze([]);
32
32
 
33
33
  function useList({
34
- ownershipFilter = USERS_ROUTE_VISIBILITY_WORKSPACE,
34
+ ownershipFilter = ROUTE_VISIBILITY_WORKSPACE,
35
35
  surfaceId = "",
36
36
  access = "auto",
37
37
  apiSuffix = "",
@@ -131,7 +131,7 @@ function useList({
131
131
  const queryParamsContext = computed(() => {
132
132
  return Object.freeze({
133
133
  surfaceId: operationScope.routeContext.currentSurfaceId.value,
134
- workspaceSlug: operationScope.workspaceSlugFromRoute.value,
134
+ scopeParamValue: operationScope.scopeParamValue.value,
135
135
  ownershipFilter: operationScope.normalizedOwnershipFilter
136
136
  });
137
137
  });
@@ -1,6 +1,6 @@
1
1
  import { computed, proxyRefs } from "vue";
2
2
  import { useRoute } from "vue-router";
3
- import { USERS_ROUTE_VISIBILITY_WORKSPACE } from "@jskit-ai/users-core/shared/support/usersVisibility";
3
+ import { ROUTE_VISIBILITY_WORKSPACE } from "@jskit-ai/kernel/shared/support/visibility";
4
4
  import { useViewCore } from "../runtime/useViewCore.js";
5
5
  import { useEndpointResource } from "../runtime/useEndpointResource.js";
6
6
  import { resolveOperationAdapter } from "../runtime/operationAdapters.js";
@@ -9,7 +9,7 @@ import { createViewUiRuntime } from "../runtime/viewUiRuntime.js";
9
9
  import { resolveRouteParamNamesInOrder } from "../support/routeTemplateHelpers.js";
10
10
 
11
11
  function useView({
12
- ownershipFilter = USERS_ROUTE_VISIBILITY_WORKSPACE,
12
+ ownershipFilter = ROUTE_VISIBILITY_WORKSPACE,
13
13
  surfaceId = "",
14
14
  access = "auto",
15
15
  apiSuffix = "",
@@ -1,14 +1,14 @@
1
1
  import { resolveEnabledRef, resolveTextRef } from "./refValueHelpers.js";
2
2
  import {
3
- USERS_ROUTE_VISIBILITY_LEVELS,
4
- USERS_ROUTE_VISIBILITY_WORKSPACE,
5
- USERS_ROUTE_VISIBILITY_WORKSPACE_USER
6
- } from "@jskit-ai/users-core/shared/support/usersVisibility";
7
-
8
- const USERS_OWNERSHIP_FILTER_VALUES = USERS_ROUTE_VISIBILITY_LEVELS;
9
- const WORKSPACE_OWNERSHIP_FILTER_SET = new Set([
10
- USERS_ROUTE_VISIBILITY_WORKSPACE,
11
- USERS_ROUTE_VISIBILITY_WORKSPACE_USER
3
+ ROUTE_VISIBILITY_TOKENS,
4
+ ROUTE_VISIBILITY_WORKSPACE,
5
+ ROUTE_VISIBILITY_WORKSPACE_USER
6
+ } from "@jskit-ai/kernel/shared/support/visibility";
7
+
8
+ const OWNERSHIP_FILTER_VALUES = ROUTE_VISIBILITY_TOKENS;
9
+ const SCOPED_OWNERSHIP_FILTER_SET = new Set([
10
+ ROUTE_VISIBILITY_WORKSPACE,
11
+ ROUTE_VISIBILITY_WORKSPACE_USER
12
12
  ]);
13
13
  const ACCESS_MODE_VALUES = Object.freeze(["auto", "always", "never"]);
14
14
 
@@ -89,31 +89,31 @@ function resolveEnabled(value, context = {}) {
89
89
  return resolveEnabledRef(value);
90
90
  }
91
91
 
92
- function normalizeOwnershipFilter(value = USERS_ROUTE_VISIBILITY_WORKSPACE) {
93
- const normalized = String(value || USERS_ROUTE_VISIBILITY_WORKSPACE).trim().toLowerCase();
94
- if (USERS_OWNERSHIP_FILTER_VALUES.includes(normalized)) {
92
+ function normalizeOwnershipFilter(value = ROUTE_VISIBILITY_WORKSPACE) {
93
+ const normalized = String(value || ROUTE_VISIBILITY_WORKSPACE).trim().toLowerCase();
94
+ if (OWNERSHIP_FILTER_VALUES.includes(normalized)) {
95
95
  return normalized;
96
96
  }
97
97
 
98
98
  throw new TypeError(
99
- `ownershipFilter must be one of: ${USERS_OWNERSHIP_FILTER_VALUES.join(", ")}. Received: ${String(value || "") || "(empty)"}`
99
+ `ownershipFilter must be one of: ${OWNERSHIP_FILTER_VALUES.join(", ")}. Received: ${String(value || "") || "(empty)"}`
100
100
  );
101
101
  }
102
102
 
103
- function isWorkspaceOwnershipFilter(ownershipFilter) {
104
- return WORKSPACE_OWNERSHIP_FILTER_SET.has(ownershipFilter);
103
+ function isScopedOwnershipFilter(ownershipFilter) {
104
+ return SCOPED_OWNERSHIP_FILTER_SET.has(ownershipFilter);
105
105
  }
106
106
 
107
107
  function resolveQueryKey(
108
108
  queryKeyFactory,
109
- { surfaceId = "", workspaceSlug = "", ownershipFilter = USERS_ROUTE_VISIBILITY_WORKSPACE } = {}
109
+ { surfaceId = "", scopeParamValue = "", ownershipFilter = ROUTE_VISIBILITY_WORKSPACE } = {}
110
110
  ) {
111
111
  if (typeof queryKeyFactory !== "function") {
112
112
  throw new TypeError("queryKeyFactory is required.");
113
113
  }
114
114
 
115
- if (isWorkspaceOwnershipFilter(ownershipFilter)) {
116
- return queryKeyFactory(surfaceId, workspaceSlug, ownershipFilter);
115
+ if (isScopedOwnershipFilter(ownershipFilter)) {
116
+ return queryKeyFactory(surfaceId, scopeParamValue, ownershipFilter);
117
117
  }
118
118
 
119
119
  return queryKeyFactory(surfaceId, ownershipFilter);
@@ -139,7 +139,7 @@ export {
139
139
  resolveApiSuffix,
140
140
  resolveEnabled,
141
141
  normalizeOwnershipFilter,
142
- isWorkspaceOwnershipFilter,
142
+ isScopedOwnershipFilter,
143
143
  resolveQueryKey,
144
144
  resolveResourceMessages
145
145
  };
@@ -20,7 +20,7 @@ function asPermissionList(value) {
20
20
  }
21
21
 
22
22
  function useAccess({
23
- workspaceSlug = "",
23
+ scopeParamValue = "",
24
24
  enabled = true,
25
25
  access = "always",
26
26
  hasPermissionRequirements = false
@@ -30,7 +30,7 @@ function useAccess({
30
30
  hasPermissionRequirements: hasPermissionRequirements === true
31
31
  });
32
32
  const { context: placementContext } = useWebPlacementContext();
33
- const normalizedWorkspaceSlug = computed(() => resolveTextRef(workspaceSlug));
33
+ const normalizedScopeParamValue = computed(() => resolveTextRef(scopeParamValue));
34
34
  const queryEnabled = computed(() => resolveEnabledRef(enabled) && accessRequired);
35
35
  const hasPlacementBootstrapPermissions = computed(() => {
36
36
  const source = placementContext.value;
@@ -95,7 +95,7 @@ function useAccess({
95
95
  return Object.freeze({
96
96
  accessMode: normalizedAccessMode,
97
97
  accessRequired,
98
- workspaceSlug: normalizedWorkspaceSlug,
98
+ scopeParamValue: normalizedScopeParamValue,
99
99
  permissions,
100
100
  bootstrapError,
101
101
  isBootstrapping,