@procedures/client 0.2.3 → 0.4.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 +94 -0
- package/README.md +77 -44
- package/dist/.tsbuildinfo +1 -1
- package/dist/adapters/http/client/transport.d.ts.map +1 -1
- package/dist/adapters/http/client/transport.js +35 -3
- package/dist/adapters/http/client/transport.js.map +1 -1
- package/dist/adapters/http/client/types.d.ts +3 -2
- package/dist/adapters/http/client/types.d.ts.map +1 -1
- package/dist/adapters/http/server/transport.d.ts +2 -2
- package/dist/adapters/http/server/transport.d.ts.map +1 -1
- package/dist/adapters/http/server/transport.js +54 -22
- package/dist/adapters/http/server/transport.js.map +1 -1
- package/dist/adapters/http/shared/headers.d.ts +1 -1
- package/dist/adapters/http/shared/headers.d.ts.map +1 -1
- package/dist/adapters/http/shared/headers.js +7 -6
- package/dist/adapters/http/shared/headers.js.map +1 -1
- package/dist/adapters/local/client/transport.d.ts +3 -0
- package/dist/adapters/local/client/transport.d.ts.map +1 -1
- package/dist/adapters/local/client/transport.js +67 -6
- package/dist/adapters/local/client/transport.js.map +1 -1
- package/dist/adapters/local/client/types.d.ts +15 -0
- package/dist/adapters/local/client/types.d.ts.map +1 -1
- package/dist/adapters/local/client/types.js.map +1 -1
- package/dist/adapters/mock/client/transport.d.ts +3 -2
- package/dist/adapters/mock/client/transport.d.ts.map +1 -1
- package/dist/adapters/mock/client/transport.js +8 -5
- package/dist/adapters/mock/client/transport.js.map +1 -1
- package/dist/adapters/mock/client/types.d.ts +7 -6
- package/dist/adapters/mock/client/types.d.ts.map +1 -1
- package/dist/adapters/port/transport.d.ts +62 -0
- package/dist/adapters/port/transport.d.ts.map +1 -0
- package/dist/adapters/port/transport.js +94 -0
- package/dist/adapters/port/transport.js.map +1 -0
- package/dist/adapters/websocket/client/index.d.ts +1 -1
- package/dist/adapters/websocket/client/index.d.ts.map +1 -1
- package/dist/adapters/websocket/client/index.js.map +1 -1
- package/dist/adapters/websocket/client/node.d.ts +30 -0
- package/dist/adapters/websocket/client/node.d.ts.map +1 -0
- package/dist/adapters/websocket/client/node.js +32 -0
- package/dist/adapters/websocket/client/node.js.map +1 -0
- package/dist/adapters/websocket/client/transport.d.ts +47 -7
- package/dist/adapters/websocket/client/transport.d.ts.map +1 -1
- package/dist/adapters/websocket/client/transport.js +229 -75
- package/dist/adapters/websocket/client/transport.js.map +1 -1
- package/dist/adapters/websocket/client/types.d.ts +71 -21
- package/dist/adapters/websocket/client/types.d.ts.map +1 -1
- package/dist/adapters/websocket/client/types.js.map +1 -1
- package/dist/adapters/websocket/server/transport.d.ts +65 -24
- package/dist/adapters/websocket/server/transport.d.ts.map +1 -1
- package/dist/adapters/websocket/server/transport.js +192 -263
- package/dist/adapters/websocket/server/transport.js.map +1 -1
- package/dist/adapters/websocket/server/types.d.ts +20 -1
- package/dist/adapters/websocket/server/types.d.ts.map +1 -1
- package/dist/adapters/websocket/shared/rpc.d.ts +129 -0
- package/dist/adapters/websocket/shared/rpc.d.ts.map +1 -0
- package/dist/adapters/websocket/shared/rpc.js +425 -0
- package/dist/adapters/websocket/shared/rpc.js.map +1 -0
- package/dist/browser.d.ts +29 -7
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +26 -3
- package/dist/browser.js.map +1 -1
- package/dist/client/call-types.d.ts +10 -10
- package/dist/client/call-types.d.ts.map +1 -1
- package/dist/client/call-types.js +1 -6
- package/dist/client/call-types.js.map +1 -1
- package/dist/client/client.d.ts +6 -1
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +23 -9
- package/dist/client/client.js.map +1 -1
- package/dist/client/deadline.d.ts +38 -0
- package/dist/client/deadline.d.ts.map +1 -0
- package/dist/client/deadline.js +60 -0
- package/dist/client/deadline.js.map +1 -0
- package/dist/client/errors/factory.d.ts.map +1 -1
- package/dist/client/errors/factory.js +11 -7
- package/dist/client/errors/factory.js.map +1 -1
- package/dist/client/errors/http-errors.d.ts.map +1 -1
- package/dist/client/errors/http-errors.js +6 -0
- package/dist/client/errors/http-errors.js.map +1 -1
- package/dist/client/errors/index.d.ts +1 -1
- package/dist/client/errors/index.js +1 -1
- package/dist/client/errors/registry.d.ts +2 -1
- package/dist/client/errors/registry.d.ts.map +1 -1
- package/dist/client/errors/registry.js +72 -22
- package/dist/client/errors/registry.js.map +1 -1
- package/dist/client/index.d.ts +9 -2
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +8 -2
- package/dist/client/index.js.map +1 -1
- package/dist/client/middleware/cache.d.ts +19 -5
- package/dist/client/middleware/cache.d.ts.map +1 -1
- package/dist/client/middleware/cache.js +106 -18
- package/dist/client/middleware/cache.js.map +1 -1
- package/dist/client/middleware/circuit-breaker.d.ts +28 -10
- package/dist/client/middleware/circuit-breaker.d.ts.map +1 -1
- package/dist/client/middleware/circuit-breaker.js +35 -24
- package/dist/client/middleware/circuit-breaker.js.map +1 -1
- package/dist/client/middleware/contexts.d.ts +16 -10
- package/dist/client/middleware/contexts.d.ts.map +1 -1
- package/dist/client/middleware/contexts.js.map +1 -1
- package/dist/client/middleware/items.d.ts +31 -2
- package/dist/client/middleware/items.d.ts.map +1 -1
- package/dist/client/middleware/items.js +86 -6
- package/dist/client/middleware/items.js.map +1 -1
- package/dist/client/middleware/lru.d.ts +2 -0
- package/dist/client/middleware/lru.d.ts.map +1 -1
- package/dist/client/middleware/lru.js +11 -0
- package/dist/client/middleware/lru.js.map +1 -1
- package/dist/client/middleware/rate-limit.d.ts +7 -6
- package/dist/client/middleware/rate-limit.d.ts.map +1 -1
- package/dist/client/middleware/rate-limit.js +9 -7
- package/dist/client/middleware/rate-limit.js.map +1 -1
- package/dist/client/middleware/resilience.d.ts +61 -0
- package/dist/client/middleware/resilience.d.ts.map +1 -0
- package/dist/client/middleware/resilience.js +59 -0
- package/dist/client/middleware/resilience.js.map +1 -0
- package/dist/client/middleware/retry.d.ts +45 -11
- package/dist/client/middleware/retry.d.ts.map +1 -1
- package/dist/client/middleware/retry.js +102 -22
- package/dist/client/middleware/retry.js.map +1 -1
- package/dist/client/middleware/timeout.d.ts +15 -12
- package/dist/client/middleware/timeout.d.ts.map +1 -1
- package/dist/client/middleware/timeout.js +48 -46
- package/dist/client/middleware/timeout.js.map +1 -1
- package/dist/client/middleware/tracing.d.ts.map +1 -1
- package/dist/client/middleware/tracing.js +11 -3
- package/dist/client/middleware/tracing.js.map +1 -1
- package/dist/client/types.d.ts +9 -1
- package/dist/client/types.d.ts.map +1 -1
- package/dist/client/types.js.map +1 -1
- package/dist/clock.d.ts +19 -0
- package/dist/clock.d.ts.map +1 -0
- package/dist/clock.js +18 -0
- package/dist/clock.js.map +1 -0
- package/dist/duration.d.ts +37 -0
- package/dist/duration.d.ts.map +1 -0
- package/dist/duration.js +44 -0
- package/dist/duration.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/machines.d.ts +90 -0
- package/dist/machines.d.ts.map +1 -0
- package/dist/machines.js +127 -0
- package/dist/machines.js.map +1 -0
- package/dist/node.d.ts +11 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +10 -0
- package/dist/node.js.map +1 -0
- package/dist/procedures/capability.d.ts +3 -6
- package/dist/procedures/capability.d.ts.map +1 -1
- package/dist/procedures/capability.js +7 -8
- package/dist/procedures/capability.js.map +1 -1
- package/dist/procedures/collection/index.d.ts +3 -3
- package/dist/procedures/collection/index.d.ts.map +1 -1
- package/dist/procedures/collection/index.js +1 -1
- package/dist/procedures/collection/index.js.map +1 -1
- package/dist/procedures/collection/procedures.d.ts.map +1 -1
- package/dist/procedures/collection/procedures.js +49 -1
- package/dist/procedures/collection/procedures.js.map +1 -1
- package/dist/procedures/collection/schemas.d.ts +33 -0
- package/dist/procedures/collection/schemas.d.ts.map +1 -1
- package/dist/procedures/collection/schemas.js +68 -0
- package/dist/procedures/collection/schemas.js.map +1 -1
- package/dist/procedures/collection/storage.d.ts +37 -0
- package/dist/procedures/collection/storage.d.ts.map +1 -1
- package/dist/procedures/core/array.d.ts +1 -1
- package/dist/procedures/core/array.d.ts.map +1 -1
- package/dist/procedures/core/array.js +81 -29
- package/dist/procedures/core/array.js.map +1 -1
- package/dist/procedures/core/index.d.ts.map +1 -1
- package/dist/procedures/core/index.js +17 -2
- package/dist/procedures/core/index.js.map +1 -1
- package/dist/procedures/core/logic.js +1 -1
- package/dist/procedures/core/logic.js.map +1 -1
- package/dist/procedures/core/math.d.ts.map +1 -1
- package/dist/procedures/core/math.js +5 -1
- package/dist/procedures/core/math.js.map +1 -1
- package/dist/procedures/core/meta.d.ts.map +1 -1
- package/dist/procedures/core/meta.js +43 -8
- package/dist/procedures/core/meta.js.map +1 -1
- package/dist/procedures/core/object.d.ts.map +1 -1
- package/dist/procedures/core/object.js +42 -13
- package/dist/procedures/core/object.js.map +1 -1
- package/dist/procedures/core/operands.d.ts.map +1 -1
- package/dist/procedures/core/operands.js +6 -1
- package/dist/procedures/core/operands.js.map +1 -1
- package/dist/procedures/core/string.d.ts.map +1 -1
- package/dist/procedures/core/string.js +4 -2
- package/dist/procedures/core/string.js.map +1 -1
- package/dist/procedures/core/type.d.ts.map +1 -1
- package/dist/procedures/core/type.js +4 -2
- package/dist/procedures/core/type.js.map +1 -1
- package/dist/procedures/define-procedure.d.ts +19 -7
- package/dist/procedures/define-procedure.d.ts.map +1 -1
- package/dist/procedures/define-procedure.js +57 -17
- package/dist/procedures/define-procedure.js.map +1 -1
- package/dist/procedures/discovery.d.ts +4 -6
- package/dist/procedures/discovery.d.ts.map +1 -1
- package/dist/procedures/discovery.js +4 -6
- package/dist/procedures/discovery.js.map +1 -1
- package/dist/procedures/effects.d.ts +16 -0
- package/dist/procedures/effects.d.ts.map +1 -1
- package/dist/procedures/effects.js +33 -0
- package/dist/procedures/effects.js.map +1 -1
- package/dist/procedures/idempotency.d.ts +73 -0
- package/dist/procedures/idempotency.d.ts.map +1 -0
- package/dist/procedures/idempotency.js +131 -0
- package/dist/procedures/idempotency.js.map +1 -0
- package/dist/procedures/index.d.ts +7 -3
- package/dist/procedures/index.d.ts.map +1 -1
- package/dist/procedures/index.js +6 -2
- package/dist/procedures/index.js.map +1 -1
- package/dist/procedures/interceptors.d.ts +17 -4
- package/dist/procedures/interceptors.d.ts.map +1 -1
- package/dist/procedures/interceptors.js +18 -7
- package/dist/procedures/interceptors.js.map +1 -1
- package/dist/procedures/invoke.d.ts +15 -3
- package/dist/procedures/invoke.d.ts.map +1 -1
- package/dist/procedures/invoke.js +8 -3
- package/dist/procedures/invoke.js.map +1 -1
- package/dist/procedures/manifest.d.ts +83 -0
- package/dist/procedures/manifest.d.ts.map +1 -0
- package/dist/procedures/manifest.js +90 -0
- package/dist/procedures/manifest.js.map +1 -0
- package/dist/procedures/ref.d.ts +4 -2
- package/dist/procedures/ref.d.ts.map +1 -1
- package/dist/procedures/ref.js +2 -1
- package/dist/procedures/ref.js.map +1 -1
- package/dist/procedures/runtime-programs.d.ts +19 -0
- package/dist/procedures/runtime-programs.d.ts.map +1 -0
- package/dist/procedures/runtime-programs.js +24 -0
- package/dist/procedures/runtime-programs.js.map +1 -0
- package/dist/procedures/types.d.ts +16 -0
- package/dist/procedures/types.d.ts.map +1 -1
- package/dist/procedures/types.js.map +1 -1
- package/dist/protocol.d.ts +47 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +68 -0
- package/dist/protocol.js.map +1 -0
- package/dist/server/host-policy.d.ts +4 -3
- package/dist/server/host-policy.d.ts.map +1 -1
- package/dist/server/host-policy.js +6 -3
- package/dist/server/host-policy.js.map +1 -1
- package/dist/server/host-procedures.d.ts +31 -0
- package/dist/server/host-procedures.d.ts.map +1 -0
- package/dist/server/host-procedures.js +75 -0
- package/dist/server/host-procedures.js.map +1 -0
- package/dist/server/index.d.ts +3 -3
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/procedure-server.d.ts +112 -5
- package/dist/server/procedure-server.d.ts.map +1 -1
- package/dist/server/procedure-server.js +273 -19
- package/dist/server/procedure-server.js.map +1 -1
- package/dist/server/request-auth.d.ts +19 -0
- package/dist/server/request-auth.d.ts.map +1 -0
- package/dist/server/request-auth.js +32 -0
- package/dist/server/request-auth.js.map +1 -0
- package/dist/server/types.d.ts +32 -0
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/types.js.map +1 -1
- package/dist/timers.d.ts +60 -0
- package/dist/timers.d.ts.map +1 -0
- package/dist/timers.js +33 -0
- package/dist/timers.js.map +1 -0
- package/dist/tracing/traceparent.d.ts +26 -0
- package/dist/tracing/traceparent.d.ts.map +1 -0
- package/dist/tracing/traceparent.js +53 -0
- package/dist/tracing/traceparent.js.map +1 -0
- package/package.json +11 -4
- package/src/adapters/http/client/transport.ts +31 -3
- package/src/adapters/http/client/types.ts +3 -2
- package/src/adapters/http/server/transport.ts +61 -26
- package/src/adapters/http/shared/headers.ts +7 -6
- package/src/adapters/local/client/transport.ts +74 -7
- package/src/adapters/local/client/types.ts +18 -0
- package/src/adapters/mock/client/transport.ts +9 -6
- package/src/adapters/mock/client/types.ts +7 -6
- package/src/adapters/port/transport.ts +124 -0
- package/src/adapters/websocket/client/index.ts +1 -0
- package/src/adapters/websocket/client/node.ts +34 -0
- package/src/adapters/websocket/client/transport.ts +251 -81
- package/src/adapters/websocket/client/types.ts +81 -21
- package/src/adapters/websocket/server/transport.ts +199 -301
- package/src/adapters/websocket/server/types.ts +20 -1
- package/src/adapters/websocket/shared/rpc.ts +453 -0
- package/src/browser.ts +51 -3
- package/src/client/call-types.ts +10 -14
- package/src/client/client.ts +28 -9
- package/src/client/deadline.ts +64 -0
- package/src/client/errors/README.md +2 -0
- package/src/client/errors/factory.ts +12 -8
- package/src/client/errors/http-errors.ts +5 -0
- package/src/client/errors/index.ts +1 -1
- package/src/client/errors/registry.ts +79 -22
- package/src/client/index.ts +21 -3
- package/src/client/middleware/cache.ts +120 -23
- package/src/client/middleware/circuit-breaker.ts +65 -35
- package/src/client/middleware/contexts.ts +17 -10
- package/src/client/middleware/items.ts +101 -6
- package/src/client/middleware/lru.ts +12 -0
- package/src/client/middleware/rate-limit.ts +9 -9
- package/src/client/middleware/resilience.ts +81 -0
- package/src/client/middleware/retry.ts +146 -34
- package/src/client/middleware/timeout.ts +57 -55
- package/src/client/middleware/tracing.ts +13 -4
- package/src/client/types.ts +9 -1
- package/src/clock.ts +21 -0
- package/src/duration.ts +56 -0
- package/src/index.ts +4 -0
- package/src/machines.ts +186 -0
- package/src/node.ts +11 -0
- package/src/procedures/capability.ts +7 -8
- package/src/procedures/collection/index.ts +9 -1
- package/src/procedures/collection/procedures.ts +57 -0
- package/src/procedures/collection/schemas.ts +110 -0
- package/src/procedures/collection/storage.ts +38 -0
- package/src/procedures/core/array.ts +79 -31
- package/src/procedures/core/index.ts +17 -2
- package/src/procedures/core/logic.ts +1 -1
- package/src/procedures/core/math.ts +5 -1
- package/src/procedures/core/meta.ts +45 -8
- package/src/procedures/core/object.ts +48 -14
- package/src/procedures/core/operands.ts +7 -0
- package/src/procedures/core/string.ts +4 -2
- package/src/procedures/core/type.ts +4 -2
- package/src/procedures/define-procedure.ts +73 -20
- package/src/procedures/discovery.ts +4 -6
- package/src/procedures/effects.ts +35 -0
- package/src/procedures/idempotency.ts +152 -0
- package/src/procedures/index.ts +18 -2
- package/src/procedures/interceptors.ts +28 -11
- package/src/procedures/invoke.ts +19 -5
- package/src/procedures/manifest.ts +158 -0
- package/src/procedures/ref.ts +4 -2
- package/src/procedures/runtime-programs.ts +27 -0
- package/src/procedures/types.ts +16 -0
- package/src/protocol.ts +108 -0
- package/src/server/host-policy.ts +8 -5
- package/src/server/host-procedures.ts +102 -0
- package/src/server/index.ts +5 -2
- package/src/server/procedure-server.ts +328 -12
- package/src/server/request-auth.ts +35 -0
- package/src/server/types.ts +37 -0
- package/src/timers.ts +82 -0
- package/src/tracing/traceparent.ts +61 -0
- package/dist/procedures/cli/announce.d.ts +0 -67
- package/dist/procedures/cli/announce.d.ts.map +0 -1
- package/dist/procedures/cli/announce.js +0 -392
- package/dist/procedures/cli/announce.js.map +0 -1
- package/dist/procedures/cli/discover.d.ts +0 -66
- package/dist/procedures/cli/discover.d.ts.map +0 -1
- package/dist/procedures/cli/discover.js +0 -310
- package/dist/procedures/cli/discover.js.map +0 -1
- package/dist/procedures/cli/index.d.ts +0 -13
- package/dist/procedures/cli/index.d.ts.map +0 -1
- package/dist/procedures/cli/index.js +0 -203
- package/dist/procedures/cli/index.js.map +0 -1
- package/dist/procedures/cli/init.d.ts +0 -17
- package/dist/procedures/cli/init.d.ts.map +0 -1
- package/dist/procedures/cli/init.js +0 -336
- package/dist/procedures/cli/init.js.map +0 -1
- package/src/procedures/cli/announce.ts +0 -470
- package/src/procedures/cli/discover.ts +0 -390
- package/src/procedures/cli/index.ts +0 -231
- package/src/procedures/cli/init.ts +0 -370
|
@@ -19,6 +19,10 @@ export {
|
|
|
19
19
|
hasOutputSchema,
|
|
20
20
|
getAllInputSchema,
|
|
21
21
|
getAllOutputSchema,
|
|
22
|
+
entriesInputSchema,
|
|
23
|
+
entriesOutputSchema,
|
|
24
|
+
changesInputSchema,
|
|
25
|
+
changesOutputSchema,
|
|
22
26
|
sizeInputSchema,
|
|
23
27
|
sizeOutputSchema,
|
|
24
28
|
clearInputSchema,
|
|
@@ -37,6 +41,10 @@ export type {
|
|
|
37
41
|
DeleteInput,
|
|
38
42
|
HasInput,
|
|
39
43
|
GetAllInput,
|
|
44
|
+
EntriesInput,
|
|
45
|
+
CollectionEntry,
|
|
46
|
+
ChangesInput,
|
|
47
|
+
ChangesOutput,
|
|
40
48
|
SizeInput,
|
|
41
49
|
ClearInput,
|
|
42
50
|
GetBatchInput,
|
|
@@ -48,4 +56,4 @@ export type {
|
|
|
48
56
|
export { createCollectionProcedures } from "./procedures.js";
|
|
49
57
|
|
|
50
58
|
// The storage interface of the core (the shape of client-collections' CollectionStorage)
|
|
51
|
-
export type { CollectionStorage, StorageMetadata } from "./storage.js";
|
|
59
|
+
export type { CollectionStorage, StorageChanges, StorageMetadata } from "./storage.js";
|
|
@@ -18,6 +18,10 @@ import {
|
|
|
18
18
|
hasOutputSchema,
|
|
19
19
|
getAllInputSchema,
|
|
20
20
|
getAllOutputSchema,
|
|
21
|
+
entriesInputSchema,
|
|
22
|
+
entriesOutputSchema,
|
|
23
|
+
changesInputSchema,
|
|
24
|
+
changesOutputSchema,
|
|
21
25
|
sizeInputSchema,
|
|
22
26
|
sizeOutputSchema,
|
|
23
27
|
clearInputSchema,
|
|
@@ -33,6 +37,9 @@ import {
|
|
|
33
37
|
type DeleteInput,
|
|
34
38
|
type HasInput,
|
|
35
39
|
type GetAllInput,
|
|
40
|
+
type EntriesInput,
|
|
41
|
+
type ChangesInput,
|
|
42
|
+
type ChangesOutput,
|
|
36
43
|
type SizeInput,
|
|
37
44
|
type ClearInput,
|
|
38
45
|
type GetBatchInput,
|
|
@@ -168,6 +175,56 @@ export function createCollectionProcedures(collectionName: string): AnyProcedure
|
|
|
168
175
|
},
|
|
169
176
|
}),
|
|
170
177
|
|
|
178
|
+
// Entries: each item with its id, for a sync (roadmap R2)
|
|
179
|
+
defineProcedure({
|
|
180
|
+
path: [...basePath, "entries"],
|
|
181
|
+
input: entriesInputSchema,
|
|
182
|
+
output: entriesOutputSchema,
|
|
183
|
+
metadata: {
|
|
184
|
+
effects: { reads: [resource], writes: [] },
|
|
185
|
+
description: `Get all items of ${collectionName} with their ids`,
|
|
186
|
+
tags: ["collections", collectionName, "read"],
|
|
187
|
+
},
|
|
188
|
+
handler: async (_input: EntriesInput, ctx: ProcedureContext) => {
|
|
189
|
+
const storage = getStorage(ctx);
|
|
190
|
+
if (!storage.getEntries) {
|
|
191
|
+
throw new Error(`The storage of ${collectionName} cannot give the ids of its items`);
|
|
192
|
+
}
|
|
193
|
+
return (await storage.getEntries()).map(([id, value]) => ({ id, value }));
|
|
194
|
+
},
|
|
195
|
+
}),
|
|
196
|
+
|
|
197
|
+
// Changes: the items that changed after a version, for a delta sync (roadmap R28)
|
|
198
|
+
defineProcedure({
|
|
199
|
+
path: [...basePath, "changes"],
|
|
200
|
+
input: changesInputSchema,
|
|
201
|
+
output: changesOutputSchema,
|
|
202
|
+
metadata: {
|
|
203
|
+
effects: { reads: [resource], writes: [] },
|
|
204
|
+
description: `Get the items of ${collectionName} that changed after a version`,
|
|
205
|
+
tags: ["collections", collectionName, "read"],
|
|
206
|
+
},
|
|
207
|
+
handler: async (input: ChangesInput, ctx: ProcedureContext): Promise<ChangesOutput> => {
|
|
208
|
+
const storage = getStorage(ctx);
|
|
209
|
+
if (storage.getChangesSince) {
|
|
210
|
+
const changes = await storage.getChangesSince(input.since);
|
|
211
|
+
return {
|
|
212
|
+
version: changes.version,
|
|
213
|
+
full: changes.full,
|
|
214
|
+
changed: changes.changed.map(([id, value]) => ({ id, value })),
|
|
215
|
+
deleted: changes.deleted,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
// A storage without a change log gives all its items. The empty version asks for all
|
|
219
|
+
// items again at the next call.
|
|
220
|
+
if (storage.getEntries) {
|
|
221
|
+
const entries = await storage.getEntries();
|
|
222
|
+
return { version: "", full: true, changed: entries.map(([id, value]) => ({ id, value })), deleted: [] };
|
|
223
|
+
}
|
|
224
|
+
throw new Error(`The storage of ${collectionName} cannot give its changes or the ids of its items`);
|
|
225
|
+
},
|
|
226
|
+
}),
|
|
227
|
+
|
|
171
228
|
// Size
|
|
172
229
|
defineProcedure({
|
|
173
230
|
path: [...basePath, "size"],
|
|
@@ -335,6 +335,116 @@ export const getAllOutputSchema : ZodLike<unknown[]> = createSchema<unknown[]>((
|
|
|
335
335
|
};
|
|
336
336
|
});
|
|
337
337
|
|
|
338
|
+
// =============================================================================
|
|
339
|
+
// Entries Operation Schemas
|
|
340
|
+
// =============================================================================
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Input for entries operation - empty object.
|
|
344
|
+
*/
|
|
345
|
+
export interface EntriesInput {}
|
|
346
|
+
|
|
347
|
+
export const entriesInputSchema : ZodLike<EntriesInput> = createSchema<EntriesInput>((data) => {
|
|
348
|
+
if (!isObject(data)) {
|
|
349
|
+
return {
|
|
350
|
+
success: false,
|
|
351
|
+
error: {
|
|
352
|
+
message: "Input must be an object",
|
|
353
|
+
errors: [{ path: [], message: "Input must be an object" }],
|
|
354
|
+
},
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
return { success: true, data: {} };
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
/** One item of a collection with its id. */
|
|
361
|
+
export interface CollectionEntry {
|
|
362
|
+
id: string;
|
|
363
|
+
value: unknown;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Output for entries operation - each item with its id. A sync needs the ids: `getAll` gives
|
|
368
|
+
* only the values (roadmap R2).
|
|
369
|
+
*/
|
|
370
|
+
export const entriesOutputSchema : ZodLike<CollectionEntry[]> = createSchema<CollectionEntry[]>((data) => {
|
|
371
|
+
if (isArray(data) && data.every((entry) => isObject(entry) && isString(entry["id"]) && "value" in entry)) {
|
|
372
|
+
return { success: true, data: data as CollectionEntry[] };
|
|
373
|
+
}
|
|
374
|
+
return {
|
|
375
|
+
success: false,
|
|
376
|
+
error: {
|
|
377
|
+
message: "Output must be an array of { id, value } objects",
|
|
378
|
+
errors: [{ path: [], message: "Output must be an array of { id, value } objects" }],
|
|
379
|
+
},
|
|
380
|
+
};
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
// =============================================================================
|
|
384
|
+
// Changes Operation Schemas
|
|
385
|
+
// =============================================================================
|
|
386
|
+
|
|
387
|
+
/** Input for changes operation: the version of an earlier call (roadmap R28). */
|
|
388
|
+
export interface ChangesInput {
|
|
389
|
+
/** The `version` of an earlier result. Without it, the result has all items. */
|
|
390
|
+
since?: string;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
export const changesInputSchema : ZodLike<ChangesInput> = createSchema<ChangesInput>((data) => {
|
|
394
|
+
if (!isObject(data)) {
|
|
395
|
+
return {
|
|
396
|
+
success: false,
|
|
397
|
+
error: {
|
|
398
|
+
message: "Input must be an object",
|
|
399
|
+
errors: [{ path: [], message: "Input must be an object" }],
|
|
400
|
+
},
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
const since = data["since"];
|
|
404
|
+
if (since !== undefined && !isString(since)) {
|
|
405
|
+
return {
|
|
406
|
+
success: false,
|
|
407
|
+
error: {
|
|
408
|
+
message: "since must be a string",
|
|
409
|
+
errors: [{ path: ["since"], message: "since must be a string" }],
|
|
410
|
+
},
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
return { success: true, data: since === undefined ? {} : { since } };
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Output for changes operation: the items that changed after the version, the deleted ids, and
|
|
418
|
+
* the new version. When `full` is true, `changed` has each item (roadmap R28).
|
|
419
|
+
*/
|
|
420
|
+
export interface ChangesOutput {
|
|
421
|
+
version: string;
|
|
422
|
+
full: boolean;
|
|
423
|
+
changed: CollectionEntry[];
|
|
424
|
+
deleted: string[];
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
export const changesOutputSchema : ZodLike<ChangesOutput> = createSchema<ChangesOutput>((data) => {
|
|
428
|
+
if (
|
|
429
|
+
isObject(data) &&
|
|
430
|
+
isString(data["version"]) &&
|
|
431
|
+
typeof data["full"] === "boolean" &&
|
|
432
|
+
isArray(data["changed"]) &&
|
|
433
|
+
data["changed"].every((entry) => isObject(entry) && isString(entry["id"]) && "value" in entry) &&
|
|
434
|
+
isArray(data["deleted"]) &&
|
|
435
|
+
data["deleted"].every((id) => isString(id))
|
|
436
|
+
) {
|
|
437
|
+
return { success: true, data: data as unknown as ChangesOutput };
|
|
438
|
+
}
|
|
439
|
+
return {
|
|
440
|
+
success: false,
|
|
441
|
+
error: {
|
|
442
|
+
message: "Output must be { version, full, changed: [{ id, value }], deleted: [id] }",
|
|
443
|
+
errors: [{ path: [], message: "Output must be { version, full, changed: [{ id, value }], deleted: [id] }" }],
|
|
444
|
+
},
|
|
445
|
+
};
|
|
446
|
+
});
|
|
447
|
+
|
|
338
448
|
// =============================================================================
|
|
339
449
|
// Size Operation Schemas
|
|
340
450
|
// =============================================================================
|
|
@@ -15,6 +15,18 @@ export interface CollectionStorage<T> {
|
|
|
15
15
|
get(id: string): Promise<T | undefined>;
|
|
16
16
|
/** Every item of the collection. */
|
|
17
17
|
getAll(): Promise<T[]>;
|
|
18
|
+
/**
|
|
19
|
+
* Every item with its id. A sync needs the ids (roadmap R2). A storage that cannot give
|
|
20
|
+
* them does not have this method.
|
|
21
|
+
*/
|
|
22
|
+
getEntries?(): Promise<Array<[string, T]>>;
|
|
23
|
+
/**
|
|
24
|
+
* The changes after a version (roadmap R28). A storage without a change log does not have
|
|
25
|
+
* this method, and a sync uses `getEntries()`.
|
|
26
|
+
*
|
|
27
|
+
* @param since - A `version` that an earlier call gave. Without it, the result has all items.
|
|
28
|
+
*/
|
|
29
|
+
getChangesSince?(since?: string): Promise<StorageChanges<T>>;
|
|
18
30
|
/** The items for which the predicate gives true. */
|
|
19
31
|
find(predicate: (item: T) => boolean): Promise<T[]>;
|
|
20
32
|
/** True when an item has this id. */
|
|
@@ -33,12 +45,38 @@ export interface CollectionStorage<T> {
|
|
|
33
45
|
deleteBatch(ids: string[]): Promise<number>;
|
|
34
46
|
/** The items of several ids. An id with no item is not in the map. */
|
|
35
47
|
getBatch(ids: string[]): Promise<Map<string, T>>;
|
|
48
|
+
/**
|
|
49
|
+
* This method sends the writes that wait in the storage to their destination (roadmap R28). A storage
|
|
50
|
+
* that keeps no writes does not have this method. `ProcedureServer.useStorage` calls it.
|
|
51
|
+
*/
|
|
52
|
+
flush?(): Promise<void>;
|
|
36
53
|
/** Release the resources of the storage. */
|
|
37
54
|
close(): Promise<void>;
|
|
38
55
|
/** The kind, the size and the statistics of the storage. */
|
|
39
56
|
getMetadata?(): Promise<StorageMetadata>;
|
|
40
57
|
}
|
|
41
58
|
|
|
59
|
+
/**
|
|
60
|
+
* The changes of a storage after a version (roadmap R28).
|
|
61
|
+
*
|
|
62
|
+
* - `version` is opaque. The next call gives it back as `since`.
|
|
63
|
+
* - When `full` is true, `changed` has every item, and each id that it does not have was
|
|
64
|
+
* deleted. A storage gives a full result when it cannot find the changes since the version:
|
|
65
|
+
* the first call, a version of an older run, or a change log that dropped old deletes.
|
|
66
|
+
* - When `full` is false, `changed` has the items that changed after the version, and `deleted`
|
|
67
|
+
* has the ids that were deleted after it.
|
|
68
|
+
*/
|
|
69
|
+
export interface StorageChanges<T> {
|
|
70
|
+
/** The version of the storage that includes these changes. */
|
|
71
|
+
version: string;
|
|
72
|
+
/** True when `changed` has every item of the storage. */
|
|
73
|
+
full: boolean;
|
|
74
|
+
/** The items that changed, with their ids. */
|
|
75
|
+
changed: Array<[string, T]>;
|
|
76
|
+
/** The ids that were deleted. Empty when `full` is true. */
|
|
77
|
+
deleted: string[];
|
|
78
|
+
}
|
|
79
|
+
|
|
42
80
|
/** The metadata that a storage gives about itself. */
|
|
43
81
|
export interface StorageMetadata {
|
|
44
82
|
type: "memory" | "api" | "hybrid" | "synced" | "custom";
|
|
@@ -10,6 +10,17 @@ import { anyOutput, arrayOutput, booleanOutput, numberOutput } from "./outputs.j
|
|
|
10
10
|
import { defineProcedure, namespace } from "../define.js";
|
|
11
11
|
import type { AnyProcedure, Procedure } from "../types.js";
|
|
12
12
|
import { PURE_EFFECTS, withEffects } from "../effects.js";
|
|
13
|
+
import { isPlainObject } from "../ref.js";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* This function gives the own field `key` of an item, or undefined. A field of the prototype
|
|
17
|
+
* (`toString`, `constructor`) is not a field of the item: before, `count` with the key
|
|
18
|
+
* `toString` counted each item (catalog test, roadmap R29, as R6 for the object procedures).
|
|
19
|
+
*/
|
|
20
|
+
function fieldOf(item: unknown, key: string): unknown {
|
|
21
|
+
if (item === null || item === undefined) return undefined;
|
|
22
|
+
return Object.hasOwn(Object(item), key) ? (item as Record<string, unknown>)[key] : undefined;
|
|
23
|
+
}
|
|
13
24
|
|
|
14
25
|
// =============================================================================
|
|
15
26
|
// First Procedure
|
|
@@ -209,8 +220,8 @@ const sortProcedure: SortProcedure = defineProcedure({
|
|
|
209
220
|
const direction = input.desc ? -1 : 1;
|
|
210
221
|
|
|
211
222
|
return items.sort((a, b) => {
|
|
212
|
-
let aVal = input.key ? (a
|
|
213
|
-
let bVal = input.key ? (b
|
|
223
|
+
let aVal = input.key ? fieldOf(a, input.key) : a;
|
|
224
|
+
let bVal = input.key ? fieldOf(b, input.key) : b;
|
|
214
225
|
|
|
215
226
|
if (typeof aVal === "string" && typeof bVal === "string") {
|
|
216
227
|
return aVal.localeCompare(bVal) * direction;
|
|
@@ -291,10 +302,47 @@ interface UniqueInput {
|
|
|
291
302
|
}
|
|
292
303
|
|
|
293
304
|
const UniqueInputSchema = z.object({
|
|
294
|
-
items: z.array(z.unknown()).describe("The array"),
|
|
295
|
-
key: z.string().optional().describe("The key (a field name of the items)"),
|
|
305
|
+
items: z.array(z.unknown()).describe("The array. Equal JSON values are duplicates: objects and arrays compare by value."),
|
|
306
|
+
key: z.string().optional().describe("The key (a field name of the items). The values of the field compare by value."),
|
|
296
307
|
});
|
|
297
308
|
|
|
309
|
+
/**
|
|
310
|
+
* This function gives a function that makes a text key for a value: two equal JSON values get
|
|
311
|
+
* the same key. An array compares by its items in order, and a plain object by its own fields in
|
|
312
|
+
* any order. A number and its string get different keys. Another object (a `Date`, a `Map`) and
|
|
313
|
+
* a symbol compare by identity.
|
|
314
|
+
*/
|
|
315
|
+
function valueKeys(): (value: unknown) => string {
|
|
316
|
+
const identities = new Map<unknown, number>();
|
|
317
|
+
const identity = (value: unknown): string => {
|
|
318
|
+
let id = identities.get(value);
|
|
319
|
+
if (id === undefined) {
|
|
320
|
+
id = identities.size;
|
|
321
|
+
identities.set(value, id);
|
|
322
|
+
}
|
|
323
|
+
return `#${id}`;
|
|
324
|
+
};
|
|
325
|
+
const keyOf = (value: unknown, parents: Set<unknown>): string => {
|
|
326
|
+
if (typeof value === "string") return JSON.stringify(value);
|
|
327
|
+
// -0 and 0 are one value, and NaN is one value, as in a Set
|
|
328
|
+
if (typeof value === "number") return Object.is(value, -0) ? "0" : String(value);
|
|
329
|
+
if (typeof value === "bigint") return `${value}n`;
|
|
330
|
+
if (value === null || value === undefined || typeof value === "boolean") return String(value);
|
|
331
|
+
// A cycle is not JSON: its object compares by identity
|
|
332
|
+
if (parents.has(value) || (!Array.isArray(value) && !isPlainObject(value))) return identity(value);
|
|
333
|
+
parents.add(value);
|
|
334
|
+
const text = Array.isArray(value)
|
|
335
|
+
? `[${value.map((item) => keyOf(item, parents)).join(",")}]`
|
|
336
|
+
: `{${Object.keys(value)
|
|
337
|
+
.sort()
|
|
338
|
+
.map((field) => `${JSON.stringify(field)}:${keyOf(value[field], parents)}`)
|
|
339
|
+
.join(",")}}`;
|
|
340
|
+
parents.delete(value);
|
|
341
|
+
return text;
|
|
342
|
+
};
|
|
343
|
+
return (value) => keyOf(value, new Set());
|
|
344
|
+
}
|
|
345
|
+
|
|
298
346
|
type UniqueProcedure = Procedure<UniqueInput, unknown[], { description: string; tags: string[] }>;
|
|
299
347
|
|
|
300
348
|
const uniqueProcedure: UniqueProcedure = defineProcedure({
|
|
@@ -302,20 +350,19 @@ const uniqueProcedure: UniqueProcedure = defineProcedure({
|
|
|
302
350
|
input: UniqueInputSchema,
|
|
303
351
|
output: arrayOutput("The items without duplicates"),
|
|
304
352
|
metadata: {
|
|
305
|
-
description: "Remove duplicate values (optionally by key)",
|
|
353
|
+
description: "Remove duplicate values (optionally by key). It compares by value and keeps the first item of each value.",
|
|
306
354
|
tags: ["core", "array"],
|
|
307
355
|
},
|
|
308
356
|
handler: async (input: UniqueInput): Promise<unknown[]> => {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
}
|
|
318
|
-
return [...new Set(input.items)];
|
|
357
|
+
// Before, objects compared by reference, so two equal objects both stayed (catalog test, R29)
|
|
358
|
+
const keyOf = valueKeys();
|
|
359
|
+
const seen = new Set<string>();
|
|
360
|
+
return input.items.filter((item) => {
|
|
361
|
+
const key = keyOf(input.key ? fieldOf(item, input.key) : item);
|
|
362
|
+
if (seen.has(key)) return false;
|
|
363
|
+
seen.add(key);
|
|
364
|
+
return true;
|
|
365
|
+
});
|
|
319
366
|
},
|
|
320
367
|
});
|
|
321
368
|
|
|
@@ -346,11 +393,13 @@ const groupByProcedure: GroupByProcedure = defineProcedure({
|
|
|
346
393
|
handler: async (input: GroupByInput): Promise<Record<string, unknown[]>> => {
|
|
347
394
|
const result: Record<string, unknown[]> = {};
|
|
348
395
|
for (const item of input.items) {
|
|
349
|
-
const keyVal = String((item
|
|
350
|
-
|
|
351
|
-
|
|
396
|
+
const keyVal = String(fieldOf(item, input.key));
|
|
397
|
+
// Only an own group: before, a group "constructor" or "toString" found the function of the
|
|
398
|
+
// prototype, and push failed (catalog test, roadmap R29)
|
|
399
|
+
if (!Object.hasOwn(result, keyVal)) {
|
|
400
|
+
Object.defineProperty(result, keyVal, { value: [], writable: true, enumerable: true, configurable: true });
|
|
352
401
|
}
|
|
353
|
-
result[keyVal]
|
|
402
|
+
result[keyVal]!.push(item);
|
|
354
403
|
}
|
|
355
404
|
return result;
|
|
356
405
|
},
|
|
@@ -611,8 +660,8 @@ interface FilterInput {
|
|
|
611
660
|
value?: unknown | undefined;
|
|
612
661
|
/** Values to match (any of these) */
|
|
613
662
|
values?: unknown[] | undefined;
|
|
614
|
-
/** Match mode: 'equals', 'not', 'in', 'notIn', 'contains', 'startsWith', 'endsWith' */
|
|
615
|
-
match?:
|
|
663
|
+
/** Match mode: 'equals', 'not', 'in', 'notIn', 'contains', 'startsWith', 'endsWith', 'gt', 'gte', 'lt', 'lte' */
|
|
664
|
+
match?:'equals' | 'not' | 'in' | 'notIn' | 'contains' | 'startsWith' | 'endsWith' | 'gt' | 'gte' | 'lt' | 'lte' | undefined;
|
|
616
665
|
/** Invert the filter */
|
|
617
666
|
invert?: boolean | undefined;
|
|
618
667
|
}
|
|
@@ -622,7 +671,7 @@ const FilterInputSchema = z.object({
|
|
|
622
671
|
key: z.string().optional().describe("Property to match against"),
|
|
623
672
|
value: z.unknown().optional().describe("Value to match (equality check)"),
|
|
624
673
|
values: z.array(z.unknown()).optional().describe("Values to match (any of these)"),
|
|
625
|
-
match: z.enum(["equals", "not", "in", "notIn", "contains", "startsWith", "endsWith", "gt", "gte", "lt", "lte"]).optional().describe("Match mode: 'equals'
|
|
674
|
+
match: z.enum(["equals", "not", "in", "notIn", "contains", "startsWith", "endsWith", "gt", "gte", "lt", "lte"]).optional().describe("Match mode (default 'equals'): 'equals' and 'not' compare with value, 'in' and 'notIn' with values. 'contains', 'startsWith' and 'endsWith' compare strings. 'gt', 'gte', 'lt' and 'lte' compare numbers."),
|
|
626
675
|
invert: z.boolean().optional().describe("Invert the filter"),
|
|
627
676
|
});
|
|
628
677
|
|
|
@@ -640,7 +689,7 @@ const filterProcedure: FilterProcedure = defineProcedure({
|
|
|
640
689
|
const { items, key, value, values, match = 'equals', invert = false } = input;
|
|
641
690
|
|
|
642
691
|
const predicate = (item: unknown): boolean => {
|
|
643
|
-
const itemValue = key ? (item
|
|
692
|
+
const itemValue = key ? fieldOf(item, key) : item;
|
|
644
693
|
|
|
645
694
|
let result: boolean;
|
|
646
695
|
switch (match) {
|
|
@@ -716,10 +765,7 @@ const whereProcedure: WhereProcedure = defineProcedure({
|
|
|
716
765
|
},
|
|
717
766
|
handler: async (input: WhereInput): Promise<unknown[]> => {
|
|
718
767
|
const { items, where } = input;
|
|
719
|
-
return items.filter((item) =>
|
|
720
|
-
const obj = item as Record<string, unknown>;
|
|
721
|
-
return Object.entries(where).every(([key, value]) => obj[key] === value);
|
|
722
|
-
});
|
|
768
|
+
return items.filter((item) => Object.entries(where).every(([key, value]) => fieldOf(item, key) === value));
|
|
723
769
|
},
|
|
724
770
|
});
|
|
725
771
|
|
|
@@ -750,7 +796,7 @@ const pluckProcedure: PluckProcedure = defineProcedure({
|
|
|
750
796
|
tags: ["core", "array", "transform"],
|
|
751
797
|
},
|
|
752
798
|
handler: async (input: PluckInput): Promise<unknown[]> => {
|
|
753
|
-
return input.items.map((item) => (item
|
|
799
|
+
return input.items.map((item) => fieldOf(item, input.key));
|
|
754
800
|
},
|
|
755
801
|
});
|
|
756
802
|
|
|
@@ -785,7 +831,9 @@ const arrPickProcedure: ArrPickProcedure = defineProcedure({
|
|
|
785
831
|
const obj = item as Record<string, unknown>;
|
|
786
832
|
const result: Record<string, unknown> = {};
|
|
787
833
|
for (const key of input.keys) {
|
|
788
|
-
|
|
834
|
+
// Only own fields, as client.pick: before, "toString" picked a function of the prototype
|
|
835
|
+
// (catalog test, roadmap R29)
|
|
836
|
+
if (Object.hasOwn(obj, key)) {
|
|
789
837
|
result[key] = obj[key];
|
|
790
838
|
}
|
|
791
839
|
}
|
|
@@ -881,7 +929,7 @@ const partitionProcedure: PartitionProcedure = defineProcedure({
|
|
|
881
929
|
const falsy: unknown[] = [];
|
|
882
930
|
|
|
883
931
|
for (const item of input.items) {
|
|
884
|
-
const itemValue = (item
|
|
932
|
+
const itemValue = fieldOf(item, input.key);
|
|
885
933
|
const matches = input.value !== undefined ? itemValue === input.value : Boolean(itemValue);
|
|
886
934
|
if (matches) {
|
|
887
935
|
truthy.push(item);
|
|
@@ -929,7 +977,7 @@ const countProcedure: CountProcedure = defineProcedure({
|
|
|
929
977
|
}
|
|
930
978
|
|
|
931
979
|
return input.items.filter((item) => {
|
|
932
|
-
const itemValue = (item
|
|
980
|
+
const itemValue = fieldOf(item, input.key!);
|
|
933
981
|
return input.value !== undefined ? itemValue === input.value : Boolean(itemValue);
|
|
934
982
|
}).length;
|
|
935
983
|
},
|
|
@@ -84,9 +84,16 @@ const ConditionalInputSchema = z.looseObject({
|
|
|
84
84
|
const LogicInputSchema = z.looseObject({
|
|
85
85
|
values: z.array(z.unknown()).describe("The operands, in order: values or calls. The evaluation stops at the deciding value."),
|
|
86
86
|
});
|
|
87
|
-
|
|
87
|
+
// not, all, any and none take values (roadmap R29, the owner's choice). They do not run a call in
|
|
88
|
+
// their operands: a call is an object, thus truthy. In a program, the calls of their input run
|
|
89
|
+
// first, as for each procedure that is not control flow. client.and and client.or run calls.
|
|
90
|
+
const NotInputSchema = z.looseObject({
|
|
91
|
+
value: operand("The value to negate. This procedure does not run a call: a call is an object, thus truthy."),
|
|
92
|
+
});
|
|
88
93
|
const VariadicBoolInputSchema = z.looseObject({
|
|
89
|
-
values: z
|
|
94
|
+
values: z
|
|
95
|
+
.array(z.unknown())
|
|
96
|
+
.describe("The values to evaluate. This procedure does not run calls: a call is an object, thus truthy. client.and and client.or run calls."),
|
|
90
97
|
});
|
|
91
98
|
const MapInputSchema = z.looseObject({
|
|
92
99
|
items: operand("The array, or a call that gives it"),
|
|
@@ -582,6 +589,10 @@ const mapProcedure: MapProcedure = defineProcedure({
|
|
|
582
589
|
// map is a control-flow procedure: its operands arrive raw, and it runs them here.
|
|
583
590
|
// Before, the handler only returned the raw items, so their refs never ran and no
|
|
584
591
|
// function was applied.
|
|
592
|
+
if (input.fn !== undefined && !isAnyProcedureRef(input.fn)) {
|
|
593
|
+
// Before, a fn that was not a call was ignored without a word (roadmap R4)
|
|
594
|
+
throw new Error("client.map: fn must be one call ({ $proc, input }), or absent");
|
|
595
|
+
}
|
|
585
596
|
const outer = scopeOf(input);
|
|
586
597
|
const items = await hydrateItems(input.items, ctx, outer);
|
|
587
598
|
if (!isAnyProcedureRef(input.fn) || !ctx?.client) {
|
|
@@ -625,6 +636,10 @@ const reduceProcedure: ReduceProcedure = defineProcedure({
|
|
|
625
636
|
tags: controlFlowTags("collection"),
|
|
626
637
|
},
|
|
627
638
|
handler: async (input: ReduceInput, ctx?: ProcedureContext): Promise<unknown> => {
|
|
639
|
+
if (input.fn !== undefined && !isAnyProcedureRef(input.fn)) {
|
|
640
|
+
// Before, a fn that was not a call was ignored without a word (roadmap R4)
|
|
641
|
+
throw new Error("client.reduce: fn must be one call ({ $proc, input }), or absent");
|
|
642
|
+
}
|
|
628
643
|
if (!ctx?.client) {
|
|
629
644
|
return input.accumulated ?? input.initial;
|
|
630
645
|
}
|
|
@@ -184,7 +184,7 @@ export const orMetadata: LogicMetadata = {
|
|
|
184
184
|
* Metadata for the NOT operator.
|
|
185
185
|
*/
|
|
186
186
|
export const notMetadata: LogicMetadata = {
|
|
187
|
-
description: "Logical NOT",
|
|
187
|
+
description: "Logical NOT of a value",
|
|
188
188
|
tags: ["core", "logic"],
|
|
189
189
|
arity: "unary",
|
|
190
190
|
commutative: false, // n/a for unary
|
|
@@ -151,10 +151,14 @@ const modProcedure: ModProcedure = defineProcedure({
|
|
|
151
151
|
input: ModInputSchema,
|
|
152
152
|
output: numberOutput("The remainder of a divided by b"),
|
|
153
153
|
metadata: {
|
|
154
|
-
description: "Modulo (remainder of a / b)",
|
|
154
|
+
description: "Modulo (remainder of a / b). It refuses b = 0, as client.divide does.",
|
|
155
155
|
tags: ["core", "math"],
|
|
156
156
|
},
|
|
157
157
|
handler: async (input: ModInput): Promise<number> => {
|
|
158
|
+
// Before, b = 0 gave NaN, and client.divide refused it (catalog test, roadmap R29)
|
|
159
|
+
if (input.b === 0) {
|
|
160
|
+
throw new Error("Division by zero");
|
|
161
|
+
}
|
|
158
162
|
return input.a % input.b;
|
|
159
163
|
},
|
|
160
164
|
});
|