@arrai-innovations/reactive-helpers 22.1.0 → 23.0.1

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 (50) 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 +17 -6
  5. package/types/config/listCrud.d.ts +22 -2
  6. package/types/config/objectCrud.d.ts +6 -4
  7. package/types/tests/benchmarks/fixtures.d.ts +1 -1
  8. package/types/tests/benchmarks/listObserved.bench.d.ts +1 -0
  9. package/types/tests/benchmarks/reviewFixtures.d.ts +102 -0
  10. package/types/tests/unit/matchers.spec.d.ts +1 -0
  11. package/types/tests/unit/use/listLoadingPropagation.spec.d.ts +1 -0
  12. package/types/tests/unit/use/listMembershipWatch.spec.d.ts +1 -0
  13. package/types/tests/unit/use/listNotifications.spec.d.ts +1 -0
  14. package/types/tests/unit/use/listObjectsVersion.spec.d.ts +1 -0
  15. package/types/tests/unit/use/ruleOptionNames.spec.d.ts +1 -0
  16. package/types/use/cancellableIntent.d.ts +4 -5
  17. package/types/use/listCalculated.d.ts +6 -1
  18. package/types/use/listFilter.d.ts +5 -0
  19. package/types/use/listInstance.d.ts +25 -20
  20. package/types/use/listRelated.d.ts +38 -12
  21. package/types/use/listSearch.d.ts +5 -0
  22. package/types/use/listSort.d.ts +5 -0
  23. package/types/use/listSubscription.d.ts +5 -0
  24. package/types/use/objectCalculated.d.ts +1 -1
  25. package/types/use/objectInstance.d.ts +3 -3
  26. package/types/use/objectRelated.d.ts +29 -8
  27. package/types/utils/cancellablePromise.d.ts +15 -0
  28. package/types/utils/getFakePk.d.ts +4 -1
  29. package/types/utils/refIfReactive.d.ts +14 -0
  30. package/types/utils/relatedCalculatedHelpers.d.ts +63 -0
  31. package/types/utils/watches.d.ts +40 -7
  32. package/use/cancellableIntent.js +4 -5
  33. package/use/list.js +3 -0
  34. package/use/listCalculated.js +30 -2
  35. package/use/listFilter.js +139 -24
  36. package/use/listInstance.js +124 -63
  37. package/use/listRelated.js +82 -15
  38. package/use/listSearch.js +111 -19
  39. package/use/listSort.js +104 -28
  40. package/use/listSubscription.js +6 -2
  41. package/use/object.js +6 -3
  42. package/use/objectCalculated.js +4 -1
  43. package/use/objectInstance.js +87 -45
  44. package/use/objectRelated.js +65 -23
  45. package/use/objectSubscription.js +14 -5
  46. package/utils/cancellablePromise.js +26 -0
  47. package/utils/getFakePk.js +7 -2
  48. package/utils/refIfReactive.js +27 -9
  49. package/utils/relatedCalculatedHelpers.js +123 -0
  50. package/utils/watches.js +32 -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.1",
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",
@@ -84,11 +89,16 @@
84
89
  },
85
90
  "scripts": {
86
91
  "benchmark": "vitest bench --run",
92
+ "benchmark:ci": "pnpm benchmark:list:ci && pnpm benchmark:stream:ci && pnpm benchmark:layers:ci && pnpm benchmark:observed:ci",
87
93
  "benchmark:list": "vitest bench --run tests/benchmarks/listPush.bench.js",
88
94
  "benchmark:list:ci": "vitest bench --run tests/benchmarks/listPush.bench.js --outputJson benchmark-results/list-push.json",
89
95
  "benchmark:check": "node check_benchmark.js",
90
96
  "benchmark:layers": "vitest bench --run tests/benchmarks/listLayers.bench.js",
97
+ "benchmark:layers:ci": "vitest bench --run tests/benchmarks/listLayers.bench.js --outputJson benchmark-results/list-layers.json",
98
+ "benchmark:observed": "vitest bench --run tests/benchmarks/listObserved.bench.js",
99
+ "benchmark:observed:ci": "vitest bench --run tests/benchmarks/listObserved.bench.js --outputJson benchmark-results/list-observed.json",
91
100
  "benchmark:stream": "vitest bench --run tests/benchmarks/listStream.bench.js",
101
+ "benchmark:stream:ci": "vitest bench --run tests/benchmarks/listStream.bench.js --outputJson benchmark-results/list-stream.json",
92
102
  "test": "vitest",
93
103
  "eslint": "eslint --fix index.js config/**/*.js tests/**/*.js use/**/*.js utils/**/*.js",
94
104
  "prettier": "prettier --write .",
@@ -98,6 +108,7 @@
98
108
  "docs:clean": "node clean_type_doc.js",
99
109
  "docs:site:dev": "vitepress dev docs",
100
110
  "docs:site:build": "vitepress build docs",
111
+ "docs:site:deploy": "node scripts/deploy-docs.mjs",
101
112
  "docs:site:preview": "vitepress preview docs",
102
113
  "types": "node make_types.js",
103
114
  "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
  /**
@@ -46,7 +46,7 @@ export namespace populatedRules {
46
46
  export { orderByRules_1 as orderByRules };
47
47
  export namespace relatedObjectsRules_1 {
48
48
  namespace org {
49
- export let pkKey: string;
49
+ export let fkKey: string;
50
50
  export { relatedOrganizations as objects };
51
51
  }
52
52
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,102 @@
1
+ /** How many entries each generated lookup collection holds. */
2
+ export const lookupSize: 13;
3
+ export function makeLookup(index: number): import("../../use/listInstance.js").ObjectsByPk;
4
+ /** Lookup collection for the array-valued rule, which resolves a list of foreign keys per record. */
5
+ export const tagLookup: import("../../use/listInstance.js").ObjectsByPk;
6
+ /** The order the array-valued rule sorts its resolved tags into. */
7
+ export const tagOrder: string[];
8
+ export function makeRelatedRules(ruleCount: number, includeArrayRule?: boolean): import("../../use/listRelated.js").ListRelatedRules;
9
+ export function makeCalculatedRules(ruleCount: number, relatedRuleCount: number): {
10
+ [rule: string]: (object: object, related: object, calculated: object) => any;
11
+ };
12
+ export function makeReviewRows(count: number, start?: number, fkCount?: number): object[];
13
+ export function makeOrderByRules(sortOn: "none" | "plain" | "related" | "calculated"): import("../../use/listSort.js").OrderByRule[];
14
+ export function makeReviewList({ relatedRuleCount, calculatedRuleCount, sortOn, includeArrayRule, filter, sortThrottleWait, }?: ReviewListOptions): ReturnType<typeof useList>;
15
+ export function composeReviewStack({ relatedRuleCount, calculatedRuleCount, sortOn, includeArrayRule, filter, sortThrottleWait, }?: ReviewListOptions): {
16
+ states: {
17
+ [layer: string]: object;
18
+ };
19
+ push: (objects: object[]) => void;
20
+ stop: () => void;
21
+ };
22
+ export namespace readChannels {
23
+ let collection: {
24
+ [channel: string]: (state: object) => void;
25
+ };
26
+ let record: {
27
+ [channel: string]: (state: object, pk: string) => void;
28
+ };
29
+ }
30
+ export function attachRenderObservers(state: object, { collectionChannels, recordChannels }?: RenderObserverOptions): {
31
+ sync: () => void;
32
+ stop: () => void;
33
+ counts: {
34
+ [channel: string]: ChannelCounts;
35
+ };
36
+ totals: () => {
37
+ effects: number;
38
+ runs: number;
39
+ triggers: number;
40
+ };
41
+ reset: () => void;
42
+ };
43
+ /**
44
+ * The shape of the review list to build.
45
+ */
46
+ export type ReviewListOptions = {
47
+ /**
48
+ * How many related rules the list carries.
49
+ */
50
+ relatedRuleCount?: number;
51
+ /**
52
+ * How many calculated rules the list carries.
53
+ */
54
+ calculatedRuleCount?: number;
55
+ /**
56
+ * Which value the sort orders on.
57
+ */
58
+ sortOn?: "none" | "plain" | "related" | "calculated";
59
+ /**
60
+ * Whether the related rules include an array-valued rule.
61
+ */
62
+ includeArrayRule?: boolean;
63
+ /**
64
+ * Whether an allowed filter is active.
65
+ */
66
+ filter?: boolean;
67
+ /**
68
+ * The sort throttle, in milliseconds.
69
+ */
70
+ sortThrottleWait?: number;
71
+ };
72
+ /**
73
+ * Which channels observe the list.
74
+ */
75
+ export type RenderObserverOptions = {
76
+ /**
77
+ * Names from `readChannels.collection` to attach once.
78
+ */
79
+ collectionChannels?: string[];
80
+ /**
81
+ * Names from `readChannels.record` to attach per record.
82
+ */
83
+ recordChannels?: string[];
84
+ };
85
+ /**
86
+ * What one channel's effects have done.
87
+ */
88
+ export type ChannelCounts = {
89
+ /**
90
+ * How many effects the channel has attached.
91
+ */
92
+ effects: number;
93
+ /**
94
+ * How many times those effects have evaluated.
95
+ */
96
+ runs: number;
97
+ /**
98
+ * How many times those effects have been notified.
99
+ */
100
+ triggers: number;
101
+ };
102
+ import { useList } from "../../use/list.js";
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -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
@@ -64,6 +64,7 @@
64
64
  * @typedef {object} ListCalculatedProperties - The properties for the list computed composition function.
65
65
  * @property {ListCalculatedState} state - The state for the list calculated property.
66
66
  * @property {ListCalculatedParentState} parentState - The parent state object.
67
+ * @property {import('../utils/watches.js').WatchMembershipChanged} watchMembershipChanged - Registers a callback for changes to the set of object keys this layer holds. The watcher belongs to the effect scope active where it is called, not to this layer, so stopping this layer silences it without disposing it.
67
68
  * @property {() => void} stop - Stops composition's effects and cleans up resources.
68
69
  */
69
70
  /**
@@ -138,7 +139,7 @@ export function useListCalculateds(listCalculatedArgs: {
138
139
  * @returns {ListCalculated} - A reactive instance that manages and provides access to calculated properties within the
139
140
  * list, facilitating real-time updates and complex dependency management across multiple components.
140
141
  */
141
- export function useListCalculated({ parentState, calculatedObjectsRules }: ListCalculatedOptions): ListCalculated;
142
+ export function useListCalculated(options: ListCalculatedOptions): ListCalculated;
142
143
  /**
143
144
  * 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
145
  */
@@ -221,6 +222,10 @@ export type ListCalculatedProperties = {
221
222
  * The parent state object.
222
223
  */
223
224
  parentState: ListCalculatedParentState;
225
+ /**
226
+ * Registers a callback for changes to the set of object keys this layer holds. The watcher belongs to the effect scope active where it is called, not to this layer, so stopping this layer silences it without disposing it.
227
+ */
228
+ watchMembershipChanged: import("../utils/watches.js").WatchMembershipChanged;
224
229
  /**
225
230
  * Stops composition's effects and cleans up resources.
226
231
  */
@@ -51,6 +51,7 @@
51
51
  * @typedef {object} ListFilterProperties - The properties of a list filter, including its state and associated Vue composition API utilities.
52
52
  * @property {ListFilterState} state - The reactive state managing the filter logic and results.
53
53
  * @property {ListFilterParentState} parentState - The state of the list being filtered.
54
+ * @property {import('../utils/watches.js').WatchMembershipChanged} watchMembershipChanged - Registers a callback for changes to the set of object keys this layer holds. The watcher belongs to the effect scope active where it is called, not to this layer, so stopping this layer silences it without disposing it.
54
55
  * @property {() => void} stop - A function to stop the effect scope and clean up resources.
55
56
  */
56
57
  /**
@@ -166,6 +167,10 @@ export type ListFilterProperties = {
166
167
  * The state of the list being filtered.
167
168
  */
168
169
  parentState: ListFilterParentState;
170
+ /**
171
+ * Registers a callback for changes to the set of object keys this layer holds. The watcher belongs to the effect scope active where it is called, not to this layer, so stopping this layer silences it without disposing it.
172
+ */
173
+ watchMembershipChanged: import("../utils/watches.js").WatchMembershipChanged;
169
174
  /**
170
175
  * A function to stop the effect scope and clean up resources.
171
176
  */