@vc-shell/vc-app-skill 2.0.4 → 2.0.6
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/CHANGELOG.md +10 -0
- package/README.md +7 -7
- package/package.json +1 -1
- package/runtime/VERSION +1 -1
- package/runtime/knowledge/docs/_BUILD_HASH.md +1 -1
- package/runtime/knowledge/docs/core/api/platform.docs.md +6 -6
- package/runtime/knowledge/docs/core/blade-navigation/blade-nav-composables.docs.md +1 -1
- package/runtime/knowledge/docs/core/composables/bladeContext/index.docs.md +2 -2
- package/runtime/knowledge/docs/core/composables/useApiClient/useApiClient.docs.md +67 -42
- package/runtime/knowledge/docs/core/composables/useAppBarMobileButtons/useAppBarMobileButtons.docs.md +2 -2
- package/runtime/knowledge/docs/core/composables/useAppBarWidget/useAppBarWidget.docs.md +15 -13
- package/runtime/knowledge/docs/core/composables/useAppInsights/useAppInsights.docs.md +11 -11
- package/runtime/knowledge/docs/core/composables/useAsync/useAsync.docs.md +17 -14
- package/runtime/knowledge/docs/core/composables/useBeforeUnload/useBeforeUnload.docs.md +4 -2
- package/runtime/knowledge/docs/core/composables/useBlade/useBlade.docs.md +31 -23
- package/runtime/knowledge/docs/core/composables/useBladeWidgets/index.docs.md +46 -26
- package/runtime/knowledge/docs/core/composables/useDashboard/useDashboard.docs.md +1 -0
- package/runtime/knowledge/docs/core/composables/useDynamicProperties/useDynamicProperties.docs.md +1 -1
- package/runtime/knowledge/docs/core/composables/useMenuExpanded/index.docs.md +1 -1
- package/runtime/knowledge/docs/core/composables/useMenuService/useMenuService.docs.md +1 -0
- package/runtime/knowledge/docs/core/composables/useNotifications/useNotifications.docs.md +20 -6
- package/runtime/knowledge/docs/core/composables/usePermissions/usePermissions.docs.md +2 -1
- package/runtime/knowledge/docs/core/composables/useSettings/useSettings.docs.md +2 -2
- package/runtime/knowledge/docs/core/composables/useToolbar/useToolbar.docs.md +109 -133
- package/runtime/knowledge/docs/core/composables/useWidgets/useWidgets.docs.md +1 -2
- package/runtime/knowledge/docs/core/notifications/composables/useBladeNotifications.docs.md +184 -0
- package/runtime/knowledge/docs/core/notifications/composables/useBroadcastFilter.docs.md +117 -0
- package/runtime/knowledge/docs/core/notifications/composables/useNotificationContext.docs.md +150 -0
- package/runtime/knowledge/docs/core/notifications/composables/useNotificationStore.docs.md +113 -0
- package/runtime/knowledge/docs/core/notifications/notifications.docs.md +12 -15
- package/runtime/knowledge/docs/core/plugins/extension-points/extension-points.docs.md +1 -1
- package/runtime/knowledge/docs/core/plugins/modularity/modularity.docs.md +54 -116
- package/runtime/knowledge/docs/core/plugins/permissions/permissions.docs.md +12 -3
- package/runtime/knowledge/docs/core/plugins/signalR/signalR.docs.md +20 -20
- package/runtime/knowledge/docs/injection-keys.docs.md +1 -1
- package/runtime/knowledge/docs/shell/auth/LoginPage/login-page.docs.md +1 -1
- package/runtime/knowledge/docs/shell/components/language-selector/language-selector.docs.md +1 -1
- package/runtime/knowledge/docs/shell/components/notification-dropdown/notification-dropdown.docs.md +1 -1
- package/runtime/knowledge/docs/shell/components/notification-template/notification-template.docs.md +1 -1
- package/runtime/knowledge/docs/shell/components/settings-menu/settings-menu.docs.md +7 -7
- package/runtime/knowledge/docs/shell/components/settings-menu-item/settings-menu-item.docs.md +2 -2
- package/runtime/knowledge/docs/shell/dashboard/draggable-dashboard/draggable-dashboard.docs.md +1 -1
- package/runtime/knowledge/docs/ui/components/atoms/vc-badge/vc-badge.docs.md +4 -4
- package/runtime/knowledge/docs/ui/components/atoms/vc-button/vc-button.docs.md +1 -1
- package/runtime/knowledge/docs/ui/components/atoms/vc-container/vc-container.docs.md +21 -1
- package/runtime/knowledge/docs/ui/components/atoms/vc-link/vc-link.docs.md +22 -6
- package/runtime/knowledge/docs/ui/components/atoms/vc-skeleton/vc-skeleton.docs.md +2 -2
- package/runtime/knowledge/docs/ui/components/atoms/vc-status-icon/vc-status-icon.docs.md +32 -26
- package/runtime/knowledge/docs/ui/components/atoms/vc-tooltip/vc-tooltip.docs.md +3 -3
- package/runtime/knowledge/docs/ui/components/molecules/multilanguage-selector/multilanguage-selector.docs.md +1 -1
- package/runtime/knowledge/docs/ui/components/molecules/vc-accordion/vc-accordion.docs.md +1 -1
- package/runtime/knowledge/docs/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.docs.md +1 -1
- package/runtime/knowledge/docs/ui/components/molecules/vc-dropdown-panel/vc-dropdown-panel.docs.md +13 -13
- package/runtime/knowledge/docs/ui/components/molecules/vc-form/vc-form.docs.md +1 -1
- package/runtime/knowledge/docs/ui/components/molecules/vc-pagination/vc-pagination.docs.md +1 -1
- package/runtime/knowledge/docs/ui/components/organisms/vc-app/vc-app.docs.md +4 -4
- package/runtime/knowledge/docs/ui/components/organisms/vc-blade/vc-blade.docs.md +39 -37
- package/runtime/knowledge/docs/ui/components/organisms/vc-data-table/vc-data-table.docs.md +17 -17
- package/runtime/knowledge/docs/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.docs.md +16 -7
- package/runtime/knowledge/docs/ui/components/organisms/vc-sidebar/vc-sidebar.docs.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.0.6](https://github.com/VirtoCommerce/vc-shell/compare/v2.0.5...v2.0.6) (2026-05-25)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- docs-sync improvements, lint rules, and reference docs alignment (#229) ([a3ddbc2](https://github.com/VirtoCommerce/vc-shell/commit/a3ddbc29a90e55632df702f776e11bc8bc4aec67)), closes [#229](https://github.com/VirtoCommerce/vc-shell/issues/229)
|
|
8
|
+
|
|
9
|
+
## [2.0.5](https://github.com/VirtoCommerce/vc-shell/compare/v2.0.4...v2.0.5) (2026-05-25)
|
|
10
|
+
|
|
11
|
+
**Note:** Version bump only for package @vc-shell/vc-app-skill
|
|
12
|
+
|
|
3
13
|
## [2.0.4](https://github.com/VirtoCommerce/vc-shell/compare/v2.0.3...v2.0.4) (2026-05-18)
|
|
4
14
|
|
|
5
15
|
**Note:** Version bump only for package @vc-shell/vc-app-skill
|
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ The skill covers:
|
|
|
22
22
|
### Claude Code / Cursor / GitHub Copilot
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
|
-
npx @vc-shell/vc-app-skill@
|
|
25
|
+
npx @vc-shell/vc-app-skill@latest install
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
Installs skill files into `~/.claude/vc-app-skill/` and registers the `/vc-app` slash command.
|
|
@@ -30,19 +30,19 @@ Installs skill files into `~/.claude/vc-app-skill/` and registers the `/vc-app`
|
|
|
30
30
|
### OpenCode
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
-
npx @vc-shell/vc-app-skill@
|
|
33
|
+
npx @vc-shell/vc-app-skill@latest install --runtime opencode
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
### Gemini CLI
|
|
37
37
|
|
|
38
38
|
```bash
|
|
39
|
-
npx @vc-shell/vc-app-skill@
|
|
39
|
+
npx @vc-shell/vc-app-skill@latest install --runtime gemini
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
### Codex
|
|
43
43
|
|
|
44
44
|
```bash
|
|
45
|
-
npx @vc-shell/vc-app-skill@
|
|
45
|
+
npx @vc-shell/vc-app-skill@latest install --runtime codex
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
### Verify installation
|
|
@@ -180,7 +180,7 @@ Handles topics: widgets, form management (`useBladeForm`), injection-key renames
|
|
|
180
180
|
## Update
|
|
181
181
|
|
|
182
182
|
```bash
|
|
183
|
-
npx @vc-shell/vc-app-skill@
|
|
183
|
+
npx @vc-shell/vc-app-skill@latest install
|
|
184
184
|
```
|
|
185
185
|
|
|
186
186
|
Or from within your AI tool:
|
|
@@ -194,7 +194,7 @@ The installer checks the installed version against the package version and overw
|
|
|
194
194
|
## Uninstall
|
|
195
195
|
|
|
196
196
|
```bash
|
|
197
|
-
npx @vc-shell/vc-app-skill@
|
|
197
|
+
npx @vc-shell/vc-app-skill@latest uninstall
|
|
198
198
|
```
|
|
199
199
|
|
|
200
200
|
Removes skill files from the AI tool's configuration directory. Does not affect your application source code.
|
|
@@ -202,7 +202,7 @@ Removes skill files from the AI tool's configuration directory. Does not affect
|
|
|
202
202
|
To uninstall for a specific runtime:
|
|
203
203
|
|
|
204
204
|
```bash
|
|
205
|
-
npx @vc-shell/vc-app-skill@
|
|
205
|
+
npx @vc-shell/vc-app-skill@latest uninstall --runtime opencode
|
|
206
206
|
```
|
|
207
207
|
|
|
208
208
|
## Architecture
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vc-shell/vc-app-skill",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.6",
|
|
4
4
|
"description": "AI coding skill for scaffolding and generating VirtoCommerce Shell applications. Works with Claude Code, OpenCode, Gemini, Codex, Cursor.",
|
|
5
5
|
"bin": "./bin/install.cjs",
|
|
6
6
|
"files": [
|
package/runtime/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.0.
|
|
1
|
+
2.0.6
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Synced from framework at commit
|
|
1
|
+
Synced from framework at commit a3ddbc29a on 2026-05-25T13:00:53.288Z
|
|
@@ -11,9 +11,9 @@ Auto-generated TypeScript API client for the VirtoCommerce Platform REST API. Ge
|
|
|
11
11
|
|
|
12
12
|
## Overview
|
|
13
13
|
|
|
14
|
-
Communicating with the VirtoCommerce platform backend requires typed HTTP client classes that match the platform's REST endpoints. Rather than manually writing fetch calls or Axios requests, the framework provides auto-generated client classes that handle URL construction, request serialization, response deserialization
|
|
14
|
+
Communicating with the VirtoCommerce platform backend requires typed HTTP client classes that match the platform's REST endpoints. Rather than manually writing fetch calls or Axios requests, the framework provides auto-generated client classes that handle URL construction, request serialization, and response deserialization.
|
|
15
15
|
|
|
16
|
-
Each API client class extends `AuthApiBase
|
|
16
|
+
Each API client class extends `AuthApiBase`. The base class carries an `authToken` field and, when that field has a value, attaches it as a `Bearer` header through `transformOptions`. In the default `useApiClient` flow, the client is instantiated without arguments and `authToken` stays empty — same-origin API calls are authenticated by the session cookie that the browser replays automatically. Code that needs to bypass cookies (cross-origin, non-browser, manual flows) can call `setAuthToken(token)` on a client instance directly. Data model types (DTOs, Commands, Queries) are generated as **interfaces** (not classes), so they cannot be instantiated with `new` -- use object literals with type annotations instead. The clients are generated by NSwag from the platform's Swagger/OpenAPI specification and should not be edited manually -- any manual changes will be overwritten during regeneration.
|
|
17
17
|
|
|
18
18
|
**File:** `platform.ts` (auto-generated, do not edit manually)
|
|
19
19
|
|
|
@@ -21,7 +21,7 @@ Each API client class extends `AuthApiBase`, which automatically attaches the Be
|
|
|
21
21
|
|
|
22
22
|
- Call platform-level REST endpoints (security, settings, notifications, modules, dynamic properties) from typed TypeScript clients
|
|
23
23
|
- Access platform DTOs (`ApplicationUser`, `PushNotification`, `Role`, `Permission`, etc.) as typed interfaces
|
|
24
|
-
- Combine with `useApiClient`
|
|
24
|
+
- Combine with `useApiClient` to obtain a configured client instance through a single composable
|
|
25
25
|
- When NOT to use: for domain-module APIs (orders, catalog, inventory) -- use their own generated clients instead; for third-party APIs -- use `fetch` or Axios directly
|
|
26
26
|
|
|
27
27
|
## API Clients
|
|
@@ -68,7 +68,7 @@ export class AuthApiBase {
|
|
|
68
68
|
authToken: string;
|
|
69
69
|
setAuthToken(token: string): void;
|
|
70
70
|
protected getBaseUrl(defaultUrl: string, baseUrl: string): string; // always returns ""
|
|
71
|
-
protected transformOptions(options: RequestInit): Promise<RequestInit>; //
|
|
71
|
+
protected transformOptions(options: RequestInit): Promise<RequestInit>; // sets the Bearer header only if `authToken` is non-empty
|
|
72
72
|
}
|
|
73
73
|
```
|
|
74
74
|
|
|
@@ -161,8 +161,8 @@ You do not need to manually set the auth token on client instances. The `useApiC
|
|
|
161
161
|
Do not import from the `platform.ts` file path directly. Always import from `@vc-shell/framework` to ensure proper module resolution and tree-shaking:
|
|
162
162
|
|
|
163
163
|
```typescript
|
|
164
|
-
// Bad: direct file
|
|
165
|
-
|
|
164
|
+
// Bad: direct file path
|
|
165
|
+
"@core/api/platform";
|
|
166
166
|
|
|
167
167
|
// Good: framework re-export
|
|
168
168
|
import { SecurityClient } from "@vc-shell/framework";
|
|
@@ -158,7 +158,7 @@ The plain data object stored in the stack for each blade:
|
|
|
158
158
|
## Related
|
|
159
159
|
|
|
160
160
|
- [`useBlade`](../composables/useBlade/) -- recommended API for everyday blade operations
|
|
161
|
-
- [`useBladeContext`](../composables/bladeContext/) -- share reactive blade data with descendant components
|
|
161
|
+
- [`useBladeContext`](../composables/bladeContext/index.docs.md) -- share reactive blade data with descendant components
|
|
162
162
|
|
|
163
163
|
<!-- internal:start -->
|
|
164
164
|
|
|
@@ -115,8 +115,8 @@ defineBladeContext(
|
|
|
115
115
|
|
|
116
116
|
## Related
|
|
117
117
|
|
|
118
|
-
- [`useBladeWidgets`](../useBladeWidgets/) -- widgets that consume blade context
|
|
119
|
-
- [`useBlade`](../useBlade/) -- cross-blade communication via `callParent` / `exposeToChildren`
|
|
118
|
+
- [`useBladeWidgets`](../useBladeWidgets/index.docs.md) -- widgets that consume blade context
|
|
119
|
+
- [`useBlade`](../useBlade/useBlade.docs.md) -- cross-blade communication via `callParent` / `exposeToChildren`
|
|
120
120
|
|
|
121
121
|
<!-- internal:start -->
|
|
122
122
|
|
|
@@ -6,31 +6,48 @@ group: data
|
|
|
6
6
|
|
|
7
7
|
# useApiClient
|
|
8
8
|
|
|
9
|
-
Creates a typed API client instance for communicating with VirtoCommerce platform APIs. The composable accepts a generated client class constructor and returns an async factory function that produces a
|
|
9
|
+
Creates a typed API client instance for communicating with VirtoCommerce platform APIs. The composable accepts a generated client class constructor (extending `AuthApiBase`) and returns an async factory function that produces a client instance. The composable itself is intentionally thin — it constructs the client and returns it. Platform authentication flows through the session cookie that the browser replays on every same-origin API call; the framework's fetch wrapper enforces timeout, offline checks, and 401-redirect on top.
|
|
10
10
|
|
|
11
11
|
!!! tip "Always call getApiClient inside async functions"
|
|
12
|
-
`getApiClient` is async. Never call it at the top level of `<script setup>` —
|
|
12
|
+
`getApiClient` is async. Never call it at the top level of `<script setup>` — call it inside the async function you pass to `useAsync`. Holding one client instance for the lifetime of the component couples your code to a single object across action runs; prefer one `await getApiClient()` per action so the call shape stays uniform with `useAsync`.
|
|
13
13
|
|
|
14
14
|
## When to Use
|
|
15
15
|
|
|
16
|
-
- Instantiate a generated VirtoCommerce API client
|
|
16
|
+
- Instantiate a generated VirtoCommerce API client that extends `AuthApiBase`
|
|
17
17
|
- Pair with `useAsync` for loading/error state on every API call in a blade or composable
|
|
18
18
|
- When NOT to use: for third-party or non-platform APIs that do not extend `AuthApiBase` -- use `fetch` or Axios directly
|
|
19
19
|
|
|
20
20
|
## Quick Start
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
<script setup lang="ts">
|
|
24
|
-
import { useApiClient } from "@vc-shell/framework";
|
|
25
|
-
import { OrderClient } from "@api/orders";
|
|
22
|
+
The canonical place to call `useApiClient` is at the top of a domain composable file. The factory is created once per module-scope; every action that needs the client awaits `getApiClient()` from the same closure.
|
|
26
23
|
|
|
27
|
-
|
|
24
|
+
```typescript title="modules/orders/composables/useOrder/index.ts"
|
|
25
|
+
// pseudo-code: replace OrderClient with your generated API client
|
|
26
|
+
import { useApiClient, useAsync } from "@vc-shell/framework";
|
|
27
|
+
import { OrderClient, type Order } from "@api/orders";
|
|
28
|
+
import { ref } from "vue";
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
|
|
30
|
+
export function useOrder() {
|
|
31
|
+
const { getApiClient } = useApiClient(OrderClient);
|
|
32
|
+
const item = ref<Order>();
|
|
33
|
+
|
|
34
|
+
const { action: loadItem, loading } = useAsync<{ id: string }>(async ({ id }) => {
|
|
35
|
+
const client = await getApiClient();
|
|
36
|
+
item.value = await client.getOrderById(id);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
return { item, loading, loadItem };
|
|
33
40
|
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
If you call `useApiClient` inside a blade's `<script setup>` directly, the same shape works. The composable pattern above is preferred because it keeps API access encapsulated behind a domain interface that the blade consumes.
|
|
44
|
+
|
|
45
|
+
```vue title="modules/orders/pages/order-details.vue"
|
|
46
|
+
<script setup lang="ts">
|
|
47
|
+
import { useOrder } from "../composables/useOrder";
|
|
48
|
+
|
|
49
|
+
const { item, loading, loadItem } = useOrder();
|
|
50
|
+
onMounted(() => loadItem({ id: param.value }));
|
|
34
51
|
</script>
|
|
35
52
|
```
|
|
36
53
|
|
|
@@ -39,6 +56,7 @@ async function loadOrder(orderId: string) {
|
|
|
39
56
|
The standard pattern for API calls in blades combines `useApiClient` with `useAsync`. This gives you automatic loading state, error handling, and a clean async action:
|
|
40
57
|
|
|
41
58
|
```typescript
|
|
59
|
+
// pseudo-code: replace ProductClient with your generated API client
|
|
42
60
|
<script setup lang="ts">
|
|
43
61
|
import { useApiClient, useAsync } from "@vc-shell/framework";
|
|
44
62
|
import { ProductClient, Product } from "@api/catalog";
|
|
@@ -78,6 +96,7 @@ The `loading` ref is `true` while the request is in-flight. The `error` ref capt
|
|
|
78
96
|
When a blade needs data from multiple platform modules, create multiple client instances using destructuring aliases:
|
|
79
97
|
|
|
80
98
|
```typescript
|
|
99
|
+
// pseudo-code: replace these clients with your generated API clients
|
|
81
100
|
<script setup lang="ts">
|
|
82
101
|
import { useApiClient, useAsync } from "@vc-shell/framework";
|
|
83
102
|
import { OrderClient } from "@api/orders";
|
|
@@ -105,6 +124,7 @@ const { action: loadOrderDetails } = useAsync(async (orderId: string) => {
|
|
|
105
124
|
API clients generated from VirtoCommerce platform endpoints follow a consistent search pattern with `SearchCriteria` objects:
|
|
106
125
|
|
|
107
126
|
```typescript
|
|
127
|
+
// pseudo-code: replace OrderClient with your generated API client
|
|
108
128
|
<script setup lang="ts">
|
|
109
129
|
import { useApiClient, useAsync } from "@vc-shell/framework";
|
|
110
130
|
import { OrderClient, OrderSearchCriteria, OrderSearchResult } from "@api/orders";
|
|
@@ -129,60 +149,63 @@ searchOrders();
|
|
|
129
149
|
|
|
130
150
|
## CRUD Operations Pattern
|
|
131
151
|
|
|
132
|
-
A complete CRUD composable for a domain entity:
|
|
152
|
+
A complete CRUD composable for a domain entity. The toolbar is declared as a plain `IBladeToolbar[]` array and bound via `<VcBlade :toolbar-items>`; reactive `disabled` follows the `loading` refs directly, without a `watch`/`updateToolbarItem` pair:
|
|
133
153
|
|
|
134
|
-
```
|
|
154
|
+
```vue
|
|
155
|
+
<!-- pseudo-code: replace ProductClient with your generated API client -->
|
|
135
156
|
<script setup lang="ts">
|
|
136
|
-
import {
|
|
137
|
-
import { useApiClient, useAsync,
|
|
138
|
-
import { ProductClient, Product } from "@api/catalog";
|
|
157
|
+
import { computed, onMounted, ref } from "vue";
|
|
158
|
+
import { useApiClient, useAsync, VcBlade, type IBladeToolbar } from "@vc-shell/framework";
|
|
159
|
+
import { ProductClient, type Product } from "@api/catalog";
|
|
139
160
|
|
|
140
161
|
const props = defineProps<{ param: string }>();
|
|
141
162
|
|
|
142
163
|
const { getApiClient } = useApiClient(ProductClient);
|
|
143
|
-
const { registerToolbarItem, updateToolbarItem } = useToolbar();
|
|
144
164
|
const product = ref<Product>();
|
|
145
165
|
|
|
146
|
-
// Load
|
|
147
166
|
const { loading, action: load } = useAsync(async () => {
|
|
148
167
|
const client = await getApiClient();
|
|
149
168
|
product.value = await client.getProductById(props.param);
|
|
150
169
|
});
|
|
151
170
|
|
|
152
|
-
// Save
|
|
153
171
|
const { loading: saving, action: save } = useAsync(async () => {
|
|
154
172
|
const client = await getApiClient();
|
|
155
173
|
product.value = await client.updateProduct(product.value);
|
|
156
174
|
});
|
|
157
175
|
|
|
158
|
-
// Delete
|
|
159
176
|
const { loading: deleting, action: remove } = useAsync(async () => {
|
|
160
177
|
const client = await getApiClient();
|
|
161
178
|
await client.deleteProducts([props.param]);
|
|
162
179
|
});
|
|
163
180
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
});
|
|
181
|
+
const busy = computed(() => saving.value || deleting.value || loading.value);
|
|
182
|
+
|
|
183
|
+
const bladeToolbar = ref<IBladeToolbar[]>([
|
|
184
|
+
{
|
|
185
|
+
id: "save",
|
|
186
|
+
title: "Save",
|
|
187
|
+
icon: "fas fa-save",
|
|
188
|
+
clickHandler: () => save(),
|
|
189
|
+
disabled: busy,
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
id: "refresh",
|
|
193
|
+
title: "Refresh",
|
|
194
|
+
icon: "fas fa-sync",
|
|
195
|
+
clickHandler: () => load(),
|
|
196
|
+
disabled: busy,
|
|
197
|
+
},
|
|
198
|
+
]);
|
|
183
199
|
|
|
184
200
|
onMounted(() => load());
|
|
185
201
|
</script>
|
|
202
|
+
|
|
203
|
+
<template>
|
|
204
|
+
<VcBlade
|
|
205
|
+
:loading="loading"
|
|
206
|
+
:toolbar-items="bladeToolbar"
|
|
207
|
+
/>
|
|
208
|
+
</template>
|
|
186
209
|
```
|
|
187
210
|
|
|
188
211
|
## Recipes
|
|
@@ -281,7 +304,7 @@ const response = await fetch("https://api.weather.com/forecast");
|
|
|
281
304
|
|
|
282
305
|
### IAuthApiBase Interface
|
|
283
306
|
|
|
284
|
-
All generated API client classes
|
|
307
|
+
All generated API client classes extend `AuthApiBase`, which conforms to this interface:
|
|
285
308
|
|
|
286
309
|
| Property / Method | Type | Description |
|
|
287
310
|
| ----------------- | ------------------------------------------------- | ----------------------------- |
|
|
@@ -289,6 +312,8 @@ All generated API client classes implement this interface:
|
|
|
289
312
|
| `setAuthToken` | `(token: string) => void` | Sets the authentication token |
|
|
290
313
|
| `getBaseUrl` | `(defaultUrl: string, baseUrl: string) => string` | Resolves the API base URL |
|
|
291
314
|
|
|
315
|
+
The interface is the public contract used by `useApiClient`'s type parameter. In the everyday flow, application code does not call `setAuthToken` — `useApiClient` constructs the client with no arguments, the `authToken` field stays empty, and authentication flows through the session cookie attached by the browser to each same-origin `/api/*` request. `setAuthToken` is the explicit-token path consumed by code that needs to attach a token directly (for example, when calling the API from a context where the cookie is unavailable).
|
|
316
|
+
|
|
292
317
|
### Generated Client Classes
|
|
293
318
|
|
|
294
319
|
API clients are generated from Swagger/OpenAPI specs using the `@vc-shell/api-client-generator` CLI tool. Each generated class:
|
|
@@ -302,5 +327,5 @@ API clients are generated from Swagger/OpenAPI specs using the `@vc-shell/api-cl
|
|
|
302
327
|
|
|
303
328
|
- [`useAsync`](../useAsync/) -- wraps async API calls with loading/error state management
|
|
304
329
|
- CLI API Client Generator (`@vc-shell/api-client-generator`) -- generates typed client classes from Swagger specs
|
|
305
|
-
- [`useToolbar`](../useToolbar/)
|
|
330
|
+
- Blade toolbar — declare as `ref<IBladeToolbar[]>([...])` and bind via `<VcBlade :toolbar-items>`; see [`useToolbar`](../useToolbar/) for the advanced dynamic-registration API
|
|
306
331
|
- [`useNotifications`](../useNotifications/) -- display success/error messages after API operations
|
|
@@ -13,7 +13,7 @@ Manages custom action buttons in the mobile app bar. Uses provide/inject to shar
|
|
|
13
13
|
- Register custom buttons (icons, components) in the mobile top bar from any blade or module
|
|
14
14
|
- Show notification badges, filter toggles, or action shortcuts in the mobile app bar
|
|
15
15
|
- Dynamically show/hide buttons based on blade state (e.g., only show a "filter" button when a list blade is active)
|
|
16
|
-
- When NOT to use: for desktop
|
|
16
|
+
- When NOT to use: for desktop blade toolbar actions, declare an `IBladeToolbar[]` array and pass it to `<VcBlade :toolbar-items>` (reach for `useToolbar` only when toolbar items must be added after mount); for buttons inside blade content, just use regular template markup
|
|
17
17
|
|
|
18
18
|
## Quick Start
|
|
19
19
|
|
|
@@ -137,6 +137,6 @@ onUnmounted(() => unregister("language-switcher"));
|
|
|
137
137
|
|
|
138
138
|
## Related
|
|
139
139
|
|
|
140
|
-
- `
|
|
140
|
+
- Desktop blade toolbar actions — declare an `IBladeToolbar[]` array bound via `<VcBlade :toolbar-items>`; `useToolbar` is the advanced API for dynamic registration after mount
|
|
141
141
|
- `framework/core/services/app-bar-mobile-buttons-service.ts` -- underlying service implementation
|
|
142
142
|
- `VcApp` -- provides the service via `provideAppBarMobileButtonsService()`
|
|
@@ -6,23 +6,25 @@ group: services
|
|
|
6
6
|
|
|
7
7
|
# useAppBarWidget
|
|
8
8
|
|
|
9
|
-
Provides access to the
|
|
9
|
+
Provides access to the widget service that powers the **Widgets** section of the App hub popover. Modules use it to register cross-app widgets — sync status indicators, language pickers, feature shortcuts — that the shell renders next to the apps grid in the hub. Uses Vue's provide/inject system.
|
|
10
10
|
|
|
11
11
|
Also exports `provideAppBarWidget()` for framework-level initialization.
|
|
12
12
|
|
|
13
|
+
> The `useAppBarWidget` name is a holdover from an earlier shell version where widgets rendered directly in the sidebar app-bar. In the current shell, the API name is the only place "app-bar" survives — the actual surface is the App hub popover.
|
|
14
|
+
|
|
13
15
|
## Overview
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
In the default VcApp shell, registered widgets render inside the **Widgets** section of the App hub popover (the panel that opens from the app-hub trigger button in the sidebar). The sidebar app-bar itself only holds the notification bell and the app-hub trigger; widgets do not appear there. On mobile, the same widgets surface in the hub tab and fly out below the panel when activated.
|
|
16
18
|
|
|
17
|
-
The `useAppBarWidget()` composable provides the `IAppBarWidgetService` interface, which allows registering, unregistering, and listing
|
|
19
|
+
The `useAppBarWidget()` composable provides the `IAppBarWidgetService` interface, which allows registering, unregistering, and listing widgets. Each widget is either an action widget (an icon plus an `onClick` handler) or a component widget (a custom Vue component that the hub expands inline when clicked).
|
|
18
20
|
|
|
19
21
|
The service follows the same provide/inject singleton pattern as other framework services. The framework calls `provideAppBarWidget()` during bootstrap; modules consume it via `useAppBarWidget()`.
|
|
20
22
|
|
|
21
23
|
## When to Use
|
|
22
24
|
|
|
23
|
-
- To register a
|
|
24
|
-
- To list or manage currently registered
|
|
25
|
-
- When NOT to use: for blade-level toolbar actions, use `useToolbar()`
|
|
25
|
+
- To register a cross-app widget (sync status, language picker, feature shortcut) in the App hub
|
|
26
|
+
- To list or manage currently registered hub widgets
|
|
27
|
+
- When NOT to use: for blade-level toolbar actions, declare an `IBladeToolbar[]` array and pass it to `<VcBlade :toolbar-items>` (use `useToolbar()` only for dynamic registration after mount)
|
|
26
28
|
|
|
27
29
|
## Basic Usage
|
|
28
30
|
|
|
@@ -49,16 +51,16 @@ None.
|
|
|
49
51
|
|
|
50
52
|
| Property / Method | Type | Description |
|
|
51
53
|
| ----------------- | -------------------------------------------------- | ---------------------------------------------------------- |
|
|
52
|
-
| `register` | `(options: registerAppBarWidgetOptions) => string` | Registers a widget in the
|
|
53
|
-
| `unregister` | `(id: string) => void` | Removes a widget from the
|
|
54
|
-
| `items` | `ComputedRef<AppBarWidget[]>` | Reactive list of all registered
|
|
54
|
+
| `register` | `(options: registerAppBarWidgetOptions) => string` | Registers a widget in the App hub, returns the assigned ID |
|
|
55
|
+
| `unregister` | `(id: string) => void` | Removes a widget from the App hub by ID |
|
|
56
|
+
| `items` | `ComputedRef<AppBarWidget[]>` | Reactive list of all registered hub widgets |
|
|
55
57
|
|
|
56
58
|
### registerAppBarWidgetOptions
|
|
57
59
|
|
|
58
60
|
| Field | Type | Required | Description |
|
|
59
61
|
| ----------- | ------------------------- | -------- | ------------------------------------------------------------- |
|
|
60
62
|
| `id` | `string` | No | Custom ID; auto-generated if omitted |
|
|
61
|
-
| `order` | `number` | No | Sort order in the
|
|
63
|
+
| `order` | `number` | No | Sort order in the hub Widgets list (lower = appears first) |
|
|
62
64
|
| `title` | `string` | No | Tooltip or label text |
|
|
63
65
|
| `icon` | `Component \| string` | No | Lucide icon name or a Vue component |
|
|
64
66
|
| `component` | `Component` | No | Custom Vue component to render instead of default icon button |
|
|
@@ -136,14 +138,14 @@ const { items } = useAppBarWidget();
|
|
|
136
138
|
|
|
137
139
|
// Iterate over all widgets (sorted by order)
|
|
138
140
|
watchEffect(() => {
|
|
139
|
-
console.log(`${items.value.length} widgets in
|
|
141
|
+
console.log(`${items.value.length} widgets in the App hub`);
|
|
140
142
|
items.value.forEach((w) => console.log(` - ${w.title ?? w.id}`));
|
|
141
143
|
});
|
|
142
144
|
```
|
|
143
145
|
|
|
144
146
|
### Pre-registration before service exists
|
|
145
147
|
|
|
146
|
-
If your module code runs before the
|
|
148
|
+
If your module code runs before the widget service is provided (e.g., during module `install()`), use the `addAppBarWidget()` bus function. Items are automatically flushed when `provideAppBarWidget()` runs:
|
|
147
149
|
|
|
148
150
|
```typescript
|
|
149
151
|
import { addAppBarWidget } from "@vc-shell/framework";
|
|
@@ -185,7 +187,7 @@ register({ component: markRaw(MyWidget) });
|
|
|
185
187
|
|
|
186
188
|
## Related
|
|
187
189
|
|
|
188
|
-
- [useToolbar](../useToolbar/)
|
|
190
|
+
- Blade toolbar actions — declare an `IBladeToolbar[]` array and bind it via `<VcBlade :toolbar-items>`; see [useToolbar](../useToolbar/) for the advanced dynamic-registration API
|
|
189
191
|
- [useWidgets](../useWidgets/useWidgets.docs.md) -- blade widget registration system
|
|
190
192
|
- `framework/injection-keys.ts` -- `AppBarWidgetServiceKey`
|
|
191
193
|
- `framework/core/services/app-bar-menu-service.ts` -- the underlying service implementation
|
|
@@ -6,7 +6,7 @@ group: utilities
|
|
|
6
6
|
|
|
7
7
|
# useAppInsights
|
|
8
8
|
|
|
9
|
-
Integrates Azure Application Insights page-view tracking with Vue Router and the current user context. This composable bridges the `vue3-application-insights` plugin with the vc-shell framework by automatically enriching every page-view event with the authenticated user's ID and name, generating fresh W3C trace IDs per navigation for distributed tracing, and optionally prefixing page names with the application name (
|
|
9
|
+
Integrates Azure Application Insights page-view tracking with Vue Router and the current user context. This composable bridges the `vue3-application-insights` plugin with the vc-shell framework by automatically enriching every page-view event with the authenticated user's ID and name, generating fresh W3C trace IDs per navigation for distributed tracing, and optionally prefixing page names with the application name (for example, `[Operations Console] Dashboard`).
|
|
10
10
|
|
|
11
11
|
## When to Use
|
|
12
12
|
|
|
@@ -42,17 +42,17 @@ export default router;
|
|
|
42
42
|
|
|
43
43
|
### Returns
|
|
44
44
|
|
|
45
|
-
| Property | Type | Description
|
|
46
|
-
| ------------------------------ | ----------------------------------------------------- |
|
|
47
|
-
| `setupPageTracking.beforeEach` | `(route: { name: string }) => void` | Call in router `beforeEach` to start page-view timing and generate a new trace ID
|
|
48
|
-
| `setupPageTracking.afterEach` | `(route: { name: string; fullPath: string }) => void` | Call in router `afterEach` to stop page-view timing and flush the telemetry event
|
|
49
|
-
| `appInsights` | `ApplicationInsights`
|
|
45
|
+
| Property | Type | Description |
|
|
46
|
+
| ------------------------------ | ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
47
|
+
| `setupPageTracking.beforeEach` | `(route: { name: string }) => void` | Call in router `beforeEach` to start page-view timing and generate a new trace ID |
|
|
48
|
+
| `setupPageTracking.afterEach` | `(route: { name: string; fullPath: string }) => void` | Call in router `afterEach` to stop page-view timing and flush the telemetry event |
|
|
49
|
+
| `appInsights` | `ApplicationInsights \| null` | Raw Application Insights instance for custom telemetry (`trackEvent`, `trackException`, `trackMetric`, etc.). `null` when the AI plugin is not installed -- `setupPageTracking` handlers are no-ops in that case. |
|
|
50
50
|
|
|
51
51
|
### Injection Key
|
|
52
52
|
|
|
53
|
-
| Key | Type | Description
|
|
54
|
-
| ----------------------- | ---------------------------------------- |
|
|
55
|
-
| `AppInsightsOptionsKey` | `InjectionKey<AppInsightsPluginOptions>` | Optional. Provide this at app level with `{ appName: '
|
|
53
|
+
| Key | Type | Description |
|
|
54
|
+
| ----------------------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------ |
|
|
55
|
+
| `AppInsightsOptionsKey` | `InjectionKey<AppInsightsPluginOptions>` | Optional. Provide this at app level with `{ appName: 'Operations Console' }` to prefix all page names. |
|
|
56
56
|
|
|
57
57
|
## How It Works
|
|
58
58
|
|
|
@@ -99,12 +99,12 @@ import { AppInsightsOptionsKey } from "@vc-shell/framework";
|
|
|
99
99
|
const app = createApp(App);
|
|
100
100
|
|
|
101
101
|
app.provide(AppInsightsOptionsKey, {
|
|
102
|
-
appName: "
|
|
102
|
+
appName: "Operations Console",
|
|
103
103
|
// ... other AppInsightsPluginOptions
|
|
104
104
|
});
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
-
This results in page names like `[
|
|
107
|
+
This results in page names like `[Operations Console] Dashboard` instead of just `Dashboard`.
|
|
108
108
|
|
|
109
109
|
## Tips
|
|
110
110
|
|
|
@@ -28,26 +28,27 @@ When the returned `action` is called, `useAsync` automatically:
|
|
|
28
28
|
## Quick Start
|
|
29
29
|
|
|
30
30
|
```typescript
|
|
31
|
+
// pseudo-code: replace OrderClient with your generated API client
|
|
31
32
|
import { useAsync, useApiClient } from "@vc-shell/framework";
|
|
32
33
|
import { OrderClient } from "@api/orders";
|
|
33
34
|
|
|
34
35
|
const { getApiClient } = useApiClient(OrderClient);
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
action: loadOrder,
|
|
40
|
-
} = useAsync<string>(async (id) => {
|
|
37
|
+
// Alias `loading` and `action` to domain names so multiple useAsync blocks in the
|
|
38
|
+
// same composable can coexist without colliding on `loading` / `action`.
|
|
39
|
+
const { loading: loadOrderLoading, action: loadOrder } = useAsync<string>(async (id) => {
|
|
41
40
|
const client = await getApiClient();
|
|
42
41
|
return await client.getOrderById(id);
|
|
43
42
|
});
|
|
44
43
|
|
|
45
|
-
// In a blade's onMounted:
|
|
46
44
|
await loadOrder("order-123");
|
|
47
|
-
//
|
|
48
|
-
//
|
|
45
|
+
// loadOrderLoading.value was true during the call, now false.
|
|
46
|
+
// Errors auto-toast through the default `notify: true` option — no need to read
|
|
47
|
+
// `error` unless you want to render a custom error UI.
|
|
49
48
|
```
|
|
50
49
|
|
|
50
|
+
Per-action aliasing scales: a CRUD composable typically has `loadItemLoading`, `saveItemLoading`, `removeItemLoading` from three separate `useAsync` calls. Aggregate them through `useLoading` to drive a single blade-level loading state.
|
|
51
|
+
|
|
51
52
|
## API Reference
|
|
52
53
|
|
|
53
54
|
### Import
|
|
@@ -204,6 +205,7 @@ const { action: silentRefresh } = useAsync(
|
|
|
204
205
|
The standard pattern for API operations in VC-Shell:
|
|
205
206
|
|
|
206
207
|
```typescript
|
|
208
|
+
// pseudo-code: replace VcmpSellerCatalogClient with your generated API client
|
|
207
209
|
import { useAsync, useApiClient } from "@vc-shell/framework";
|
|
208
210
|
import { VcmpSellerCatalogClient } from "@api/client";
|
|
209
211
|
|
|
@@ -246,6 +248,7 @@ The standard VC-Shell pattern: encapsulate all CRUD operations for an entity in
|
|
|
246
248
|
|
|
247
249
|
```typescript
|
|
248
250
|
// composables/useFulfillmentCenter/index.ts
|
|
251
|
+
// pseudo-code: replace VcmpSellerCatalogClient with your generated API client
|
|
249
252
|
import { useApiClient, useAsync, useLoading } from "@vc-shell/framework";
|
|
250
253
|
import { VcmpSellerCatalogClient, type FulfillmentCenter } from "@api/client";
|
|
251
254
|
|
|
@@ -423,9 +426,9 @@ const { action: save, loading: saveLoading } = useAsync(async () => saveData());
|
|
|
423
426
|
|
|
424
427
|
## Related
|
|
425
428
|
|
|
426
|
-
| Resource
|
|
427
|
-
|
|
|
428
|
-
| [`useApiClient`](../useApiClient/)
|
|
429
|
-
| [`useLoading`](../useLoading/)
|
|
430
|
-
| [`useModificationTracker`](../useModificationTracker/)
|
|
431
|
-
| [
|
|
429
|
+
| Resource | Description |
|
|
430
|
+
| ---------------------------------------------------------- | ----------------------------------------------------------------------------------- |
|
|
431
|
+
| [`useApiClient`](../useApiClient/) | Provides typed API client instances to pass into `useAsync` |
|
|
432
|
+
| [`useLoading`](../useLoading/) | Combines multiple `loading` refs into a single boolean |
|
|
433
|
+
| [`useModificationTracker`](../useModificationTracker/) | Tracks dirty state for forms -- often used alongside `useAsync` for save operations |
|
|
434
|
+
| [Notifications](../../notifications/notifications.docs.md) | The notification and toast system used by `useAsync` for error display |
|
|
@@ -8,11 +8,13 @@ group: utilities
|
|
|
8
8
|
|
|
9
9
|
Prevents the browser tab from closing when unsaved changes exist by hooking into the native `beforeunload` event. This composable is the last line of defense against accidental data loss -- it triggers the browser's built-in "Leave site?" confirmation dialog whenever the user tries to close or refresh the tab while the `modified` flag is `true`. It complements in-app guards (like blade `onBeforeClose`) by covering the case where the user bypasses the application entirely via the browser chrome.
|
|
10
10
|
|
|
11
|
+
> Form blades already wire this for you. `useBladeForm` registers `useBeforeUnload(isModified)` by default; pass `autoBeforeUnload: false` if you ever need to opt out. Reach for `useBeforeUnload` directly only when the unsaved state lives outside a form (a kanban board, a wizard, a custom editor not backed by `useBladeForm`).
|
|
12
|
+
|
|
11
13
|
## When to Use
|
|
12
14
|
|
|
13
|
-
- Protect
|
|
15
|
+
- Protect non-form blades with unsaved edits (kanban, wizard, custom editor) from accidental tab/window close or page refresh
|
|
14
16
|
- Pair with `useModificationTracker` to get a reactive `modified` flag automatically
|
|
15
|
-
- When NOT to use: for in-app navigation guards (use Vue Router `beforeRouteLeave` or blade `onBeforeClose` instead). This composable only handles the browser-level close/refresh event, not SPA route changes.
|
|
17
|
+
- When NOT to use: inside a blade backed by `useBladeForm` (the form already registers it); for in-app navigation guards (use Vue Router `beforeRouteLeave` or blade `onBeforeClose` instead). This composable only handles the browser-level close/refresh event, not SPA route changes.
|
|
16
18
|
|
|
17
19
|
## Quick Start
|
|
18
20
|
|