@procedures/client 0.8.0 → 0.8.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.
- package/CHANGELOG.md +58 -0
- package/README.md +95 -8
- package/dist/.tsbuildinfo +1 -1
- package/dist/adapters/http/client/transport.d.ts +4 -0
- package/dist/adapters/http/client/transport.d.ts.map +1 -1
- package/dist/adapters/http/client/transport.js +11 -1
- package/dist/adapters/http/client/transport.js.map +1 -1
- package/dist/adapters/http/client/types.d.ts +19 -0
- package/dist/adapters/http/client/types.d.ts.map +1 -1
- package/dist/adapters/http/server/cors.d.ts +64 -0
- package/dist/adapters/http/server/cors.d.ts.map +1 -0
- package/dist/adapters/http/server/cors.js +113 -0
- package/dist/adapters/http/server/cors.js.map +1 -0
- package/dist/adapters/http/server/handler.d.ts +136 -0
- package/dist/adapters/http/server/handler.d.ts.map +1 -0
- package/dist/adapters/http/server/handler.js +495 -0
- package/dist/adapters/http/server/handler.js.map +1 -0
- package/dist/adapters/http/server/strategies.d.ts +14 -5
- package/dist/adapters/http/server/strategies.d.ts.map +1 -1
- package/dist/adapters/http/server/strategies.js.map +1 -1
- package/dist/adapters/http/server/transport.d.ts +30 -46
- package/dist/adapters/http/server/transport.d.ts.map +1 -1
- package/dist/adapters/http/server/transport.js +48 -432
- package/dist/adapters/http/server/transport.js.map +1 -1
- package/dist/adapters/http/server/types.d.ts +13 -0
- package/dist/adapters/http/server/types.d.ts.map +1 -1
- package/dist/adapters/websocket/server/transport.d.ts +46 -1
- package/dist/adapters/websocket/server/transport.d.ts.map +1 -1
- package/dist/adapters/websocket/server/transport.js +152 -15
- package/dist/adapters/websocket/server/transport.js.map +1 -1
- package/dist/adapters/websocket/server/types.d.ts +10 -3
- package/dist/adapters/websocket/server/types.d.ts.map +1 -1
- package/dist/adapters/websocket/server/upgrade-router.d.ts +28 -0
- package/dist/adapters/websocket/server/upgrade-router.d.ts.map +1 -0
- package/dist/adapters/websocket/server/upgrade-router.js +62 -0
- package/dist/adapters/websocket/server/upgrade-router.js.map +1 -0
- package/dist/adapters/websocket/server/upgrade.d.ts +68 -0
- package/dist/adapters/websocket/server/upgrade.d.ts.map +1 -0
- package/dist/adapters/websocket/server/upgrade.js +49 -0
- package/dist/adapters/websocket/server/upgrade.js.map +1 -0
- package/dist/adapters/websocket/shared/rpc.d.ts +2 -0
- package/dist/adapters/websocket/shared/rpc.d.ts.map +1 -1
- package/dist/adapters/websocket/shared/rpc.js +8 -2
- package/dist/adapters/websocket/shared/rpc.js.map +1 -1
- package/dist/browser.d.ts +12 -4
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +11 -2
- package/dist/browser.js.map +1 -1
- package/dist/client/client.d.ts +43 -0
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +69 -1
- package/dist/client/client.js.map +1 -1
- package/dist/events/publisher.d.ts +14 -0
- package/dist/events/publisher.d.ts.map +1 -1
- package/dist/events/publisher.js +42 -4
- package/dist/events/publisher.js.map +1 -1
- package/dist/events/rows.d.ts +31 -0
- package/dist/events/rows.d.ts.map +1 -0
- package/dist/events/rows.js +39 -0
- package/dist/events/rows.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/node.d.ts +14 -0
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +9 -0
- package/dist/node.js.map +1 -1
- package/dist/procedures/capability.d.ts +6 -0
- package/dist/procedures/capability.d.ts.map +1 -1
- package/dist/procedures/capability.js +25 -0
- package/dist/procedures/capability.js.map +1 -1
- package/dist/procedures/collection/changes.d.ts +94 -0
- package/dist/procedures/collection/changes.d.ts.map +1 -0
- package/dist/procedures/collection/changes.js +182 -0
- package/dist/procedures/collection/changes.js.map +1 -0
- package/dist/procedures/collection/index.d.ts +8 -3
- package/dist/procedures/collection/index.d.ts.map +1 -1
- package/dist/procedures/collection/index.js +6 -1
- package/dist/procedures/collection/index.js.map +1 -1
- package/dist/procedures/collection/procedures.d.ts +39 -2
- package/dist/procedures/collection/procedures.d.ts.map +1 -1
- package/dist/procedures/collection/procedures.js +111 -8
- package/dist/procedures/collection/procedures.js.map +1 -1
- package/dist/procedures/collection/query.d.ts +246 -0
- package/dist/procedures/collection/query.d.ts.map +1 -0
- package/dist/procedures/collection/query.js +854 -0
- package/dist/procedures/collection/query.js.map +1 -0
- package/dist/procedures/collection/schemas.d.ts +50 -0
- package/dist/procedures/collection/schemas.d.ts.map +1 -1
- package/dist/procedures/collection/schemas.js +144 -6
- package/dist/procedures/collection/schemas.js.map +1 -1
- package/dist/procedures/collection/storage.d.ts +58 -6
- package/dist/procedures/collection/storage.d.ts.map +1 -1
- package/dist/procedures/collection/storage.js +23 -0
- package/dist/procedures/collection/storage.js.map +1 -1
- package/dist/procedures/elicit.d.ts +190 -0
- package/dist/procedures/elicit.d.ts.map +1 -0
- package/dist/procedures/elicit.js +127 -0
- package/dist/procedures/elicit.js.map +1 -0
- package/dist/procedures/hints.d.ts +43 -0
- package/dist/procedures/hints.d.ts.map +1 -0
- package/dist/procedures/hints.js +74 -0
- package/dist/procedures/hints.js.map +1 -0
- package/dist/procedures/index.d.ts +9 -2
- package/dist/procedures/index.d.ts.map +1 -1
- package/dist/procedures/index.js +5 -1
- package/dist/procedures/index.js.map +1 -1
- package/dist/procedures/invoke.d.ts +20 -0
- package/dist/procedures/invoke.d.ts.map +1 -1
- package/dist/procedures/invoke.js +13 -0
- package/dist/procedures/invoke.js.map +1 -1
- package/dist/procedures/progress.d.ts +24 -0
- package/dist/procedures/progress.d.ts.map +1 -0
- package/dist/procedures/progress.js +11 -0
- package/dist/procedures/progress.js.map +1 -0
- package/dist/procedures/registry.d.ts.map +1 -1
- package/dist/procedures/registry.js +5 -0
- package/dist/procedures/registry.js.map +1 -1
- package/dist/procedures/types.d.ts +42 -0
- package/dist/procedures/types.d.ts.map +1 -1
- package/dist/procedures/types.js.map +1 -1
- package/dist/procedures/untrusted.d.ts +28 -0
- package/dist/procedures/untrusted.d.ts.map +1 -0
- package/dist/procedures/untrusted.js +32 -0
- package/dist/procedures/untrusted.js.map +1 -0
- package/dist/server/browser-guard.d.ts +12 -2
- package/dist/server/browser-guard.d.ts.map +1 -1
- package/dist/server/browser-guard.js +43 -6
- package/dist/server/browser-guard.js.map +1 -1
- package/dist/server/host-policy.d.ts +10 -1
- package/dist/server/host-policy.d.ts.map +1 -1
- package/dist/server/host-policy.js +5 -0
- package/dist/server/host-policy.js.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/procedure-server.d.ts +38 -6
- package/dist/server/procedure-server.d.ts.map +1 -1
- package/dist/server/procedure-server.js +65 -13
- package/dist/server/procedure-server.js.map +1 -1
- package/dist/server/request-auth.d.ts +51 -4
- package/dist/server/request-auth.d.ts.map +1 -1
- package/dist/server/request-auth.js +116 -5
- package/dist/server/request-auth.js.map +1 -1
- package/dist/server/types.d.ts +73 -5
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/types.js.map +1 -1
- package/package.json +5 -1
- package/src/adapters/http/client/transport.ts +11 -1
- package/src/adapters/http/client/types.ts +22 -0
- package/src/adapters/http/server/cors.ts +144 -0
- package/src/adapters/http/server/handler.ts +624 -0
- package/src/adapters/http/server/strategies.ts +16 -6
- package/src/adapters/http/server/transport.ts +55 -478
- package/src/adapters/http/server/types.ts +15 -0
- package/src/adapters/websocket/server/transport.ts +166 -16
- package/src/adapters/websocket/server/types.ts +11 -3
- package/src/adapters/websocket/server/upgrade-router.ts +77 -0
- package/src/adapters/websocket/server/upgrade.ts +88 -0
- package/src/adapters/websocket/shared/rpc.ts +9 -2
- package/src/browser.ts +79 -2
- package/src/client/client.ts +83 -1
- package/src/events/publisher.ts +48 -4
- package/src/events/rows.ts +48 -0
- package/src/index.ts +1 -1
- package/src/node.ts +21 -0
- package/src/procedures/capability.ts +21 -0
- package/src/procedures/collection/changes.ts +245 -0
- package/src/procedures/collection/index.ts +53 -1
- package/src/procedures/collection/procedures.ts +163 -7
- package/src/procedures/collection/query.ts +1009 -0
- package/src/procedures/collection/schemas.ts +196 -7
- package/src/procedures/collection/storage.ts +78 -6
- package/src/procedures/elicit.ts +320 -0
- package/src/procedures/hints.ts +91 -0
- package/src/procedures/index.ts +78 -2
- package/src/procedures/invoke.ts +29 -0
- package/src/procedures/progress.ts +25 -0
- package/src/procedures/registry.ts +4 -0
- package/src/procedures/types.ts +49 -0
- package/src/procedures/untrusted.ts +50 -0
- package/src/server/browser-guard.ts +48 -6
- package/src/server/host-policy.ts +13 -1
- package/src/server/index.ts +3 -0
- package/src/server/procedure-server.ts +82 -14
- package/src/server/request-auth.ts +128 -6
- package/src/server/types.ts +82 -5
|
@@ -21,6 +21,10 @@ export {
|
|
|
21
21
|
getAllOutputSchema,
|
|
22
22
|
entriesInputSchema,
|
|
23
23
|
entriesOutputSchema,
|
|
24
|
+
findInputSchema,
|
|
25
|
+
findOutputSchema,
|
|
26
|
+
patchInputSchema,
|
|
27
|
+
patchOutputSchema,
|
|
24
28
|
idsInputSchema,
|
|
25
29
|
idsOutputSchema,
|
|
26
30
|
changesInputSchema,
|
|
@@ -46,6 +50,8 @@ export type {
|
|
|
46
50
|
GetAllInput,
|
|
47
51
|
EntriesInput,
|
|
48
52
|
CollectionEntry,
|
|
53
|
+
FindInput,
|
|
54
|
+
PatchInput,
|
|
49
55
|
IdsInput,
|
|
50
56
|
ChangesInput,
|
|
51
57
|
ChangesOutput,
|
|
@@ -58,6 +64,52 @@ export type {
|
|
|
58
64
|
|
|
59
65
|
// Procedures
|
|
60
66
|
export { createCollectionProcedures } from "./procedures.js";
|
|
67
|
+
export type { CollectionProceduresOptions, CollectionChangeEventsOptions } from "./procedures.js";
|
|
68
|
+
|
|
69
|
+
// The change events of the writes (roadmap CLI-15)
|
|
70
|
+
export { collectionChangeTopic, collectionTopicReads } from "./changes.js";
|
|
71
|
+
export type { CollectionChangeEvent } from "./changes.js";
|
|
61
72
|
|
|
62
73
|
// The storage interface of the core (the shape of client-collections' CollectionStorage)
|
|
63
|
-
export type {
|
|
74
|
+
export type {
|
|
75
|
+
CollectionStorage,
|
|
76
|
+
StorageChanges,
|
|
77
|
+
StorageMetadata,
|
|
78
|
+
StorageWriteOptions,
|
|
79
|
+
StorageSetChange,
|
|
80
|
+
StorageDeleteChange,
|
|
81
|
+
StorageClearChange,
|
|
82
|
+
StorageChangeEvent,
|
|
83
|
+
StorageChangeBatch,
|
|
84
|
+
StorageObserver,
|
|
85
|
+
} from "./storage.js";
|
|
86
|
+
|
|
87
|
+
// The query language of the storages: the same JSON on the wire and in query() (roadmap CLI-34:
|
|
88
|
+
// the one copy of the language)
|
|
89
|
+
export {
|
|
90
|
+
DEFAULT_FIND_LIMIT,
|
|
91
|
+
DEFAULT_QUERY_OPERATORS,
|
|
92
|
+
DEFAULT_QUERY_POLICY,
|
|
93
|
+
QUERY_OPERATORS,
|
|
94
|
+
applyPatch,
|
|
95
|
+
compareStorageValues,
|
|
96
|
+
compileSelector,
|
|
97
|
+
isPatchOperations,
|
|
98
|
+
matchesSelector,
|
|
99
|
+
mergePatch,
|
|
100
|
+
patchProblems,
|
|
101
|
+
queryEntries,
|
|
102
|
+
queryOptionsProblems,
|
|
103
|
+
selectorProblems,
|
|
104
|
+
} from "./query.js";
|
|
105
|
+
export type {
|
|
106
|
+
StorageFieldOperators,
|
|
107
|
+
StoragePatch,
|
|
108
|
+
StoragePatchOperations,
|
|
109
|
+
StorageQueryOperator,
|
|
110
|
+
StorageQueryOptions,
|
|
111
|
+
StorageQueryPolicy,
|
|
112
|
+
StorageSelector,
|
|
113
|
+
StorageSort,
|
|
114
|
+
StorageSortDirection,
|
|
115
|
+
} from "./query.js";
|
|
@@ -34,6 +34,12 @@ import {
|
|
|
34
34
|
setBatchOutputSchema,
|
|
35
35
|
deleteBatchInputSchema,
|
|
36
36
|
deleteBatchOutputSchema,
|
|
37
|
+
findInputSchemaOf,
|
|
38
|
+
findOutputSchema,
|
|
39
|
+
patchInputSchema,
|
|
40
|
+
patchOutputSchema,
|
|
41
|
+
type FindInput,
|
|
42
|
+
type PatchInput,
|
|
37
43
|
type GetInput,
|
|
38
44
|
type GetFoundOutput,
|
|
39
45
|
type SetInput,
|
|
@@ -50,6 +56,9 @@ import {
|
|
|
50
56
|
type SetBatchInput,
|
|
51
57
|
type DeleteBatchInput,
|
|
52
58
|
} from "./schemas.js";
|
|
59
|
+
import { DEFAULT_FIND_LIMIT, applyPatch, queryEntries, type StoragePatch, type StorageQueryOptions, type StorageQueryPolicy } from "./query.js";
|
|
60
|
+
import type { CollectionStorage, StorageWriteOptions } from "./storage.js";
|
|
61
|
+
import { collectionChangeTopic, startChangeChain, writeWithChangeEvent } from "./changes.js";
|
|
53
62
|
|
|
54
63
|
// =============================================================================
|
|
55
64
|
// Handler Factory
|
|
@@ -77,6 +86,93 @@ function getStorage<T>(ctx: ProcedureContext): ReturnType<NonNullable<ProcedureC
|
|
|
77
86
|
return ctx.repository.getStorage<T>(collection);
|
|
78
87
|
}
|
|
79
88
|
|
|
89
|
+
/** The options of a query from the input of `find`. */
|
|
90
|
+
function queryOptionsOf(input: FindInput, policy: StorageQueryPolicy): StorageQueryOptions {
|
|
91
|
+
// A find without a limit gets the maxLimit of the policy (roadmap CLI-14)
|
|
92
|
+
const limit = input.limit ?? (Number.isFinite(policy.maxLimit) ? policy.maxLimit : undefined);
|
|
93
|
+
return {
|
|
94
|
+
...(input.sort !== undefined && { sort: input.sort }),
|
|
95
|
+
...(input.skip !== undefined && { skip: input.skip }),
|
|
96
|
+
...(limit !== undefined && { limit }),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** The options of the change events of the collection procedures (roadmap CLI-15). */
|
|
101
|
+
export interface CollectionChangeEventsOptions {
|
|
102
|
+
/**
|
|
103
|
+
* The topic of the change events of a call, or undefined for no event. The partition of a
|
|
104
|
+
* collection (roadmap CLI-17) goes into the topic here, for example from the scope of the call.
|
|
105
|
+
* @default the topic `collections.<name>` of `collectionChangeTopic()`
|
|
106
|
+
*/
|
|
107
|
+
topic?: ((collection: string, ctx: ProcedureContext) => string | undefined) | undefined;
|
|
108
|
+
/**
|
|
109
|
+
* True: the events also carry the values of the changed items. Each row `{ id, value }` passes
|
|
110
|
+
* the output filter of the host (`admitItem`) for each subscriber, and a refused row stays out of
|
|
111
|
+
* that event: its id goes to `withheld`. Without it, the events carry only the ids and the
|
|
112
|
+
* versions, and a subscriber reads the values with `changes`.
|
|
113
|
+
* @default false
|
|
114
|
+
*/
|
|
115
|
+
values?: boolean | undefined;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** The options of the collection procedures. */
|
|
119
|
+
export interface CollectionProceduresOptions {
|
|
120
|
+
/**
|
|
121
|
+
* The query policy of `find`: the operators, and the limits of a selector and of the result. A
|
|
122
|
+
* selector or a limit that the policy does not permit is a `VALIDATION_ERROR`. The policy also
|
|
123
|
+
* goes to `query()` of the storage. `$regex` is off unless the policy has it in `operators`.
|
|
124
|
+
* @default DEFAULT_QUERY_POLICY, with `maxLimit` DEFAULT_FIND_LIMIT (1000)
|
|
125
|
+
*/
|
|
126
|
+
queryPolicy?: StorageQueryPolicy | undefined;
|
|
127
|
+
/**
|
|
128
|
+
* The change events of the writes (roadmap CLI-15). Each write publishes a
|
|
129
|
+
* `CollectionChangeEvent` on the bus of its context, while a subscriber listens to the topic.
|
|
130
|
+
* The event has the ids and the versions, and the values only with `values`. False: the
|
|
131
|
+
* procedures publish no event.
|
|
132
|
+
* @default true, with the topic `collections.<name>` and no values
|
|
133
|
+
*/
|
|
134
|
+
changeEvents?: boolean | CollectionChangeEventsOptions | undefined;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** The write options of an input with an origin. */
|
|
138
|
+
function writeOptionsOf(input: { origin?: string }): StorageWriteOptions | undefined {
|
|
139
|
+
return input.origin === undefined ? undefined : { origin: input.origin };
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* The patches of a storage without `patch()` that run, for each id. A patch of an id waits for the
|
|
144
|
+
* patch before it, so two patches of one process keep each field. A write of another writer
|
|
145
|
+
* between the read and the write of a patch is lost: give the storage a `patch()` for one step.
|
|
146
|
+
*/
|
|
147
|
+
const PATCHES = new WeakMap<object, Map<string, Promise<unknown>>>();
|
|
148
|
+
|
|
149
|
+
/** This function patches an item of a storage without `patch()`: a read, a merge and a write. */
|
|
150
|
+
function patchInParts(storage: CollectionStorage<unknown>, id: string, fields: StoragePatch, options?: StorageWriteOptions): Promise<unknown> {
|
|
151
|
+
let running = PATCHES.get(storage);
|
|
152
|
+
if (!running) {
|
|
153
|
+
running = new Map();
|
|
154
|
+
PATCHES.set(storage, running);
|
|
155
|
+
}
|
|
156
|
+
const queue = running;
|
|
157
|
+
const before = queue.get(id) ?? Promise.resolve();
|
|
158
|
+
const patch = before.then(async () => {
|
|
159
|
+
const current = await storage.get(id);
|
|
160
|
+
if (current === undefined) return undefined;
|
|
161
|
+
const next = applyPatch(current, fields);
|
|
162
|
+
await storage.set(id, next, options);
|
|
163
|
+
return next;
|
|
164
|
+
});
|
|
165
|
+
const settled = patch.then(
|
|
166
|
+
() => undefined,
|
|
167
|
+
() => undefined,
|
|
168
|
+
);
|
|
169
|
+
queue.set(id, settled);
|
|
170
|
+
void settled.then(() => {
|
|
171
|
+
if (queue.get(id) === settled) queue.delete(id);
|
|
172
|
+
});
|
|
173
|
+
return patch;
|
|
174
|
+
}
|
|
175
|
+
|
|
80
176
|
// =============================================================================
|
|
81
177
|
// Collection Procedure Definitions
|
|
82
178
|
// =============================================================================
|
|
@@ -85,6 +181,7 @@ function getStorage<T>(ctx: ProcedureContext): ReturnType<NonNullable<ProcedureC
|
|
|
85
181
|
* Create collection procedures for a specific collection name.
|
|
86
182
|
*
|
|
87
183
|
* @param collectionName - Name of the collection
|
|
184
|
+
* @param options - The query policy of `find`
|
|
88
185
|
* @returns Array of procedure definitions
|
|
89
186
|
*
|
|
90
187
|
* @example
|
|
@@ -93,10 +190,21 @@ function getStorage<T>(ctx: ProcedureContext): ReturnType<NonNullable<ProcedureC
|
|
|
93
190
|
* registry.registerAll(userProcedures);
|
|
94
191
|
* ```
|
|
95
192
|
*/
|
|
96
|
-
export function createCollectionProcedures(collectionName: string): AnyProcedure[] {
|
|
193
|
+
export function createCollectionProcedures(collectionName: string, options: CollectionProceduresOptions = {}): AnyProcedure[] {
|
|
97
194
|
const basePath = ["collections", collectionName];
|
|
195
|
+
// A find of a caller gets a limit: DEFAULT_FIND_LIMIT, unless the policy gives its own maxLimit
|
|
196
|
+
const queryPolicy: StorageQueryPolicy = { ...options.queryPolicy, maxLimit: options.queryPolicy?.maxLimit ?? DEFAULT_FIND_LIMIT };
|
|
98
197
|
// Each collection is a resource of its own (CAPABILITIES-2026-10): a capability can permit one
|
|
99
198
|
const resource = `collection:${collectionName}`;
|
|
199
|
+
// The topic of the change events of a call (roadmap CLI-15). CLI-17 adds the partition with the option topic.
|
|
200
|
+
const events = options.changeEvents ?? true;
|
|
201
|
+
const topicRule: ((collection: string, ctx: ProcedureContext) => string | undefined) | undefined =
|
|
202
|
+
events === false ? undefined : (events !== true && events.topic) || ((name: string) => collectionChangeTopic(name));
|
|
203
|
+
const topicOf = (ctx: ProcedureContext): string | undefined => topicRule?.(collectionName, ctx);
|
|
204
|
+
const withValues = events !== false && events !== true && events.values === true;
|
|
205
|
+
/** A write, and then its change event on the bus of the context. */
|
|
206
|
+
const changing = <R>(ctx: ProcedureContext, storage: CollectionStorage<unknown>, ids: readonly string[] | "*", origin: string | undefined, write: () => Promise<R>): Promise<R> =>
|
|
207
|
+
writeWithChangeEvent(ctx.bus, storage, topicRule ? topicOf(ctx) : undefined, ids, origin, write, withValues);
|
|
100
208
|
|
|
101
209
|
return [
|
|
102
210
|
// Get
|
|
@@ -131,7 +239,7 @@ export function createCollectionProcedures(collectionName: string): AnyProcedure
|
|
|
131
239
|
},
|
|
132
240
|
handler: async (input: SetInput, ctx: ProcedureContext) => {
|
|
133
241
|
const storage = getStorage(ctx);
|
|
134
|
-
await storage.set(input.id, input.value);
|
|
242
|
+
await changing(ctx, storage, [input.id], input.origin, () => storage.set(input.id, input.value, writeOptionsOf(input)));
|
|
135
243
|
},
|
|
136
244
|
}),
|
|
137
245
|
|
|
@@ -147,7 +255,7 @@ export function createCollectionProcedures(collectionName: string): AnyProcedure
|
|
|
147
255
|
},
|
|
148
256
|
handler: async (input: DeleteInput, ctx: ProcedureContext) => {
|
|
149
257
|
const storage = getStorage(ctx);
|
|
150
|
-
return storage.delete(input.id);
|
|
258
|
+
return changing(ctx, storage, [input.id], input.origin, () => storage.delete(input.id, writeOptionsOf(input)));
|
|
151
259
|
},
|
|
152
260
|
}),
|
|
153
261
|
|
|
@@ -235,6 +343,9 @@ export function createCollectionProcedures(collectionName: string): AnyProcedure
|
|
|
235
343
|
const storage = getStorage(ctx);
|
|
236
344
|
if (storage.getChangesSince) {
|
|
237
345
|
const changes = await storage.getChangesSince(input.since);
|
|
346
|
+
// The chain of the change events starts at this version: the caller then applies the
|
|
347
|
+
// next event without a read (roadmap CLI-15)
|
|
348
|
+
if (topicRule) startChangeChain(ctx.bus, storage, topicOf(ctx), changes.version);
|
|
238
349
|
return {
|
|
239
350
|
version: changes.version,
|
|
240
351
|
full: changes.full,
|
|
@@ -252,6 +363,51 @@ export function createCollectionProcedures(collectionName: string): AnyProcedure
|
|
|
252
363
|
},
|
|
253
364
|
}),
|
|
254
365
|
|
|
366
|
+
// Find: the items that match a JSON selector, with an order, a skip and a limit (roadmap CLI-14)
|
|
367
|
+
defineProcedure({
|
|
368
|
+
path: [...basePath, "find"],
|
|
369
|
+
input: findInputSchemaOf(queryPolicy),
|
|
370
|
+
output: findOutputSchema,
|
|
371
|
+
metadata: {
|
|
372
|
+
effects: { reads: [resource], writes: [] },
|
|
373
|
+
description: `Find the items of ${collectionName} that match a selector, with their ids, an order, a skip and a limit`,
|
|
374
|
+
tags: ["collections", collectionName, "read", "query"],
|
|
375
|
+
},
|
|
376
|
+
handler: async (input: FindInput, ctx: ProcedureContext) => {
|
|
377
|
+
const storage = getStorage(ctx);
|
|
378
|
+
const selector = input.selector ?? {};
|
|
379
|
+
const query = queryOptionsOf(input, queryPolicy);
|
|
380
|
+
// The storage runs the selector itself when it can: a database does not read each item. It
|
|
381
|
+
// gets the policy of the host, so it permits what the procedure permits.
|
|
382
|
+
if (storage.query) return (await storage.query(selector, query, queryPolicy)).map(([id, value]) => ({ id, value }));
|
|
383
|
+
if (!storage.getEntries) {
|
|
384
|
+
throw new Error(`The storage of ${collectionName} cannot run a selector or give the ids of its items`);
|
|
385
|
+
}
|
|
386
|
+
return queryEntries(await storage.getEntries(), selector, query, queryPolicy).map(([id, value]) => ({ id, value }));
|
|
387
|
+
},
|
|
388
|
+
}),
|
|
389
|
+
|
|
390
|
+
// Patch: merge fields into one item, a JSON Merge Patch (roadmap CLI-14)
|
|
391
|
+
defineProcedure({
|
|
392
|
+
path: [...basePath, "patch"],
|
|
393
|
+
input: patchInputSchema,
|
|
394
|
+
output: patchOutputSchema,
|
|
395
|
+
metadata: {
|
|
396
|
+
effects: { reads: [resource], writes: [resource], idempotent: true },
|
|
397
|
+
description: `Merge fields into one item of ${collectionName}: a JSON Merge Patch, or the operations $set and $unset`,
|
|
398
|
+
tags: ["collections", collectionName, "write"],
|
|
399
|
+
},
|
|
400
|
+
handler: async (input: PatchInput, ctx: ProcedureContext) => {
|
|
401
|
+
const storage = getStorage(ctx);
|
|
402
|
+
const write = writeOptionsOf(input);
|
|
403
|
+
const value = await changing(ctx, storage, [input.id], input.origin, () =>
|
|
404
|
+
storage.patch ? storage.patch(input.id, input.fields, write) : patchInParts(storage, input.id, input.fields, write),
|
|
405
|
+
);
|
|
406
|
+
const output: GetFoundOutput = value === undefined ? { found: false } : { found: true, value };
|
|
407
|
+
return output;
|
|
408
|
+
},
|
|
409
|
+
}),
|
|
410
|
+
|
|
255
411
|
// Size
|
|
256
412
|
defineProcedure({
|
|
257
413
|
path: [...basePath, "size"],
|
|
@@ -278,9 +434,9 @@ export function createCollectionProcedures(collectionName: string): AnyProcedure
|
|
|
278
434
|
description: `Clear all items from ${collectionName}`,
|
|
279
435
|
tags: ["collections", collectionName, "write"],
|
|
280
436
|
},
|
|
281
|
-
handler: async (
|
|
437
|
+
handler: async (input: ClearInput, ctx: ProcedureContext) => {
|
|
282
438
|
const storage = getStorage(ctx);
|
|
283
|
-
await storage.clear();
|
|
439
|
+
await changing(ctx, storage, "*", input.origin, () => storage.clear(writeOptionsOf(input)));
|
|
284
440
|
},
|
|
285
441
|
}),
|
|
286
442
|
|
|
@@ -318,7 +474,7 @@ export function createCollectionProcedures(collectionName: string): AnyProcedure
|
|
|
318
474
|
item.id,
|
|
319
475
|
item.value,
|
|
320
476
|
]);
|
|
321
|
-
await storage.setBatch(items);
|
|
477
|
+
await changing(ctx, storage, items.map(([id]) => id), input.origin, () => storage.setBatch(items, writeOptionsOf(input)));
|
|
322
478
|
},
|
|
323
479
|
}),
|
|
324
480
|
|
|
@@ -334,7 +490,7 @@ export function createCollectionProcedures(collectionName: string): AnyProcedure
|
|
|
334
490
|
},
|
|
335
491
|
handler: async (input: DeleteBatchInput, ctx: ProcedureContext) => {
|
|
336
492
|
const storage = getStorage(ctx);
|
|
337
|
-
return storage.deleteBatch(input.ids);
|
|
493
|
+
return changing(ctx, storage, input.ids, input.origin, () => storage.deleteBatch(input.ids, writeOptionsOf(input)));
|
|
338
494
|
},
|
|
339
495
|
}),
|
|
340
496
|
];
|