@procedures/client 0.8.0 → 0.9.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.
- package/CHANGELOG.md +78 -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/client/transport.d.ts.map +1 -1
- package/dist/adapters/websocket/client/transport.js +4 -12
- package/dist/adapters/websocket/client/transport.js.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 +13 -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 +25 -1
- package/dist/events/publisher.d.ts.map +1 -1
- package/dist/events/publisher.js +66 -9
- 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 +10 -3
- package/dist/procedures/collection/index.d.ts.map +1 -1
- package/dist/procedures/collection/index.js +8 -1
- package/dist/procedures/collection/index.js.map +1 -1
- package/dist/procedures/collection/partition.d.ts +67 -0
- package/dist/procedures/collection/partition.d.ts.map +1 -0
- package/dist/procedures/collection/partition.js +82 -0
- package/dist/procedures/collection/partition.js.map +1 -0
- 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 +147 -44
- 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 +24 -2
- package/dist/procedures/invoke.d.ts.map +1 -1
- package/dist/procedures/invoke.js +14 -1
- 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 +55 -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 +68 -7
- package/dist/server/procedure-server.d.ts.map +1 -1
- package/dist/server/procedure-server.js +124 -24
- 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 +7 -3
- 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/client/transport.ts +4 -12
- 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 +85 -2
- package/src/client/client.ts +83 -1
- package/src/events/publisher.ts +75 -11
- 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 +57 -1
- package/src/procedures/collection/partition.ts +123 -0
- package/src/procedures/collection/procedures.ts +206 -51
- 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 +83 -2
- package/src/procedures/invoke.ts +33 -2
- package/src/procedures/progress.ts +25 -0
- package/src/procedures/registry.ts +4 -0
- package/src/procedures/types.ts +65 -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 +147 -26
- package/src/server/request-auth.ts +128 -6
- package/src/server/types.ts +82 -5
|
@@ -6,6 +6,16 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import type { ZodLike, ZodErrorLike } from "../../client/validation/types.js";
|
|
9
|
+
import {
|
|
10
|
+
DEFAULT_FIND_LIMIT,
|
|
11
|
+
patchProblems,
|
|
12
|
+
queryOptionsProblems,
|
|
13
|
+
selectorProblems,
|
|
14
|
+
type StoragePatch,
|
|
15
|
+
type StorageQueryPolicy,
|
|
16
|
+
type StorageSelector,
|
|
17
|
+
type StorageSort,
|
|
18
|
+
} from "./query.js";
|
|
9
19
|
|
|
10
20
|
// =============================================================================
|
|
11
21
|
// Generic Schema Builder
|
|
@@ -53,6 +63,26 @@ function isObject(value: unknown): value is Record<string, unknown> {
|
|
|
53
63
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
54
64
|
}
|
|
55
65
|
|
|
66
|
+
/** The longest origin of a write, in characters. */
|
|
67
|
+
const MAX_ORIGIN_LENGTH = 256;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The error of the field `origin` of a write input (roadmap CLI-15), or undefined. An origin is a
|
|
71
|
+
* string of 1 to 256 characters. The procedure gives it to the storage and to the change event.
|
|
72
|
+
*/
|
|
73
|
+
function originError(data: Record<string, unknown>): ZodErrorLike | undefined {
|
|
74
|
+
const origin = data["origin"];
|
|
75
|
+
if (origin === undefined || (isString(origin) && origin.length > 0 && origin.length <= MAX_ORIGIN_LENGTH)) return undefined;
|
|
76
|
+
const message = `origin must be a string of 1 to ${MAX_ORIGIN_LENGTH} characters`;
|
|
77
|
+
return { message, errors: [{ path: ["origin"], message }] };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** The input with the origin of the data, when the data has one. */
|
|
81
|
+
function withOriginOf<I extends object>(data: Record<string, unknown>, input: I): I & { origin?: string } {
|
|
82
|
+
const origin = data["origin"];
|
|
83
|
+
return (isString(origin) ? { ...input, origin } : input) as I & { origin?: string };
|
|
84
|
+
}
|
|
85
|
+
|
|
56
86
|
// =============================================================================
|
|
57
87
|
// Common Schemas
|
|
58
88
|
// =============================================================================
|
|
@@ -185,6 +215,8 @@ export const getOutputSchema : ZodLike<unknown> = createSchema<unknown>((data) =
|
|
|
185
215
|
export interface SetInput {
|
|
186
216
|
id: string;
|
|
187
217
|
value: unknown;
|
|
218
|
+
/** The origin of the write, for the observers of the storage and the change event (roadmap CLI-15). */
|
|
219
|
+
origin?: string;
|
|
188
220
|
}
|
|
189
221
|
|
|
190
222
|
export const setInputSchema : ZodLike<SetInput> = createSchema<SetInput>((data) => {
|
|
@@ -215,7 +247,9 @@ export const setInputSchema : ZodLike<SetInput> = createSchema<SetInput>((data)
|
|
|
215
247
|
},
|
|
216
248
|
};
|
|
217
249
|
}
|
|
218
|
-
|
|
250
|
+
const error = originError(data);
|
|
251
|
+
if (error) return { success: false, error };
|
|
252
|
+
return { success: true, data: withOriginOf(data, { id: data["id"], value: data["value"] }) };
|
|
219
253
|
});
|
|
220
254
|
|
|
221
255
|
/**
|
|
@@ -234,6 +268,8 @@ export const setOutputSchema : ZodLike<void> = createSchema<void>((_data) => {
|
|
|
234
268
|
*/
|
|
235
269
|
export interface DeleteInput {
|
|
236
270
|
id: string;
|
|
271
|
+
/** The origin of the write, for the observers of the storage and the change event (roadmap CLI-15). */
|
|
272
|
+
origin?: string;
|
|
237
273
|
}
|
|
238
274
|
|
|
239
275
|
export const deleteInputSchema : ZodLike<DeleteInput> = createSchema<DeleteInput>((data) => {
|
|
@@ -255,7 +291,9 @@ export const deleteInputSchema : ZodLike<DeleteInput> = createSchema<DeleteInput
|
|
|
255
291
|
},
|
|
256
292
|
};
|
|
257
293
|
}
|
|
258
|
-
|
|
294
|
+
const error = originError(data);
|
|
295
|
+
if (error) return { success: false, error };
|
|
296
|
+
return { success: true, data: withOriginOf(data, { id: data["id"] }) };
|
|
259
297
|
});
|
|
260
298
|
|
|
261
299
|
/**
|
|
@@ -406,6 +444,144 @@ export const entriesOutputSchema : ZodLike<CollectionEntry[]> = createSchema<Col
|
|
|
406
444
|
};
|
|
407
445
|
});
|
|
408
446
|
|
|
447
|
+
// =============================================================================
|
|
448
|
+
// Find Operation Schemas
|
|
449
|
+
// =============================================================================
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Input for find operation: a JSON selector, and the order, the skip and the limit. The selector
|
|
453
|
+
* is the selector of `query()` of a storage.
|
|
454
|
+
*/
|
|
455
|
+
export interface FindInput {
|
|
456
|
+
/** The selector. Without it, each item matches. */
|
|
457
|
+
selector?: StorageSelector;
|
|
458
|
+
/** The order of the result: field paths with 1 (ascending) or -1 (descending). */
|
|
459
|
+
sort?: StorageSort;
|
|
460
|
+
/** The number of items to skip after the sort. */
|
|
461
|
+
skip?: number;
|
|
462
|
+
/** The largest number of items in the result. */
|
|
463
|
+
limit?: number;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/** The problems of a find input under a query policy, as the errors of a schema. */
|
|
467
|
+
function findErrors(data: Record<string, unknown>, policy: StorageQueryPolicy): Array<{ path: Array<string | number>; message: string }> {
|
|
468
|
+
const errors: Array<{ path: Array<string | number>; message: string }> = [];
|
|
469
|
+
for (const key of Object.keys(data)) {
|
|
470
|
+
if (data[key] !== undefined && key !== "selector" && key !== "sort" && key !== "skip" && key !== "limit") {
|
|
471
|
+
errors.push({ path: [key], message: `${key} is not a field of the input: use selector, sort, skip and limit` });
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
if (data["selector"] !== undefined) {
|
|
475
|
+
for (const message of selectorProblems(data["selector"], policy)) errors.push({ path: ["selector"], message });
|
|
476
|
+
}
|
|
477
|
+
const options = { sort: data["sort"], skip: data["skip"], limit: data["limit"] };
|
|
478
|
+
for (const message of queryOptionsProblems(options, policy)) errors.push({ path: [/^(sort|skip|limit)/.exec(message)?.[1] ?? "options"], message });
|
|
479
|
+
return errors;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* The input schema of find under a query policy: a selector or options that the policy does not
|
|
484
|
+
* permit are a validation error (`VALIDATION_ERROR`), with the reason.
|
|
485
|
+
*/
|
|
486
|
+
export function findInputSchemaOf(policy: StorageQueryPolicy): ZodLike<FindInput> {
|
|
487
|
+
return createSchema<FindInput>((data) => findInputOf(data, policy));
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/** The find input of the data, or the errors of the schema. */
|
|
491
|
+
function findInputOf(data: unknown, policy: StorageQueryPolicy): { success: true; data: FindInput } | { success: false; error: ZodErrorLike } {
|
|
492
|
+
if (!isObject(data)) {
|
|
493
|
+
return {
|
|
494
|
+
success: false,
|
|
495
|
+
error: {
|
|
496
|
+
message: "Input must be an object",
|
|
497
|
+
errors: [{ path: [], message: "Input must be an object" }],
|
|
498
|
+
},
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
const errors = findErrors(data, policy);
|
|
502
|
+
if (errors.length > 0) {
|
|
503
|
+
return { success: false, error: { message: errors.map((error) => error.message).join(". "), errors } };
|
|
504
|
+
}
|
|
505
|
+
const input: FindInput = {};
|
|
506
|
+
if (data["selector"] !== undefined) input.selector = data["selector"] as StorageSelector;
|
|
507
|
+
if (data["sort"] !== undefined) input.sort = data["sort"] as StorageSort;
|
|
508
|
+
if (data["skip"] !== undefined) input.skip = data["skip"] as number;
|
|
509
|
+
if (data["limit"] !== undefined) input.limit = data["limit"] as number;
|
|
510
|
+
return { success: true, data: input };
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/** The input schema of find under the default query policy: no `$regex`, at most `DEFAULT_FIND_LIMIT` items. */
|
|
514
|
+
export const findInputSchema : ZodLike<FindInput> = findInputSchemaOf({ maxLimit: DEFAULT_FIND_LIMIT });
|
|
515
|
+
|
|
516
|
+
/** Output for find operation: the matching items with their ids, in the order of the query. */
|
|
517
|
+
export const findOutputSchema : ZodLike<CollectionEntry[]> = createSchema<CollectionEntry[]>((data) => entriesOutputSchema.safeParse(data));
|
|
518
|
+
|
|
519
|
+
// =============================================================================
|
|
520
|
+
// Patch Operation Schemas
|
|
521
|
+
// =============================================================================
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* Input for patch operation: the id, and the fields. The fields are a JSON Merge Patch (RFC 7386),
|
|
525
|
+
* or the operations `{ $set, $unset }`, which can set `null` and nested field paths.
|
|
526
|
+
*/
|
|
527
|
+
export interface PatchInput {
|
|
528
|
+
id: string;
|
|
529
|
+
fields: StoragePatch;
|
|
530
|
+
/** The origin of the write, for the observers of the storage and the change event (roadmap CLI-15). */
|
|
531
|
+
origin?: string;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
export const patchInputSchema : ZodLike<PatchInput> = createSchema<PatchInput>((data) => {
|
|
535
|
+
if (!isObject(data)) {
|
|
536
|
+
return {
|
|
537
|
+
success: false,
|
|
538
|
+
error: {
|
|
539
|
+
message: "Input must be an object",
|
|
540
|
+
errors: [{ path: [], message: "Input must be an object" }],
|
|
541
|
+
},
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
if (!isString(data["id"]) || data["id"].length === 0) {
|
|
545
|
+
return {
|
|
546
|
+
success: false,
|
|
547
|
+
error: {
|
|
548
|
+
message: "id must be a non-empty string",
|
|
549
|
+
errors: [{ path: ["id"], message: "id must be a non-empty string" }],
|
|
550
|
+
},
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
const [problem] = patchProblems(data["fields"]);
|
|
554
|
+
if (problem !== undefined) {
|
|
555
|
+
return {
|
|
556
|
+
success: false,
|
|
557
|
+
error: {
|
|
558
|
+
message: problem,
|
|
559
|
+
errors: [{ path: ["fields"], message: problem }],
|
|
560
|
+
},
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
const error = originError(data);
|
|
564
|
+
if (error) return { success: false, error };
|
|
565
|
+
return { success: true, data: withOriginOf(data, { id: data["id"], fields: data["fields"] as StoragePatch }) };
|
|
566
|
+
});
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Output for patch operation: `found` is true when the collection has the id. Then `value` is the
|
|
570
|
+
* new item.
|
|
571
|
+
*/
|
|
572
|
+
export const patchOutputSchema : ZodLike<GetFoundOutput> = createSchema<GetFoundOutput>((data) => {
|
|
573
|
+
if (isObject(data) && typeof data["found"] === "boolean") {
|
|
574
|
+
return { success: true, data: data as unknown as GetFoundOutput };
|
|
575
|
+
}
|
|
576
|
+
return {
|
|
577
|
+
success: false,
|
|
578
|
+
error: {
|
|
579
|
+
message: "Output must be { found, value }",
|
|
580
|
+
errors: [{ path: [], message: "Output must be { found, value }" }],
|
|
581
|
+
},
|
|
582
|
+
};
|
|
583
|
+
});
|
|
584
|
+
|
|
409
585
|
// =============================================================================
|
|
410
586
|
// Ids Operation Schemas
|
|
411
587
|
// =============================================================================
|
|
@@ -553,7 +729,10 @@ export const sizeOutputSchema : ZodLike<number> = createSchema<number>((data) =>
|
|
|
553
729
|
/**
|
|
554
730
|
* Input for clear operation - empty object.
|
|
555
731
|
*/
|
|
556
|
-
export interface ClearInput {
|
|
732
|
+
export interface ClearInput {
|
|
733
|
+
/** The origin of the write, for the observers of the storage and the change event (roadmap CLI-15). */
|
|
734
|
+
origin?: string;
|
|
735
|
+
}
|
|
557
736
|
|
|
558
737
|
export const clearInputSchema : ZodLike<ClearInput> = createSchema<ClearInput>((data) => {
|
|
559
738
|
if (!isObject(data)) {
|
|
@@ -565,7 +744,9 @@ export const clearInputSchema : ZodLike<ClearInput> = createSchema<ClearInput>((
|
|
|
565
744
|
},
|
|
566
745
|
};
|
|
567
746
|
}
|
|
568
|
-
|
|
747
|
+
const error = originError(data);
|
|
748
|
+
if (error) return { success: false, error };
|
|
749
|
+
return { success: true, data: withOriginOf(data, {}) };
|
|
569
750
|
});
|
|
570
751
|
|
|
571
752
|
/**
|
|
@@ -629,6 +810,8 @@ export const getBatchOutputSchema : ZodLike<Record<string, unknown>> = createSch
|
|
|
629
810
|
*/
|
|
630
811
|
export interface SetBatchInput {
|
|
631
812
|
items: Array<{ id: string; value: unknown }>;
|
|
813
|
+
/** The origin of the write, for the observers of the storage and the change event (roadmap CLI-15). */
|
|
814
|
+
origin?: string;
|
|
632
815
|
}
|
|
633
816
|
|
|
634
817
|
export const setBatchInputSchema : ZodLike<SetBatchInput> = createSchema<SetBatchInput>((data) => {
|
|
@@ -662,11 +845,13 @@ export const setBatchInputSchema : ZodLike<SetBatchInput> = createSchema<SetBatc
|
|
|
662
845
|
};
|
|
663
846
|
}
|
|
664
847
|
}
|
|
848
|
+
const error = originError(data);
|
|
849
|
+
if (error) return { success: false, error };
|
|
665
850
|
return {
|
|
666
851
|
success: true,
|
|
667
|
-
data: {
|
|
852
|
+
data: withOriginOf(data, {
|
|
668
853
|
items: data["items"].map((item: any) => ({ id: item["id"], value: item["value"] })),
|
|
669
|
-
},
|
|
854
|
+
}),
|
|
670
855
|
};
|
|
671
856
|
});
|
|
672
857
|
|
|
@@ -682,6 +867,8 @@ export const setBatchOutputSchema : ZodLike<void> = createSchema<void>((_data) =
|
|
|
682
867
|
*/
|
|
683
868
|
export interface DeleteBatchInput {
|
|
684
869
|
ids: string[];
|
|
870
|
+
/** The origin of the write, for the observers of the storage and the change event (roadmap CLI-15). */
|
|
871
|
+
origin?: string;
|
|
685
872
|
}
|
|
686
873
|
|
|
687
874
|
export const deleteBatchInputSchema : ZodLike<DeleteBatchInput> = createSchema<DeleteBatchInput>((data) => {
|
|
@@ -703,7 +890,9 @@ export const deleteBatchInputSchema : ZodLike<DeleteBatchInput> = createSchema<D
|
|
|
703
890
|
},
|
|
704
891
|
};
|
|
705
892
|
}
|
|
706
|
-
|
|
893
|
+
const error = originError(data);
|
|
894
|
+
if (error) return { success: false, error };
|
|
895
|
+
return { success: true, data: withOriginOf(data, { ids: data["ids"] as string[] }) };
|
|
707
896
|
});
|
|
708
897
|
|
|
709
898
|
/**
|
|
@@ -17,7 +17,25 @@
|
|
|
17
17
|
* - A delta of `getChangesSince` follows the order of the last change of each id.
|
|
18
18
|
* - After `close()`, each operation rejects with an error whose message says "closed". A second
|
|
19
19
|
* `close()` does nothing.
|
|
20
|
+
* - `query()` gives the result of `queryEntries()` of `@procedures/collections` for the entries.
|
|
21
|
+
* - `observe()` gives one batch for each write that changes the storage, before the write resolves.
|
|
22
|
+
* - `patch()` merges the fields into the item in one step.
|
|
20
23
|
*/
|
|
24
|
+
|
|
25
|
+
import type { StoragePatch, StorageQueryOptions, StorageQueryPolicy, StorageSelector } from "./query.js";
|
|
26
|
+
|
|
27
|
+
export type {
|
|
28
|
+
StorageFieldOperators,
|
|
29
|
+
StoragePatch,
|
|
30
|
+
StoragePatchOperations,
|
|
31
|
+
StorageQueryOperator,
|
|
32
|
+
StorageQueryOptions,
|
|
33
|
+
StorageQueryPolicy,
|
|
34
|
+
StorageSelector,
|
|
35
|
+
StorageSort,
|
|
36
|
+
StorageSortDirection,
|
|
37
|
+
} from "./query.js";
|
|
38
|
+
|
|
21
39
|
export interface CollectionStorage<T> {
|
|
22
40
|
/** The item with this id, or undefined. A stored null is null. */
|
|
23
41
|
get(id: string): Promise<T | undefined>;
|
|
@@ -42,20 +60,38 @@ export interface CollectionStorage<T> {
|
|
|
42
60
|
getChangesSince?(since?: string): Promise<StorageChanges<T>>;
|
|
43
61
|
/** The items for which the predicate gives true. */
|
|
44
62
|
find(predicate: (item: T) => boolean): Promise<T[]>;
|
|
63
|
+
/**
|
|
64
|
+
* The entries whose items match a JSON selector, with an order, a skip and a limit. The
|
|
65
|
+
* procedure `find` uses it, and gives the query policy of the host. A storage without it gives
|
|
66
|
+
* its entries, and the procedure runs the selector itself. Without a policy, the storage uses its
|
|
67
|
+
* own policy: `$regex` is off by default.
|
|
68
|
+
*/
|
|
69
|
+
query?(selector: StorageSelector, options?: StorageQueryOptions, policy?: StorageQueryPolicy): Promise<Array<[string, T]>>;
|
|
70
|
+
/**
|
|
71
|
+
* This method sends a batch of changes to the observer for each write that changes the storage,
|
|
72
|
+
* before the write resolves. It gives the function that stops the batches.
|
|
73
|
+
*/
|
|
74
|
+
observe?(observer: StorageObserver<T>): () => void;
|
|
45
75
|
/** True when an item has this id. */
|
|
46
76
|
has(id: string): Promise<boolean>;
|
|
47
77
|
/** The number of items. */
|
|
48
78
|
size(): Promise<number>;
|
|
49
|
-
/** Set the item of an id. */
|
|
50
|
-
set(id: string, value: T): Promise<void>;
|
|
79
|
+
/** Set the item of an id. The options give the origin of the write to the observers. */
|
|
80
|
+
set(id: string, value: T, options?: StorageWriteOptions): Promise<void>;
|
|
51
81
|
/** Delete the item of an id. True when it existed. */
|
|
52
|
-
delete(id: string): Promise<boolean>;
|
|
82
|
+
delete(id: string, options?: StorageWriteOptions): Promise<boolean>;
|
|
53
83
|
/** Delete every item. */
|
|
54
|
-
clear(): Promise<void>;
|
|
84
|
+
clear(options?: StorageWriteOptions): Promise<void>;
|
|
85
|
+
/**
|
|
86
|
+
* This method changes the item of an id in one step, and gives the new item, or undefined for a
|
|
87
|
+
* missing id. The fields are a JSON Merge Patch, or the operations `{ $set, $unset }`. The
|
|
88
|
+
* procedure `patch` uses it. A storage without it gets a read and a write of the item.
|
|
89
|
+
*/
|
|
90
|
+
patch?(id: string, fields: StoragePatch, options?: StorageWriteOptions): Promise<T | undefined>;
|
|
55
91
|
/** Set several items. */
|
|
56
|
-
setBatch(items: Array<[string, T]
|
|
92
|
+
setBatch(items: Array<[string, T]>, options?: StorageWriteOptions): Promise<void>;
|
|
57
93
|
/** Delete several items. The number of items that existed. */
|
|
58
|
-
deleteBatch(ids: string[]): Promise<number>;
|
|
94
|
+
deleteBatch(ids: string[], options?: StorageWriteOptions): Promise<number>;
|
|
59
95
|
/** The items of several ids. An id with no item is not in the map. */
|
|
60
96
|
getBatch(ids: string[]): Promise<Map<string, T>>;
|
|
61
97
|
/**
|
|
@@ -72,6 +108,42 @@ export interface CollectionStorage<T> {
|
|
|
72
108
|
getMetadata?(): Promise<StorageMetadata>;
|
|
73
109
|
}
|
|
74
110
|
|
|
111
|
+
/** The options of a write. */
|
|
112
|
+
export interface StorageWriteOptions {
|
|
113
|
+
/** The tag of the writer. Each change that the write gives has it. */
|
|
114
|
+
readonly origin?: string | undefined;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** A change of `observe()`: an id got a value. */
|
|
118
|
+
export interface StorageSetChange<T> {
|
|
119
|
+
readonly type: "set";
|
|
120
|
+
readonly id: string;
|
|
121
|
+
readonly value: T;
|
|
122
|
+
readonly origin?: string | undefined;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** A change of `observe()`: an id lost its item. */
|
|
126
|
+
export interface StorageDeleteChange {
|
|
127
|
+
readonly type: "delete";
|
|
128
|
+
readonly id: string;
|
|
129
|
+
readonly origin?: string | undefined;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** A change of `observe()`: the storage lost each item. */
|
|
133
|
+
export interface StorageClearChange {
|
|
134
|
+
readonly type: "clear";
|
|
135
|
+
readonly origin?: string | undefined;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** One change of `observe()`. */
|
|
139
|
+
export type StorageChangeEvent<T> = StorageSetChange<T> | StorageDeleteChange | StorageClearChange;
|
|
140
|
+
|
|
141
|
+
/** The changes of one write, in the order of the write. */
|
|
142
|
+
export type StorageChangeBatch<T> = readonly StorageChangeEvent<T>[];
|
|
143
|
+
|
|
144
|
+
/** The function that gets each batch of `observe()`. */
|
|
145
|
+
export type StorageObserver<T> = (changes: StorageChangeBatch<T>) => void;
|
|
146
|
+
|
|
75
147
|
/**
|
|
76
148
|
* The changes of a storage after a version (roadmap R28).
|
|
77
149
|
*
|