@ramathibodi/nuxt-commons 4.0.4 → 4.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.
@@ -37,12 +37,12 @@ declare function openDialog(item?: object): void;
37
37
  declare var __VLS_15: {
38
38
  operation: {
39
39
  openDialog: typeof openDialog;
40
- createItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<void>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<any>);
41
- importItems: ((importItems: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void) | ((importItemsList: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void);
42
- updateItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<void>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>);
43
- deleteItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<unknown>);
44
- reload: (() => void) | (() => void);
45
- setSearch: ((keyword: string) => void) | ((keyword: string) => void);
40
+ createItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<any>;
41
+ importItems: (importItemsList: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void;
42
+ updateItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>;
43
+ deleteItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>;
44
+ reload: () => void;
45
+ setSearch: (keyword: string) => void;
46
46
  canServerPageable: boolean;
47
47
  canServerSearch: boolean;
48
48
  canCreate: boolean;
@@ -73,12 +73,12 @@ declare var __VLS_15: {
73
73
  item: import("vuetify/lib/components/VDataIterator/composables/items.mjs").DataIteratorItem<Record<string, any>>;
74
74
  operation: {
75
75
  openDialog: typeof openDialog;
76
- createItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<void>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<any>);
77
- importItems: ((importItems: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void) | ((importItemsList: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void);
78
- updateItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<void>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>);
79
- deleteItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<unknown>);
80
- reload: (() => void) | (() => void);
81
- setSearch: ((keyword: string) => void) | ((keyword: string) => void);
76
+ createItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<any>;
77
+ importItems: (importItemsList: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void;
78
+ updateItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>;
79
+ deleteItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>;
80
+ reload: () => void;
81
+ setSearch: (keyword: string) => void;
82
82
  canServerPageable: boolean;
83
83
  canServerSearch: boolean;
84
84
  canCreate: boolean;
@@ -92,12 +92,12 @@ declare var __VLS_15: {
92
92
  items: Record<string, any>[];
93
93
  operation: {
94
94
  openDialog: typeof openDialog;
95
- createItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<void>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<any>);
96
- importItems: ((importItems: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void) | ((importItemsList: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void);
97
- updateItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<void>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>);
98
- deleteItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<unknown>);
99
- reload: (() => void) | (() => void);
100
- setSearch: ((keyword: string) => void) | ((keyword: string) => void);
95
+ createItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<any>;
96
+ importItems: (importItemsList: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void;
97
+ updateItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>;
98
+ deleteItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>;
99
+ reload: () => void;
100
+ setSearch: (keyword: string) => void;
101
101
  canServerPageable: boolean;
102
102
  canServerSearch: boolean;
103
103
  canCreate: boolean;
@@ -124,17 +124,17 @@ declare var __VLS_15: {
124
124
  itemsCount: number;
125
125
  groupedItems: readonly (import("vuetify/lib/components/VDataIterator/composables/items.mjs").DataIteratorItem<Record<string, any>> | import("vuetify/lib/components/VDataTable/composables/group.mjs").Group<import("vuetify/lib/components/VDataIterator/composables/items.mjs").DataIteratorItem<Record<string, any>>> | import("vuetify/lib/components/VDataTable/composables/group.mjs").GroupSummary<import("vuetify/lib/components/VDataIterator/composables/items.mjs").DataIteratorItem<Record<string, any>>>)[];
126
126
  }, __VLS_92: {
127
- reload: (() => void) | (() => void);
127
+ reload: () => void;
128
128
  }, __VLS_108: {
129
129
  items: Record<string, any>[];
130
130
  operation: {
131
131
  openDialog: typeof openDialog;
132
- createItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<void>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<any>);
133
- importItems: ((importItems: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void) | ((importItemsList: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void);
134
- updateItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<void>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>);
135
- deleteItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<unknown>);
136
- reload: (() => void) | (() => void);
137
- setSearch: ((keyword: string) => void) | ((keyword: string) => void);
132
+ createItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<any>;
133
+ importItems: (importItemsList: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void;
134
+ updateItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>;
135
+ deleteItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>;
136
+ reload: () => void;
137
+ setSearch: (keyword: string) => void;
138
138
  canServerPageable: boolean;
139
139
  canServerSearch: boolean;
140
140
  canCreate: boolean;
@@ -145,12 +145,12 @@ declare var __VLS_15: {
145
145
  items: Record<string, any>[];
146
146
  operation: {
147
147
  openDialog: typeof openDialog;
148
- createItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<void>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<any>);
149
- importItems: ((importItems: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void) | ((importItemsList: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void);
150
- updateItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<void>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>);
151
- deleteItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<unknown>);
152
- reload: (() => void) | (() => void);
153
- setSearch: ((keyword: string) => void) | ((keyword: string) => void);
148
+ createItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<any>;
149
+ importItems: (importItemsList: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void;
150
+ updateItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>;
151
+ deleteItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>;
152
+ reload: () => void;
153
+ setSearch: (keyword: string) => void;
154
154
  canServerPageable: boolean;
155
155
  canServerSearch: boolean;
156
156
  canCreate: boolean;
@@ -160,12 +160,12 @@ declare var __VLS_15: {
160
160
  }, __VLS_175: never, __VLS_176: {
161
161
  operation: {
162
162
  openDialog: typeof openDialog;
163
- createItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<void>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<any>);
164
- importItems: ((importItems: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void) | ((importItemsList: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void);
165
- updateItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<void>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>);
166
- deleteItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<unknown>);
167
- reload: (() => void) | (() => void);
168
- setSearch: ((keyword: string) => void) | ((keyword: string) => void);
163
+ createItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<any>;
164
+ importItems: (importItemsList: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void;
165
+ updateItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>;
166
+ deleteItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>;
167
+ reload: () => void;
168
+ setSearch: (keyword: string) => void;
169
169
  canServerPageable: boolean;
170
170
  canServerSearch: boolean;
171
171
  canCreate: boolean;
@@ -175,12 +175,12 @@ declare var __VLS_15: {
175
175
  }, __VLS_201: never, __VLS_202: {
176
176
  operation: {
177
177
  openDialog: typeof openDialog;
178
- createItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<void>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<any>);
179
- importItems: ((importItems: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void) | ((importItemsList: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void);
180
- updateItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<void>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>);
181
- deleteItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<unknown>);
182
- reload: (() => void) | (() => void);
183
- setSearch: ((keyword: string) => void) | ((keyword: string) => void);
178
+ createItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<any>;
179
+ importItems: (importItemsList: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void;
180
+ updateItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>;
181
+ deleteItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>;
182
+ reload: () => void;
183
+ setSearch: (keyword: string) => void;
184
184
  canServerPageable: boolean;
185
185
  canServerSearch: boolean;
186
186
  canCreate: boolean;
@@ -233,15 +233,15 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
233
233
  itemsPerPage: number;
234
234
  api: boolean;
235
235
  }>>, {
236
- reload: (() => void) | (() => void);
236
+ reload: () => void;
237
237
  operation: import("vue").Ref<{
238
238
  openDialog: typeof openDialog;
239
- createItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<void>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<any>);
240
- importItems: ((importItems: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void) | ((importItemsList: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void);
241
- updateItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<void>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>);
242
- deleteItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<unknown>);
243
- reload: (() => void) | (() => void);
244
- setSearch: ((keyword: string) => void) | ((keyword: string) => void);
239
+ createItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<any>;
240
+ importItems: (importItemsList: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void;
241
+ updateItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>;
242
+ deleteItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>;
243
+ reload: () => void;
244
+ setSearch: (keyword: string) => void;
245
245
  canServerPageable: boolean;
246
246
  canServerSearch: boolean;
247
247
  canCreate: boolean;
@@ -249,12 +249,12 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
249
249
  canDelete: boolean;
250
250
  }, {
251
251
  openDialog: typeof openDialog;
252
- createItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<void>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<any>);
253
- importItems: ((importItems: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void) | ((importItemsList: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void);
254
- updateItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<void>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>);
255
- deleteItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<unknown>);
256
- reload: (() => void) | (() => void);
257
- setSearch: ((keyword: string) => void) | ((keyword: string) => void);
252
+ createItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<any>;
253
+ importItems: (importItemsList: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void;
254
+ updateItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>;
255
+ deleteItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>;
256
+ reload: () => void;
257
+ setSearch: (keyword: string) => void;
258
258
  canServerPageable: import("vue").ComputedRef<boolean>;
259
259
  canServerSearch: import("vue").ComputedRef<boolean>;
260
260
  canCreate: import("vue").ComputedRef<boolean>;
@@ -262,12 +262,12 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
262
262
  canDelete: import("vue").ComputedRef<boolean>;
263
263
  } | {
264
264
  openDialog: typeof openDialog;
265
- createItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<void>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<any>);
266
- importItems: ((importItems: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void) | ((importItemsList: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void);
267
- updateItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<void>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>);
268
- deleteItem: ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>) | ((item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<unknown>);
269
- reload: (() => void) | (() => void);
270
- setSearch: ((keyword: string) => void) | ((keyword: string) => void);
265
+ createItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback, importing?: boolean) => Promise<any>;
266
+ importItems: (importItemsList: Record<string, any>[], callback?: import("../../types/formDialog.js").FormDialogCallback) => void;
267
+ updateItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>;
268
+ deleteItem: (item: Record<string, any>, callback?: import("../../types/formDialog.js").FormDialogCallback) => Promise<any>;
269
+ reload: () => void;
270
+ setSearch: (keyword: string) => void;
271
271
  canServerPageable: boolean;
272
272
  canServerSearch: boolean;
273
273
  canCreate: boolean;
@@ -1,6 +1,54 @@
1
1
  /**
2
- * useAlert manages reactive alert state, creation helpers, and queue lifecycle used by notification components.
3
- * This doc block is consumed by vue-docgen for generated API documentation.
2
+ * Reactive alert queue shared between `createAlert()` (provider) and `useAlert()` (consumer).
3
+ *
4
+ * ## Setup
5
+ * `createAlert()` must be called **once** in an ancestor component — typically the root
6
+ * `app.vue` in a Nuxt app — to register the provider via Vue `provide()`. The `<Alert />`
7
+ * component only *consumes* the queue; it does not set it up. If no ancestor calls
8
+ * `createAlert()`, every `useAlert()` call returns `null` and toast pushes will throw.
9
+ *
10
+ * ```vue
11
+ * <!-- app.vue -->
12
+ * <script lang="ts" setup>
13
+ * createAlert()
14
+ * </script>
15
+ *
16
+ * <template>
17
+ * <VApp>
18
+ * <NuxtLayout><NuxtPage /></NuxtLayout>
19
+ * <DialogHost />
20
+ * <Alert />
21
+ * </VApp>
22
+ * </template>
23
+ * ```
24
+ *
25
+ * ## Usage
26
+ * `useAlert()` returns an `AlertProvide | null`. There are **no** convenience methods
27
+ * like `.success()` / `.error()` / `.warning()` / `.info()` — push items via `addAlert`:
28
+ *
29
+ * ```ts
30
+ * const alert = useAlert()
31
+ * alert?.addAlert({ alertType: 'success', message: 'Saved' })
32
+ * alert?.addAlert({ alertType: 'error', message: 'Failed: ' + err.message })
33
+ * alert?.addAlert({ alertType: 'warning', message: 'Check your input' })
34
+ * alert?.addAlert({ alertType: 'info', message: 'Processing...' })
35
+ * ```
36
+ *
37
+ * `alertType` must be one of `'success' | 'error' | 'warning' | 'info'`. `message` is
38
+ * required — items without a `message` are silently dropped. Optional fields:
39
+ * `alertLocation` (default `'default'`, lets multiple `<Alert />` hosts filter),
40
+ * `alertExpireIn` (ms, default 60000), `alertIcon`, `data`.
41
+ *
42
+ * Always null-check the handle: `alert?.addAlert(...)`.
43
+ *
44
+ * ## Returned API (`AlertProvide`)
45
+ * - `addAlert(item)` — push a new alert onto the queue.
46
+ * - `takeAlert(location?)` — pop the next alert for the given location (default `'default'`).
47
+ * - `hasAlert(location?)` — whether anything is queued for the given location.
48
+ * - `clear()` — drop all queued alerts.
49
+ * - `items` — the underlying reactive ref (for custom consumers).
50
+ *
51
+ * Expired items (past `alertDateTime + alertExpireIn`) are auto-pruned once per second.
4
52
  */
5
53
  import { type InjectionKey, type Ref } from 'vue';
6
54
  import type { AlertItem } from '../types/alert.js';
@@ -1,14 +1,70 @@
1
1
  /**
2
2
  * useApi wraps authenticated HTTP calls, URL resolution, and optional response caching for runtime services.
3
+ *
4
+ * Caching contract for the `cache` parameter on get / getPromise / post / postPromise:
5
+ *
6
+ * - `false` (default) — no caching, every call hits the network.
7
+ * - `true` — cache the response for 5 minutes (legacy default; preserved
8
+ * for back-compat). Prefer `{ ttlSeconds }` for new code.
9
+ * - `{ ttlSeconds: 5 }` — cache for exactly 5 seconds. PREFERRED form.
10
+ * - `{ ttlMs: 5000 }` — same, expressed in milliseconds.
11
+ * - `number` (legacy) — DEPRECATED. Treated by an undocumented size-based
12
+ * heuristic where values <= 60 are read as MINUTES and
13
+ * values > 60 as SECONDS. Emits a console warning the
14
+ * first time a session sees this form. Migrate to
15
+ * `{ ttlSeconds }` / `{ ttlMs }` to remove the warning
16
+ * and get unambiguous behaviour.
17
+ *
18
+ * Mutations that change resources read by a cached query should call
19
+ * `useApi().invalidate(prefix)` so the next read fetches fresh data. Without that,
20
+ * cached entries stay valid until their TTL expires — `localStorage` survives reloads,
21
+ * so users can see stale empty / outdated lists for the full TTL window even after
22
+ * creating data themselves.
23
+ *
3
24
  * This doc block is consumed by vue-docgen for generated API documentation.
4
25
  */
5
26
  import type { UseFetchOptions } from 'nuxt/app';
6
27
  import type { SearchParameters } from 'ofetch';
28
+ /**
29
+ * Explicit cache options. Use this in new code instead of passing a bare number.
30
+ * - `ttlSeconds`: cache lifetime in seconds. Mutually exclusive with `ttlMs`.
31
+ * - `ttlMs` : cache lifetime in milliseconds. Mutually exclusive with `ttlSeconds`.
32
+ */
33
+ export type CacheOption = boolean | number | {
34
+ ttlSeconds: number;
35
+ } | {
36
+ ttlMs: number;
37
+ };
38
+ export declare function _resetLegacyHeuristicWarning(): void;
39
+ /**
40
+ * Resolve a cache option to seconds. Pure function, exported for tests.
41
+ *
42
+ * - false / 0 / null / undefined → 0 (no cache)
43
+ * - true → DEFAULT_TTL_SECONDS_FOR_TRUE
44
+ * - { ttlSeconds: n } → n (clamped to >= 0, floored)
45
+ * - { ttlMs: n } → ceil(n / 1000)
46
+ * - number (legacy) → heuristic + warn
47
+ */
48
+ export declare function resolveCacheTtlSeconds(cache: CacheOption | undefined | null): number;
49
+ /**
50
+ * Drop every `api-cache-*` localStorage entry whose stored URL contains `prefix`.
51
+ * Pass `undefined` (or no arg) to drop ALL api-cache entries.
52
+ *
53
+ * Recommended invalidation path after a mutation:
54
+ *
55
+ * await useApi().postPromise('/model/resource/create', input)
56
+ * useApi().invalidate('/model/resource') // drops list + lookup caches
57
+ *
58
+ * Returns the number of entries removed. Safe to call when the cache is empty.
59
+ */
60
+ declare function invalidateCache(prefix?: string): number;
7
61
  export declare function useApi(): {
8
62
  urlBuilder: (url: string | string[]) => string;
9
- get: <T>(url: string | string[], body?: Record<string, any> | [], params?: SearchParameters, options?: UseFetchOptions<unknown>, cache?: boolean | number) => Promise<T>;
10
- getPromise: <T>(url: string | string[], body?: Record<string, any> | [], params?: SearchParameters, options?: UseFetchOptions<unknown>, cache?: boolean | number) => Promise<T>;
11
- post: <T>(url: string | string[], body?: Record<string, any> | [], params?: SearchParameters, options?: UseFetchOptions<unknown>, cache?: boolean | number) => Promise<T>;
12
- postPromise: <T>(url: string | string[], body?: Record<string, any> | [], params?: SearchParameters, options?: UseFetchOptions<unknown>, cache?: boolean | number) => Promise<T>;
63
+ get: <T>(url: string | string[], body?: Record<string, any> | [], params?: SearchParameters, options?: UseFetchOptions<unknown>, cache?: CacheOption) => Promise<T>;
64
+ getPromise: <T>(url: string | string[], body?: Record<string, any> | [], params?: SearchParameters, options?: UseFetchOptions<unknown>, cache?: CacheOption) => Promise<T>;
65
+ post: <T>(url: string | string[], body?: Record<string, any> | [], params?: SearchParameters, options?: UseFetchOptions<unknown>, cache?: CacheOption) => Promise<T>;
66
+ postPromise: <T>(url: string | string[], body?: Record<string, any> | [], params?: SearchParameters, options?: UseFetchOptions<unknown>, cache?: CacheOption) => Promise<T>;
13
67
  hashKey: (data: any) => Promise<string>;
68
+ invalidate: typeof invalidateCache;
14
69
  };
70
+ export {};
@@ -5,9 +5,65 @@ import { stableStringify } from "../utils/object.js";
5
5
  import { sha256 } from "../utils/hash.js";
6
6
  import { useRuntimeConfig } from "#imports";
7
7
  import { useAuthentication } from "../bridges/authentication.js";
8
+ const DEFAULT_TTL_SECONDS_FOR_TRUE = 5 * 60;
9
+ const CACHE_PREFIX = "api-cache-";
10
+ let _legacyHeuristicWarned = false;
11
+ function warnLegacyHeuristic(value, resolvedSeconds) {
12
+ if (_legacyHeuristicWarned) return;
13
+ _legacyHeuristicWarned = true;
14
+ console.warn(
15
+ `[useApi] cache=${value} resolved to ${resolvedSeconds}s via the legacy heuristic (values <=60 are minutes, >60 are seconds). This is ambiguous \u2014 pass { ttlSeconds: N } or { ttlMs: N } instead. See useApi() docblock for details.`
16
+ );
17
+ }
18
+ export function _resetLegacyHeuristicWarning() {
19
+ _legacyHeuristicWarned = false;
20
+ }
21
+ export function resolveCacheTtlSeconds(cache) {
22
+ if (!cache) return 0;
23
+ if (typeof cache === "boolean") return DEFAULT_TTL_SECONDS_FOR_TRUE;
24
+ if (typeof cache === "number") {
25
+ const n = Math.max(0, Number(cache));
26
+ if (!Number.isFinite(n) || n === 0) return 0;
27
+ const resolved = n > 60 ? n : n * 60;
28
+ warnLegacyHeuristic(n, resolved);
29
+ return resolved;
30
+ }
31
+ if (typeof cache === "object") {
32
+ if ("ttlSeconds" in cache) return Math.max(0, Math.floor(Number(cache.ttlSeconds) || 0));
33
+ if ("ttlMs" in cache) return Math.max(0, Math.ceil((Number(cache.ttlMs) || 0) / 1e3));
34
+ }
35
+ return 0;
36
+ }
37
+ function invalidateCache(prefix) {
38
+ if (typeof window === "undefined" || !window.localStorage) return 0;
39
+ const keys = [];
40
+ for (let i = 0; i < window.localStorage.length; i++) {
41
+ const k = window.localStorage.key(i);
42
+ if (k && k.startsWith(CACHE_PREFIX)) keys.push(k);
43
+ }
44
+ let removed = 0;
45
+ for (const k of keys) {
46
+ if (!prefix) {
47
+ try {
48
+ ls.remove(k);
49
+ removed++;
50
+ } catch {
51
+ }
52
+ continue;
53
+ }
54
+ try {
55
+ const raw = window.localStorage.getItem(k);
56
+ if (raw && raw.includes(prefix)) {
57
+ ls.remove(k);
58
+ removed++;
59
+ }
60
+ } catch {
61
+ }
62
+ }
63
+ return removed;
64
+ }
8
65
  export function useApi() {
9
66
  const config = useRuntimeConfig();
10
- const CACHE_PREFIX = "api-cache-";
11
67
  function urlBuilder(url) {
12
68
  let returnUrl;
13
69
  if (Array.isArray(url)) {
@@ -64,12 +120,6 @@ export function useApi() {
64
120
  const jsonString = stableStringify(data);
65
121
  return sha256(jsonString);
66
122
  }
67
- function computeTtlSecond(cache) {
68
- if (!cache) return 0;
69
- if (typeof cache === "boolean") return 5 * 60;
70
- let ttlNum = Math.max(0, Number(cache));
71
- return ttlNum > 60 ? ttlNum : ttlNum * 60;
72
- }
73
123
  function safeGetCache(key) {
74
124
  try {
75
125
  const v = ls.get(key);
@@ -80,7 +130,7 @@ export function useApi() {
80
130
  }
81
131
  async function ofetchWithCache(url, method, body, params, options, cache) {
82
132
  const builtUrl = urlBuilder(url);
83
- const ttl = computeTtlSecond(cache);
133
+ const ttl = resolveCacheTtlSeconds(cache);
84
134
  if (ttl === 0) {
85
135
  return ofetch(builtUrl, optionBuilder(method, body, params, options));
86
136
  }
@@ -94,5 +144,5 @@ export function useApi() {
94
144
  ls.set(key, result, { ttl });
95
145
  return result;
96
146
  }
97
- return { urlBuilder, get, getPromise, post, postPromise, hashKey };
147
+ return { urlBuilder, get, getPromise, post, postPromise, hashKey, invalidate: invalidateCache };
98
148
  }
@@ -1,6 +1,7 @@
1
1
  /**
2
- * useApiLookupList loads and normalizes lookup options for fields that depend on remote or cached reference lists,
3
- * using REST API calls via useApi().postPromise() instead of GraphQL.
2
+ * useApiLookupList loads and normalizes lookup options for fields that depend on remote or cached reference lists.
3
+ * Routes both the lookup-load Read (props.modelName) and the selection-resolution Read (props.modelSelectedItem)
4
+ * through useApiModelOperation, which owns the API-mode URL/body rules.
4
5
  * This doc block is consumed by vue-docgen for generated API documentation.
5
6
  */
6
7
  import { type Ref } from 'vue';
@@ -2,8 +2,7 @@ import { computed, ref, shallowRef, watch } from "vue";
2
2
  import { watchDebounced } from "@vueuse/core";
3
3
  import { union, isEmpty, isArray, sortBy, castArray } from "lodash-es";
4
4
  import { useFuzzy } from "./utils/fuzzy.js";
5
- import { useApi } from "./api.js";
6
- import { buildApiEndpoint } from "./apiModel.js";
5
+ import { useApiModelOperation } from "./apiModelOperation.js";
7
6
  export function useApiLookupList(props, emit, selectedItems) {
8
7
  const modelItems = shallowRef([]);
9
8
  const items = shallowRef([]);
@@ -50,13 +49,8 @@ export function useApiLookupList(props, emit, selectedItems) {
50
49
  variables[props.serverSearchKey] = searchData.value;
51
50
  }
52
51
  try {
53
- const result = await useApi().postPromise(
54
- buildApiEndpoint(props.modelName),
55
- { fields: queryFields.value, variables },
56
- void 0,
57
- void 0,
58
- props.cache
59
- );
52
+ const ops = useApiModelOperation(props.modelName);
53
+ const result = await ops.read(queryFields.value, variables, props.cache);
60
54
  if (id !== requestId) return;
61
55
  if (isArray(result)) {
62
56
  modelItems.value = result;
@@ -127,13 +121,8 @@ export function useApiLookupList(props, emit, selectedItems) {
127
121
  const key = props.modelSelectedItemKey || "id";
128
122
  const variables = { ...props.modelSelectedItemBy || {} };
129
123
  variables[key] = stillMissing;
130
- const result = await useApi().postPromise(
131
- buildApiEndpoint(props.modelSelectedItem),
132
- { fields: queryFields.value, variables },
133
- void 0,
134
- void 0,
135
- props.cache
136
- );
124
+ const ops = useApiModelOperation(props.modelSelectedItem);
125
+ const result = await ops.read(queryFields.value, variables, props.cache);
137
126
  const resolved = castArray(result);
138
127
  for (const obj of resolved) {
139
128
  const v = obj?.[props.itemValue];
@@ -33,7 +33,7 @@ export declare function useApiModel<T extends ApiModelComposableProps>(props: T)
33
33
  createItem: (item: Record<string, any>, callback?: FormDialogCallback, importing?: boolean) => Promise<any>;
34
34
  importItems: (importItemsList: Record<string, any>[], callback?: FormDialogCallback) => void;
35
35
  updateItem: (item: Record<string, any>, callback?: FormDialogCallback) => Promise<any>;
36
- deleteItem: (item: Record<string, any>, callback?: FormDialogCallback) => Promise<unknown>;
36
+ deleteItem: (item: Record<string, any>, callback?: FormDialogCallback) => Promise<any>;
37
37
  loadItems: (options: any) => void;
38
38
  reload: () => void;
39
39
  isLoading: import("vue").Ref<boolean, boolean>;
@@ -1,7 +1,7 @@
1
1
  import { computed, onMounted, ref } from "vue";
2
2
  import { watchDebounced } from "@vueuse/core";
3
3
  import { useAlert } from "./alert.js";
4
- import { useApi } from "./api.js";
4
+ import { useApiModelOperation } from "./apiModelOperation.js";
5
5
  import { arrayWrap } from "../utils/array.js";
6
6
  import pLimit from "p-limit";
7
7
  export function stripModelByQualifier(modelName) {
@@ -14,7 +14,7 @@ export function buildApiEndpoint(modelName, action) {
14
14
  }
15
15
  export function useApiModel(props) {
16
16
  const alert = useAlert();
17
- const api = useApi();
17
+ const ops = computed(() => useApiModelOperation(props.modelName));
18
18
  const items = ref([]);
19
19
  const itemsLength = ref(0);
20
20
  const search = ref();
@@ -49,13 +49,9 @@ export function useApiModel(props) {
49
49
  }
50
50
  return [.../* @__PURE__ */ new Set([...fieldsProps, ...tmpFields])];
51
51
  });
52
- function mutationModelName() {
53
- return stripModelByQualifier(props.modelName);
54
- }
55
52
  function createItem(item, callback, importing = false) {
56
53
  isLoading.value = true;
57
- const endpoint = buildApiEndpoint(mutationModelName(), "create");
58
- return api.postPromise(endpoint, { input: item, fields: fields.value }).then((result) => {
54
+ return ops.value.create(item, fields.value).then((result) => {
59
55
  if (canServerPageable.value) {
60
56
  if (!importing) loadItems(currentOptions.value);
61
57
  } else {
@@ -92,8 +88,7 @@ export function useApiModel(props) {
92
88
  }
93
89
  function updateItem(item, callback) {
94
90
  isLoading.value = true;
95
- const endpoint = buildApiEndpoint(mutationModelName(), "update");
96
- return api.postPromise(endpoint, { input: item, fields: fields.value }).then((result) => {
91
+ return ops.value.update(item, fields.value).then((result) => {
97
92
  if (canServerPageable.value) {
98
93
  loadItems(currentOptions.value);
99
94
  } else {
@@ -113,8 +108,7 @@ export function useApiModel(props) {
113
108
  }
114
109
  function deleteItem(item, callback) {
115
110
  isLoading.value = true;
116
- const endpoint = buildApiEndpoint(mutationModelName(), "delete");
117
- return api.postPromise(endpoint, { input: item, fields: fields.value }).catch((error) => {
111
+ return ops.value.delete(item, fields.value).catch((error) => {
118
112
  alert?.addAlert({ alertType: "error", message: error?.message || String(error) });
119
113
  }).finally(() => {
120
114
  isLoading.value = false;
@@ -124,17 +118,15 @@ export function useApiModel(props) {
124
118
  }
125
119
  function loadItems(options) {
126
120
  currentOptions.value = options;
127
- const endpoint = buildApiEndpoint(props.modelName, "pageable");
128
121
  isLoading.value = true;
129
- api.postPromise(
130
- endpoint,
131
- Object.assign({}, props.modelBy, {
132
- variables: props.modelBy,
133
- fields: fields.value,
122
+ ops.value.readPageable(
123
+ fields.value,
124
+ props.modelBy,
125
+ {
134
126
  page: options?.page,
135
127
  perPage: options?.itemsPerPage,
136
128
  sortBy: options?.sortBy
137
- })
129
+ }
138
130
  ).then((result) => {
139
131
  items.value = result.data;
140
132
  itemsLength.value = result.meta.totalItems;
@@ -151,10 +143,9 @@ export function useApiModel(props) {
151
143
  loadItems(currentOptions.value);
152
144
  } else {
153
145
  isLoading.value = true;
154
- const endpoint = buildApiEndpoint(props.modelName);
155
- api.postPromise(
156
- endpoint,
157
- { variables: props.modelBy, fields: fields.value }
146
+ ops.value.read(
147
+ fields.value,
148
+ props.modelBy
158
149
  ).then((result) => {
159
150
  items.value = arrayWrap(result);
160
151
  }).catch((error) => {