@chill-sharp/vue-client 1.1.12 → 1.1.15

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/README.md CHANGED
@@ -1,449 +1,449 @@
1
- # @chill-sharp/vue-client
2
-
3
- Vue helpers for a generic ChillSharp service.
4
-
5
- This package wraps [`@chill-sharp/ts-client`](../chill-sharp-ts-client) and adds:
6
-
7
- - `createChillSharpPlugin()` for app-wide client injection
8
- - `useChillSharpClient()` to access the raw client
9
- - `useSchema()` for localized schema loading
10
- - `useSchemaList()` for registered type discovery
11
- - `useText()` and `useTexts()` for i18n label lookups
12
- - `useTest()` for endpoint health checks
13
- - `useQueryMutation()`, `useLookupMutation()`, `useEntityMutation()`, `useAutocompleteMutation()`, and `useValidateMutation()` for generic API actions
14
-
15
- It stays generic on purpose. Payloads are plain objects so the same package can work against arbitrary ChillSharp models.
16
-
17
- ## Install
18
-
19
- From the repository root:
20
-
21
- ```bash
22
- cd extra/chill-sharp-vue-client
23
- npm install
24
- ```
25
-
26
- This package expects:
27
-
28
- - `vue` 3
29
- - `@chill-sharp/ts-client`
30
- - a runtime `fetch` implementation, which modern browsers and Node.js 18+ already provide
31
-
32
- ## Local Linking
33
-
34
- The package builds automatically on `npm install`, `npm pack`, and `npm link`.
35
- Link `@chill-sharp/ts-client` first, then this package:
36
-
37
- ```bash
38
- cd extra/chill-sharp-ts-client
39
- npm install
40
- npm link
41
-
42
- cd ../chill-sharp-vue-client
43
- npm install
44
- npm link
45
-
46
- cd path/to/your-vue-app
47
- npm link @chill-sharp/ts-client
48
- npm link @chill-sharp/vue-client
49
- ```
50
-
51
- ## Quick Start
52
-
53
- ```ts
54
- import { createApp, defineComponent } from "vue";
55
- import { createChillSharpPlugin, useSchema, useSchemaList, useText, useTexts } from "@chill-sharp/vue-client";
56
-
57
- const BlogSchemaName = defineComponent({
58
- setup() {
59
- const { data, isLoading, error } = useSchema("Model.Blog", "default");
60
- return { data, isLoading, error };
61
- },
62
- template: `
63
- <p v-if="isLoading">Loading...</p>
64
- <p v-else-if="error">Failed to load schema.</p>
65
- <h1 v-else>{{ String(data?.DisplayName ?? "") }}</h1>
66
- `
67
- });
68
-
69
- const app = createApp(BlogSchemaName);
70
-
71
- app.use(createChillSharpPlugin({
72
- baseUrl: "http://localhost:5000/api/chill",
73
- options: { cultureName: "it-IT" }
74
- }));
75
-
76
- app.mount("#app");
77
- ```
78
-
79
- ## Plugin Setup
80
-
81
- ### Plugin creates the client
82
-
83
- ```ts
84
- app.use(createChillSharpPlugin({
85
- baseUrl: "http://localhost:5000/api/chill",
86
- options: {
87
- cultureName: "it-IT",
88
- accessToken: "your-jwt-token"
89
- }
90
- }));
91
- ```
92
-
93
- ### Plugin receives a prebuilt client
94
-
95
- ```ts
96
- import { ChillSharpClient, createChillSharpPlugin } from "@chill-sharp/vue-client";
97
-
98
- const client = new ChillSharpClient("http://localhost:5000/api/chill", {
99
- cultureName: "it-IT"
100
- });
101
-
102
- app.use(createChillSharpPlugin({
103
- baseUrl: "http://localhost:5000/api/chill",
104
- client
105
- }));
106
- ```
107
-
108
- ## Composables
109
-
110
- ### `useChillSharpClient()`
111
-
112
- Use the raw client when you need the full API surface.
113
-
114
- ```ts
115
- import { defineComponent, onMounted, ref } from "vue";
116
- import { useChillSharpClient } from "@chill-sharp/vue-client";
117
-
118
- export default defineComponent({
119
- setup() {
120
- const client = useChillSharpClient();
121
- const count = ref(0);
122
-
123
- onMounted(async () => {
124
- const result = await client.query({
125
- ChillType: "Query.PostQuery",
126
- ResultProperties: [{ Name: "Guid" }]
127
- });
128
-
129
- const rows = Array.isArray(result.Results) ? result.Results : [];
130
- count.value = rows.length;
131
- });
132
-
133
- return { count };
134
- }
135
- });
136
- ```
137
-
138
- ### `useSchema()`
139
-
140
- `useSchema()` loads metadata and tracks `isLoading`, `error`, and `reload`.
141
-
142
- ```ts
143
- const { data, isLoading, error, reload } = useSchema("Model.Post", "default");
144
- const handleAttachments = computed(() => data.value?.handleAttachments ?? false);
145
- const relations = computed(() => data.value?.relations ?? []);
146
- ```
147
-
148
- You can override the plugin culture for one call:
149
-
150
- ```ts
151
- const englishSchema = useSchema("Model.Post", "default", "en-GB");
152
- ```
153
-
154
- Pass `update: true` as the fourth argument when you want the server to refresh a persisted schema from the current runtime model:
155
-
156
- ```ts
157
- const refreshedSchema = useSchema("Model.Post", "default", undefined, true);
158
- ```
159
-
160
- Existing properties keep their saved metadata, new model properties are added, and removed model properties are dropped from the persisted schema.
161
-
162
- The schema and entity-option payloads re-exported by this package include `handleAttachments` and schema-level `relations`. Query payloads also include `ordering`, and entity payloads include `position` with backend default `0`.
163
-
164
- `useSchema()` also accepts refs:
165
-
166
- ```ts
167
- const chillType = ref("Model.Post");
168
- const schema = useSchema(chillType, "default");
169
- ```
170
-
171
- ### `useSchemaList()`
172
-
173
- ```ts
174
- const schemaListState = useSchemaList();
175
- const englishSchemaListState = useSchemaList("en-GB");
176
- ```
177
-
178
- ### `useText()`
179
-
180
- ```ts
181
- const textState = useText({
182
- LabelGuid: "4e16f6c0-6b95-4d67-98bc-9f4d0d63eaf1",
183
- CultureName: "it-IT",
184
- PrimaryCultureName: "en-GB",
185
- PrimaryDefaultText: "Blog title",
186
- SecondaryCultureName: "it-IT",
187
- SecondaryDefaultText: "Titolo del blog"
188
- });
189
- ```
190
-
191
- ### `useTexts()`
192
-
193
- ```ts
194
- const textsState = useTexts([
195
- {
196
- LabelGuid: "4e16f6c0-6b95-4d67-98bc-9f4d0d63eaf1",
197
- CultureName: "it-IT",
198
- PrimaryCultureName: "en-GB",
199
- PrimaryDefaultText: "Blog title",
200
- SecondaryCultureName: "it-IT",
201
- SecondaryDefaultText: "Titolo del blog"
202
- },
203
- {
204
- LabelGuid: "2f6ef6f7-b0a9-44f8-bfd2-a3b3ed5b9a81",
205
- CultureName: "it-IT",
206
- PrimaryCultureName: "en-GB",
207
- PrimaryDefaultText: "Blog url",
208
- SecondaryCultureName: "it-IT",
209
- SecondaryDefaultText: "Url del blog"
210
- }
211
- ]);
212
- ```
213
-
214
- ### `useTest()`
215
-
216
- ```ts
217
- const statusState = useTest();
218
- ```
219
-
220
- `useTest()` calls `GET /api/chill/test` and exposes the plain-text service status.
221
-
222
- ### `useQueryMutation()`
223
-
224
- Use `useQueryMutation()` when `ChillType` points to a concrete query type such as `Query.PostQuery`.
225
-
226
- ` s
227
- const { execute, data, isLoading } = useQueryMutation();
228
-
229
- async function runQuery() {
230
- await execute({
231
- chillType: "Query.PostQuery",
232
- properties: { title: "Hello" },
233
- ordering: {
234
- propertyName: "Position",
235
- direction: "ASC"
236
- },
237
- resultProperties: [{ name: "Guid" }, { name: "Title" }]
238
- });
239
- }
240
- ```
241
-
242
- If `ordering.propertyName` points to a Chill entity reference, the backend orders by that referenced entity `Label`.
243
-
244
- ### `useLookupMutation()`
245
-
246
- ```ts
247
- const lookupPosts = useLookupMutation();
248
-
249
- await lookupPosts.execute({
250
- chillType: "Model.Post",
251
- properties: {
252
- fullTextSearch: "Ada Lovelace"
253
- },
254
- ordering: {
255
- propertyName: "Blog",
256
- direction: "ASC"
257
- },
258
- resultProperties: [{ name: "Guid" }, { name: "Title" }]
259
- });
260
- ```
261
-
262
- Use `useLookupMutation()` when `ChillType` points to an entity type and you only need generic full-text search.
263
-
264
- ### `useAutocompleteMutation()`
265
-
266
- ```ts
267
- const autocompletePost = useAutocompleteMutation();
268
-
269
- await autocompletePost.execute({
270
- ChillType: "Model.Post",
271
- Properties: {
272
- Title: " Draft title "
273
- }
274
- });
275
- ```
276
-
277
- ### `useValidateMutation()`
278
-
279
- ```ts
280
- const validatePost = useValidateMutation();
281
-
282
- const errors = await validatePost.execute({
283
- ChillType: "Model.Post",
284
- Properties: {
285
- Title: ""
286
- }
287
- });
288
- ```
289
-
290
- ### `useEntityMutation()`
291
-
292
- Use one composable instance per entity action:
293
-
294
- ```ts
295
- const createPost = useEntityMutation("create");
296
- const updatePost = useEntityMutation("update");
297
- const deletePost = useEntityMutation("delete");
298
- ```
299
-
300
- Example:
301
-
302
- ```ts
303
- await createPost.execute({
304
- chillType: "Model.Post",
305
- guid: crypto.randomUUID(),
306
- position: 10,
307
- properties: {
308
- title: "New title",
309
- author: "Grace Hopper"
310
- }
311
- });
312
- ```
313
-
314
- ## Attachments
315
-
316
- Use the raw client from `useChillSharpClient()` for attachment helpers:
317
-
318
- ```ts
319
- const client = useChillSharpClient();
320
-
321
- await client.uploadAttachment(
322
- {
323
- ChillType: "Model.Post",
324
- Guid: postGuid
325
- },
326
- {
327
- fileName: "contract.txt",
328
- content: new Blob(["hello attachment"], { type: "text/plain" }),
329
- contentType: "text/plain"
330
- },
331
- {
332
- title: "Contract",
333
- description: "Signed draft",
334
- isPublic: false
335
- }
336
- );
337
-
338
- const attachments = await client.getAttachments({
339
- ChillType: "Model.Post",
340
- Guid: postGuid
341
- });
342
- ```
343
-
344
- ## Chunk batches
345
-
346
- Call `chunk()` through `useChillSharpClient()` when several operations should be sent in one request.
347
-
348
- ```ts
349
- const client = useChillSharpClient();
350
-
351
- await client.chunk([
352
- { Index: 0, Verb: "transaction" },
353
- {
354
- Index: 1,
355
- Verb: "create",
356
- Entity: {
357
- ChillType: "Model.Post",
358
- Guid: crypto.randomUUID(),
359
- Properties: {
360
- Title: "Batched post",
361
- Author: "Grace Hopper"
362
- }
363
- }
364
- },
365
- {
366
- Index: 2,
367
- Verb: "update",
368
- Entity: {
369
- ChillType: "Model.Post",
370
- Guid: existingGuid,
371
- Properties: {
372
- Title: "Updated in the same batch"
373
- }
374
- }
375
- },
376
- { Index: 3, Verb: "commit" }
377
- ]);
378
- ```
379
-
380
- Use `transaction` and `commit` only when the enclosed write operations must be committed together.
381
-
382
- ## Authentication
383
-
384
- Because the Vue package reuses the TypeScript client, it inherits the same auth behavior:
385
-
386
- - pass `accessToken` when you already have a token
387
- - pass `username` and `password` when the client should log in and refresh automatically
388
- - pass `DisplayCultureName` during registration when the server should preset auth-user display preferences
389
- - call `useChillSharpClient()` when you need direct access to auth account methods, auth management methods, or schema-management methods like `getEntityOptions()`, `setEntityOptions()`, `getMenu()`, `setMenu()`, and `deleteMenu()`
390
- - schema and entity option payloads re-exported by this package include the `handleAttachments` flag from `@chill-sharp/ts-client`
391
- - query payloads re-exported by this package include `ordering`, and entity payloads include `position`
392
-
393
- Auth user list/detail payloads exposed through the raw client include:
394
-
395
- - `displayCultureName`
396
- - `displayTimeZone`
397
- - `displayDateFormat`
398
- - `displayNumberFormat`
399
-
400
- ## Error Handling
401
-
402
- The composables expose the last thrown error. The underlying client throws `ChillSharpClientError`.
403
-
404
- ```ts
405
- import { computed } from "vue";
406
- import { ChillSharpClientError, useSchema } from "@chill-sharp/vue-client";
407
-
408
- const { error } = useSchema("Model.Post", "default");
409
-
410
- const errorText = computed(() => {
411
- return error.value instanceof ChillSharpClientError
412
- ? error.value.responseText ?? ""
413
- : "";
414
- });
415
- ```
416
-
417
- ## When To Use The Vue Package
418
-
419
- Use this package when you want Vue-friendly state handling on top of the generic client.
420
-
421
- Use the plain TypeScript package instead when:
422
-
423
- - you are not using Vue
424
- - you already have your own data-fetching layer
425
- - you want complete control over caching, retries, and optimistic updates
426
-
427
- ## Generic Payload Strategy
428
-
429
- This package does not generate components or model-specific composables for your Chill entities.
430
-
431
- That is intentional:
432
-
433
- - ChillSharp models are application-specific
434
- - generic object payloads are enough to talk to the standard ChillSharp API
435
- - model-specific Vue composables are better generated from OpenAPI for each host application
436
-
437
- If you need typed model clients, generate them from your host OpenAPI document as described in [doc/ClientGeneration/README.md](../../doc/ClientGeneration/README.md).
438
-
439
-
440
-
441
-
442
-
443
-
444
-
445
- ## Menu endpoints
446
-
447
- When you use the raw client from `useChillSharpClient()`, `getMenu()` loads root menu nodes or the direct children of one menu item, `setMenu()` creates or updates one menu item, and `deleteMenu()` removes one menu item together with its child subtree. Menu items include `positionNo`, which the backend persists and uses to order siblings.
448
-
1
+ # @chill-sharp/vue-client
2
+
3
+ Vue helpers for a generic ChillSharp service.
4
+
5
+ This package wraps [`@chill-sharp/ts-client`](../chill-sharp-ts-client) and adds:
6
+
7
+ - `createChillSharpPlugin()` for app-wide client injection
8
+ - `useChillSharpClient()` to access the raw client
9
+ - `useSchema()` for localized schema loading
10
+ - `useSchemaList()` for registered type discovery
11
+ - `useText()` and `useTexts()` for i18n label lookups
12
+ - `useTest()` for endpoint health checks
13
+ - `useQueryMutation()`, `useLookupMutation()`, `useEntityMutation()`, `useAutocompleteMutation()`, and `useValidateMutation()` for generic API actions
14
+
15
+ It stays generic on purpose. Payloads are plain objects so the same package can work against arbitrary ChillSharp models.
16
+
17
+ ## Install
18
+
19
+ From the repository root:
20
+
21
+ ```bash
22
+ cd extra/chill-sharp-vue-client
23
+ npm install
24
+ ```
25
+
26
+ This package expects:
27
+
28
+ - `vue` 3
29
+ - `@chill-sharp/ts-client`
30
+ - a runtime `fetch` implementation, which modern browsers and Node.js 18+ already provide
31
+
32
+ ## Local Linking
33
+
34
+ The package builds automatically on `npm install`, `npm pack`, and `npm link`.
35
+ Link `@chill-sharp/ts-client` first, then this package:
36
+
37
+ ```bash
38
+ cd extra/chill-sharp-ts-client
39
+ npm install
40
+ npm link
41
+
42
+ cd ../chill-sharp-vue-client
43
+ npm install
44
+ npm link
45
+
46
+ cd path/to/your-vue-app
47
+ npm link @chill-sharp/ts-client
48
+ npm link @chill-sharp/vue-client
49
+ ```
50
+
51
+ ## Quick Start
52
+
53
+ ```ts
54
+ import { createApp, defineComponent } from "vue";
55
+ import { createChillSharpPlugin, useSchema, useSchemaList, useText, useTexts } from "@chill-sharp/vue-client";
56
+
57
+ const BlogSchemaName = defineComponent({
58
+ setup() {
59
+ const { data, isLoading, error } = useSchema("Model.Blog", "default");
60
+ return { data, isLoading, error };
61
+ },
62
+ template: `
63
+ <p v-if="isLoading">Loading...</p>
64
+ <p v-else-if="error">Failed to load schema.</p>
65
+ <h1 v-else>{{ String(data?.DisplayName ?? "") }}</h1>
66
+ `
67
+ });
68
+
69
+ const app = createApp(BlogSchemaName);
70
+
71
+ app.use(createChillSharpPlugin({
72
+ baseUrl: "http://localhost:5000/api/chill",
73
+ options: { cultureName: "it-IT" }
74
+ }));
75
+
76
+ app.mount("#app");
77
+ ```
78
+
79
+ ## Plugin Setup
80
+
81
+ ### Plugin creates the client
82
+
83
+ ```ts
84
+ app.use(createChillSharpPlugin({
85
+ baseUrl: "http://localhost:5000/api/chill",
86
+ options: {
87
+ cultureName: "it-IT",
88
+ accessToken: "your-jwt-token"
89
+ }
90
+ }));
91
+ ```
92
+
93
+ ### Plugin receives a prebuilt client
94
+
95
+ ```ts
96
+ import { ChillSharpClient, createChillSharpPlugin } from "@chill-sharp/vue-client";
97
+
98
+ const client = new ChillSharpClient("http://localhost:5000/api/chill", {
99
+ cultureName: "it-IT"
100
+ });
101
+
102
+ app.use(createChillSharpPlugin({
103
+ baseUrl: "http://localhost:5000/api/chill",
104
+ client
105
+ }));
106
+ ```
107
+
108
+ ## Composables
109
+
110
+ ### `useChillSharpClient()`
111
+
112
+ Use the raw client when you need the full API surface.
113
+
114
+ ```ts
115
+ import { defineComponent, onMounted, ref } from "vue";
116
+ import { useChillSharpClient } from "@chill-sharp/vue-client";
117
+
118
+ export default defineComponent({
119
+ setup() {
120
+ const client = useChillSharpClient();
121
+ const count = ref(0);
122
+
123
+ onMounted(async () => {
124
+ const result = await client.query({
125
+ ChillType: "Query.PostQuery",
126
+ ResultProperties: [{ Name: "Guid" }]
127
+ });
128
+
129
+ const rows = Array.isArray(result.Results) ? result.Results : [];
130
+ count.value = rows.length;
131
+ });
132
+
133
+ return { count };
134
+ }
135
+ });
136
+ ```
137
+
138
+ ### `useSchema()`
139
+
140
+ `useSchema()` loads metadata and tracks `isLoading`, `error`, and `reload`.
141
+
142
+ ```ts
143
+ const { data, isLoading, error, reload } = useSchema("Model.Post", "default");
144
+ const handleAttachments = computed(() => data.value?.handleAttachments ?? false);
145
+ const relations = computed(() => data.value?.relations ?? []);
146
+ ```
147
+
148
+ You can override the plugin culture for one call:
149
+
150
+ ```ts
151
+ const englishSchema = useSchema("Model.Post", "default", "en-GB");
152
+ ```
153
+
154
+ Pass `update: true` as the fourth argument when you want the server to refresh a persisted schema from the current runtime model:
155
+
156
+ ```ts
157
+ const refreshedSchema = useSchema("Model.Post", "default", undefined, true);
158
+ ```
159
+
160
+ Existing properties keep their saved metadata, new model properties are added, and removed model properties are dropped from the persisted schema.
161
+
162
+ The schema and entity-option payloads re-exported by this package include `handleAttachments` and schema-level `relations`. Query payloads also include `ordering`, and entity payloads include `position` with backend default `0`.
163
+
164
+ `useSchema()` also accepts refs:
165
+
166
+ ```ts
167
+ const chillType = ref("Model.Post");
168
+ const schema = useSchema(chillType, "default");
169
+ ```
170
+
171
+ ### `useSchemaList()`
172
+
173
+ ```ts
174
+ const schemaListState = useSchemaList();
175
+ const englishSchemaListState = useSchemaList("en-GB");
176
+ ```
177
+
178
+ ### `useText()`
179
+
180
+ ```ts
181
+ const textState = useText({
182
+ LabelGuid: "4e16f6c0-6b95-4d67-98bc-9f4d0d63eaf1",
183
+ CultureName: "it-IT",
184
+ PrimaryCultureName: "en-GB",
185
+ PrimaryDefaultText: "Blog title",
186
+ SecondaryCultureName: "it-IT",
187
+ SecondaryDefaultText: "Titolo del blog"
188
+ });
189
+ ```
190
+
191
+ ### `useTexts()`
192
+
193
+ ```ts
194
+ const textsState = useTexts([
195
+ {
196
+ LabelGuid: "4e16f6c0-6b95-4d67-98bc-9f4d0d63eaf1",
197
+ CultureName: "it-IT",
198
+ PrimaryCultureName: "en-GB",
199
+ PrimaryDefaultText: "Blog title",
200
+ SecondaryCultureName: "it-IT",
201
+ SecondaryDefaultText: "Titolo del blog"
202
+ },
203
+ {
204
+ LabelGuid: "2f6ef6f7-b0a9-44f8-bfd2-a3b3ed5b9a81",
205
+ CultureName: "it-IT",
206
+ PrimaryCultureName: "en-GB",
207
+ PrimaryDefaultText: "Blog url",
208
+ SecondaryCultureName: "it-IT",
209
+ SecondaryDefaultText: "Url del blog"
210
+ }
211
+ ]);
212
+ ```
213
+
214
+ ### `useTest()`
215
+
216
+ ```ts
217
+ const statusState = useTest();
218
+ ```
219
+
220
+ `useTest()` calls `GET /api/chill/test` and exposes the plain-text service status.
221
+
222
+ ### `useQueryMutation()`
223
+
224
+ Use `useQueryMutation()` when `ChillType` points to a concrete query type such as `Query.PostQuery`.
225
+
226
+ ` s
227
+ const { execute, data, isLoading } = useQueryMutation();
228
+
229
+ async function runQuery() {
230
+ await execute({
231
+ chillType: "Query.PostQuery",
232
+ properties: { title: "Hello" },
233
+ ordering: {
234
+ propertyName: "Position",
235
+ direction: "ASC"
236
+ },
237
+ resultProperties: [{ name: "Guid" }, { name: "Title" }]
238
+ });
239
+ }
240
+ ```
241
+
242
+ If `ordering.propertyName` points to a Chill entity reference, the backend orders by that referenced entity `Label`.
243
+
244
+ ### `useLookupMutation()`
245
+
246
+ ```ts
247
+ const lookupPosts = useLookupMutation();
248
+
249
+ await lookupPosts.execute({
250
+ chillType: "Model.Post",
251
+ properties: {
252
+ fullTextSearch: "Ada Lovelace"
253
+ },
254
+ ordering: {
255
+ propertyName: "Blog",
256
+ direction: "ASC"
257
+ },
258
+ resultProperties: [{ name: "Guid" }, { name: "Title" }]
259
+ });
260
+ ```
261
+
262
+ Use `useLookupMutation()` when `ChillType` points to an entity type and you only need generic full-text search.
263
+
264
+ ### `useAutocompleteMutation()`
265
+
266
+ ```ts
267
+ const autocompletePost = useAutocompleteMutation();
268
+
269
+ await autocompletePost.execute({
270
+ ChillType: "Model.Post",
271
+ Properties: {
272
+ Title: " Draft title "
273
+ }
274
+ });
275
+ ```
276
+
277
+ ### `useValidateMutation()`
278
+
279
+ ```ts
280
+ const validatePost = useValidateMutation();
281
+
282
+ const errors = await validatePost.execute({
283
+ ChillType: "Model.Post",
284
+ Properties: {
285
+ Title: ""
286
+ }
287
+ });
288
+ ```
289
+
290
+ ### `useEntityMutation()`
291
+
292
+ Use one composable instance per entity action:
293
+
294
+ ```ts
295
+ const createPost = useEntityMutation("create");
296
+ const updatePost = useEntityMutation("update");
297
+ const deletePost = useEntityMutation("delete");
298
+ ```
299
+
300
+ Example:
301
+
302
+ ```ts
303
+ await createPost.execute({
304
+ chillType: "Model.Post",
305
+ guid: crypto.randomUUID(),
306
+ position: 10,
307
+ properties: {
308
+ title: "New title",
309
+ author: "Grace Hopper"
310
+ }
311
+ });
312
+ ```
313
+
314
+ ## Attachments
315
+
316
+ Use the raw client from `useChillSharpClient()` for attachment helpers:
317
+
318
+ ```ts
319
+ const client = useChillSharpClient();
320
+
321
+ await client.uploadAttachment(
322
+ {
323
+ ChillType: "Model.Post",
324
+ Guid: postGuid
325
+ },
326
+ {
327
+ fileName: "contract.txt",
328
+ content: new Blob(["hello attachment"], { type: "text/plain" }),
329
+ contentType: "text/plain"
330
+ },
331
+ {
332
+ title: "Contract",
333
+ description: "Signed draft",
334
+ isPublic: false
335
+ }
336
+ );
337
+
338
+ const attachments = await client.getAttachments({
339
+ ChillType: "Model.Post",
340
+ Guid: postGuid
341
+ });
342
+ ```
343
+
344
+ ## Chunk batches
345
+
346
+ Call `chunk()` through `useChillSharpClient()` when several operations should be sent in one request.
347
+
348
+ ```ts
349
+ const client = useChillSharpClient();
350
+
351
+ await client.chunk([
352
+ { Index: 0, Verb: "transaction" },
353
+ {
354
+ Index: 1,
355
+ Verb: "create",
356
+ Entity: {
357
+ ChillType: "Model.Post",
358
+ Guid: crypto.randomUUID(),
359
+ Properties: {
360
+ Title: "Batched post",
361
+ Author: "Grace Hopper"
362
+ }
363
+ }
364
+ },
365
+ {
366
+ Index: 2,
367
+ Verb: "update",
368
+ Entity: {
369
+ ChillType: "Model.Post",
370
+ Guid: existingGuid,
371
+ Properties: {
372
+ Title: "Updated in the same batch"
373
+ }
374
+ }
375
+ },
376
+ { Index: 3, Verb: "commit" }
377
+ ]);
378
+ ```
379
+
380
+ Use `transaction` and `commit` only when the enclosed write operations must be committed together.
381
+
382
+ ## Authentication
383
+
384
+ Because the Vue package reuses the TypeScript client, it inherits the same auth behavior:
385
+
386
+ - pass `accessToken` when you already have a token
387
+ - pass `username` and `password` when the client should log in and refresh automatically
388
+ - pass `DisplayCultureName` during registration when the server should preset auth-user display preferences
389
+ - call `useChillSharpClient()` when you need direct access to auth account methods, auth management methods, or schema-management methods like `getEntityOptions()`, `setEntityOptions()`, `getMenu()`, `setMenu()`, and `deleteMenu()`
390
+ - schema and entity option payloads re-exported by this package include the `handleAttachments` flag from `@chill-sharp/ts-client`
391
+ - query payloads re-exported by this package include `ordering`, and entity payloads include `position`
392
+
393
+ Auth user list/detail payloads exposed through the raw client include:
394
+
395
+ - `displayCultureName`
396
+ - `displayTimeZone`
397
+ - `displayDateFormat`
398
+ - `displayNumberFormat`
399
+
400
+ ## Error Handling
401
+
402
+ The composables expose the last thrown error. The underlying client throws `ChillSharpClientError`.
403
+
404
+ ```ts
405
+ import { computed } from "vue";
406
+ import { ChillSharpClientError, useSchema } from "@chill-sharp/vue-client";
407
+
408
+ const { error } = useSchema("Model.Post", "default");
409
+
410
+ const errorText = computed(() => {
411
+ return error.value instanceof ChillSharpClientError
412
+ ? error.value.responseText ?? ""
413
+ : "";
414
+ });
415
+ ```
416
+
417
+ ## When To Use The Vue Package
418
+
419
+ Use this package when you want Vue-friendly state handling on top of the generic client.
420
+
421
+ Use the plain TypeScript package instead when:
422
+
423
+ - you are not using Vue
424
+ - you already have your own data-fetching layer
425
+ - you want complete control over caching, retries, and optimistic updates
426
+
427
+ ## Generic Payload Strategy
428
+
429
+ This package does not generate components or model-specific composables for your Chill entities.
430
+
431
+ That is intentional:
432
+
433
+ - ChillSharp models are application-specific
434
+ - generic object payloads are enough to talk to the standard ChillSharp API
435
+ - model-specific Vue composables are better generated from OpenAPI for each host application
436
+
437
+ If you need typed model clients, generate them from your host OpenAPI document as described in [doc/ClientGeneration/README.md](../../doc/ClientGeneration/README.md).
438
+
439
+
440
+
441
+
442
+
443
+
444
+
445
+ ## Menu endpoints
446
+
447
+ When you use the raw client from `useChillSharpClient()`, `getMenu()` loads root menu nodes or the direct children of one menu item, `setMenu()` creates or updates one menu item, and `deleteMenu()` removes one menu item together with its child subtree. Menu items include `positionNo`, which the backend persists and uses to order siblings.
448
+
449
449
  For the complete tree model, delete behavior, and `MenuHierarchy` filtering behavior, see [../../doc/MenuGuide/README.md](../../doc/MenuGuide/README.md).