@arrai-innovations/reactive-helpers 22.1.0 → 23.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +66 -89
  2. package/config/listCrud.js +10 -4
  3. package/config/objectCrud.js +8 -6
  4. package/package.json +12 -6
  5. package/types/config/listCrud.d.ts +22 -2
  6. package/types/config/objectCrud.d.ts +6 -4
  7. package/types/tests/unit/matchers.spec.d.ts +1 -0
  8. package/types/tests/unit/use/ruleOptionNames.spec.d.ts +1 -0
  9. package/types/use/cancellableIntent.d.ts +4 -5
  10. package/types/use/listCalculated.d.ts +1 -1
  11. package/types/use/listInstance.d.ts +18 -18
  12. package/types/use/listRelated.d.ts +33 -12
  13. package/types/use/objectCalculated.d.ts +1 -1
  14. package/types/use/objectInstance.d.ts +3 -3
  15. package/types/use/objectRelated.d.ts +29 -8
  16. package/types/utils/cancellablePromise.d.ts +15 -0
  17. package/types/utils/getFakePk.d.ts +4 -1
  18. package/types/utils/refIfReactive.d.ts +14 -0
  19. package/types/utils/relatedCalculatedHelpers.d.ts +63 -0
  20. package/use/cancellableIntent.js +4 -5
  21. package/use/list.js +3 -0
  22. package/use/listCalculated.js +5 -1
  23. package/use/listFilter.js +10 -7
  24. package/use/listInstance.js +120 -62
  25. package/use/listRelated.js +57 -14
  26. package/use/listSearch.js +15 -11
  27. package/use/listSort.js +20 -5
  28. package/use/listSubscription.js +3 -2
  29. package/use/object.js +6 -3
  30. package/use/objectCalculated.js +4 -1
  31. package/use/objectInstance.js +87 -45
  32. package/use/objectRelated.js +65 -23
  33. package/use/objectSubscription.js +14 -5
  34. package/utils/cancellablePromise.js +26 -0
  35. package/utils/getFakePk.js +7 -2
  36. package/utils/refIfReactive.js +27 -9
  37. package/utils/relatedCalculatedHelpers.js +123 -0
package/README.md CHANGED
@@ -1,10 +1,11 @@
1
1
  # reactive-helpers
2
2
 
3
- ![Tests](https://docs.arrai.dev/reactive-helpers/artifacts/main/tests.svg)
4
- [![Coverage](https://docs.arrai.dev/reactive-helpers/artifacts/main/tests.coverage.svg)](https://docs.arrai.dev/reactive-helpers/artifacts/main/coverage_tests/)
5
- ![ESLint](https://docs.arrai.dev/reactive-helpers/artifacts/main/eslint.svg)
6
- ![Prettier](https://docs.arrai.dev/reactive-helpers/artifacts/main/prettier.svg)
7
- ![Audit](https://docs.arrai.dev/reactive-helpers/artifacts/main/pnpm-audit.svg)
3
+ [![npm](https://img.shields.io/npm/v/%40arrai-innovations%2Freactive-helpers.svg?style=for-the-badge)](https://www.npmjs.com/package/@arrai-innovations/reactive-helpers)
4
+ ![Tests](https://reactive-helpers.arrai.dev/artifacts/main/tests.svg)
5
+ [![Coverage](https://reactive-helpers.arrai.dev/artifacts/main/tests.coverage.svg)](https://reactive-helpers.arrai.dev/artifacts/main/coverage_tests/)
6
+ ![ESLint](https://reactive-helpers.arrai.dev/artifacts/main/eslint.svg)
7
+ ![Prettier](https://reactive-helpers.arrai.dev/artifacts/main/prettier.svg)
8
+ ![Audit](https://reactive-helpers.arrai.dev/artifacts/main/pnpm-audit.svg)
8
9
  [![License: BSD-3-Clause](https://img.shields.io/badge/License-BSD--3--Clause-blue.svg?style=for-the-badge)](./LICENSE)
9
10
 
10
11
  Vue.js 3 composition utilities to manage reactive lists, objects, loading and error state, and the small helpers that
@@ -18,12 +19,11 @@ reaches your backend), so the package stays transport agnostic.
18
19
  - [Features](#features)
19
20
  - [Requirements](#requirements)
20
21
  - [Install](#install)
21
- - [Usage](#usage)
22
- - [Quick start](#quick-start)
23
- - [Wiring a data layer](#wiring-a-data-layer)
22
+ - [Documentation](#documentation)
24
23
  - [Changelog](#changelog)
25
24
  - [Contributing](#contributing)
26
25
  - [Development](#development)
26
+ - [Deploy documentation](#deploy-documentation)
27
27
  - [License](#license)
28
28
 
29
29
  <!-- END doctoc generated TOC please keep comment here to allow auto update -->
@@ -31,25 +31,18 @@ reaches your backend), so the package stays transport agnostic.
31
31
 
32
32
  ## Features
33
33
 
34
- - **List composables** for managing collections of objects: `useListInstance`, `useList`, `useListFilter`,
35
- `useListSort`, `useListSearch`, `useListCalculated`, `useListRelated`, and `useListSubscription`.
36
- - **Object composables** for managing single objects: `useObjectInstance`, `useObject`, `useObjectCalculated`,
37
- `useObjectRelated`, and `useObjectSubscription`.
38
- - **Loading and error state** as small, composable primitives: `useLoading`, `useError`, `useLoadingError`, and their
39
- read-only proxy variants `useProxyLoading`, `useProxyError`, `useProxyLoadingError`.
40
- - **Standalone helpers** such as `useSearch` (FlexSearch-backed), `useCancellableIntent`, and `useCombineClasses`.
41
- - **Pluggable CRUD configuration** via `setListCrud` / `setObjectCrud`, so the same composables can drive any backend.
42
- - **Reactive and object utilities**: `deepUnref`, `assignReactiveObject`, `refIfReactive`, `toRefsIfReactive`,
43
- `isReactiveTyped`, `set`, `deleteKey`, `keyDiff`, `flattenPaths`, `cancellablePromise`, `cancellableFetch`, and more.
44
-
45
- Most list and object composables also ship a plural batch variant (for example `useListInstances`,
46
- `useObjectInstances`) for creating several keyed instances at once. See the full API in
47
- [docs/reference/api/index.md](./docs/reference/api/index.md).
34
+ - **Reactive lists** with stable identity, ordering, filtering, sorting, searching, related data, calculated values, and
35
+ subscriptions.
36
+ - **Reactive objects** that retrieve, edit, create, delete, and subscribe through transport-neutral handlers.
37
+ - **Loading and error state** as small primitives that can be composed across asynchronous work.
38
+ - **Pluggable CRUD configuration** so instances can share app-wide handlers for any backend.
39
+ - **Focused utilities** for reactive data, cancellable work, object paths, classes, and search.
48
40
 
49
41
  ## Requirements
50
42
 
51
43
  - **Vue** `^3.5.13` (peer dependency).
52
- - **Node.js** with ES module support. This package is ESM only (`"type": "module"`); there is no CommonJS build.
44
+ - **Node.js** `>=22`. Node 20 reached end of life in April 2026, so the supported lines are 22 and 24. This package is
45
+ ESM only (`"type": "module"`); there is no CommonJS build.
53
46
  - Peer dependencies you install alongside it: [`vue`](https://www.npmjs.com/package/vue),
54
47
  [`@vueuse/core`](https://www.npmjs.com/package/@vueuse/core), and
55
48
  [`lodash-es`](https://www.npmjs.com/package/lodash-es).
@@ -60,67 +53,17 @@ Most list and object composables also ship a plural batch variant (for example `
60
53
  $ npm install @arrai-innovations/reactive-helpers vue @vueuse/core lodash-es
61
54
  ```
62
55
 
63
- ## Usage
56
+ ## Documentation
64
57
 
65
- ### Quick start
58
+ The [reactive-helpers documentation](https://reactive-helpers.arrai.dev/v23/) is versioned by package major.
66
59
 
67
- The loading and error composables are self contained and need no configuration. They return readonly reactive state
68
- plus actions to drive it, which is handy for wiring UI to any asynchronous work:
69
-
70
- ```javascript
71
- import { useLoadingError } from "@arrai-innovations/reactive-helpers";
72
-
73
- const { loading, error, errored, setLoading, clearLoading, setError, clearError } = useLoadingError();
74
-
75
- async function save() {
76
- setLoading();
77
- try {
78
- await doWork();
79
- clearError();
80
- } catch (e) {
81
- setError(e);
82
- } finally {
83
- clearLoading();
84
- }
85
- }
86
-
87
- // `loading`, `error`, and `errored` are readonly refs you can render or watch.
88
- ```
89
-
90
- ### Wiring a data layer
91
-
92
- The list and object instance composables manage reactive collections but stay transport agnostic: you provide the CRUD
93
- handlers that reach your backend. A list handler receives a `pushObjects` callback to feed results (one or more pages)
94
- into the reactive state and resolves when it is done:
95
-
96
- ```javascript
97
- import { useListInstance } from "@arrai-innovations/reactive-helpers";
98
- import { reactive } from "vue";
99
-
100
- const contacts = useListInstance({
101
- props: {
102
- pkKey: "id",
103
- params: reactive({ fields: ["id", "name"] }),
104
- target: { stream: "contacts" }, // implementation-specific args passed through to your handlers
105
- },
106
- handlers: {
107
- list: async ({ pushObjects }) => {
108
- const rows = await fetch("/api/contacts").then((r) => r.json());
109
- pushObjects(rows);
110
- return true;
111
- },
112
- },
113
- });
114
-
115
- await contacts.list();
116
- console.log(contacts.state.objects);
117
- ```
118
-
119
- To share one data layer across every instance instead of passing `handlers` each time, register defaults once with
120
- `setListCrud` (and `setObjectCrud` for object instances).
121
-
122
- See [docs/reference/api/index.md](./docs/reference/api/index.md) for the full list of modules, composables, and
123
- utilities, along with their arguments and properties.
60
+ - [Get started](https://reactive-helpers.arrai.dev/v23/guide/) with installation and a complete reactive list.
61
+ - [Build a reactive list](https://reactive-helpers.arrai.dev/v23/tutorials/build-a-reactive-list) step by step.
62
+ - [Pass backend arguments](https://reactive-helpers.arrai.dev/v23/guide/data-layer) or
63
+ [register app-wide CRUD defaults](https://reactive-helpers.arrai.dev/v23/guide/register-crud-defaults).
64
+ - Read about [instances and transport](https://reactive-helpers.arrai.dev/v23/concepts/instances-and-transport) to
65
+ understand the library's core boundary.
66
+ - Use the [API reference](https://reactive-helpers.arrai.dev/v23/reference/api/) for exact signatures and return values.
124
67
 
125
68
  ## Changelog
126
69
 
@@ -133,8 +76,9 @@ Issues and pull requests are welcome. A few things to know before you start:
133
76
  - Commits follow [Conventional Commits](https://www.conventionalcommits.org/) and are validated by commitlint through a
134
77
  git hook (installed automatically by `pnpm install`).
135
78
  - Run the tests, linters, and formatter before opening a pull request (see [Development](#development)).
136
- - Generated output under `docs/` and `types/` is committed and checked in CI; regenerate it with `pnpm run docs` and
137
- `pnpm run types` when you change public APIs or their JSDoc.
79
+ - Generated output under `types/` and `docs/reference/api/` is committed and checked in CI. Regenerate it with
80
+ `pnpm run docs` when you change public APIs or their JSDoc. Everything else under `docs/` is hand-authored; see
81
+ [`docs/README.md`](./docs/README.md) before editing it.
138
82
 
139
83
  ## Development
140
84
 
@@ -144,16 +88,17 @@ Issues and pull requests are welcome. A few things to know before you start:
144
88
  $ git clone git@github.com:arrai-innovations/reactive-helpers.git
145
89
  ```
146
90
 
147
- 2. Install dependencies:
91
+ 2. Install dependencies. Development needs Node `>=22.13`, above the `>=22` the package itself declares, because
92
+ `eslint-plugin-jsdoc` and `vite` require it:
148
93
 
149
94
  ```bash
150
95
  $ pnpm install
151
96
  ```
152
97
 
153
- 3. Run tests via vitest:
98
+ 3. Run tests via vitest. Pass `run` for a single pass; `pnpm test` on its own starts watch mode:
154
99
 
155
100
  ```bash
156
- $ pnpm test
101
+ $ pnpm test run
157
102
  ```
158
103
 
159
104
  4. Run tests with coverage output:
@@ -162,13 +107,21 @@ Issues and pull requests are welcome. A few things to know before you start:
162
107
  $ pnpm coverage
163
108
  ```
164
109
 
165
- 5. Generate types and typedocs:
110
+ 5. Lint and format. Both rewrite files in place, and a git hook runs them on staged files:
111
+
112
+ ```bash
113
+ $ pnpm eslint
114
+ $ pnpm prettier
115
+ ```
116
+
117
+ 6. Generate types and typedocs, then confirm the committed output matches:
166
118
 
167
119
  ```bash
168
120
  $ pnpm run docs
121
+ $ pnpm run docs:check
169
122
  ```
170
123
 
171
- 6. Type-only workflows:
124
+ 7. Type-only workflows:
172
125
 
173
126
  - Generate types without docs:
174
127
  ```bash
@@ -179,6 +132,30 @@ Issues and pull requests are welcome. A few things to know before you start:
179
132
  $ pnpm run types:check -- --skip-gen
180
133
  ```
181
134
 
135
+ 8. Preview the documentation site. The build fails on dead links, so run it before proposing documentation changes:
136
+
137
+ ```bash
138
+ $ pnpm run docs:site:dev
139
+ $ pnpm run docs:site:build
140
+ ```
141
+
142
+ ### Deploy documentation
143
+
144
+ Tagging a release publishes the documentation. The `docs-site` CircleCI job runs after the npm publish succeeds, takes
145
+ the major from the tag, and deploys to `https://reactive-helpers.arrai.dev/v<major>/`. Releasing needs no separate
146
+ documentation step.
147
+
148
+ Publishing between releases is the out-of-band case: a correction or a new page that should not wait for the next tag.
149
+ Authenticate the CircleCI CLI with `circleci setup`, then run:
150
+
151
+ ```bash
152
+ $ pnpm run docs:site:deploy
153
+ ```
154
+
155
+ This triggers a docs-only pipeline against `main`. It derives the major from `package.json`, deploys to that same
156
+ per-major path, and does not publish the npm package. The script reuses the CLI's authentication. `CIRCLECI_TOKEN`
157
+ remains available as an override for automation.
158
+
182
159
  ## License
183
160
 
184
161
  [BSD-3-Clause](./LICENSE) © Arrai Innovations Inc.
@@ -45,6 +45,8 @@ import { readonly } from "vue";
45
45
  * @property {import('../config/objectCrud.js').TargetArgs} target - The arguments to be passed to the crud handlers.
46
46
  * @property {import('./commonCrud.js').Pk[]} pks - The pks of the objects to be deleted.
47
47
  * @property {string} pkKey - The key name of the primary key.
48
+ * @property {{[key:string]: any}} params - Your listing arguments, passed through to the crud handlers.
49
+ * @property {Readonly<import('vue').Ref<boolean>>} isCancelled - A readonly ref that becomes true once the request is cancelled.
48
50
  */
49
51
 
50
52
  /**
@@ -77,6 +79,8 @@ import { readonly } from "vue";
77
79
  * @property {import('./commonCrud.js').Pk[]} pks - The pks of the objects to be acted upon.
78
80
  * @property {string} pkKey - The key name of the primary key.
79
81
  * @property {string} action - The action to execute.
82
+ * @property {{[key:string]: any}} params - Your listing arguments, passed through to the crud handlers.
83
+ * @property {Readonly<import('vue').Ref<boolean>>} isCancelled - A readonly ref that becomes true once the request is cancelled.
80
84
  */
81
85
 
82
86
  /**
@@ -94,8 +98,9 @@ import { readonly } from "vue";
94
98
  /**
95
99
  * @callback CrudBulkDeleteFn - Signature for the handler that bulk-deletes objects from the backing store.
96
100
  * @param {BulkDeleteArgs} args - The arguments to be passed to the crud handlers.
97
- * @returns {Promise<boolean>} - A promise whose resolution means the bulk delete succeeded; the resolved value is not
98
- * inspected, and the instance then empties the list.
101
+ * @returns {import('../utils/cancellablePromise.js').MaybeCancellablePromise<boolean>} - A promise whose resolution
102
+ * means the bulk delete succeeded; the resolved value is not inspected, and the instance then empties the list.
103
+ * Carry a `cancel` method to let the caller abandon the run.
99
104
  */
100
105
 
101
106
  /**
@@ -107,8 +112,9 @@ import { readonly } from "vue";
107
112
  /**
108
113
  * @callback CrudExecuteActionFn - Signature for the handler that executes an action on a list of objects in the backing store.
109
114
  * @param {ExecuteActionArgs} args - The arguments to be passed to the crud handlers.
110
- * @returns {Promise<object|string|null>} - A promise resolving the action's result, which `listInstance.executeAction`
111
- * passes through to its caller.
115
+ * @returns {import('../utils/cancellablePromise.js').MaybeCancellablePromise<object|string|null>} - A promise
116
+ * resolving the action's result, which `listInstance.executeAction` passes through to its caller. Carry a `cancel`
117
+ * method to let the caller abandon the run.
112
118
  */
113
119
 
114
120
  /**
@@ -133,9 +133,10 @@ import { readonly } from "vue";
133
133
 
134
134
  /**
135
135
  * @typedef {import('../utils/cancellablePromise.js').MaybeCancellablePromise<object|string|void>} CrudCompletionResponse -
136
- * The value returned by an object CRUD handler whose resolved value is ignored: delete, and executeAction. A
137
- * possibly-cancellable promise whose resolution signals success and nothing more, so it may resolve a record, a
138
- * primary key string, or nothing at all.
136
+ * The value returned by an object CRUD handler that does not populate the managed record: delete, and
137
+ * executeAction. A possibly-cancellable promise that may resolve a record, a primary key string, or nothing at
138
+ * all. `delete` ignores the resolved value, treating resolution alone as success. `executeAction` passes the
139
+ * resolved value through to its caller, and resolves `null` instead when the action failed.
139
140
  */
140
141
 
141
142
  /**
@@ -169,10 +170,11 @@ import { readonly } from "vue";
169
170
  */
170
171
 
171
172
  /**
172
- * @callback CrudObjectExecuteActionFn - Signature for the handler that executes an action on a single object in the backing store.
173
+ * @callback CrudObjectExecuteActionFn - Signature for the handler that executes an action on a single object in the
174
+ * backing store. Its resolved value is passed through to the caller of `objectInstance.executeAction`.
173
175
  * @param {ObjectExecuteActionArgs} args - The arguments to be passed to the executeAction function.
174
- * @returns {CrudCompletionResponse} - A promise whose resolution means the action succeeded; its value is ignored, and
175
- * `objectInstance.executeAction` resolves `true`.
176
+ * @returns {CrudCompletionResponse} - A promise resolving the action's result, which
177
+ * `objectInstance.executeAction` passes through to its caller. A stored failure resolves `null` instead.
176
178
  */
177
179
 
178
180
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arrai-innovations/reactive-helpers",
3
- "version": "22.1.0",
3
+ "version": "23.0.0",
4
4
  "description": "VueJS 3 utility composition functions to help manipulate objects and lists.",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -37,10 +37,15 @@
37
37
  "bugs": {
38
38
  "url": "https://github.com/arrai-innovations/reactive-helpers/issues"
39
39
  },
40
- "homepage": "https://github.com/arrai-innovations/reactive-helpers#readme",
40
+ "homepage": "https://reactive-helpers.arrai.dev/v23/",
41
+ "engines": {
42
+ "node": ">=22"
43
+ },
41
44
  "devDependencies": {
42
- "@arrai-innovations/commitlint-config": "^2.1.0",
43
- "@commitlint/cli": "^19.8.1",
45
+ "@arrai-innovations/commitlint-config": "^3.0.0",
46
+ "@arrai-innovations/diction-md": "^1.0.0",
47
+ "@arrai-innovations/vitepress-theme": "1.0.1",
48
+ "@commitlint/cli": "^21.2.1",
44
49
  "@eslint/js": "9.39.4",
45
50
  "@godaddy/dmd": "^1.0.4",
46
51
  "@trivago/prettier-plugin-sort-imports": "^5.2.2",
@@ -60,9 +65,9 @@
60
65
  "eslint-plugin-vue": "^10.9.2",
61
66
  "flush-promises": "^1.0.2",
62
67
  "globals": "^16.5.0",
63
- "jsdom": "^26.1.0",
68
+ "jsdom": "^30.0.1",
64
69
  "lefthook": "^1.13.6",
65
- "prettier": "^3.8.4",
70
+ "prettier": "^3.9.6",
66
71
  "typedoc": "^0.28.19",
67
72
  "typedoc-plugin-markdown": "^4.12.0",
68
73
  "typescript": "^5.9.3",
@@ -98,6 +103,7 @@
98
103
  "docs:clean": "node clean_type_doc.js",
99
104
  "docs:site:dev": "vitepress dev docs",
100
105
  "docs:site:build": "vitepress build docs",
106
+ "docs:site:deploy": "node scripts/deploy-docs.mjs",
101
107
  "docs:site:preview": "vitepress preview docs",
102
108
  "types": "node make_types.js",
103
109
  "types:check": "node check_types.js"
@@ -84,6 +84,16 @@ export type BulkDeleteArgsRaw = {
84
84
  * The key name of the primary key.
85
85
  */
86
86
  pkKey: string;
87
+ /**
88
+ * Your listing arguments, passed through to the crud handlers.
89
+ */
90
+ params: {
91
+ [key: string]: any;
92
+ };
93
+ /**
94
+ * A readonly ref that becomes true once the request is cancelled.
95
+ */
96
+ isCancelled: Readonly<import("vue").Ref<boolean>>;
87
97
  };
88
98
  /**
89
99
  * Arguments for a bulk-delete operation, combining the raw arguments with any additional list CRUD arguments.
@@ -142,6 +152,16 @@ export type ExecuteActionArgsRaw = {
142
152
  * The action to execute.
143
153
  */
144
154
  action: string;
155
+ /**
156
+ * Your listing arguments, passed through to the crud handlers.
157
+ */
158
+ params: {
159
+ [key: string]: any;
160
+ };
161
+ /**
162
+ * A readonly ref that becomes true once the request is cancelled.
163
+ */
164
+ isCancelled: Readonly<import("vue").Ref<boolean>>;
145
165
  };
146
166
  /**
147
167
  * Arguments for a list execute-action operation, combining the raw arguments with any additional list CRUD arguments.
@@ -154,7 +174,7 @@ export type CrudListFn = (args: ListArgs) => import("../utils/cancellablePromise
154
174
  /**
155
175
  * Signature for the handler that bulk-deletes objects from the backing store.
156
176
  */
157
- export type CrudBulkDeleteFn = (args: BulkDeleteArgs) => Promise<boolean>;
177
+ export type CrudBulkDeleteFn = (args: BulkDeleteArgs) => import("../utils/cancellablePromise.js").MaybeCancellablePromise<boolean>;
158
178
  /**
159
179
  * Signature for the handler that subscribes to list changes in the backing store.
160
180
  */
@@ -162,7 +182,7 @@ export type CrudListSubscribeFn = (args: ListSubscribeArgs) => import("../utils/
162
182
  /**
163
183
  * Signature for the handler that executes an action on a list of objects in the backing store.
164
184
  */
165
- export type CrudExecuteActionFn = (args: ExecuteActionArgs) => Promise<object | string | null>;
185
+ export type CrudExecuteActionFn = (args: ExecuteActionArgs) => import("../utils/cancellablePromise.js").MaybeCancellablePromise<object | string | null>;
166
186
  /**
167
187
  * The set of optional CRUD handler functions (list, bulkDelete, executeAction, subscribe) for a list.
168
188
  */
@@ -274,9 +274,10 @@ export type ObjectSubscribeArgs = ObjectSubscribeArgsRaw & import("../use/cancel
274
274
  export type CrudResponse = import("../utils/cancellablePromise.js").MaybeCancellablePromise<object>;
275
275
  /**
276
276
  * -
277
- * The value returned by an object CRUD handler whose resolved value is ignored: delete, and executeAction. A
278
- * possibly-cancellable promise whose resolution signals success and nothing more, so it may resolve a record, a
279
- * primary key string, or nothing at all.
277
+ * The value returned by an object CRUD handler that does not populate the managed record: delete, and
278
+ * executeAction. A possibly-cancellable promise that may resolve a record, a primary key string, or nothing at
279
+ * all. `delete` ignores the resolved value, treating resolution alone as success. `executeAction` passes the
280
+ * resolved value through to its caller, and resolves `null` instead when the action failed.
280
281
  */
281
282
  export type CrudCompletionResponse = import("../utils/cancellablePromise.js").MaybeCancellablePromise<object | string | void>;
282
283
  /**
@@ -300,7 +301,8 @@ export type CrudPatchFn = (args: PartialArgs) => CrudResponse;
300
301
  */
301
302
  export type CrudDeleteFn = (args: DeleteArgs) => CrudCompletionResponse;
302
303
  /**
303
- * Signature for the handler that executes an action on a single object in the backing store.
304
+ * Signature for the handler that executes an action on a single object in the
305
+ * backing store. Its resolved value is passed through to the caller of `objectInstance.executeAction`.
304
306
  */
305
307
  export type CrudObjectExecuteActionFn = (args: ObjectExecuteActionArgs) => CrudCompletionResponse;
306
308
  /**
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -60,11 +60,10 @@
60
60
  *
61
61
  * If the watch arguments change again before the promise resolves, the in-flight promise is cancelled only when it
62
62
  * carries a `cancel` method (a `MaybeCancellablePromise`); a plain promise is left to run to completion. That
63
- * distinction is visible through the composables built on this one. `useObjectSubscription` calls
64
- * `objectInstance.retrieve()` again for the new key, and that call returns the promise already in flight for the
65
- * previous key, so the stale record is assigned and the new key is never fetched. `useListSubscription` guards its
66
- * list intent on the list's own loading state, so the superseded run is left to finish and the list is then listed
67
- * again with the current arguments.
63
+ * distinction is visible through the composables built on this one. Both `useObjectSubscription` and
64
+ * `useListSubscription` guard their intents on the instance's own loading state, so a superseded run is left to
65
+ * finish and the intent then re-runs with the current arguments. The stale result is assigned first, and the
66
+ * re-run replaces it.
68
67
  *
69
68
  * @example
70
69
  * ```vue
@@ -138,7 +138,7 @@ export function useListCalculateds(listCalculatedArgs: {
138
138
  * @returns {ListCalculated} - A reactive instance that manages and provides access to calculated properties within the
139
139
  * list, facilitating real-time updates and complex dependency management across multiple components.
140
140
  */
141
- export function useListCalculated({ parentState, calculatedObjectsRules }: ListCalculatedOptions): ListCalculated;
141
+ export function useListCalculated(options: ListCalculatedOptions): ListCalculated;
142
142
  /**
143
143
  * Defines rules for dynamically calculating new properties for objects in a list. Each rule is a function that takes an object from the list, optionally its related objects, and previously calculated properties to compute a new property. These functions are reactive and re-evaluate when underlying dependencies change. Each entry of the third argument is backed by a computed, but it is read through a reactive proxy that unwraps it, so a rule reads `calculatedObjects.otherRule` directly and never `.value`.
144
144
  */
@@ -18,13 +18,13 @@
18
18
  * subscribe function.
19
19
  */
20
20
  /**
21
- * @typedef {{[pk: import('../config/commonCrud.js').Pk]: import('../use/objectInstance.js').ExistingCrudObject}} ObjectsByPk - The objects by pk.
21
+ * @typedef {{readonly [pk: import('../config/commonCrud.js').Pk]: import('../use/objectInstance.js').ExistingCrudObject}} ObjectsByPk - The objects by pk. The collection itself is read-only; mutate it through the list's own methods. Each object it holds stays reactive and writable.
22
22
  */
23
23
  /**
24
- * @typedef {import('vue').ComputedRef<import('../use/objectInstance.js').ExistingCrudObject[]>} ObjectsInOrder - The objects in order, based on .order & .objects.
24
+ * @typedef {import('vue').ComputedRef<readonly import('../use/objectInstance.js').ExistingCrudObject[]>} ObjectsInOrder - The objects in order, based on .order & .objects. The array is read-only; each object in it stays reactive and writable.
25
25
  */
26
26
  /**
27
- * @typedef {import('vue').ComputedRef<import('../config/commonCrud.js').Pk[]>} ListOrder - The order of the objects in the list.
27
+ * @typedef {import('vue').ComputedRef<readonly import('../config/commonCrud.js').Pk[]>} ListOrder - The read-only order of the objects in the list. Change presentation order through `useListSort` rather than by writing to it.
28
28
  */
29
29
  /**
30
30
  * @typedef {object} ListInstanceRawStateCrud - The raw CRUD handlers and target args stored in a list instance's reactive state.
@@ -35,7 +35,7 @@
35
35
  * @property {import('../config/listCrud.js').CrudExecuteActionFn} executeAction - The execute action function.
36
36
  */
37
37
  /**
38
- * @typedef {Map<import('../config/commonCrud.js').Pk, import('vue').Reactive<import('../use/objectInstance.js').ExistingCrudObject>>} ObjectsMap - A Map of primary keys to the list's reactive existing objects.
38
+ * @typedef {ReadonlyMap<import('../config/commonCrud.js').Pk, import('vue').Reactive<import('../use/objectInstance.js').ExistingCrudObject>>} ObjectsMap - A read-only Map of primary keys to the list's reactive existing objects. Mutate it through the list's own methods. Each object it holds stays reactive and writable.
39
39
  */
40
40
  /**
41
41
  * @typedef {object} PaginateInfo - Pagination details for a list, including total records, total pages, per-page count, and current page.
@@ -94,8 +94,8 @@
94
94
  * or error state.
95
95
  * @property {() => import('../config/commonCrud.js').Pk} getFakePk - Generates a unique fake pk for use within the list.
96
96
  * @property {(args?: import('../config/listCrud.js').AdditionalListArgs) => import('../utils/cancellablePromise.js').MaybeCancellablePromise<boolean|never>} list - Initiates a fetch to retrieve objects according to the CRUD configuration, returning a promise to a boolean indicating success.
97
- * @property {(args?: {pks?: import('../config/commonCrud.js').Pk[]} & import('../config/listCrud.js').AdditionalListArgs) => Promise<boolean>} bulkDelete - Deletes objects from the list by pk, returning a promise to a boolean indicating success.
98
- * @property {(args: {action: string, pks?: import('../config/commonCrud.js').Pk[]} & import('../config/listCrud.js').AdditionalListArgs) => Promise<object|string|boolean|null>} executeAction - Initiates an action on all objects in the list, returning the response, or null if the action failed.
97
+ * @property {(args?: {pks?: import('../config/commonCrud.js').Pk[]} & import('../config/listCrud.js').AdditionalListArgs) => import('../utils/cancellablePromise.js').MaybeCancellablePromise<boolean>} bulkDelete - Deletes objects from the list by pk, returning a promise to a boolean indicating success. The promise carries a `cancel` method when the handler's promise did.
98
+ * @property {(args: {action: string, pks?: import('../config/commonCrud.js').Pk[]} & import('../config/listCrud.js').AdditionalListArgs) => import('../utils/cancellablePromise.js').MaybeCancellablePromise<object|string|boolean|null>} executeAction - Initiates an action on all objects in the list, returning the response, or null if the action failed. The promise carries a `cancel` method when the handler's promise did.
99
99
  * @property {(info: PaginateInfo) => void} setPaginateInfo - The method to update pagination information.
100
100
  * @property {(total: ColumnTotals) => void} setColumnTotals - The method to update column totals.
101
101
  */
@@ -227,19 +227,19 @@ export type ListInstanceOptions = {
227
227
  };
228
228
  };
229
229
  /**
230
- * The objects by pk.
230
+ * The objects by pk. The collection itself is read-only; mutate it through the list's own methods. Each object it holds stays reactive and writable.
231
231
  */
232
232
  export type ObjectsByPk = {
233
- [pk: import("../config/commonCrud.js").Pk]: import("../use/objectInstance.js").ExistingCrudObject;
233
+ readonly [pk: import("../config/commonCrud.js").Pk]: import("../use/objectInstance.js").ExistingCrudObject;
234
234
  };
235
235
  /**
236
- * The objects in order, based on .order & .objects.
236
+ * The objects in order, based on .order & .objects. The array is read-only; each object in it stays reactive and writable.
237
237
  */
238
- export type ObjectsInOrder = import("vue").ComputedRef<import("../use/objectInstance.js").ExistingCrudObject[]>;
238
+ export type ObjectsInOrder = import("vue").ComputedRef<readonly import("../use/objectInstance.js").ExistingCrudObject[]>;
239
239
  /**
240
- * The order of the objects in the list.
240
+ * The read-only order of the objects in the list. Change presentation order through `useListSort` rather than by writing to it.
241
241
  */
242
- export type ListOrder = import("vue").ComputedRef<import("../config/commonCrud.js").Pk[]>;
242
+ export type ListOrder = import("vue").ComputedRef<readonly import("../config/commonCrud.js").Pk[]>;
243
243
  /**
244
244
  * The raw CRUD handlers and target args stored in a list instance's reactive state.
245
245
  */
@@ -266,9 +266,9 @@ export type ListInstanceRawStateCrud = {
266
266
  executeAction: import("../config/listCrud.js").CrudExecuteActionFn;
267
267
  };
268
268
  /**
269
- * A Map of primary keys to the list's reactive existing objects.
269
+ * A read-only Map of primary keys to the list's reactive existing objects. Mutate it through the list's own methods. Each object it holds stays reactive and writable.
270
270
  */
271
- export type ObjectsMap = Map<import("../config/commonCrud.js").Pk, import("vue").Reactive<import("../use/objectInstance.js").ExistingCrudObject>>;
271
+ export type ObjectsMap = ReadonlyMap<import("../config/commonCrud.js").Pk, import("vue").Reactive<import("../use/objectInstance.js").ExistingCrudObject>>;
272
272
  /**
273
273
  * Pagination details for a list, including total records, total pages, per-page count, and current page.
274
274
  */
@@ -416,18 +416,18 @@ export type ListInstanceMyFunctions = {
416
416
  */
417
417
  list: (args?: import("../config/listCrud.js").AdditionalListArgs) => import("../utils/cancellablePromise.js").MaybeCancellablePromise<boolean | never>;
418
418
  /**
419
- * Deletes objects from the list by pk, returning a promise to a boolean indicating success.
419
+ * Deletes objects from the list by pk, returning a promise to a boolean indicating success. The promise carries a `cancel` method when the handler's promise did.
420
420
  */
421
421
  bulkDelete: (args?: {
422
422
  pks?: import("../config/commonCrud.js").Pk[];
423
- } & import("../config/listCrud.js").AdditionalListArgs) => Promise<boolean>;
423
+ } & import("../config/listCrud.js").AdditionalListArgs) => import("../utils/cancellablePromise.js").MaybeCancellablePromise<boolean>;
424
424
  /**
425
- * Initiates an action on all objects in the list, returning the response, or null if the action failed.
425
+ * Initiates an action on all objects in the list, returning the response, or null if the action failed. The promise carries a `cancel` method when the handler's promise did.
426
426
  */
427
427
  executeAction: (args: {
428
428
  action: string;
429
429
  pks?: import("../config/commonCrud.js").Pk[];
430
- } & import("../config/listCrud.js").AdditionalListArgs) => Promise<object | string | boolean | null>;
430
+ } & import("../config/listCrud.js").AdditionalListArgs) => import("../utils/cancellablePromise.js").MaybeCancellablePromise<object | string | boolean | null>;
431
431
  /**
432
432
  * The method to update pagination information.
433
433
  */
@@ -1,13 +1,9 @@
1
- /**
2
- * Vue Composition API composable function for managing relationships among objects in a list.
3
- * It enables linking objects based on predefined rules and dynamically adjusts as the underlying data changes.
4
- *
5
- * @module use/listRelated.js
6
- */
7
1
  /**
8
2
  * @typedef {object} ListRelatedRule - The rule for defining relationships for objects in a list.
9
- * @property {string} [pkKey] - Specifies the foreign key used to link objects across lists. Defaults to the rule's
10
- * own key when omitted. Planned to be renamed to 'fkKey' to better reflect its usage.
3
+ * @property {string} [fkKey] - Specifies the foreign key on each row used to link objects across lists. Defaults to
4
+ * the rule's own key when omitted.
5
+ * @property {string} [pkKey] - Deprecated alias for `fkKey`, removed in v24. The option never named a primary key.
6
+ * A rule setting both uses `fkKey`.
11
7
  * @property {string[]} [order] - Specifies the order in which related objects should be sorted, if applicable.
12
8
  * @property {import('./listInstance.js').ObjectsByPk} objects - The objects that can be related based on the foreign key.
13
9
  */
@@ -130,7 +126,7 @@ export function useListRelateds(listRelatedArgs: {
130
126
  * relatedObjectsRules: {
131
127
  * someRule: {
132
128
  * // this can point to a key or an array of keys to relate to
133
- * pkKey: "dot.separated.key.to.pk.on.an.listInstance.object",
129
+ * fkKey: "dot.separated.key.to.the.foreign.key.on.a.listInstance.object",
134
130
  * objects: toRef(props, "objects"),
135
131
  * order: toRef(props, "order"),
136
132
  * },
@@ -157,14 +153,39 @@ export function useListRelateds(listRelatedArgs: {
157
153
  * @returns {ListRelated} - A reactive instance that manages related objects, providing real-time updates and
158
154
  * maintaining the integrity of object relationships as per the specified rules.
159
155
  */
160
- export function useListRelated({ parentState, relatedObjectsRules }: ListRelatedOptions): ListRelated;
156
+ export function useListRelated(options: ListRelatedOptions): ListRelated;
157
+ /**
158
+ * Vue Composition API composable function for managing relationships among objects in a list.
159
+ * It enables linking objects based on predefined rules and dynamically adjusts as the underlying data changes.
160
+ *
161
+ * @module use/listRelated.js
162
+ */
163
+ /**
164
+ * Defines a custom error class specific to list related rules, encapsulating details about rules that cannot be
165
+ * resolved as configured.
166
+ */
167
+ export class ListRelatedError extends Error {
168
+ /**
169
+ * Creates an instance of ListRelatedError.
170
+ *
171
+ * @param {string} message - The error message.
172
+ * @param {string} code - The error code.
173
+ */
174
+ constructor(message: string, code: string);
175
+ code: string;
176
+ }
161
177
  /**
162
178
  * The rule for defining relationships for objects in a list.
163
179
  */
164
180
  export type ListRelatedRule = {
165
181
  /**
166
- * Specifies the foreign key used to link objects across lists. Defaults to the rule's
167
- * own key when omitted. Planned to be renamed to 'fkKey' to better reflect its usage.
182
+ * Specifies the foreign key on each row used to link objects across lists. Defaults to
183
+ * the rule's own key when omitted.
184
+ */
185
+ fkKey?: string;
186
+ /**
187
+ * Deprecated alias for `fkKey`, removed in v24. The option never named a primary key.
188
+ * A rule setting both uses `fkKey`.
168
189
  */
169
190
  pkKey?: string;
170
191
  /**