@vc-shell/vc-app-skill 2.1.0-pr255.87acc71 → 2.1.0-pr256.0fe3abb

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 (139) hide show
  1. package/package.json +1 -1
  2. package/runtime/knowledge/docs/core/api/platform.docs.md +20 -18
  3. package/runtime/knowledge/docs/core/blade-navigation/blade-nav-composables.docs.md +43 -34
  4. package/runtime/knowledge/docs/core/blade-navigation/table-query-state/useTableQueryState.docs.md +95 -0
  5. package/runtime/knowledge/docs/core/composables/useAppBarMobileButtons/useAppBarMobileButtons.docs.md +5 -3
  6. package/runtime/knowledge/docs/core/composables/useAppBarWidget/useAppBarWidget.docs.md +12 -10
  7. package/runtime/knowledge/docs/core/composables/useAppInsights/useAppInsights.docs.md +7 -5
  8. package/runtime/knowledge/docs/core/composables/useAssets/useAssets.docs.md +8 -6
  9. package/runtime/knowledge/docs/core/composables/useAssetsManager/useAssetsManager.docs.md +3 -1
  10. package/runtime/knowledge/docs/core/composables/useAsync/useAsync.docs.md +1 -1
  11. package/runtime/knowledge/docs/core/composables/useBladeRegistry/useBladeRegistry.docs.md +8 -5
  12. package/runtime/knowledge/docs/core/composables/useBladeWidgets/index.docs.md +12 -12
  13. package/runtime/knowledge/docs/core/composables/useBreadcrumbs/useBreadcrumbs.docs.md +3 -3
  14. package/runtime/knowledge/docs/core/composables/useConnectionStatus/useConnectionStatus.docs.md +4 -3
  15. package/runtime/knowledge/docs/core/composables/useDynamicProperties/useDynamicProperties.docs.md +1 -0
  16. package/runtime/knowledge/docs/core/composables/useFunctions/useFunctions.docs.md +3 -3
  17. package/runtime/knowledge/docs/core/composables/useKeyboardNavigation/useKeyboardNavigation.docs.md +5 -4
  18. package/runtime/knowledge/docs/core/composables/useLanguages/useLanguages.docs.md +3 -3
  19. package/runtime/knowledge/docs/core/composables/useLoading/useLoading.docs.md +2 -0
  20. package/runtime/knowledge/docs/core/composables/useModificationTracker/useModificationTracker.docs.md +1 -2
  21. package/runtime/knowledge/docs/core/composables/useNotifications/useNotifications.docs.md +1 -1
  22. package/runtime/knowledge/docs/core/composables/usePermissions/usePermissions.docs.md +3 -3
  23. package/runtime/knowledge/docs/core/composables/usePlatformLocaleSync/usePlatformLocaleSync.docs.md +35 -0
  24. package/runtime/knowledge/docs/core/composables/usePopup/usePopup.docs.md +1 -1
  25. package/runtime/knowledge/docs/core/composables/useResponsive/useResponsive.docs.md +2 -2
  26. package/runtime/knowledge/docs/core/composables/useSettings/useSettings.docs.md +2 -1
  27. package/runtime/knowledge/docs/core/composables/useSettingsMenu/useSettingsMenu.docs.md +18 -18
  28. package/runtime/knowledge/docs/core/composables/useSidebarState/useSidebarState.docs.md +3 -3
  29. package/runtime/knowledge/docs/core/composables/useSlowNetworkDetection/useSlowNetworkDetection.docs.md +10 -7
  30. package/runtime/knowledge/docs/core/composables/useTheme/useTheme.docs.md +7 -7
  31. package/runtime/knowledge/docs/core/composables/useToolbar/useToolbar.docs.md +18 -12
  32. package/runtime/knowledge/docs/core/composables/useUser/useUser.docs.md +2 -2
  33. package/runtime/knowledge/docs/core/composables/useUserManagement/useUserManagement.docs.md +20 -20
  34. package/runtime/knowledge/docs/core/composables/useWidgets/useWidgets.docs.md +15 -24
  35. package/runtime/knowledge/docs/core/directives/loading/loading.docs.md +2 -2
  36. package/runtime/knowledge/docs/core/notifications/composables/useBladeNotifications.docs.md +183 -0
  37. package/runtime/knowledge/docs/core/notifications/composables/useBroadcastFilter.docs.md +117 -0
  38. package/runtime/knowledge/docs/core/notifications/composables/useNotificationContext.docs.md +150 -0
  39. package/runtime/knowledge/docs/core/notifications/composables/useNotificationStore.docs.md +114 -0
  40. package/runtime/knowledge/docs/core/notifications/notifications.docs.md +50 -30
  41. package/runtime/knowledge/docs/core/plugins/ai-agent/ai-agent.docs.md +30 -11
  42. package/runtime/knowledge/docs/core/plugins/extension-points/extension-points.docs.md +1 -1
  43. package/runtime/knowledge/docs/core/plugins/global-error-handler/global-error-handler.docs.md +2 -3
  44. package/runtime/knowledge/docs/core/plugins/modularity/modularity.docs.md +26 -26
  45. package/runtime/knowledge/docs/core/plugins/permissions/permissions.docs.md +2 -3
  46. package/runtime/knowledge/docs/core/plugins/signalR/signalR.docs.md +11 -50
  47. package/runtime/knowledge/docs/core/plugins/validation/validation.docs.md +9 -6
  48. package/runtime/knowledge/docs/core/services/services.docs.md +15 -13
  49. package/runtime/knowledge/docs/core/types/types.docs.md +37 -40
  50. package/runtime/knowledge/docs/core/utilities/date/date-utilities.docs.md +1 -2
  51. package/runtime/knowledge/docs/core/utilities/shared-utilities.docs.md +21 -30
  52. package/runtime/knowledge/docs/core/utilities/thumbnail/thumbnail.docs.md +2 -2
  53. package/runtime/knowledge/docs/core/utilities/utilities.docs.md +9 -8
  54. package/runtime/knowledge/docs/injection-keys.docs.md +6 -11
  55. package/runtime/knowledge/docs/modules/assets/assets-details.docs.md +123 -0
  56. package/runtime/knowledge/docs/modules/assets-manager/assets-manager.docs.md +1 -1
  57. package/runtime/knowledge/docs/shell/_internal/popup/common/popup-common.docs.md +20 -12
  58. package/runtime/knowledge/docs/shell/auth/ChangePasswordPage/change-password-page.docs.md +10 -10
  59. package/runtime/knowledge/docs/shell/auth/ForgotPasswordPage/forgot-password-page.docs.md +6 -6
  60. package/runtime/knowledge/docs/shell/auth/InvitePage/invite-page.docs.md +4 -4
  61. package/runtime/knowledge/docs/shell/auth/LoginPage/login-page.docs.md +16 -14
  62. package/runtime/knowledge/docs/shell/auth/ResetPasswordPage/reset-password-page.docs.md +1 -1
  63. package/runtime/knowledge/docs/shell/auth/sign-in/sign-in.docs.md +12 -11
  64. package/runtime/knowledge/docs/shell/components/change-password/change-password.docs.md +10 -3
  65. package/runtime/knowledge/docs/shell/components/change-password-button/change-password-button.docs.md +3 -3
  66. package/runtime/knowledge/docs/shell/components/error-interceptor/error-interceptor.docs.md +9 -2
  67. package/runtime/knowledge/docs/shell/components/language-selector/language-selector.docs.md +4 -2
  68. package/runtime/knowledge/docs/shell/components/logout-button/logout-button.docs.md +1 -1
  69. package/runtime/knowledge/docs/shell/components/notification-dropdown/notification-dropdown.docs.md +35 -31
  70. package/runtime/knowledge/docs/shell/components/notification-template/notification-template.docs.md +17 -11
  71. package/runtime/knowledge/docs/shell/components/settings-menu/settings-menu.docs.md +8 -7
  72. package/runtime/knowledge/docs/shell/components/settings-menu-item/settings-menu-item.docs.md +23 -21
  73. package/runtime/knowledge/docs/shell/components/sidebar/sidebar.docs.md +5 -3
  74. package/runtime/knowledge/docs/shell/components/theme-selector/theme-selector.docs.md +7 -7
  75. package/runtime/knowledge/docs/shell/components/user-dropdown-button/user-dropdown-button.docs.md +11 -11
  76. package/runtime/knowledge/docs/shell/dashboard/dashboard-charts/dashboard-charts.docs.md +28 -16
  77. package/runtime/knowledge/docs/shell/dashboard/dashboard-widget-card/dashboard-widget-card.docs.md +17 -19
  78. package/runtime/knowledge/docs/shell/dashboard/draggable-dashboard/dashboard-widget-skeleton.docs.md +33 -0
  79. package/runtime/knowledge/docs/shell/dashboard/draggable-dashboard/draggable-dashboard.docs.md +21 -0
  80. package/runtime/knowledge/docs/ui/components/atoms/vc-badge/vc-badge.docs.md +2 -1
  81. package/runtime/knowledge/docs/ui/components/atoms/vc-banner/vc-banner.docs.md +2 -2
  82. package/runtime/knowledge/docs/ui/components/atoms/vc-button/vc-button.docs.md +15 -14
  83. package/runtime/knowledge/docs/ui/components/atoms/vc-container/vc-container.docs.md +9 -6
  84. package/runtime/knowledge/docs/ui/components/atoms/vc-environment-banner/vc-environment-banner.docs.md +42 -0
  85. package/runtime/knowledge/docs/ui/components/atoms/vc-hint/vc-hint.docs.md +1 -1
  86. package/runtime/knowledge/docs/ui/components/atoms/vc-icon/vc-icon.docs.md +10 -9
  87. package/runtime/knowledge/docs/ui/components/atoms/vc-image/vc-image.docs.md +19 -4
  88. package/runtime/knowledge/docs/ui/components/atoms/vc-label/vc-label.docs.md +2 -2
  89. package/runtime/knowledge/docs/ui/components/atoms/vc-link/vc-link.docs.md +5 -4
  90. package/runtime/knowledge/docs/ui/components/atoms/vc-loading/vc-loading.docs.md +5 -4
  91. package/runtime/knowledge/docs/ui/components/atoms/vc-progress/vc-progress.docs.md +9 -8
  92. package/runtime/knowledge/docs/ui/components/atoms/vc-scrollable-container/vc-scrollable-container.docs.md +7 -0
  93. package/runtime/knowledge/docs/ui/components/atoms/vc-skeleton/vc-skeleton.docs.md +1 -1
  94. package/runtime/knowledge/docs/ui/components/atoms/vc-status/vc-status.docs.md +2 -2
  95. package/runtime/knowledge/docs/ui/components/atoms/vc-status-icon/vc-status-icon.docs.md +1 -1
  96. package/runtime/knowledge/docs/ui/components/atoms/vc-tooltip/vc-tooltip.docs.md +11 -10
  97. package/runtime/knowledge/docs/ui/components/atoms/vc-video/vc-video.docs.md +28 -8
  98. package/runtime/knowledge/docs/ui/components/atoms/vc-widget/vc-widget.docs.md +22 -19
  99. package/runtime/knowledge/docs/ui/components/molecules/multilanguage-selector/multilanguage-selector.docs.md +8 -8
  100. package/runtime/knowledge/docs/ui/components/molecules/vc-accordion/vc-accordion.docs.md +16 -6
  101. package/runtime/knowledge/docs/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.docs.md +9 -8
  102. package/runtime/knowledge/docs/ui/components/molecules/vc-checkbox/vc-checkbox.docs.md +42 -34
  103. package/runtime/knowledge/docs/ui/components/molecules/vc-checkbox-group/vc-checkbox-group.docs.md +1 -1
  104. package/runtime/knowledge/docs/ui/components/molecules/vc-color-input/vc-color-input.docs.md +14 -1
  105. package/runtime/knowledge/docs/ui/components/molecules/vc-date-picker/vc-date-picker.docs.md +3 -1
  106. package/runtime/knowledge/docs/ui/components/molecules/vc-dropdown/vc-dropdown.docs.md +34 -33
  107. package/runtime/knowledge/docs/ui/components/molecules/vc-editor/vc-editor.docs.md +26 -24
  108. package/runtime/knowledge/docs/ui/components/molecules/vc-field/vc-field.docs.md +12 -14
  109. package/runtime/knowledge/docs/ui/components/molecules/vc-file-upload/vc-file-upload.docs.md +30 -30
  110. package/runtime/knowledge/docs/ui/components/molecules/vc-input/vc-input.docs.md +2 -2
  111. package/runtime/knowledge/docs/ui/components/molecules/vc-input-currency/vc-input-currency.docs.md +1 -1
  112. package/runtime/knowledge/docs/ui/components/molecules/vc-input-dropdown/vc-input-dropdown.docs.md +34 -31
  113. package/runtime/knowledge/docs/ui/components/molecules/vc-input-group/vc-input-group.docs.md +14 -12
  114. package/runtime/knowledge/docs/ui/components/molecules/vc-menu/vc-menu.docs.md +1 -1
  115. package/runtime/knowledge/docs/ui/components/molecules/vc-multivalue/vc-multivalue.docs.md +36 -27
  116. package/runtime/knowledge/docs/ui/components/molecules/vc-pagination/vc-pagination.docs.md +5 -1
  117. package/runtime/knowledge/docs/ui/components/molecules/{vc-dropdown-panel/vc-dropdown-panel.docs.md → vc-popover/vc-popover.docs.md} +26 -25
  118. package/runtime/knowledge/docs/ui/components/molecules/vc-radio-button/vc-radio-button.docs.md +10 -9
  119. package/runtime/knowledge/docs/ui/components/molecules/vc-select/vc-select.docs.md +44 -19
  120. package/runtime/knowledge/docs/ui/components/molecules/vc-slider/vc-slider.docs.md +11 -11
  121. package/runtime/knowledge/docs/ui/components/molecules/vc-switch/vc-switch.docs.md +15 -14
  122. package/runtime/knowledge/docs/ui/components/molecules/vc-textarea/vc-textarea.docs.md +15 -15
  123. package/runtime/knowledge/docs/ui/components/molecules/vc-toast/vc-toast.docs.md +15 -13
  124. package/runtime/knowledge/docs/ui/components/organisms/vc-app/vc-app.docs.md +5 -1
  125. package/runtime/knowledge/docs/ui/components/organisms/vc-auth-layout/vc-auth-layout.docs.md +18 -0
  126. package/runtime/knowledge/docs/ui/components/organisms/vc-blade/vc-blade.docs.md +48 -78
  127. package/runtime/knowledge/docs/ui/components/organisms/vc-data-table/composables/table-composables.docs.md +9 -11
  128. package/runtime/knowledge/docs/ui/components/organisms/vc-data-table/vc-data-table.docs.md +71 -43
  129. package/runtime/knowledge/docs/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.docs.md +27 -20
  130. package/runtime/knowledge/docs/ui/components/organisms/vc-gallery/vc-gallery.docs.md +2 -2
  131. package/runtime/knowledge/docs/ui/components/organisms/vc-image-upload/vc-image-upload.docs.md +12 -12
  132. package/runtime/knowledge/docs/ui/components/organisms/vc-popup/vc-popup.docs.md +33 -24
  133. package/runtime/knowledge/docs/ui/components/organisms/vc-scheduler/vc-scheduler.docs.md +412 -0
  134. package/runtime/knowledge/docs/ui/components/organisms/vc-sidebar/vc-sidebar.docs.md +43 -26
  135. package/runtime/knowledge/docs/ui/composables/ui-composables.docs.md +15 -9
  136. package/runtime/knowledge/docs/ui/composables/useDataTableSort.docs.md +8 -6
  137. package/runtime/knowledge/docs/ui/composables/useTableSearch.docs.md +130 -0
  138. package/runtime/knowledge/docs/ui/composables/useTableSelection.docs.md +4 -4
  139. package/runtime/knowledge/docs/ui/composables/useTableSort.docs.md +2 -3
@@ -0,0 +1,114 @@
1
+ ---
2
+ title: useNotificationStore
3
+ category: composables
4
+ group: notifications
5
+ ---
6
+
7
+ # useNotificationStore
8
+
9
+ !!! warning "Advanced — most apps do not need this"
10
+ Reach for [useBladeNotifications](./useBladeNotifications.md), [useBroadcastFilter](./useBroadcastFilter.md), and the `notifications` option on `defineAppModule` first. The bell dropdown, unread badge, and toast pipeline are already wired by the shell. This composable is an **escape hatch** for the small set of cases where those facades do not fit.
11
+
12
+ Returns the singleton store that backs the framework's notification system. Direct access exposes the full reactive state plus low-level actions: subscribing, ingesting synthetic messages, controlling the broadcast filter, paging history.
13
+
14
+ ## When to use
15
+
16
+ There are only two cases where this composable belongs in app code:
17
+
18
+ - **A test or scripted harness** that needs to push synthetic messages through the same pipeline SignalR uses, via `ingest`. Real-time production code never calls `ingest` directly.
19
+ - **A custom shell** that replaces the framework's bell dropdown entirely — typically a module-federation host with its own chrome — and therefore needs to bind to `history`, `unreadCount`, and `markAllAsRead` outside the default surface. Apps that use the standard `VcApp` shell do not need this; the dropdown is already there.
20
+
21
+ For everything else — reacting in a blade, gating broadcasts, registering types, displaying a toast — use the facades. Direct store mutations can bypass invariants the facades enforce (broadcast filter, scope-aware cleanup, type validation).
22
+
23
+ ## Quick Start
24
+
25
+ ```ts
26
+ import { useNotificationStore } from "@vc-shell/framework";
27
+
28
+ const store = useNotificationStore();
29
+
30
+ await store.loadHistory(50);
31
+ ```
32
+
33
+ ## API
34
+
35
+ The store exposes the full reactive state plus actions. The shape is summarized below; the underlying types live in `core/notifications/store.ts` and `core/notifications/types.ts`.
36
+
37
+ | Member | Type | Description |
38
+ | ------------------------ | ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
39
+ | `registry` | `Map<string, NotificationTypeConfig>` | Notification types registered through `defineAppModule({ notifications })`. |
40
+ | `history` | `Ref<PushNotification[]>` | Full history. `loadHistory` replaces it with the server's returned order; `ingest` appends new messages in arrival order. Not sorted — sort in the consumer for newest-first display. |
41
+ | `realtime` | `Ref<PushNotification[]>` | Session-only realtime queue from the SignalR hub. Drives `messages` in `useBladeNotifications`. |
42
+ | `unreadCount` | `ComputedRef<number>` | Count of unread items in `history`. Drives the bell badge. |
43
+ | `hasUnread` | `ComputedRef<boolean>` | Convenience boolean over `unreadCount`. |
44
+ | `registerType(t, cfg)` | `(string, NotificationTypeConfig) => void` | Register a type. Called by the framework when `defineAppModule({ notifications })` runs — rarely needed manually. |
45
+ | `ingest(msg, opts?)` | `(PushNotification, { broadcast?: boolean }?) => void` | Push a message through the same pipeline SignalR uses. Broadcasts pass through the active broadcast filter. |
46
+ | `setBroadcastFilter(fn)` | `((PushNotification) => boolean) => void` | Install a filter for broadcast messages. Prefer [useBroadcastFilter](./useBroadcastFilter.md) — same method. |
47
+ | `clearBroadcastFilter()` | `() => void` | Remove the broadcast filter. |
48
+ | `markAsRead(msg)` | `(PushNotification) => void` | Mark one message as read locally (flips `isNew` on the matching history and realtime entries). Local-only — no server call; server read-state is reconciled by `markAllAsRead`/`loadHistory`. |
49
+ | `markAllAsRead()` | `() => Promise<void>` | Flips local state to read immediately and syncs to the server. Server failure is logged only (no rollback) and reconciled on the next `loadHistory`. |
50
+ | `loadHistory(take?)` | `(number?) => Promise<void>` | Fetch history from the platform. Default page size is 10. The shell already calls this at bootstrap. |
51
+ | `subscribe(opts)` | `({ types, filter?, handler? }) => () => void` | Low-level pub/sub. Returns an `unsub` function. Inside blades use [useBladeNotifications](./useBladeNotifications.md) — it wraps this and registers cleanup automatically. |
52
+ | `getByType(type)` | `(string) => PushNotification[]` | Filter `history` by `notifyType`. |
53
+
54
+ ## Escape-hatch patterns
55
+
56
+ ### Manually ingest a message (tests, scripted replay)
57
+
58
+ ```ts
59
+ const store = useNotificationStore();
60
+
61
+ store.ingest({
62
+ id: "test-1",
63
+ notifyType: "OrderCreatedDomainEvent",
64
+ title: "Test order",
65
+ isNew: true,
66
+ created: new Date().toISOString(),
67
+ } as PushNotification);
68
+ ```
69
+
70
+ The ingest pipeline runs the configured toast logic and notifies subscribers exactly like a real SignalR message would, so you can verify the end-to-end behavior of `defineAppModule({ notifications })` + `useBladeNotifications` without a live hub.
71
+
72
+ `ingest` with `{ broadcast: true }` simulates `SendSystemEvents` and runs the broadcast filter; without it the message is treated as targeted and bypasses the filter.
73
+
74
+ ### Custom shell surface (replace the bell dropdown)
75
+
76
+ When you are building a shell variant that omits the framework's bell dropdown — for example, a module-federation host that renders its own header — bind to the store directly:
77
+
78
+ ```ts
79
+ import { useNotificationStore } from "@vc-shell/framework";
80
+ import { onMounted } from "vue";
81
+
82
+ const store = useNotificationStore();
83
+
84
+ onMounted(() => store.loadHistory(100));
85
+ // Use store.history, store.unreadCount, store.markAllAsRead in your own components.
86
+ ```
87
+
88
+ If you are using `VcApp` (the default shell), do **not** do this — the dropdown is already mounted and binding to the same store, so a second surface duplicates what is already on screen.
89
+
90
+ ## Resolution
91
+
92
+ `useNotificationStore()` resolves in this order:
93
+
94
+ 1. If called inside a Vue component's `setup` (or `app.runWithContext()`), it uses `inject(NotificationStoreKey)`.
95
+ 2. Otherwise it returns a module-level singleton created on first call.
96
+
97
+ The fallback exists so module-federation remotes and standalone scripts see the same store the host app uses.
98
+
99
+ ## Tips
100
+
101
+ - **Prefer facades.** Every time you find yourself writing `store.subscribe(...)` inside a blade, you want `useBladeNotifications`. Every time you write `store.setBroadcastFilter(...)`, you want `useBroadcastFilter`. The facades exist to keep cleanup, typing, and invariants in one place.
102
+ - **Do not iterate `realtime` for unread counts inside a blade.** That is what `useBladeNotifications` does correctly. Touching `realtime` directly couples your component to shell internals.
103
+ - **`loadHistory` replaces.** It overwrites `history` with the fetched page (`take` controls page size, default 10); it does not merge with or accumulate onto existing entries.
104
+ - **`markAllAsRead` flips local state immediately.** The change is kept even if the server call fails — the failure is logged only (no rollback, no error toast) and reconciled on the next `loadHistory`.
105
+ - **Direct store mutations can bypass invariants.** The broadcast filter only runs through `ingest({ broadcast: true })`. Pushing arrays around `history.value` directly is not supported.
106
+ - **`createNotificationStore({ toastHandle })` is exported.** `useNotificationStore()` always builds a default store wired to the real toast controller. For tests or a custom shell, construct a store directly with `createNotificationStore({ toastHandle })` to inject a stub toast handler.
107
+
108
+ ## Related
109
+
110
+ - [useBladeNotifications](./useBladeNotifications.md) — recommended scope-aware subscription. **Start here.**
111
+ - [useBroadcastFilter](./useBroadcastFilter.md) — broadcast acceptance gate.
112
+ - [useNotificationContext](./useNotificationContext.md) — payload access inside templates.
113
+ - [Notifications concept page.](../../concepts/notifications.md)
114
+ - [Notifications plugin reference.](../../plugins/notifications.md)
@@ -51,22 +51,22 @@ Returns the shared `NotificationStore` singleton. Resolution order:
51
51
 
52
52
  ### `NotificationStore` Interface
53
53
 
54
- | Member | Type | Description |
55
- | ---------------------------- | -------------------------------------------- | -------------------------------------------------------------------- |
56
- | `registry` | `Map<string, NotificationTypeConfig>` | Registered notification type configurations |
57
- | `history` | `Ref<PushNotification[]>` | All notifications (loaded from API + ingested) |
58
- | `realtime` | `Ref<PushNotification[]>` | Session-only notifications from SignalR |
59
- | `unreadCount` | `ComputedRef<number>` | Count of unread notifications in history |
60
- | `hasUnread` | `ComputedRef<boolean>` | Whether any unread notifications exist |
61
- | `registerType(type, config)` | `(string, NotificationTypeConfig) => void` | Register a notification type with toast/template config |
62
- | `ingest(message, opts?)` | `(PushNotification, {broadcast?}?) => void` | Process an incoming notification; broadcast messages are filtered |
63
- | `setBroadcastFilter(fn)` | `((PushNotification) => boolean) => void` | Set filter for broadcast messages (SendSystemEvents) |
64
- | `clearBroadcastFilter()` | `() => void` | Remove the broadcast filter |
65
- | `markAsRead(message)` | `(PushNotification) => void` | Mark a single notification as read |
66
- | `markAllAsRead()` | `() => Promise<void>` | Optimistic mark-all-as-read with server sync and rollback on failure |
67
- | `loadHistory(take?)` | `(number?) => Promise<void>` | Load notification history from the API (default: 10) |
68
- | `subscribe(opts)` | `({types, filter?, handler?}) => () => void` | Subscribe to notification types; returns unsubscribe function |
69
- | `getByType(type)` | `(string) => PushNotification[]` | Filter history by `notifyType` |
54
+ | Member | Type | Description |
55
+ | ---------------------------- | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
56
+ | `registry` | `Map<string, NotificationTypeConfig>` | Registered notification type configurations |
57
+ | `history` | `Ref<PushNotification[]>` | All notifications (loaded from API + ingested) |
58
+ | `realtime` | `Ref<PushNotification[]>` | Session-only notifications from SignalR |
59
+ | `unreadCount` | `ComputedRef<number>` | Count of unread notifications in history |
60
+ | `hasUnread` | `ComputedRef<boolean>` | Whether any unread notifications exist |
61
+ | `registerType(type, config)` | `(string, NotificationTypeConfig) => void` | Register a notification type with toast/template config |
62
+ | `ingest(message, opts?)` | `(PushNotification, {broadcast?}?) => void` | Process an incoming notification; broadcast messages are filtered |
63
+ | `setBroadcastFilter(fn)` | `((PushNotification) => boolean) => void` | Set filter for broadcast messages (SendSystemEvents) |
64
+ | `clearBroadcastFilter()` | `() => void` | Remove the broadcast filter |
65
+ | `markAsRead(message)` | `(PushNotification) => void` | Mark a single notification as read |
66
+ | `markAllAsRead()` | `() => Promise<void>` | Mark-all-as-read: flips local state immediately and syncs to the server; server failure is logged only, no rollback |
67
+ | `loadHistory(take?)` | `(number?) => Promise<void>` | Load notification history from the API (default: 10) |
68
+ | `subscribe(opts)` | `({types, filter?, handler?}) => () => void` | Subscribe to notification types; returns unsubscribe function |
69
+ | `getByType(type)` | `(string) => PushNotification[]` | Filter history by `notifyType` |
70
70
 
71
71
  **File:** `store.ts`
72
72
 
@@ -150,7 +150,7 @@ clearBroadcastFilter();
150
150
 
151
151
  ### Toast Controller
152
152
 
153
- Handles toast popup display based on `NotificationTypeConfig.toast` settings. Created internally by the store.
153
+ Handles toast popup display based on `NotificationTypeConfig.toast` settings. Created internally by the store. `createToastController()` and `createNotificationStore(options?)` are both exported factories for custom shells and test harnesses — pass `createNotificationStore({ toastHandle })` to inject a stub toast handler.
154
154
 
155
155
  **File:** `toast-controller.ts`
156
156
 
@@ -162,20 +162,40 @@ Handles toast popup display based on `NotificationTypeConfig.toast` settings. Cr
162
162
  | `"progress"` | Persistent toast updated on each message; auto-completes when `isComplete()` returns `true` |
163
163
  | `"silent"` | No toast displayed |
164
164
 
165
+ ### Imperative `notification` API
166
+
167
+ Low-level toast helper exported from `index.ts` for firing toasts directly (used by the Toast Controller for progress toasts and by framework internals). Call `notification(content, options?)` for a default toast, or use the typed helpers.
168
+
169
+ **File:** `notification.ts`
170
+
171
+ | Method | Description |
172
+ | --------------------------------- | --------------------------------------------------------------------------- |
173
+ | `notification(content, opts?)` | Show a default toast; returns the notification id |
174
+ | `notification.error(...)` | Show an error-styled toast |
175
+ | `notification.warning(...)` | Show a warning-styled toast |
176
+ | `notification.success(...)` | Show a success-styled toast |
177
+ | `notification.update(id, opts)` | Update an existing toast by id (used for progress toasts) |
178
+ | `notification.remove(id?)` | Dismiss one toast by id, or all if id omitted |
179
+ | `notification.clearAll()` | Dismiss all toasts |
180
+ | `notification.setPosition(pos)` | Set the default toast position |
181
+ | `notification.clearPosition(pos)` | Dismiss all toasts at the given position |
182
+ | `notification.debug()` | Log active toasts and default options; returns `{ active, defaultOptions }` |
183
+
165
184
  ### Types
166
185
 
167
186
  **File:** `types.ts`
168
187
 
169
- | Type | Description |
170
- | ----------------------------- | --------------------------------------------------------------------------------------- |
171
- | `Severity` | `"info" \| "warning" \| "error" \| "critical"` |
172
- | `ToastConfig` | Toast behavior: mode, severity (static or function), timeout, isComplete, completedType |
173
- | `NotificationTypeConfig` | Per-type config: optional Vue `template` component, `toast` config, `groupBy` field |
174
- | `ModuleNotificationsConfig` | Record mapping `notifyType` strings to `NotificationTypeConfig` |
175
- | `NotificationAction` | Action button in notification UI: label, icon, handler, visibility |
176
- | `NotificationSubscription` | Internal subscriber record: id, types, filter, handler |
177
- | `SEVERITY_TIMEOUTS` | Default timeouts: info=5s, warning=8s, error=persistent, critical=persistent |
178
- | `EXCLUDED_NOTIFICATION_TYPES` | Types excluded from ingestion (e.g. `"IndexProgressPushNotification"`) |
188
+ | Type | Description |
189
+ | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
190
+ | `Severity` | `"info" \| "warning" \| "error" \| "critical"` |
191
+ | `ToastConfig` | Toast behavior: mode, severity (static or function), timeout, isComplete, completedType |
192
+ | `NotificationTypeConfig` | Per-type config: optional Vue `template` component, `toast` config, `groupBy` field |
193
+ | `ModuleNotificationsConfig` | Record mapping `notifyType` strings to `NotificationTypeConfig` |
194
+ | `NotificationAction` | Action button in notification UI: label, icon, handler, visibility |
195
+ | `NotificationSubscription` | Internal subscriber record: id, types, filter, handler |
196
+ | `SEVERITY_TIMEOUTS` | Default timeouts: info=5s, warning=8s, error=persistent, critical=persistent |
197
+ | `EXCLUDED_NOTIFICATION_TYPES` | Types excluded from ingestion (e.g. `"IndexProgressPushNotification"`) |
198
+ | `NotificationContextKey` | `InjectionKey<ComputedRef<PushNotification>>` — injection key `useNotificationContext()` reads to get the current template payload |
179
199
 
180
200
  ## Usage Examples
181
201
 
@@ -233,13 +253,13 @@ const store = useNotificationStore();
233
253
  await store.loadHistory(20);
234
254
  console.log(`${store.unreadCount.value} unread notifications`);
235
255
 
236
- await store.markAllAsRead(); // optimistic update with rollback on failure
256
+ await store.markAllAsRead(); // flips local state immediately; server failure is logged only, no rollback
237
257
  ```
238
258
 
239
259
  ## Related
240
260
 
241
- - `framework/injection-keys.ts` -- `NotificationStoreKey`, `NotificationTemplatesKey`
242
- - `framework/shared/components/notifications/` -- Notification dropdown UI
261
+ - `framework/injection-keys.ts` -- `NotificationStoreKey`
262
+ - `framework/shell/components/notification-dropdown/` -- Notification dropdown UI
243
263
  - `framework/core/api/platform.ts` -- `PushNotification`, `PushNotificationClient`
244
264
 
245
265
  <!-- internal:start -->
@@ -49,18 +49,37 @@ app.use(aiAgentPlugin, {
49
49
 
50
50
  ### `IAiAgentConfig`
51
51
 
52
- | Field | Type | Default | Description |
53
- | ---------------- | ---------- | ------------ | ------------------------------------------ |
54
- | `url` | `string` | `""` | Chatbot iframe URL (required) |
55
- | `title` | `string` | `"Virto OZ"` | Panel header title |
56
- | `width` | `number` | `362` | Panel width in pixels |
57
- | `expandedWidth` | `number` | `500` | Panel width when expanded |
58
- | `allowedOrigins` | `string[]` | `["*"]` | Allowed origins for postMessage validation |
52
+ | Field | Type | Default | Description |
53
+ | ---------------- | ---------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
54
+ | `url` | `string` | `""` | Chatbot iframe URL (required) |
55
+ | `title` | `string` | `"Virto OZ"` | Panel header title |
56
+ | `width` | `number` | `362` | Panel width in pixels |
57
+ | `expandedWidth` | `number` | `500` | Panel width when expanded |
58
+ | `allowedOrigins` | `string[]` | `[]` | Origins accepted for **incoming** postMessage; the first entry is the target origin for **outbound** messages to the chatbot iframe. Required — see below |
59
+ | `parentOrigin` | `string` | -- | Explicit parent origin for **outbound** embedded postMessage. Required in embedded mode — see below |
60
+
61
+ !!! danger "Origins must be configured — secure by default"
62
+ The bridge is locked down by default. Set both fields to explicit origins; a wildcard `"*"` or empty value is refused (the message is dropped and logged), never trusted.
63
+
64
+ - **`allowedOrigins`** governs messages the shell **accepts**, and its first entry is the target origin the shell uses to **send** `INIT_CONTEXT`/`UPDATE_CONTEXT` to the chatbot iframe. With the default `[]`, all incoming postMessages are ignored and outbound iframe messages are dropped (these carry the access token, so they are never sent to `"*"`). Set it to the chatbot's origin(s), e.g. `["https://chat.example.com"]`. A `"*"` entry is rejected outright — replace it with explicit origins.
65
+ - **`parentOrigin`** governs messages the shell **sends to the parent frame** in embedded mode (`AI_CONTEXT_UPDATE`, `AI_TOGGLE_PANEL`, etc.). These payloads can carry the access token, so with no explicit `parentOrigin` (or `"*"`) the outbound message is dropped. Set it to the exact host origin, e.g. `"https://host.example.com"`.
66
+
67
+ ```ts
68
+ app.use(AiAgentPlugin, {
69
+ config: {
70
+ url: "https://chat.example.com",
71
+ allowedOrigins: ["https://chat.example.com"], // incoming
72
+ parentOrigin: "https://host.example.com", // outbound (embedded mode)
73
+ },
74
+ });
75
+ ```
59
76
 
60
77
  ### Composable: `useAiAgent()`
61
78
 
62
79
  Access the AI agent service from any component within the app.
63
80
 
81
+ Returns `UseAiAgentReturn | undefined`. When `provideAiAgentService()` has not run, `useAiAgent()` logs an error and returns `undefined`, so guard the result before destructuring (e.g. `const ai = useAiAgent(); ai?.togglePanel()`).
82
+
64
83
  | Return | Type | Description |
65
84
  | ----------------- | ------------------------------------------- | ---------------------------------------------- |
66
85
  | `panelState` | `Ref<"closed" \| "open" \| "expanded">` | Current panel state |
@@ -123,19 +142,19 @@ useAiAgentContext({ dataRef: selectedItems });
123
142
  ### Toggling the Panel Programmatically
124
143
 
125
144
  ```typescript
126
- const { togglePanel, isOpen } = useAiAgent();
145
+ const ai = useAiAgent();
127
146
 
128
147
  function onAiButtonClick() {
129
- togglePanel();
148
+ ai?.togglePanel();
130
149
  }
131
150
  ```
132
151
 
133
152
  ### Listening for Chatbot Messages
134
153
 
135
154
  ```typescript
136
- const { onMessage } = useAiAgent();
155
+ const ai = useAiAgent();
137
156
 
138
- onMessage((message) => {
157
+ ai?.onMessage((message) => {
139
158
  if (message.type === "NAVIGATE_TO_APP") {
140
159
  console.log("Chatbot wants to navigate to:", message.payload);
141
160
  }
@@ -582,7 +582,7 @@ function defineExtensionPoint<M = Record<string, unknown>>(name: string, options
582
582
 
583
583
  interface DefineExtensionPointReturn<M> {
584
584
  /** Sorted list of registered components (by priority, ascending) */
585
- components: ComputedRef<Array<ExtensionComponent & { meta?: M }>>;
585
+ components: ComputedRef<Array<Omit<ExtensionComponent, "meta"> & { meta?: M }>>;
586
586
  /** True when at least one component is registered */
587
587
  hasComponents: ComputedRef<boolean>;
588
588
  }
@@ -33,7 +33,6 @@ All caught errors are parsed into human-readable messages via `parseError()` and
33
33
 
34
34
  ```typescript
35
35
  // Automatic -- called by the framework during app initialization.
36
- import { setupGlobalErrorHandlers } from "@vc-shell/framework";
37
36
  setupGlobalErrorHandlers(app);
38
37
  ```
39
38
 
@@ -150,6 +149,6 @@ try {
150
149
  ## Related
151
150
 
152
151
  - `framework/core/utilities/error.ts` -- `parseError()` function that extracts readable messages
153
- - `framework/shared/components/notifications/core/notification.ts` -- `notification.error()` toast API
152
+ - `framework/core/notifications/notification.ts` -- `notification.error()` toast API
154
153
  - `framework/core/utilities/logger.ts` -- `createLogger()` for structured console logging
155
- - `framework/shared/components/error-interceptor/` -- blade-level error boundary that intercepts errors before the global handler
154
+ - `framework/shell/components/error-interceptor/` -- blade-level error boundary that intercepts errors before the global handler
@@ -176,12 +176,12 @@ export default defineAppModule({
176
176
 
177
177
  Key differences:
178
178
 
179
- | | `createAppModule` | `defineAppModule` |
180
- | ----------------- | --------------------------------------- | ---------------------------------- |
181
- | API style | Positional args | Named options object |
182
- | Notifications | `notificationTemplates` (legacy) | `notifications` (new typed config) |
183
- | Global components | 4th arg registers via `app.component()` | Not supported (use provide/inject) |
184
- | Status | **Deprecated** -- will be removed | **Current** -- use this |
179
+ | | `createAppModule` | `defineAppModule` |
180
+ | ----------------- | ----------------------------------------------------------------------------------- | ---------------------------------- |
181
+ | API style | Positional args | Named options object |
182
+ | Notifications | `notificationTemplates` (legacy) | `notifications` (new typed config) |
183
+ | Global components | 4th arg accepted for backward compatibility but ignored (no `app.component()` call) | Not supported (use provide/inject) |
184
+ | Status | **Deprecated** -- will be removed | **Current** -- use this |
185
185
 
186
186
  Migration is a one-line change:
187
187
 
@@ -278,7 +278,7 @@ defineBlade({
278
278
  title: "ORDERS.MENU.TITLE", // i18n key or plain string
279
279
  icon: "lucide-shopping-cart", // Icon name (lucide or fas)
280
280
  priority: 1, // Lower = higher in menu
281
- permissions: ["seller:orders:view"], // Optional override
281
+ permissions: ["seller:orders:view"], // Optional fallback (used only when the blade has no permissions)
282
282
  },
283
283
  });
284
284
  </script>
@@ -317,7 +317,7 @@ defineBlade({
317
317
  </script>
318
318
  ```
319
319
 
320
- Under the hood, `defineAppModule` calls `addMenuItem()` from `useMenuService` with:
320
+ Under the hood, the BladeRegistry registration function (invoked during `defineAppModule`'s install) calls `addMenuItem()` from `useMenuService` with:
321
321
 
322
322
  ```typescript
323
323
  addMenuItem({
@@ -383,7 +383,7 @@ export default defineAppModule({
383
383
  | Field | Type | Default | Description |
384
384
  | --------------- | ---------------------------------- | ----------------- | ------------------------------------------------------------------------------------- |
385
385
  | `mode` | `"auto" \| "progress" \| "silent"` | required | `auto` = show and auto-dismiss; `progress` = stay until complete; `silent` = no toast |
386
- | `severity` | `Severity \| (msg) => Severity` | `"info"` | Toast type: `"info"`, `"success"`, `"warning"`, `"error"` |
386
+ | `severity` | `Severity \| (msg) => Severity` | `"info"` | Toast type: `"info"`, `"warning"`, `"error"`, `"critical"` |
387
387
  | `timeout` | `number` | varies | Auto-dismiss timeout in milliseconds |
388
388
  | `isComplete` | `(msg) => boolean` | `msg.finished` | For `progress` mode: when to close the toast |
389
389
  | `completedType` | `(msg) => "success" \| "error"` | `() => "success"` | For `progress` mode: final toast type |
@@ -507,7 +507,7 @@ flowchart TD
507
507
 
508
508
  Non-OK manifest responses (401 / 403 / 404 / 5xx) are treated as "no plugins" — the host logs a `console.warn`, sets `modulesReady=true`, and mounts without extensions. Only network or parse failures set `modulesLoadError=true`.
509
509
 
510
- See the [Module Federation guide](../guides/module-federation/index.md) for the full plugin-author + host-app walkthrough.
510
+ See [Plugin Loading (Module Federation)](#plugin-loading-module-federation) above and the `packages/mf-host/` package for the full plugin-author + host-app walkthrough.
511
511
 
512
512
  The host shares singleton instances of core dependencies (Vue, Vue Router, vue-i18n, @vc-shell/framework) so that remote modules use the same runtime. This is critical for reactivity, routing, and DI to work across module boundaries.
513
513
 
@@ -853,12 +853,12 @@ interface DashboardWidget {
853
853
 
854
854
  **`MenuItemConfig`:**
855
855
 
856
- | Field | Type | Description |
857
- | ------------- | ---------- | --------------------------------------------------------------- |
858
- | `title` | `string` | Display text or i18n key |
859
- | `icon` | `string` | Icon name (lucide-_ or fas fa-_) |
860
- | `priority` | `number` | Sort order (lower = higher in menu) |
861
- | `permissions` | `string[]` | Permission override (optional, falls back to blade permissions) |
856
+ | Field | Type | Description |
857
+ | ------------- | ---------- | ---------------------------------------------------------------------------------------------------- |
858
+ | `title` | `string` | Display text or i18n key |
859
+ | `icon` | `string` | Icon name (lucide-_ or fas fa-_) |
860
+ | `priority` | `number` | Sort order (lower = higher in menu) |
861
+ | `permissions` | `string[]` | Optional fallback used only when the blade has no `permissions`; blade `permissions` take precedence |
862
862
 
863
863
  ---
864
864
 
@@ -893,13 +893,13 @@ interface ToastConfig {
893
893
 
894
894
  ## Related
895
895
 
896
- | Resource | Path | Description |
897
- | ----------------------- | ------------------------------------- | ------------------------------------------------ |
898
- | Extension Points Plugin | `core/plugins/extension-points/` | Cross-module UI extension system |
899
- | BladeRegistry | `core/composables/useBladeRegistry/` | Where blades are stored and looked up |
900
- | useMenuService | `core/composables/useMenuService/` | `addMenuItem()` for sidebar navigation |
901
- | useDashboard | `core/composables/useDashboard/` | Dashboard widget management |
902
- | NotificationStore | `core/notifications/` | Notification type registration and dispatch |
903
- | i18n Plugin | `core/plugins/i18n/` | vue-i18n singleton for locale merging |
904
- | mf-host | `packages/mf-host/` | Module Federation host that loads remote modules |
905
- | Blade Navigation | `shared/components/blade-navigation/` | Blade stack rendering and navigation |
896
+ | Resource | Path | Description |
897
+ | ----------------------- | ------------------------------------ | ------------------------------------------------ |
898
+ | Extension Points Plugin | `core/plugins/extension-points/` | Cross-module UI extension system |
899
+ | BladeRegistry | `core/composables/useBladeRegistry/` | Where blades are stored and looked up |
900
+ | useMenuService | `core/composables/useMenuService/` | `addMenuItem()` for sidebar navigation |
901
+ | useDashboard | `core/composables/useDashboard/` | Dashboard widget management |
902
+ | NotificationStore | `core/notifications/` | Notification type registration and dispatch |
903
+ | i18n Plugin | `core/plugins/i18n/` | vue-i18n singleton for locale merging |
904
+ | mf-host | `packages/mf-host/` | Module Federation host that loads remote modules |
905
+ | Blade Navigation | `core/blade-navigation/` | Blade stack logic and navigation |
@@ -13,7 +13,7 @@ Permission-based access control plugin. Exposes a global `$hasAccess` helper for
13
13
 
14
14
  The VirtoCommerce platform uses a role-based permission system where each user is assigned one or more roles, and each role grants a set of named permissions (e.g., `order:read`, `order:create`, `catalog:manage`). The permissions plugin bridges this system into the Vue application layer so that UI elements can be shown or hidden based on the current user's access rights.
15
15
 
16
- The plugin installs the `hasAccess()` function from the `usePermissions()` composable as both a Vue global property (`$hasAccess`) and a provide/inject injectable (`"$hasAccess"`). This means permission checks are available everywhere: in templates via `$hasAccess()`, in composition API code via `usePermissions()`, and in any injecting component.
16
+ The plugin installs the `hasAccess()` function from the `usePermissions()` composable as a Vue global property (`$hasAccess`). This means permission checks are available everywhere: in templates via `$hasAccess()` and in composition API code via `usePermissions()`.
17
17
 
18
18
  ## When to Use
19
19
 
@@ -28,14 +28,13 @@ The framework installs this plugin automatically during app setup. Module develo
28
28
  ```typescript
29
29
  // Automatic -- installed by the framework during app setup.
30
30
  // The plugin source is straightforward:
31
- import { usePermissions } from "@core/composables/usePermissions";
31
+ import { usePermissions } from "@vc-shell/framework";
32
32
  import { App } from "vue";
33
33
 
34
34
  export const permissions = {
35
35
  install(app: App) {
36
36
  const { hasAccess } = usePermissions();
37
37
  app.config.globalProperties.$hasAccess = hasAccess;
38
- app.provide("$hasAccess", hasAccess);
39
38
  },
40
39
  };
41
40
  ```
@@ -21,8 +21,8 @@ The VirtoCommerce platform uses ASP.NET SignalR to push real-time notifications
21
21
 
22
22
  The SignalR plugin establishes a persistent WebSocket connection to the platform hub and listens for two event channels:
23
23
 
24
- - **`Send`** -- broadcast messages sent to all connected clients
25
- - **`SendSystemEvents`** -- messages filtered by `creator` field, scoped to a specific user or organization
24
+ - **`Send`** -- targeted messages ingested with default routing
25
+ - **`SendSystemEvents`** -- ingested as broadcast (`store.ingest(message, { broadcast: true })`), no creator filtering
26
26
 
27
27
  Incoming messages are ingested into the `NotificationStore`, which dispatches them to registered notification type handlers and triggers toast notifications based on per-type configuration.
28
28
 
@@ -32,38 +32,21 @@ The connection lifecycle is tied to the user's authentication state: it connects
32
32
 
33
33
  ```typescript
34
34
  // Automatic -- installed by the framework during app setup.
35
- // The `creator` option is typically set to the current user/organization ID.
36
- app.use(signalR, { creator: currentUserId });
35
+ // The plugin takes no options.
36
+ app.use(signalR);
37
37
  ```
38
38
 
39
39
  Module developers do not install this plugin. It is registered once by the framework during bootstrap.
40
40
 
41
41
  ## API
42
42
 
43
- ### Plugin Options
44
-
45
- | Option | Type | Description |
46
- | --------- | --------------------- | -------------------------------------------------------------------------- |
47
- | `creator` | `string \| undefined` | Filters `SendSystemEvents` messages to only those matching this creator ID |
48
-
49
43
  ### Exports
50
44
 
51
- | Export | Type | Description |
52
- | ---------------------------- | -------------- | --------------------------------------------- |
53
- | `signalR` | `Plugin` | Vue plugin object with `install()` method |
54
- | `updateSignalRCreatorSymbol` | `InjectionKey` | Injection key for the creator update function |
55
-
56
- ### Provided Injectables
57
-
58
- | Key | Type | Description |
59
- | ---------------------------- | ---------------------------------------- | --------------------------------------------- |
60
- | `updateSignalRCreatorSymbol` | `(creator: string \| undefined) => void` | Updates the SignalR creator filter at runtime |
61
-
62
- ### Global Properties
45
+ | Export | Type | Description |
46
+ | --------- | -------- | ----------------------------------------- |
47
+ | `signalR` | `Plugin` | Vue plugin object with `install()` method |
63
48
 
64
- | Property | Type | Description |
65
- | ----------------------- | ---------------------------------------- | ------------------------------------------------------------------- |
66
- | `$updateSignalRCreator` | `(creator: string \| undefined) => void` | Same as the injectable, accessible via `this.$updateSignalRCreator` |
49
+ The plugin installs with no options: `app.use(signalR)`.
67
50
 
68
51
  ## Connection Lifecycle
69
52
 
@@ -80,7 +63,7 @@ sequenceDiagram
80
63
 
81
64
  Hub-->>C: "Send" (targeted)
82
65
  C->>Store: ingest(message)
83
- Hub-->>C: "SendSystemEvents" (broadcast, filtered by creator)
66
+ Hub-->>C: "SendSystemEvents" (broadcast)
84
67
  C->>Store: ingest(message, { broadcast: true })
85
68
 
86
69
  Store->>Store: toast • subscriber callbacks • history update
@@ -98,24 +81,6 @@ sequenceDiagram
98
81
 
99
82
  ## Usage
100
83
 
101
- ### Updating the Creator Filter
102
-
103
- After login or when switching organizations, update the creator to scope system events:
104
-
105
- ```typescript
106
- import { inject } from "vue";
107
- import { updateSignalRCreatorSymbol } from "@vc-shell/framework";
108
-
109
- const updateCreator = inject(updateSignalRCreatorSymbol);
110
- updateCreator?.(currentUser.id);
111
- ```
112
-
113
- Or via the global property in Options API (legacy):
114
-
115
- ```typescript
116
- this.$updateSignalRCreator(currentUser.id);
117
- ```
118
-
119
84
  ### How Messages Flow
120
85
 
121
86
  1. Platform sends a `PushNotification` via SignalR
@@ -156,13 +121,9 @@ cy.signalR("pushNotificationHub").invoke("Send", {
156
121
  });
157
122
  ```
158
123
 
159
- ## Tip: Creator vs. Broadcast
160
-
161
- If your notification type should reach all connected clients regardless of who triggered it, use the `Send` channel (the platform sends it as a broadcast). For user-scoped notifications (e.g., "your export is complete"), use `SendSystemEvents` with the `creator` field set to the user's ID on the server side.
162
-
163
- ## Common Mistake
124
+ ## Tip: Send vs. SendSystemEvents
164
125
 
165
- Do not call `updateCreator` before the SignalR connection is established. The plugin watches the `currentCreator` ref and re-registers the `SendSystemEvents` handler only when the connection state is `"Connected"`. If you set the creator before authentication, it will be applied when the connection starts.
126
+ Both channels ingest into the same `NotificationStore`. `Send` messages are ingested with default routing; `SendSystemEvents` messages are ingested as broadcast (`{ broadcast: true }`). The plugin does not filter either channel by a creator field -- any scoping to a specific user or organization must happen server-side before the message is pushed.
166
127
 
167
128
  ## Related
168
129