@registrystack/client 0.38.0 → 0.40.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/README.md +30 -7
- package/breg/client.d.ts +120 -10
- package/breg/client.js +53 -35
- package/breg/index.d.ts +64 -2
- package/casework/client.d.ts +84 -30
- package/casework/client.js +22 -17
- package/casework/index.d.ts +7 -0
- package/discovery/client.d.ts +9 -52
- package/discovery/client.js +1 -21
- package/discovery/index.d.ts +0 -4
- package/evidence/client.d.ts +1 -1
- package/evidence/index.d.ts +3 -6
- package/index.d.ts +2 -2
- package/index.js +1 -1
- package/messaging/client.d.ts +23 -4
- package/messaging/client.js +32 -21
- package/messaging/index.d.ts +1 -10
- package/native.js +2 -2
- package/package.json +9 -9
- package/scheduling/client.d.ts +226 -0
- package/scheduling/client.js +141 -0
- package/scheduling/index.d.ts +27 -0
- package/scheduling/index.js +3 -0
- package/relay/client.d.ts +0 -460
- package/relay/client.js +0 -172
- package/relay/index.d.ts +0 -59
- package/relay/index.js +0 -3
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @registrystack/client
|
|
2
2
|
|
|
3
|
-
One versioned Node.js package for the Discovery, Evidence,
|
|
4
|
-
Engine, Casework, and
|
|
3
|
+
One versioned Node.js package for the Discovery, Evidence, Base Registry
|
|
4
|
+
Engine, Casework, Messaging, and Scheduling client APIs in Registry Stack.
|
|
5
5
|
|
|
6
6
|
## Install
|
|
7
7
|
|
|
@@ -17,7 +17,7 @@ bindings.
|
|
|
17
17
|
## Usage
|
|
18
18
|
|
|
19
19
|
```js
|
|
20
|
-
const { discovery, evidence,
|
|
20
|
+
const { discovery, evidence, breg, casework, messaging, scheduling } = require('@registrystack/client');
|
|
21
21
|
|
|
22
22
|
const registry = new breg.BaseRegistryClient({
|
|
23
23
|
baseUrl: 'https://registry.example.invalid/',
|
|
@@ -28,6 +28,9 @@ const work = new casework.CaseworkClient({
|
|
|
28
28
|
const messages = new messaging.MessagingClient({
|
|
29
29
|
baseUrl: 'https://messaging.example.invalid/',
|
|
30
30
|
});
|
|
31
|
+
const appointments = new scheduling.SchedulingClient({
|
|
32
|
+
baseUrl: 'https://scheduling.example.invalid/',
|
|
33
|
+
});
|
|
31
34
|
```
|
|
32
35
|
|
|
33
36
|
## Products
|
|
@@ -36,13 +39,14 @@ const messages = new messaging.MessagingClient({
|
|
|
36
39
|
curated index.
|
|
37
40
|
- `evidence`: Evidence Gateway, request and verify signed minimum-disclosure
|
|
38
41
|
assertions.
|
|
39
|
-
- `relay`: Registry Relay, scoped read-only APIs over existing sources.
|
|
40
42
|
- `breg`: Base Registry Engine, records, contracts, writes, lifecycle, and typed
|
|
41
43
|
applied-request result navigation.
|
|
42
44
|
- `casework`: Registry Casework, staff inbox, claims, drafts, decisions,
|
|
43
45
|
recovery, history, holdings, and directory bootstrap.
|
|
44
46
|
- `messaging`: Registry Messaging, submit, inspect, cancel, and preview
|
|
45
47
|
institution-owned messages.
|
|
48
|
+
- `scheduling`: Registry Scheduling, published offerings, availability,
|
|
49
|
+
holds, and appointments over operator-anchored supply.
|
|
46
50
|
|
|
47
51
|
Each product remains in its own namespace because its routing,
|
|
48
52
|
authentication, errors, and verification rules are different.
|
|
@@ -80,11 +84,21 @@ descriptions grant no authority, so select the opaque create, patch, and
|
|
|
80
84
|
lifecycle authorities from that same contract before executing a mutation.
|
|
81
85
|
Methods ending in `Json` keep values exact across the Node number boundary:
|
|
82
86
|
they accept domain JSON text and return `valueJson` alongside the usual
|
|
83
|
-
trace, ETag, location, and opaque continuation.
|
|
84
|
-
mutation automatically. See
|
|
87
|
+
trace, ETag, location, and opaque continuation. See
|
|
85
88
|
[Exact JSON in Node](https://docs.registrystack.org/reference/client-api/#exact-json-in-node)
|
|
86
89
|
for the full rules.
|
|
87
90
|
|
|
91
|
+
A keyed BReg, Casework, Messaging, or Scheduling mutation whose outcome is
|
|
92
|
+
unknown is resent identically under the same idempotency key up to
|
|
93
|
+
`maxMutationRetries` times, a client option: 0 to 2, default 2, and 0 sends it
|
|
94
|
+
once. Reads, unkeyed calls, and every 4xx refusal are never resent. When the returned error
|
|
95
|
+
still reports `outcomeUnknown`, the mutation may have taken effect: recover by
|
|
96
|
+
sending it again under the same key, because a new key could apply it twice.
|
|
97
|
+
`outcomeUnknown` is false for `410 idempotency.expired`, but there an earlier
|
|
98
|
+
attempt under the key was answered and may have committed: reconcile that
|
|
99
|
+
attempt before choosing a new key.
|
|
100
|
+
See [Unknown outcomes](https://docs.registrystack.org/reference/client-api/#unknown-outcomes-and-the-same-key-retry).
|
|
101
|
+
|
|
88
102
|
`breg.verifyWebhookDelivery({ method, path, headers, body, key })` authenticates
|
|
89
103
|
the exact bytes of one Version 1 webhook delivery. The result returns
|
|
90
104
|
`deliveryTime` and `idempotencyKey`; the receiver must bound clock skew and
|
|
@@ -107,6 +121,9 @@ Registry Stack v0.30.0.
|
|
|
107
121
|
The `messaging` namespace is part of the unified package beginning with
|
|
108
122
|
Registry Stack v0.38.0.
|
|
109
123
|
|
|
124
|
+
The `scheduling` namespace is part of the unified package beginning with
|
|
125
|
+
Registry Stack v0.40.0.
|
|
126
|
+
|
|
110
127
|
## Casework notes
|
|
111
128
|
|
|
112
129
|
The Casework module is for a trusted server host. Each call takes that request's
|
|
@@ -115,9 +132,15 @@ selected source profile. The client does not retain them. Browsers should send
|
|
|
115
132
|
only the host's session cookie. Claim, release, and decide consume the
|
|
116
133
|
caller-filtered action returned on the item, including its exact route and
|
|
117
134
|
`ifMatch` revision. Mutations require a caller-controlled idempotency key and
|
|
118
|
-
are
|
|
135
|
+
are resent only under the bounded same-key retry above; review request create
|
|
136
|
+
and cancel are never resent. After a lost response, use
|
|
119
137
|
`recoverDecisionByKey` with the original key so recovery does not depend on the
|
|
120
138
|
attempt identifier being received.
|
|
139
|
+
Reviewer inboxes accept an `ownership` filter before pagination.
|
|
140
|
+
`supervisoryReviewTasks` returns only task and accountability references for
|
|
141
|
+
queues the selected supervisor currently serves; its state is a holder-free
|
|
142
|
+
string. A single decided-task read
|
|
143
|
+
includes `decisionReceipt` only for the caller who recorded that decision.
|
|
121
144
|
|
|
122
145
|
## Documentation
|
|
123
146
|
|
package/breg/client.d.ts
CHANGED
|
@@ -8,10 +8,10 @@ export type JsonObject = { readonly [key: string]: JsonValue }
|
|
|
8
8
|
export type SafeInteger = number
|
|
9
9
|
|
|
10
10
|
export type WebhookVerificationRefusalCode =
|
|
11
|
-
| '
|
|
12
|
-
| '
|
|
13
|
-
| '
|
|
14
|
-
| '
|
|
11
|
+
| 'missing-header'
|
|
12
|
+
| 'malformed-signature'
|
|
13
|
+
| 'signature-mismatch'
|
|
14
|
+
| 'unsupported-version'
|
|
15
15
|
|
|
16
16
|
export interface WebhookDeliveryInput {
|
|
17
17
|
method: string
|
|
@@ -137,10 +137,44 @@ export interface BaseRegistryClientConfig {
|
|
|
137
137
|
maxResponseBytes?: SafeInteger | null
|
|
138
138
|
userAgent?: string | null
|
|
139
139
|
trustedRootCertificates?: string | null
|
|
140
|
+
/**
|
|
141
|
+
* How many times a keyed mutation (create, patch, attachment upload or
|
|
142
|
+
* delete, lifecycle action, immediate action, batch, tombstone, statistics
|
|
143
|
+
* publish or withdraw) whose outcome is unknown is resent, identically and
|
|
144
|
+
* under the same idempotency key, before its error is returned: a whole
|
|
145
|
+
* number from 0 to 2, default 2; 0 sends it once. Any other value is a
|
|
146
|
+
* `configuration` error.
|
|
147
|
+
*/
|
|
148
|
+
maxMutationRetries?: SafeInteger | null
|
|
140
149
|
}
|
|
141
150
|
|
|
142
151
|
export type RecordFormat = 'json' | 'json-ld'
|
|
143
152
|
|
|
153
|
+
export interface BRegStatisticalDimensionDescriptor {
|
|
154
|
+
readonly field: string
|
|
155
|
+
readonly vocabulary: string
|
|
156
|
+
readonly codes: ReadonlyArray<string>
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export interface BRegStatisticalDatasetDescriptor {
|
|
160
|
+
readonly id: string
|
|
161
|
+
readonly unit: string
|
|
162
|
+
readonly periodKind: 'flow' | 'stock'
|
|
163
|
+
readonly granularity: 'day' | 'month' | 'quarter' | 'year'
|
|
164
|
+
readonly firstPeriod: string
|
|
165
|
+
readonly dimensions: ReadonlyArray<BRegStatisticalDimensionDescriptor>
|
|
166
|
+
readonly definitionDigest: string
|
|
167
|
+
readonly operations: ReadonlyArray<
|
|
168
|
+
| 'read-live'
|
|
169
|
+
| 'list-releases'
|
|
170
|
+
| 'read-released-series'
|
|
171
|
+
| 'read-latest-release'
|
|
172
|
+
| 'read-release-version'
|
|
173
|
+
| 'publish-release'
|
|
174
|
+
| 'withdraw-release'
|
|
175
|
+
>
|
|
176
|
+
}
|
|
177
|
+
|
|
144
178
|
export interface RecordProjectionOptions {
|
|
145
179
|
select?: ReadonlyArray<string> | null
|
|
146
180
|
accessProfile?: string | null
|
|
@@ -224,8 +258,8 @@ export type BRegRequestResultReferenceData = JsonObject & {
|
|
|
224
258
|
}
|
|
225
259
|
export type BRegRequestState = 'draft' | 'submitted' | 'cancelled' | 'applied'
|
|
226
260
|
export type BRegRequestReviewRequirement =
|
|
227
|
-
| Readonly<{
|
|
228
|
-
| Readonly<{ authority: string; policyId: string }>
|
|
261
|
+
| Readonly<{ type: 'none' }>
|
|
262
|
+
| Readonly<{ type: 'required'; authority: string; policyId: string }>
|
|
229
263
|
export type BRegExternalReviewStatus = Readonly<{
|
|
230
264
|
submission: Readonly<{
|
|
231
265
|
state: 'pending' | 'accepted' | 'uncertain' | 'cancelling' | 'cancelled' | 'failed'
|
|
@@ -349,8 +383,17 @@ export interface RawOutcome {
|
|
|
349
383
|
mediaType: string
|
|
350
384
|
traceId: string
|
|
351
385
|
etag?: string
|
|
386
|
+
reprDigest?: string
|
|
352
387
|
}
|
|
353
388
|
|
|
389
|
+
export type StatisticsFormat = 'json' | 'csv'
|
|
390
|
+
export type StatisticsReleaseStatus = 'provisional' | 'final'
|
|
391
|
+
export type StatisticsReleaseSelection = 'any' | 'final'
|
|
392
|
+
export type StatisticsWithdrawalReason =
|
|
393
|
+
| 'computation-error'
|
|
394
|
+
| 'source-data-error'
|
|
395
|
+
| 'disclosure-risk'
|
|
396
|
+
|
|
354
397
|
export interface PatchOperation {
|
|
355
398
|
op: 'add' | 'replace' | 'test'
|
|
356
399
|
field: string
|
|
@@ -451,9 +494,9 @@ export interface BRegQueryDescriptor {
|
|
|
451
494
|
readonly sortableFields: ReadonlyArray<BRegQueryField>
|
|
452
495
|
readonly allowCount: boolean
|
|
453
496
|
readonly defaultPageSize: number
|
|
454
|
-
readonly
|
|
455
|
-
readonly
|
|
456
|
-
readonly
|
|
497
|
+
readonly maximumPageSize: number
|
|
498
|
+
readonly maximumFilterClauses: number
|
|
499
|
+
readonly maximumInValues: number
|
|
457
500
|
readonly pagination: { readonly parameter: string; readonly responsePath: string; readonly exclusive: boolean }
|
|
458
501
|
readonly temporal: JsonObject | null
|
|
459
502
|
readonly spatialQueries?: {
|
|
@@ -811,7 +854,7 @@ export interface BRegAttachmentState {
|
|
|
811
854
|
|
|
812
855
|
/** What one record projection says about one slot. */
|
|
813
856
|
export type BRegAttachmentSlotValue =
|
|
814
|
-
| { readonly kind: '
|
|
857
|
+
| { readonly kind: 'not-selected'; readonly value: null }
|
|
815
858
|
| { readonly kind: 'empty'; readonly value: null }
|
|
816
859
|
| { readonly kind: 'filled'; readonly value: BRegAttachmentState }
|
|
817
860
|
|
|
@@ -931,6 +974,18 @@ export declare class BRegLifecycleAction {
|
|
|
931
974
|
readonly body: JsonObject
|
|
932
975
|
}
|
|
933
976
|
|
|
977
|
+
/**
|
|
978
|
+
* Inert bounded immediate-action evidence: inputs, saved target conditions,
|
|
979
|
+
* and the idempotency key. Persist these bytes with owner-only access before
|
|
980
|
+
* invoking.
|
|
981
|
+
*/
|
|
982
|
+
export declare class BRegPreparedAction {
|
|
983
|
+
private constructor()
|
|
984
|
+
private readonly __opaque: void
|
|
985
|
+
static fromBytes(bytes: Buffer): BRegPreparedAction
|
|
986
|
+
toBytes(): Buffer
|
|
987
|
+
}
|
|
988
|
+
|
|
934
989
|
/** Inert bounded Create evidence. Persist these bytes with owner-only access. */
|
|
935
990
|
export declare class BRegPreparedCreate {
|
|
936
991
|
private constructor()
|
|
@@ -947,6 +1002,12 @@ export declare class BRegPreparedLifecycle {
|
|
|
947
1002
|
toBytes(): Buffer
|
|
948
1003
|
}
|
|
949
1004
|
|
|
1005
|
+
/** Revalidated action invocation and key. It still requires fresh metadata authority to send. */
|
|
1006
|
+
export declare class BRegRecoveredAction {
|
|
1007
|
+
private constructor()
|
|
1008
|
+
private readonly __opaque: void
|
|
1009
|
+
}
|
|
1010
|
+
|
|
950
1011
|
/** Revalidated Create request. It still requires fresh metadata authority to send. */
|
|
951
1012
|
export declare class BRegRecoveredCreate {
|
|
952
1013
|
private constructor()
|
|
@@ -966,6 +1027,8 @@ export declare class BRegMetadata {
|
|
|
966
1027
|
readonly operations: ReadonlyArray<BRegOperationDescriptor>
|
|
967
1028
|
readonly immediateActions: ReadonlyArray<BRegImmediateActionDescriptor>
|
|
968
1029
|
readonly actionsJson: string | null
|
|
1030
|
+
/** Validated caller-filtered inert descriptions. They never grant entity authority. */
|
|
1031
|
+
readonly statisticalDatasets: ReadonlyArray<BRegStatisticalDatasetDescriptor> | null
|
|
969
1032
|
readonly registryIdentifier: string
|
|
970
1033
|
readonly registryVersion: string
|
|
971
1034
|
readonly registryRevision: string
|
|
@@ -986,10 +1049,26 @@ export interface BaseRegistryClientFailure extends Error {
|
|
|
986
1049
|
readonly code?: string
|
|
987
1050
|
readonly planRefusal?: string
|
|
988
1051
|
readonly refusalCode?: string
|
|
1052
|
+
readonly reasonCode?: string
|
|
1053
|
+
readonly fieldPath?: string
|
|
989
1054
|
readonly status?: number
|
|
990
1055
|
readonly traceId?: string
|
|
991
1056
|
readonly transportKind?: string
|
|
992
1057
|
readonly tokenKind?: string
|
|
1058
|
+
/**
|
|
1059
|
+
* Whether the request may have taken effect although this error was raised:
|
|
1060
|
+
* a timeout or broken exchange after sending, an unusable answer, or a 5xx
|
|
1061
|
+
* other than `action.handler_failed` and
|
|
1062
|
+
* `statistical_dataset.domain_violation`, which the engine returns only with
|
|
1063
|
+
* the attempt rolled back. When true, recover a keyed mutation by sending it
|
|
1064
|
+
* again under the same idempotency key; a new key could apply it twice.
|
|
1065
|
+
* False for a configuration or request defect, a credential the token
|
|
1066
|
+
* provider could not supply, a connection never established, and every 4xx
|
|
1067
|
+
* refusal. It is false for `410 idempotency.expired` too, but there an
|
|
1068
|
+
* earlier attempt under the key committed and only its held response is
|
|
1069
|
+
* gone: read the resource before choosing a new key.
|
|
1070
|
+
*/
|
|
1071
|
+
readonly outcomeUnknown: boolean
|
|
993
1072
|
}
|
|
994
1073
|
|
|
995
1074
|
export declare class BaseRegistryClientError extends Error implements BaseRegistryClientFailure {
|
|
@@ -997,10 +1076,26 @@ export declare class BaseRegistryClientError extends Error implements BaseRegist
|
|
|
997
1076
|
readonly code?: string
|
|
998
1077
|
readonly planRefusal?: string
|
|
999
1078
|
readonly refusalCode?: string
|
|
1079
|
+
readonly reasonCode?: string
|
|
1080
|
+
readonly fieldPath?: string
|
|
1000
1081
|
readonly status?: number
|
|
1001
1082
|
readonly traceId?: string
|
|
1002
1083
|
readonly transportKind?: string
|
|
1003
1084
|
readonly tokenKind?: string
|
|
1085
|
+
/**
|
|
1086
|
+
* Whether the request may have taken effect although this error was raised:
|
|
1087
|
+
* a timeout or broken exchange after sending, an unusable answer, or a 5xx
|
|
1088
|
+
* other than `action.handler_failed` and
|
|
1089
|
+
* `statistical_dataset.domain_violation`, which the engine returns only with
|
|
1090
|
+
* the attempt rolled back. When true, recover a keyed mutation by sending it
|
|
1091
|
+
* again under the same idempotency key; a new key could apply it twice.
|
|
1092
|
+
* False for a configuration or request defect, a credential the token
|
|
1093
|
+
* provider could not supply, a connection never established, and every 4xx
|
|
1094
|
+
* refusal. It is false for `410 idempotency.expired` too, but there an
|
|
1095
|
+
* earlier attempt under the key committed and only its held response is
|
|
1096
|
+
* gone: read the resource before choosing a new key.
|
|
1097
|
+
*/
|
|
1098
|
+
readonly outcomeUnknown: boolean
|
|
1004
1099
|
}
|
|
1005
1100
|
|
|
1006
1101
|
export declare class BaseRegistryClient {
|
|
@@ -1009,6 +1104,13 @@ export declare class BaseRegistryClient {
|
|
|
1009
1104
|
ready(): Promise<CompleteOutcome<ProbeStatus>>
|
|
1010
1105
|
openapi(accessProfile?: string | null): Promise<RawOutcome>
|
|
1011
1106
|
registryMetadata(accessProfile?: string | null): Promise<RawOutcome>
|
|
1107
|
+
statisticsLive(dataset: string, from?: string | null, to?: string | null, accessProfile?: string | null, format?: StatisticsFormat | null): Promise<RawOutcome>
|
|
1108
|
+
statisticsReleases(dataset: string, top?: SafeInteger | null, skipToken?: string | null, accessProfile?: string | null): Promise<RawOutcome>
|
|
1109
|
+
statisticsLatestRelease(dataset: string, period: string, selection: StatisticsReleaseSelection, accessProfile?: string | null, format?: StatisticsFormat | null): Promise<RawOutcome>
|
|
1110
|
+
statisticsReleaseVersion(dataset: string, period: string, version: SafeInteger, accessProfile?: string | null, format?: StatisticsFormat | null): Promise<RawOutcome>
|
|
1111
|
+
statisticsReleaseSeries(dataset: string, from: string, to: string, selection: StatisticsReleaseSelection, accessProfile?: string | null, format?: StatisticsFormat | null): Promise<RawOutcome>
|
|
1112
|
+
statisticsPublish(dataset: string, period: string, status: StatisticsReleaseStatus, accessProfile: string, idempotencyKey: string): Promise<RawOutcome>
|
|
1113
|
+
statisticsWithdraw(dataset: string, period: string, version: SafeInteger, reason: StatisticsWithdrawalReason, accessProfile: string, idempotencyKey: string): Promise<RawOutcome>
|
|
1012
1114
|
registryContract(accessProfile?: string | null): Promise<BRegMetadata>
|
|
1013
1115
|
entitySchema(entityIdentifier: string, accessProfile?: string | null): Promise<RawOutcome>
|
|
1014
1116
|
recordRevisions(entityRoute: string, recordIdentifier: string, accessProfile?: string | null): Promise<RawOutcome>
|
|
@@ -1032,6 +1134,14 @@ export declare class BaseRegistryClient {
|
|
|
1032
1134
|
actionTargetConditionsJson(binding: BRegImmediateActionBinding, inputsJson: string): Promise<BRegActionTargetConditions>
|
|
1033
1135
|
invokeAction(binding: BRegImmediateActionBinding, inputs: JsonObject, idempotencyKey: string, conditions?: BRegActionTargetConditions | null): Promise<CompleteOutcome<BRegActionReceipt>>
|
|
1034
1136
|
invokeActionJson(binding: BRegImmediateActionBinding, inputsJson: string, idempotencyKey: string, conditions?: BRegActionTargetConditions | null): Promise<JsonOutcome>
|
|
1137
|
+
/** Validate and retain one invocation before any I/O, for recovery after a lost response. */
|
|
1138
|
+
prepareAction(binding: BRegImmediateActionBinding, inputs: JsonObject, idempotencyKey: string, conditions?: BRegActionTargetConditions | null): BRegPreparedAction
|
|
1139
|
+
prepareActionJson(binding: BRegImmediateActionBinding, inputsJson: string, idempotencyKey: string, conditions?: BRegActionTargetConditions | null): BRegPreparedAction
|
|
1140
|
+
/** Revalidate saved evidence against fresh authority and the original inputs and key. Performs no I/O. */
|
|
1141
|
+
recoverAction(binding: BRegImmediateActionBinding, prepared: BRegPreparedAction, inputs: JsonObject, idempotencyKey: string): BRegRecoveredAction
|
|
1142
|
+
recoverActionJson(binding: BRegImmediateActionBinding, prepared: BRegPreparedAction, inputsJson: string, idempotencyKey: string): BRegRecoveredAction
|
|
1143
|
+
executeRecoveredAction(binding: BRegImmediateActionBinding, recovered: BRegRecoveredAction): Promise<CompleteOutcome<BRegActionReceipt>>
|
|
1144
|
+
executeRecoveredActionJson(binding: BRegImmediateActionBinding, recovered: BRegRecoveredAction): Promise<JsonOutcome>
|
|
1035
1145
|
createRecord(binding: BRegCreateBinding, data: JsonObject, idempotencyKey: string, format?: RecordFormat | null): Promise<CompleteOutcome<RecordEnvelope>>
|
|
1036
1146
|
prepareCreate(binding: BRegCreateBinding, data: JsonObject, idempotencyKey: string, format?: RecordFormat | null): BRegPreparedCreate
|
|
1037
1147
|
prepareCreateJson(binding: BRegCreateBinding, dataJson: string, idempotencyKey: string, format?: RecordFormat | null): BRegPreparedCreate
|
package/breg/client.js
CHANGED
|
@@ -12,9 +12,18 @@ class BaseRegistryClientError extends Error {
|
|
|
12
12
|
super(envelope.message);
|
|
13
13
|
this.name = 'BaseRegistryClientError';
|
|
14
14
|
this.kind = envelope.kind;
|
|
15
|
-
|
|
15
|
+
this.outcomeUnknown = envelope.outcomeUnknown === true;
|
|
16
|
+
for (const field of ['code', 'planRefusal', 'refusalCode', 'reasonCode', 'status', 'traceId', 'transportKind', 'tokenKind']) {
|
|
16
17
|
if (envelope[field] !== undefined && envelope[field] !== null) this[field] = envelope[field];
|
|
17
18
|
}
|
|
19
|
+
if (envelope.fieldPath !== undefined && envelope.fieldPath !== null) {
|
|
20
|
+
Object.defineProperty(this, 'fieldPath', {
|
|
21
|
+
value: envelope.fieldPath,
|
|
22
|
+
configurable: true,
|
|
23
|
+
enumerable: false,
|
|
24
|
+
writable: true,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
18
27
|
}
|
|
19
28
|
}
|
|
20
29
|
|
|
@@ -52,19 +61,19 @@ function inputError(kind) {
|
|
|
52
61
|
|
|
53
62
|
function plainDataObject(value, expectedFields) {
|
|
54
63
|
if (value === null || typeof value !== 'object' || Array.isArray(value) || isProxy(value)) {
|
|
55
|
-
throw inputError('
|
|
64
|
+
throw inputError('invalid-request');
|
|
56
65
|
}
|
|
57
66
|
const prototype = Object.getPrototypeOf(value);
|
|
58
|
-
if (prototype !== Object.prototype && prototype !== null) throw inputError('
|
|
67
|
+
if (prototype !== Object.prototype && prototype !== null) throw inputError('invalid-request');
|
|
59
68
|
const keys = Reflect.ownKeys(value);
|
|
60
69
|
if (keys.some((key) => typeof key !== 'string')
|
|
61
70
|
|| keys.length !== expectedFields.length
|
|
62
|
-
|| keys.some((key) => !expectedFields.includes(key))) throw inputError('
|
|
71
|
+
|| keys.some((key) => !expectedFields.includes(key))) throw inputError('invalid-request');
|
|
63
72
|
const result = Object.create(null);
|
|
64
73
|
for (const field of expectedFields) {
|
|
65
74
|
const descriptor = Object.getOwnPropertyDescriptor(value, field);
|
|
66
75
|
if (!descriptor || !descriptor.enumerable || !Object.hasOwn(descriptor, 'value')) {
|
|
67
|
-
throw inputError('
|
|
76
|
+
throw inputError('invalid-request');
|
|
68
77
|
}
|
|
69
78
|
result[field] = descriptor.value;
|
|
70
79
|
}
|
|
@@ -73,19 +82,19 @@ function plainDataObject(value, expectedFields) {
|
|
|
73
82
|
|
|
74
83
|
function webhookHeaders(value) {
|
|
75
84
|
if (value === null || typeof value !== 'object' || Array.isArray(value) || isProxy(value)) {
|
|
76
|
-
throw inputError('
|
|
85
|
+
throw inputError('invalid-request');
|
|
77
86
|
}
|
|
78
87
|
const prototype = Object.getPrototypeOf(value);
|
|
79
|
-
if (prototype !== Object.prototype && prototype !== null) throw inputError('
|
|
88
|
+
if (prototype !== Object.prototype && prototype !== null) throw inputError('invalid-request');
|
|
80
89
|
const keys = Reflect.ownKeys(value);
|
|
81
90
|
if (keys.some((key) => typeof key !== 'string')) {
|
|
82
|
-
throw inputError('
|
|
91
|
+
throw inputError('invalid-request');
|
|
83
92
|
}
|
|
84
93
|
const result = Object.create(null);
|
|
85
94
|
for (const name of keys) {
|
|
86
95
|
const descriptor = Object.getOwnPropertyDescriptor(value, name);
|
|
87
96
|
if (!descriptor || !descriptor.enumerable || !Object.hasOwn(descriptor, 'value')
|
|
88
|
-
|| typeof descriptor.value !== 'string') throw inputError('
|
|
97
|
+
|| typeof descriptor.value !== 'string') throw inputError('invalid-request');
|
|
89
98
|
result[name] = descriptor.value;
|
|
90
99
|
}
|
|
91
100
|
return result;
|
|
@@ -97,14 +106,14 @@ function verifyWebhookDelivery(value) {
|
|
|
97
106
|
if (typeof input.method !== 'string' || typeof input.path !== 'string'
|
|
98
107
|
|| !Buffer.isBuffer(input.body) || !Buffer.isBuffer(input.key)
|
|
99
108
|
|| isSharedArrayBuffer(input.body.buffer) || isSharedArrayBuffer(input.key.buffer)) {
|
|
100
|
-
throw inputError('
|
|
109
|
+
throw inputError('invalid-request');
|
|
101
110
|
}
|
|
102
111
|
input.headers = webhookHeaders(input.headers);
|
|
103
112
|
input.body = Buffer.from(input.body);
|
|
104
113
|
input.key = Buffer.from(input.key);
|
|
105
114
|
return native.verifyWebhookDelivery(input);
|
|
106
115
|
} catch (error) {
|
|
107
|
-
throw normalize(error, '
|
|
116
|
+
throw normalize(error, 'invalid-request');
|
|
108
117
|
}
|
|
109
118
|
}
|
|
110
119
|
|
|
@@ -176,10 +185,10 @@ function sanitizeArguments(args, jsonIndexes, requiredIndexes) {
|
|
|
176
185
|
return args.map((value, index) => {
|
|
177
186
|
if (!jsonIndexes.has(index)) return value;
|
|
178
187
|
if (value === undefined || value === null) {
|
|
179
|
-
if (requiredIndexes.has(index)) throw inputError('
|
|
188
|
+
if (requiredIndexes.has(index)) throw inputError('invalid-request');
|
|
180
189
|
return value;
|
|
181
190
|
}
|
|
182
|
-
return cloneJson(value, budget, 0, '
|
|
191
|
+
return cloneJson(value, budget, 0, 'invalid-request');
|
|
183
192
|
});
|
|
184
193
|
}
|
|
185
194
|
|
|
@@ -190,13 +199,16 @@ function wrapAsync(name, jsonIndexes = [], requiredIndexes = []) {
|
|
|
190
199
|
const sanitized = sanitizeArguments(args, new Set(jsonIndexes), new Set(requiredIndexes));
|
|
191
200
|
return original.apply(this, sanitized).catch((error) => { throw normalize(error); });
|
|
192
201
|
} catch (error) {
|
|
193
|
-
throw normalize(error, '
|
|
202
|
+
throw normalize(error, 'invalid-request');
|
|
194
203
|
}
|
|
195
204
|
};
|
|
196
205
|
}
|
|
197
206
|
|
|
198
207
|
for (const [method, jsonIndexes, requiredIndexes] of [
|
|
199
208
|
['health'], ['ready'], ['openapi'], ['registryMetadata'], ['registryContract'], ['entitySchema'],
|
|
209
|
+
['statisticsLive'], ['statisticsReleases'], ['statisticsLatestRelease'],
|
|
210
|
+
['statisticsReleaseVersion'], ['statisticsReleaseSeries'], ['statisticsPublish'],
|
|
211
|
+
['statisticsWithdraw'],
|
|
200
212
|
['recordRevisions'], ['getRecordRevision', [3]],
|
|
201
213
|
['getRecord', [2]], ['listRecords', [1]], ['continueList', [0], [0]],
|
|
202
214
|
['getGeoJsonRecord', [2]], ['listGeoJsonRecords', [1]], ['continueGeoJsonList', [0], [0]],
|
|
@@ -206,7 +218,7 @@ for (const [method, jsonIndexes, requiredIndexes] of [
|
|
|
206
218
|
['listRelationshipRecords', [3]], ['continueRelationshipList', [0], [0]],
|
|
207
219
|
['lookupRecord', [2, 3]], ['createRecord', [1], [1]],
|
|
208
220
|
['actionTargetConditions', [1], [1]], ['invokeAction', [1], [1]],
|
|
209
|
-
['executeRecoveredCreate'],
|
|
221
|
+
['executeRecoveredAction'], ['executeRecoveredCreate'],
|
|
210
222
|
['patchRecord', [3], [3]], ['batchRecords', [1], [1]], ['tombstoneRecord'],
|
|
211
223
|
['executeLifecycleAction'],
|
|
212
224
|
['executeRecoveredLifecycleAction'],
|
|
@@ -220,13 +232,16 @@ for (const [method, jsonIndexes, requiredIndexes] of [
|
|
|
220
232
|
['listRelationshipRecordsJson', [3]], ['continueRelationshipListJson', [0], [0]],
|
|
221
233
|
['lookupRecordJson', [3]], ['createRecordJson'], ['patchRecordJson'], ['executeLifecycleActionJson'],
|
|
222
234
|
['actionTargetConditionsJson'], ['invokeActionJson'], ['batchRecordsJson'], ['tombstoneRecordJson'],
|
|
223
|
-
['
|
|
235
|
+
['executeRecoveredActionJson'], ['executeRecoveredCreateJson'],
|
|
236
|
+
['executeRecoveredLifecycleActionJson'],
|
|
224
237
|
['uploadAttachmentJson'], ['deleteAttachmentJson'],
|
|
225
238
|
['createIngestionRun', [1], [1]], ['listIngestionRuns', [1]],
|
|
226
239
|
['readIngestionRun'], ['submitIngestionChunk'], ['cancelIngestionRun'],
|
|
227
240
|
]) wrapAsync(method, jsonIndexes, requiredIndexes);
|
|
228
241
|
|
|
229
242
|
for (const [method, jsonIndexes, requiredIndexes] of [
|
|
243
|
+
['prepareAction', [1], [1]], ['prepareActionJson'],
|
|
244
|
+
['recoverAction', [2], [2]], ['recoverActionJson'],
|
|
230
245
|
['prepareCreate', [1], [1]], ['prepareCreateJson'], ['recoverCreate'],
|
|
231
246
|
['prepareLifecycleAction', [1], [1]], ['prepareLifecycleActionJson'],
|
|
232
247
|
['recoverLifecycleAction'],
|
|
@@ -238,7 +253,7 @@ for (const [method, jsonIndexes, requiredIndexes] of [
|
|
|
238
253
|
args, new Set(jsonIndexes), new Set(requiredIndexes),
|
|
239
254
|
));
|
|
240
255
|
} catch (error) {
|
|
241
|
-
throw normalize(error, '
|
|
256
|
+
throw normalize(error, 'invalid-request');
|
|
242
257
|
}
|
|
243
258
|
};
|
|
244
259
|
}
|
|
@@ -258,10 +273,10 @@ function preparedClass(Class, label) {
|
|
|
258
273
|
fromBytes: {
|
|
259
274
|
value(bytes) {
|
|
260
275
|
try {
|
|
261
|
-
if (!Buffer.isBuffer(bytes)) throw inputError('
|
|
276
|
+
if (!Buffer.isBuffer(bytes)) throw inputError('invalid-request');
|
|
262
277
|
return Class.fromBytes(bytes);
|
|
263
278
|
} catch (error) {
|
|
264
|
-
throw normalize(error, '
|
|
279
|
+
throw normalize(error, 'invalid-request');
|
|
265
280
|
}
|
|
266
281
|
},
|
|
267
282
|
},
|
|
@@ -273,6 +288,7 @@ function preparedClass(Class, label) {
|
|
|
273
288
|
return Facade;
|
|
274
289
|
}
|
|
275
290
|
|
|
291
|
+
const BRegPreparedAction = preparedClass(native.BRegPreparedAction, 'BRegPreparedAction');
|
|
276
292
|
const BRegPreparedCreate = preparedClass(native.BRegPreparedCreate, 'BRegPreparedCreate');
|
|
277
293
|
const BRegPreparedLifecycle = preparedClass(
|
|
278
294
|
native.BRegPreparedLifecycle, 'BRegPreparedLifecycle',
|
|
@@ -281,17 +297,17 @@ const BRegPreparedLifecycle = preparedClass(
|
|
|
281
297
|
const withReason = native.BRegLifecycleAction.prototype.withReason;
|
|
282
298
|
native.BRegLifecycleAction.prototype.withReason = function (reason) {
|
|
283
299
|
try {
|
|
284
|
-
if (typeof reason !== 'string' || !reason.isWellFormed()) throw inputError('
|
|
300
|
+
if (typeof reason !== 'string' || !reason.isWellFormed()) throw inputError('invalid-request');
|
|
285
301
|
return withReason.call(this, reason);
|
|
286
302
|
} catch (error) {
|
|
287
|
-
throw normalize(error, '
|
|
303
|
+
throw normalize(error, 'invalid-request');
|
|
288
304
|
}
|
|
289
305
|
};
|
|
290
306
|
|
|
291
307
|
const lifecycleActionsJson = native.BaseRegistryClient.prototype.lifecycleActionsJson;
|
|
292
308
|
native.BaseRegistryClient.prototype.lifecycleActionsJson = function (...args) {
|
|
293
309
|
try { return lifecycleActionsJson.apply(this, args); }
|
|
294
|
-
catch (error) { throw normalize(error, '
|
|
310
|
+
catch (error) { throw normalize(error, 'invalid-request'); }
|
|
295
311
|
};
|
|
296
312
|
|
|
297
313
|
const lifecycleActions = native.BaseRegistryClient.prototype.lifecycleActions;
|
|
@@ -300,7 +316,7 @@ native.BaseRegistryClient.prototype.lifecycleActions = function (...args) {
|
|
|
300
316
|
const sanitized = sanitizeArguments(args, new Set([1]), new Set([1]));
|
|
301
317
|
return lifecycleActions.apply(this, sanitized);
|
|
302
318
|
} catch (error) {
|
|
303
|
-
throw normalize(error, '
|
|
319
|
+
throw normalize(error, 'invalid-request');
|
|
304
320
|
}
|
|
305
321
|
};
|
|
306
322
|
|
|
@@ -310,7 +326,7 @@ native.BaseRegistryClient.prototype.requestHistory = function (...args) {
|
|
|
310
326
|
const sanitized = sanitizeArguments(args, new Set([0]), new Set([0]));
|
|
311
327
|
return requestHistory.apply(this, sanitized);
|
|
312
328
|
} catch (error) {
|
|
313
|
-
throw normalize(error, '
|
|
329
|
+
throw normalize(error, 'invalid-request');
|
|
314
330
|
}
|
|
315
331
|
};
|
|
316
332
|
|
|
@@ -321,11 +337,11 @@ for (const name of ['findProposal', 'findApplication']) {
|
|
|
321
337
|
const proposalVersion = args[2];
|
|
322
338
|
if (!Number.isSafeInteger(proposalVersion)
|
|
323
339
|
|| proposalVersion < 1 || proposalVersion > 0xffff_ffff) {
|
|
324
|
-
throw inputError('
|
|
340
|
+
throw inputError('invalid-request');
|
|
325
341
|
}
|
|
326
342
|
return original.apply(this, args);
|
|
327
343
|
} catch (error) {
|
|
328
|
-
throw normalize(error, '
|
|
344
|
+
throw normalize(error, 'invalid-request');
|
|
329
345
|
}
|
|
330
346
|
};
|
|
331
347
|
}
|
|
@@ -335,7 +351,7 @@ native.BRegAttachmentSlot.prototype.valueIn = function (...args) {
|
|
|
335
351
|
try {
|
|
336
352
|
return valueIn.apply(this, sanitizeArguments(args, new Set([0]), new Set([0])));
|
|
337
353
|
} catch (error) {
|
|
338
|
-
throw normalize(error, '
|
|
354
|
+
throw normalize(error, 'invalid-request');
|
|
339
355
|
}
|
|
340
356
|
};
|
|
341
357
|
|
|
@@ -345,7 +361,7 @@ for (const name of ['prepareUpload', 'acceptsContentType']) {
|
|
|
345
361
|
try {
|
|
346
362
|
return original.apply(this, args);
|
|
347
363
|
} catch (error) {
|
|
348
|
-
throw normalize(error, '
|
|
364
|
+
throw normalize(error, 'invalid-request');
|
|
349
365
|
}
|
|
350
366
|
};
|
|
351
367
|
}
|
|
@@ -359,20 +375,20 @@ for (const name of [
|
|
|
359
375
|
try {
|
|
360
376
|
return original.apply(this, args);
|
|
361
377
|
} catch (error) {
|
|
362
|
-
throw normalize(error, '
|
|
378
|
+
throw normalize(error, 'invalid-request');
|
|
363
379
|
}
|
|
364
380
|
};
|
|
365
381
|
}
|
|
366
382
|
|
|
367
383
|
function encodeIngestionChunk(chunkIndex, items, prefixDigest) {
|
|
368
384
|
try {
|
|
369
|
-
if (!Number.isSafeInteger(chunkIndex)) throw inputError('
|
|
385
|
+
if (!Number.isSafeInteger(chunkIndex)) throw inputError('invalid-request');
|
|
370
386
|
const sanitized = sanitizeArguments(
|
|
371
387
|
[chunkIndex, items, prefixDigest], new Set([1]), new Set([1]),
|
|
372
388
|
);
|
|
373
389
|
return native.encodeIngestionChunk(...sanitized);
|
|
374
390
|
} catch (error) {
|
|
375
|
-
throw normalize(error, '
|
|
391
|
+
throw normalize(error, 'invalid-request');
|
|
376
392
|
}
|
|
377
393
|
}
|
|
378
394
|
|
|
@@ -381,10 +397,10 @@ function encodeIngestionChunk(chunkIndex, items, prefixDigest) {
|
|
|
381
397
|
const ingestionChunkReceipt = native.BaseRegistryClient.prototype.ingestionChunkReceipt;
|
|
382
398
|
native.BaseRegistryClient.prototype.ingestionChunkReceipt = function (...args) {
|
|
383
399
|
try {
|
|
384
|
-
if (!Number.isSafeInteger(args[2])) throw inputError('
|
|
400
|
+
if (!Number.isSafeInteger(args[2])) throw inputError('invalid-request');
|
|
385
401
|
return ingestionChunkReceipt.apply(this, args).catch((error) => { throw normalize(error); });
|
|
386
402
|
} catch (error) {
|
|
387
|
-
throw normalize(error, '
|
|
403
|
+
throw normalize(error, 'invalid-request');
|
|
388
404
|
}
|
|
389
405
|
};
|
|
390
406
|
|
|
@@ -392,11 +408,11 @@ const ingestionPrefixDigestUpdate = native.BRegIngestionPrefixDigest.prototype.u
|
|
|
392
408
|
native.BRegIngestionPrefixDigest.prototype.update = function (data) {
|
|
393
409
|
try {
|
|
394
410
|
if (!Buffer.isBuffer(data) || isSharedArrayBuffer(data.buffer)) {
|
|
395
|
-
throw inputError('
|
|
411
|
+
throw inputError('invalid-request');
|
|
396
412
|
}
|
|
397
413
|
return ingestionPrefixDigestUpdate.call(this, data);
|
|
398
414
|
} catch (error) {
|
|
399
|
-
throw normalize(error, '
|
|
415
|
+
throw normalize(error, 'invalid-request');
|
|
400
416
|
}
|
|
401
417
|
};
|
|
402
418
|
|
|
@@ -445,8 +461,10 @@ module.exports = {
|
|
|
445
461
|
BRegActionTargetConditions: native.BRegActionTargetConditions,
|
|
446
462
|
BRegTombstoneBinding: native.BRegTombstoneBinding,
|
|
447
463
|
BRegBatchBinding: native.BRegBatchBinding,
|
|
464
|
+
BRegPreparedAction,
|
|
448
465
|
BRegPreparedCreate,
|
|
449
466
|
BRegPreparedLifecycle,
|
|
467
|
+
BRegRecoveredAction: native.BRegRecoveredAction,
|
|
450
468
|
BRegRecoveredCreate: native.BRegRecoveredCreate,
|
|
451
469
|
BRegRecoveredLifecycle: native.BRegRecoveredLifecycle,
|
|
452
470
|
BRegIngestionChunk: native.BRegIngestionChunk,
|