@jskit-ai/workspaces-web 0.1.19 → 0.1.21

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.
@@ -1,7 +1,7 @@
1
1
  export default Object.freeze({
2
2
  packageVersion: 1,
3
3
  packageId: "@jskit-ai/workspaces-web",
4
- version: "0.1.19",
4
+ version: "0.1.21",
5
5
  kind: "runtime",
6
6
  description: "Workspace web module: workspace selector, tools widget, workspace surfaces, and members/settings UI.",
7
7
  dependsOn: [
@@ -56,6 +56,7 @@ export default Object.freeze({
56
56
  "workspaces.web.workspace-members.menu-item",
57
57
  "workspaces.web.members-admin.element",
58
58
  "workspaces.web.bootstrap-placement.runtime",
59
+ "workspaces.web.scope-support",
59
60
  "workspaces.web.account-settings.section.invites"
60
61
  ]
61
62
  }
@@ -147,8 +148,8 @@ export default Object.freeze({
147
148
  mutations: {
148
149
  dependencies: {
149
150
  runtime: {
150
- "@jskit-ai/workspaces-core": "0.1.19",
151
- "@jskit-ai/users-web": "0.1.58",
151
+ "@jskit-ai/workspaces-core": "0.1.21",
152
+ "@jskit-ai/users-web": "0.1.60",
152
153
  "vuetify": "^4.0.0"
153
154
  },
154
155
  dev: {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jskit-ai/workspaces-web",
3
- "version": "0.1.19",
3
+ "version": "0.1.21",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "test": "node --test"
@@ -14,12 +14,12 @@
14
14
  "dependencies": {
15
15
  "@tanstack/vue-query": "5.92.12",
16
16
  "@mdi/js": "^7.4.47",
17
- "@jskit-ai/http-runtime": "0.1.42",
18
- "@jskit-ai/kernel": "0.1.43",
19
- "@jskit-ai/shell-web": "0.1.42",
20
- "@jskit-ai/users-core": "0.1.53",
21
- "@jskit-ai/users-web": "0.1.58",
22
- "@jskit-ai/workspaces-core": "0.1.19",
17
+ "@jskit-ai/http-runtime": "0.1.44",
18
+ "@jskit-ai/kernel": "0.1.45",
19
+ "@jskit-ai/shell-web": "0.1.44",
20
+ "@jskit-ai/users-core": "0.1.55",
21
+ "@jskit-ai/users-web": "0.1.60",
22
+ "@jskit-ai/workspaces-core": "0.1.21",
23
23
  "vuetify": "^4.0.0"
24
24
  }
25
25
  }
@@ -1,26 +1,15 @@
1
1
  import { computed } from "vue";
2
- import {
3
- extractWorkspaceSlugFromSurfacePathname
4
- } from "../lib/workspaceSurfacePaths.js";
5
2
  import { useSurfaceRouteContext } from "@jskit-ai/users-web/client/composables/useSurfaceRouteContext";
3
+ import { readWorkspaceRouteScope } from "../support/workspaceScopeSupport.js";
6
4
 
7
5
  function useWorkspaceRouteContext() {
8
- const { route, routePath, placementContext, mergePlacementContext, currentSurfaceId } = useSurfaceRouteContext();
6
+ const routeContext = useSurfaceRouteContext();
9
7
  const workspaceSlugFromRoute = computed(() => {
10
- const workspaceSlug = extractWorkspaceSlugFromSurfacePathname(
11
- placementContext.value,
12
- currentSurfaceId.value,
13
- routePath.value
14
- );
15
- return String(workspaceSlug || "").trim();
8
+ return readWorkspaceRouteScope(routeContext).workspaceSlug;
16
9
  });
17
10
 
18
11
  return Object.freeze({
19
- route,
20
- routePath,
21
- placementContext,
22
- mergePlacementContext,
23
- currentSurfaceId,
12
+ ...routeContext,
24
13
  workspaceSlugFromRoute
25
14
  });
26
15
  }
@@ -7,6 +7,10 @@ import UsersWorkspaceSettingsMenuItem from "../components/UsersWorkspaceSettings
7
7
  import UsersWorkspaceMembersMenuItem from "../components/UsersWorkspaceMembersMenuItem.vue";
8
8
  import MembersAdminClientElement from "../components/MembersAdminClientElement.vue";
9
9
  import { createBootstrapPlacementRuntime } from "../runtime/bootstrapPlacementRuntime.js";
10
+ import {
11
+ WORKSPACES_WEB_SCOPE_SUPPORT_INJECTION_KEY,
12
+ createWorkspaceScopeSupport
13
+ } from "../support/workspaceScopeSupport.js";
10
14
 
11
15
  class WorkspacesWebClientProvider {
12
16
  static id = "workspaces.web.client";
@@ -24,6 +28,7 @@ class WorkspacesWebClientProvider {
24
28
  app.singleton("workspaces.web.workspace-members.menu-item", () => UsersWorkspaceMembersMenuItem);
25
29
  app.singleton("workspaces.web.members-admin.element", () => MembersAdminClientElement);
26
30
  app.singleton("workspaces.web.bootstrap-placement.runtime", (scope) => createBootstrapPlacementRuntime({ app: scope }));
31
+ app.singleton("workspaces.web.scope-support", () => createWorkspaceScopeSupport());
27
32
  app.singleton("workspaces.web.account-settings.section.invites", () =>
28
33
  Object.freeze({
29
34
  title: "Invites",
@@ -45,6 +50,20 @@ class WorkspacesWebClientProvider {
45
50
  if (runtime && typeof runtime.initialize === "function") {
46
51
  await runtime.initialize();
47
52
  }
53
+
54
+ if (!app.has("jskit.client.vue.app")) {
55
+ return;
56
+ }
57
+
58
+ const vueApp = app.make("jskit.client.vue.app");
59
+ if (!vueApp || typeof vueApp.provide !== "function") {
60
+ return;
61
+ }
62
+
63
+ vueApp.provide(
64
+ WORKSPACES_WEB_SCOPE_SUPPORT_INJECTION_KEY,
65
+ app.make("workspaces.web.scope-support")
66
+ );
48
67
  }
49
68
 
50
69
  shutdown(app) {
@@ -0,0 +1,48 @@
1
+ import { getClientAppConfig } from "@jskit-ai/kernel/client";
2
+ import { normalizeText } from "@jskit-ai/kernel/shared/support/normalize";
3
+ import {
4
+ extractWorkspaceSlugFromSurfacePathname
5
+ } from "../lib/workspaceSurfacePaths.js";
6
+
7
+ const WORKSPACES_WEB_SCOPE_SUPPORT_INJECTION_KEY = "jskit.workspaces.web.scope-support";
8
+
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
+ function readWorkspaceRouteScope(routeContext = {}) {
18
+ const placementContext = unwrapRefValue(routeContext?.placementContext);
19
+ const currentSurfaceId = normalizeText(unwrapRefValue(routeContext?.currentSurfaceId)).toLowerCase();
20
+ const routePath = normalizeText(unwrapRefValue(routeContext?.routePath));
21
+ const workspaceSlug = extractWorkspaceSlugFromSurfacePathname(
22
+ placementContext,
23
+ currentSurfaceId,
24
+ routePath
25
+ );
26
+
27
+ return Object.freeze({
28
+ workspaceSlug: String(workspaceSlug || "").trim()
29
+ });
30
+ }
31
+
32
+ function createWorkspaceScopeSupport() {
33
+ const appConfig = getClientAppConfig();
34
+ const tenancyMode = normalizeText(appConfig?.tenancyMode).toLowerCase();
35
+
36
+ return Object.freeze({
37
+ available: tenancyMode === "personal" || tenancyMode === "workspaces",
38
+ readRouteScope(routeContext = {}) {
39
+ return readWorkspaceRouteScope(routeContext);
40
+ }
41
+ });
42
+ }
43
+
44
+ export {
45
+ WORKSPACES_WEB_SCOPE_SUPPORT_INJECTION_KEY,
46
+ createWorkspaceScopeSupport,
47
+ readWorkspaceRouteScope
48
+ };
@@ -0,0 +1,74 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import {
4
+ createWorkspaceScopeSupport,
5
+ readWorkspaceRouteScope
6
+ } from "../src/client/support/workspaceScopeSupport.js";
7
+
8
+ test("readWorkspaceRouteScope extracts workspace slug from the current dynamic surface path", () => {
9
+ const scope = readWorkspaceRouteScope({
10
+ placementContext: {
11
+ value: {
12
+ surfaceConfig: {
13
+ defaultSurfaceId: "app",
14
+ surfacesById: {
15
+ app: {
16
+ id: "app",
17
+ routeBase: "w/[workspaceSlug]",
18
+ requiresWorkspace: true
19
+ },
20
+ admin: {
21
+ id: "admin",
22
+ routeBase: "w/[workspaceSlug]/admin",
23
+ requiresWorkspace: true
24
+ }
25
+ }
26
+ }
27
+ }
28
+ },
29
+ currentSurfaceId: {
30
+ value: "admin"
31
+ },
32
+ routePath: {
33
+ value: "/w/acme/admin/settings"
34
+ }
35
+ });
36
+
37
+ assert.deepEqual(scope, {
38
+ workspaceSlug: "acme"
39
+ });
40
+ });
41
+
42
+ test("workspace scope support exposes the shared route-scope reader", () => {
43
+ const support = createWorkspaceScopeSupport();
44
+
45
+ assert.equal(typeof support.available, "boolean");
46
+ assert.equal(typeof support.readRouteScope, "function");
47
+ assert.deepEqual(
48
+ support.readRouteScope({
49
+ placementContext: {
50
+ value: {
51
+ surfaceConfig: {
52
+ defaultSurfaceId: "app",
53
+ surfacesById: {
54
+ app: {
55
+ id: "app",
56
+ routeBase: "w/[workspaceSlug]",
57
+ requiresWorkspace: true
58
+ }
59
+ }
60
+ }
61
+ }
62
+ },
63
+ currentSurfaceId: {
64
+ value: "app"
65
+ },
66
+ routePath: {
67
+ value: "/w/dogandgroom"
68
+ }
69
+ }),
70
+ {
71
+ workspaceSlug: "dogandgroom"
72
+ }
73
+ );
74
+ });