@interop/was-client 0.15.0 → 0.16.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/dist/Collection.d.ts +17 -26
- package/dist/Collection.d.ts.map +1 -1
- package/dist/Collection.js +60 -59
- package/dist/Collection.js.map +1 -1
- package/dist/Resource.d.ts +27 -3
- package/dist/Resource.d.ts.map +1 -1
- package/dist/Resource.js +60 -22
- package/dist/Resource.js.map +1 -1
- package/dist/Space.d.ts.map +1 -1
- package/dist/Space.js +19 -11
- package/dist/Space.js.map +1 -1
- package/dist/WasClient.d.ts.map +1 -1
- package/dist/WasClient.js +4 -13
- package/dist/WasClient.js.map +1 -1
- package/dist/edv/EdvCodec.d.ts +11 -2
- package/dist/edv/EdvCodec.d.ts.map +1 -1
- package/dist/edv/EdvCodec.js +79 -67
- package/dist/edv/EdvCodec.js.map +1 -1
- package/dist/edv/WasTransport.d.ts +23 -44
- package/dist/edv/WasTransport.d.ts.map +1 -1
- package/dist/edv/WasTransport.js +109 -155
- package/dist/edv/WasTransport.js.map +1 -1
- package/dist/edv/constants.d.ts +0 -14
- package/dist/edv/constants.d.ts.map +1 -1
- package/dist/edv/constants.js +4 -8
- package/dist/edv/constants.js.map +1 -1
- package/dist/edv/epochCrypto.d.ts +1 -1
- package/dist/edv/epochCrypto.d.ts.map +1 -1
- package/dist/edv/epochCrypto.js +33 -4
- package/dist/edv/epochCrypto.js.map +1 -1
- package/dist/edv/epochKeys.js +11 -1
- package/dist/edv/epochKeys.js.map +1 -1
- package/dist/edv/recipients.d.ts +5 -1
- package/dist/edv/recipients.d.ts.map +1 -1
- package/dist/edv/recipients.js +38 -16
- package/dist/edv/recipients.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/internal/codec.d.ts +19 -0
- package/dist/internal/codec.d.ts.map +1 -1
- package/dist/internal/codec.js +26 -8
- package/dist/internal/codec.js.map +1 -1
- package/dist/internal/conditional.d.ts +11 -0
- package/dist/internal/conditional.d.ts.map +1 -1
- package/dist/internal/conditional.js +12 -0
- package/dist/internal/conditional.js.map +1 -1
- package/dist/internal/content.d.ts +7 -0
- package/dist/internal/content.d.ts.map +1 -1
- package/dist/internal/content.js +5 -3
- package/dist/internal/content.js.map +1 -1
- package/dist/internal/describe.d.ts +49 -1
- package/dist/internal/describe.d.ts.map +1 -1
- package/dist/internal/describe.js +47 -6
- package/dist/internal/describe.js.map +1 -1
- package/dist/internal/features.d.ts +73 -0
- package/dist/internal/features.d.ts.map +1 -0
- package/dist/internal/features.js +129 -0
- package/dist/internal/features.js.map +1 -0
- package/dist/internal/grant.d.ts.map +1 -1
- package/dist/internal/grant.js +2 -1
- package/dist/internal/grant.js.map +1 -1
- package/dist/internal/pagination.d.ts +30 -1
- package/dist/internal/pagination.d.ts.map +1 -1
- package/dist/internal/pagination.js +44 -1
- package/dist/internal/pagination.js.map +1 -1
- package/dist/internal/paths.d.ts.map +1 -1
- package/dist/internal/paths.js +38 -10
- package/dist/internal/paths.js.map +1 -1
- package/dist/internal/policy.d.ts +28 -0
- package/dist/internal/policy.d.ts.map +1 -1
- package/dist/internal/policy.js +31 -0
- package/dist/internal/policy.js.map +1 -1
- package/dist/internal/revoke.d.ts +11 -0
- package/dist/internal/revoke.d.ts.map +1 -1
- package/dist/internal/revoke.js +14 -1
- package/dist/internal/revoke.js.map +1 -1
- package/dist/internal/write.d.ts +10 -1
- package/dist/internal/write.d.ts.map +1 -1
- package/dist/internal/write.js +29 -4
- package/dist/internal/write.js.map +1 -1
- package/dist/types.d.ts +12 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
|
@@ -36,7 +36,9 @@
|
|
|
36
36
|
* `/{id}/chunks/{n}` sub-segment (the server's `chunked-streams` affordance),
|
|
37
37
|
* storing the chunk object as an opaque JSON body -- so `EdvClientCore.insert({
|
|
38
38
|
* stream })` / `getStream` drive chunked encrypted blobs over a WAS server
|
|
39
|
-
* unchanged.
|
|
39
|
+
* unchanged. Both chunk methods are gated on the backend advertising
|
|
40
|
+
* `chunked-streams` (throwing `NotSupportedError` when it is absent), like
|
|
41
|
+
* `find` is on `blinded-index-query`.
|
|
40
42
|
* `insert` uses an atomic `If-None-Match: *` create when the backend
|
|
41
43
|
* advertises the optional `conditional-writes` feature; otherwise (and for
|
|
42
44
|
* `update`) writes are advisory -- the EDV `sequence` is not enforced
|
|
@@ -57,7 +59,7 @@ export declare class WasTransport extends Transport {
|
|
|
57
59
|
readonly collectionId: string;
|
|
58
60
|
readonly contentType: string;
|
|
59
61
|
private readonly _was;
|
|
60
|
-
private
|
|
62
|
+
private readonly _features;
|
|
61
63
|
/**
|
|
62
64
|
* @param options {object}
|
|
63
65
|
* @param options.was {WasClient} a WAS client holding the signer
|
|
@@ -96,42 +98,6 @@ export declare class WasTransport extends Transport {
|
|
|
96
98
|
* @returns {Promise<HttpResponse>}
|
|
97
99
|
*/
|
|
98
100
|
private _put;
|
|
99
|
-
/**
|
|
100
|
-
* The feature tokens the collection's backend advertises in its "Collection
|
|
101
|
-
* Backend Selected" descriptor (e.g. `conditional-writes`,
|
|
102
|
-
* `blinded-index-query`). Memoized once it produces a definitive answer: a
|
|
103
|
-
* successful read (including one that lists no features) and a definitive
|
|
104
|
-
* "endpoint absent" (`404` / `405` / `501`) both resolve to a cached feature
|
|
105
|
-
* list, so every affordance gate falls closed against a server that has no
|
|
106
|
-
* backend descriptors.
|
|
107
|
-
*
|
|
108
|
-
* A transient/ambiguous failure (network error, timeout, `401`, `429`, other
|
|
109
|
-
* `5xx`) is NOT cached: the memo is cleared so the next call re-probes, and
|
|
110
|
-
* the error is rethrown so the caller fails loud rather than silently
|
|
111
|
-
* degrading atomicity against a server that may well be capable. (A single
|
|
112
|
-
* transient failure must not poison the transport for its lifetime.)
|
|
113
|
-
*
|
|
114
|
-
* @returns {Promise<string[]>}
|
|
115
|
-
*/
|
|
116
|
-
private _backendFeatures;
|
|
117
|
-
/**
|
|
118
|
-
* Reads and parses the backend descriptor once. On a definitive answer
|
|
119
|
-
* (success, or a `404` / `405` / `501` that means the endpoint is legitimately
|
|
120
|
-
* absent) resolves the feature list, which `_backendFeatures` then caches. On
|
|
121
|
-
* a transient failure, clears the memo (so the next call re-probes) and
|
|
122
|
-
* rethrows.
|
|
123
|
-
*
|
|
124
|
-
* @returns {Promise<string[]>}
|
|
125
|
-
*/
|
|
126
|
-
private _probeBackendFeatures;
|
|
127
|
-
/**
|
|
128
|
-
* Whether the collection's backend advertises the optional
|
|
129
|
-
* `conditional-writes` feature, so `insert` can use an atomic
|
|
130
|
-
* `If-None-Match: *` create instead of the advisory existence-check path.
|
|
131
|
-
*
|
|
132
|
-
* @returns {Promise<boolean>}
|
|
133
|
-
*/
|
|
134
|
-
private _conditionalWrites;
|
|
135
101
|
/**
|
|
136
102
|
* @inheritdoc
|
|
137
103
|
*
|
|
@@ -187,6 +153,16 @@ export declare class WasTransport extends Transport {
|
|
|
187
153
|
get({ id }?: {
|
|
188
154
|
id?: string;
|
|
189
155
|
}): Promise<IEncryptedDocument>;
|
|
156
|
+
/**
|
|
157
|
+
* Throws a `NotSupportedError` (the name `EdvClientCore` dispatches on)
|
|
158
|
+
* unless the collection's backend advertises the given affordance token --
|
|
159
|
+
* the shared gate in front of every optional-feature operation.
|
|
160
|
+
*
|
|
161
|
+
* @param feature {string} the affordance token (e.g. `chunked-streams`)
|
|
162
|
+
* @param what {string} the operation name, for the message
|
|
163
|
+
* @returns {Promise<void>}
|
|
164
|
+
*/
|
|
165
|
+
private _requireFeature;
|
|
190
166
|
/**
|
|
191
167
|
* Resolves to `true` if a resource exists at the document's path, via a
|
|
192
168
|
* bodiless `HEAD` (the stored envelope is not needed, only its existence). A
|
|
@@ -249,9 +225,11 @@ export declare class WasTransport extends Transport {
|
|
|
249
225
|
* `PUT` as an opaque binary body ({@link CHUNK_CONTENT_TYPE}) to the chunk's
|
|
250
226
|
* own URL (`.../chunks/{index}`), signed like every other write. The server
|
|
251
227
|
* stores the bytes verbatim -- it never parses the chunk -- so any
|
|
252
|
-
* client-side crypto framing is transparent to it.
|
|
253
|
-
*
|
|
254
|
-
*
|
|
228
|
+
* client-side crypto framing is transparent to it. Requires the backend's
|
|
229
|
+
* `chunked-streams` affordance (throws `NotSupportedError` when it is
|
|
230
|
+
* absent). The parent Resource must already exist
|
|
231
|
+
* (`EdvClientCore.insert`/`update` writes the document envelope before
|
|
232
|
+
* draining the stream), so a 404 here surfaces as a `NotFoundError`.
|
|
255
233
|
*
|
|
256
234
|
* @param options {object}
|
|
257
235
|
* @param options.docId {string} the owning document id (= WAS resource id)
|
|
@@ -267,9 +245,10 @@ export declare class WasTransport extends Transport {
|
|
|
267
245
|
*
|
|
268
246
|
* Reads one encrypted chunk back by index, `GET`ting the chunk's own URL and
|
|
269
247
|
* parsing the opaque body (stored as raw bytes, so parsed client-side) back
|
|
270
|
-
* into the EDV chunk object the decrypt stream consumes.
|
|
271
|
-
*
|
|
272
|
-
*
|
|
248
|
+
* into the EDV chunk object the decrypt stream consumes. Requires the
|
|
249
|
+
* backend's `chunked-streams` affordance (throws `NotSupportedError` when it
|
|
250
|
+
* is absent). A missing chunk (404) surfaces as a `NotFoundError` (the name
|
|
251
|
+
* `EdvClientCore` expects), so a reassembling reader can distinguish it.
|
|
273
252
|
*
|
|
274
253
|
* @param options {object}
|
|
275
254
|
* @param options.docId {string} the owning document id
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WasTransport.d.ts","sourceRoot":"","sources":["../../src/edv/WasTransport.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH
|
|
1
|
+
{"version":3,"file":"WasTransport.d.ts","sourceRoot":"","sources":["../../src/edv/WasTransport.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAE/C,OAAO,KAAK,EACV,SAAS,EACT,SAAS,EACT,kBAAkB,EACnB,MAAM,8BAA8B,CAAA;AACrC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAUhD,OAAO,EAGL,iBAAiB,EAClB,MAAM,gBAAgB,CAAA;AAEvB,OAAO,EAAE,iBAAiB,EAAE,CAAA;AAsB5B;;;GAGG;AACH,KAAK,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;AAqD9C,qBAAa,YAAa,SAAQ,SAAS;IACzC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAE5B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAc;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiB;IAE3C;;;;;;;;;OASG;gBACS,EACV,GAAG,EACH,OAAO,EACP,YAAY,EACZ,WAAkC,EACnC,EAAE;QACD,GAAG,EAAE,YAAY,CAAA;QACjB,OAAO,EAAE,MAAM,CAAA;QACf,YAAY,EAAE,MAAM,CAAA;QACpB,WAAW,CAAC,EAAE,MAAM,CAAA;KACrB;IAkBD;;;;;;;;OAQG;IACH,OAAO,CAAC,aAAa;IAIrB;;;;;;;;;;OAUG;YACW,IAAI;IAclB;;;;;;;;;;;;;;;;OAgBG;IACY,MAAM,CAAC,EACpB,SAAS,EACV,GAAE;QAAE,SAAS,CAAC,EAAE,kBAAkB,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAoC1D;;;;;;;;;;;;;;;;;;OAkBG;IACY,MAAM,CAAC,EACpB,SAAS,EACV,GAAE;QAAE,SAAS,CAAC,EAAE,kBAAkB,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB1D;;;;;;;;;OASG;IACY,GAAG,CAAC,EACjB,EAAE,EACH,GAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAkBrD;;;;;;;;OAQG;YACW,eAAe;IAW7B;;;;;;;OAOG;YACW,OAAO;IAYrB;;;;;;;;;;;;;;;;;;;;OAoBG;IACY,IAAI,CAAC,EAAE,KAAK,EAAE,GAAE;QAAE,KAAK,CAAC,EAAE,SAAS,CAAA;KAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IA6B3E;;;;;;;;;OASG;IACY,WAAW,IAAI,OAAO,CAAC,KAAK,CAAC;IAU5C;;;;;;;;OAQG;IACH,OAAO,CAAC,UAAU;IAIlB;;;;;;;;;;;;;;;;;;OAkBG;IACY,UAAU,CAAC,EACxB,KAAK,EACL,KAAK,EACN,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,SAAS,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IA8B7D;;;;;;;;;;;;;;OAcG;IACY,QAAQ,CAAC,EACtB,KAAK,EACL,UAAU,EACX,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,SAAS,CAAC;CA6BrE"}
|
package/dist/edv/WasTransport.js
CHANGED
|
@@ -36,7 +36,9 @@
|
|
|
36
36
|
* `/{id}/chunks/{n}` sub-segment (the server's `chunked-streams` affordance),
|
|
37
37
|
* storing the chunk object as an opaque JSON body -- so `EdvClientCore.insert({
|
|
38
38
|
* stream })` / `getStream` drive chunked encrypted blobs over a WAS server
|
|
39
|
-
* unchanged.
|
|
39
|
+
* unchanged. Both chunk methods are gated on the backend advertising
|
|
40
|
+
* `chunked-streams` (throwing `NotSupportedError` when it is absent), like
|
|
41
|
+
* `find` is on `blinded-index-query`.
|
|
40
42
|
* `insert` uses an atomic `If-None-Match: *` create when the backend
|
|
41
43
|
* advertises the optional `conditional-writes` feature; otherwise (and for
|
|
42
44
|
* `update`) writes are advisory -- the EDV `sequence` is not enforced
|
|
@@ -44,6 +46,7 @@
|
|
|
44
46
|
*/
|
|
45
47
|
import { Transport } from '@interop/edv-client';
|
|
46
48
|
import { httpStatus } from '../errors.js';
|
|
49
|
+
import { BackendFeatures } from '../internal/features.js';
|
|
47
50
|
import { readJsonData } from '../internal/content.js';
|
|
48
51
|
import { collectionBackend, collectionQuery, resourceChunkPath, resourcePath } from '../internal/paths.js';
|
|
49
52
|
import { DEFAULT_CONTENT_TYPE, envelopeBytes, JOSE_CONTENT_TYPE } from './constants.js';
|
|
@@ -59,16 +62,12 @@ export { JOSE_CONTENT_TYPE };
|
|
|
59
62
|
*/
|
|
60
63
|
const CHUNK_CONTENT_TYPE = 'application/octet-stream';
|
|
61
64
|
/**
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* (not implemented). These are a definitive "this server advertises no
|
|
66
|
-
* backend features" answer and are safe to cache -- every affordance gate
|
|
67
|
-
* then falls closed against a server that has no backend descriptors. Any
|
|
68
|
-
* other failure (network error, timeout, `401`, `429`, other `5xx`) is
|
|
69
|
-
* transient/ambiguous and is re-probed instead of cached.
|
|
65
|
+
* The message for the EDV unique-attribute collision (HTTP 409): a
|
|
66
|
+
* `unique: true` blinded attribute value already held by another document.
|
|
67
|
+
* Shared by every write method that can trip it.
|
|
70
68
|
*/
|
|
71
|
-
const
|
|
69
|
+
const DUPLICATE_ATTRIBUTE_MESSAGE = 'A unique indexed attribute value is already held by another document in ' +
|
|
70
|
+
'this collection.';
|
|
72
71
|
/**
|
|
73
72
|
* Builds an `Error` carrying the `name` that `EdvClientCore` (and the reference
|
|
74
73
|
* `HttpsTransport`) dispatch on -- `DuplicateError`, `InvalidStateError`,
|
|
@@ -88,12 +87,31 @@ function namedError({ name, message, cause }) {
|
|
|
88
87
|
}
|
|
89
88
|
return err;
|
|
90
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Rethrows a caught transport error as the named error `EdvClientCore`
|
|
92
|
+
* dispatches on, selected by the error's HTTP status from `mapping`; an
|
|
93
|
+
* unmapped status (or a non-HTTP error) is rethrown verbatim. The single
|
|
94
|
+
* status-to-named-error funnel every transport method's catch goes through.
|
|
95
|
+
*
|
|
96
|
+
* @param err {unknown} the caught error
|
|
97
|
+
* @param mapping {object} HTTP status to `{ name, message }` of the named
|
|
98
|
+
* error to throw in its place (the original error becomes its `cause`)
|
|
99
|
+
* @returns {never}
|
|
100
|
+
*/
|
|
101
|
+
function mapTransportError(err, mapping) {
|
|
102
|
+
const status = httpStatus(err);
|
|
103
|
+
const entry = status === undefined ? undefined : mapping[status];
|
|
104
|
+
if (entry) {
|
|
105
|
+
throw namedError({ ...entry, cause: err });
|
|
106
|
+
}
|
|
107
|
+
throw err;
|
|
108
|
+
}
|
|
91
109
|
export class WasTransport extends Transport {
|
|
92
110
|
spaceId;
|
|
93
111
|
collectionId;
|
|
94
112
|
contentType;
|
|
95
113
|
_was;
|
|
96
|
-
|
|
114
|
+
_features;
|
|
97
115
|
/**
|
|
98
116
|
* @param options {object}
|
|
99
117
|
* @param options.was {WasClient} a WAS client holding the signer
|
|
@@ -110,6 +128,16 @@ export class WasTransport extends Transport {
|
|
|
110
128
|
this.spaceId = spaceId;
|
|
111
129
|
this.collectionId = collectionId;
|
|
112
130
|
this.contentType = contentType;
|
|
131
|
+
// The shared memoizing feature probe (see `BackendFeatures` for the
|
|
132
|
+
// definitive-vs-transient caching rules), reading this collection's
|
|
133
|
+
// "Collection Backend Selected" descriptor with a signed GET.
|
|
134
|
+
this._features = new BackendFeatures(async () => {
|
|
135
|
+
const response = await this._was.request({
|
|
136
|
+
path: collectionBackend(this.spaceId, this.collectionId),
|
|
137
|
+
method: 'GET'
|
|
138
|
+
});
|
|
139
|
+
return readJsonData(response);
|
|
140
|
+
});
|
|
113
141
|
}
|
|
114
142
|
/**
|
|
115
143
|
* The WAS resource path for a document id, delegating to was-client's
|
|
@@ -143,68 +171,6 @@ export class WasTransport extends Transport {
|
|
|
143
171
|
headers: { 'content-type': this.contentType, ...headers }
|
|
144
172
|
});
|
|
145
173
|
}
|
|
146
|
-
/**
|
|
147
|
-
* The feature tokens the collection's backend advertises in its "Collection
|
|
148
|
-
* Backend Selected" descriptor (e.g. `conditional-writes`,
|
|
149
|
-
* `blinded-index-query`). Memoized once it produces a definitive answer: a
|
|
150
|
-
* successful read (including one that lists no features) and a definitive
|
|
151
|
-
* "endpoint absent" (`404` / `405` / `501`) both resolve to a cached feature
|
|
152
|
-
* list, so every affordance gate falls closed against a server that has no
|
|
153
|
-
* backend descriptors.
|
|
154
|
-
*
|
|
155
|
-
* A transient/ambiguous failure (network error, timeout, `401`, `429`, other
|
|
156
|
-
* `5xx`) is NOT cached: the memo is cleared so the next call re-probes, and
|
|
157
|
-
* the error is rethrown so the caller fails loud rather than silently
|
|
158
|
-
* degrading atomicity against a server that may well be capable. (A single
|
|
159
|
-
* transient failure must not poison the transport for its lifetime.)
|
|
160
|
-
*
|
|
161
|
-
* @returns {Promise<string[]>}
|
|
162
|
-
*/
|
|
163
|
-
_backendFeatures() {
|
|
164
|
-
this._backendFeaturesPromise ??= this._probeBackendFeatures();
|
|
165
|
-
return this._backendFeaturesPromise;
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* Reads and parses the backend descriptor once. On a definitive answer
|
|
169
|
-
* (success, or a `404` / `405` / `501` that means the endpoint is legitimately
|
|
170
|
-
* absent) resolves the feature list, which `_backendFeatures` then caches. On
|
|
171
|
-
* a transient failure, clears the memo (so the next call re-probes) and
|
|
172
|
-
* rethrows.
|
|
173
|
-
*
|
|
174
|
-
* @returns {Promise<string[]>}
|
|
175
|
-
*/
|
|
176
|
-
async _probeBackendFeatures() {
|
|
177
|
-
try {
|
|
178
|
-
const response = await this._was.request({
|
|
179
|
-
path: collectionBackend(this.spaceId, this.collectionId),
|
|
180
|
-
method: 'GET'
|
|
181
|
-
});
|
|
182
|
-
const descriptor = (await readJsonData(response));
|
|
183
|
-
return Array.isArray(descriptor?.features)
|
|
184
|
-
? descriptor.features.filter((feature) => typeof feature === 'string')
|
|
185
|
-
: [];
|
|
186
|
-
}
|
|
187
|
-
catch (err) {
|
|
188
|
-
const status = httpStatus(err);
|
|
189
|
-
if (status !== undefined && DESCRIPTOR_ABSENT_STATUSES.has(status)) {
|
|
190
|
-
return [];
|
|
191
|
-
}
|
|
192
|
-
// Transient/ambiguous: do not cache this failure -- drop the memo so the
|
|
193
|
-
// next call re-probes -- and rethrow.
|
|
194
|
-
this._backendFeaturesPromise = undefined;
|
|
195
|
-
throw err;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* Whether the collection's backend advertises the optional
|
|
200
|
-
* `conditional-writes` feature, so `insert` can use an atomic
|
|
201
|
-
* `If-None-Match: *` create instead of the advisory existence-check path.
|
|
202
|
-
*
|
|
203
|
-
* @returns {Promise<boolean>}
|
|
204
|
-
*/
|
|
205
|
-
async _conditionalWrites() {
|
|
206
|
-
return (await this._backendFeatures()).includes('conditional-writes');
|
|
207
|
-
}
|
|
208
174
|
/**
|
|
209
175
|
* @inheritdoc
|
|
210
176
|
*
|
|
@@ -226,27 +192,21 @@ export class WasTransport extends Transport {
|
|
|
226
192
|
if (!encrypted) {
|
|
227
193
|
throw new TypeError('"encrypted" is required.');
|
|
228
194
|
}
|
|
229
|
-
if (await this.
|
|
195
|
+
if (await this._features.has('conditional-writes')) {
|
|
230
196
|
try {
|
|
231
197
|
await this._put(encrypted.id, encrypted, { 'if-none-match': '*' });
|
|
232
198
|
}
|
|
233
199
|
catch (err) {
|
|
234
|
-
|
|
235
|
-
|
|
200
|
+
mapTransportError(err, {
|
|
201
|
+
412: {
|
|
236
202
|
name: 'DuplicateError',
|
|
237
|
-
message: `A document with id "${encrypted.id}" already exists
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
}
|
|
241
|
-
if (httpStatus(err) === 409) {
|
|
242
|
-
throw namedError({
|
|
203
|
+
message: `A document with id "${encrypted.id}" already exists.`
|
|
204
|
+
},
|
|
205
|
+
409: {
|
|
243
206
|
name: 'DuplicateError',
|
|
244
|
-
message:
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
throw err;
|
|
207
|
+
message: DUPLICATE_ATTRIBUTE_MESSAGE
|
|
208
|
+
}
|
|
209
|
+
});
|
|
250
210
|
}
|
|
251
211
|
return;
|
|
252
212
|
}
|
|
@@ -260,15 +220,9 @@ export class WasTransport extends Transport {
|
|
|
260
220
|
await this._put(encrypted.id, encrypted);
|
|
261
221
|
}
|
|
262
222
|
catch (err) {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
message: 'A unique indexed attribute value is already held by another ' +
|
|
267
|
-
'document in this collection.',
|
|
268
|
-
cause: err
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
|
-
throw err;
|
|
223
|
+
mapTransportError(err, {
|
|
224
|
+
409: { name: 'DuplicateError', message: DUPLICATE_ATTRIBUTE_MESSAGE }
|
|
225
|
+
});
|
|
272
226
|
}
|
|
273
227
|
}
|
|
274
228
|
/**
|
|
@@ -298,23 +252,14 @@ export class WasTransport extends Transport {
|
|
|
298
252
|
await this._put(encrypted.id, encrypted);
|
|
299
253
|
}
|
|
300
254
|
catch (err) {
|
|
301
|
-
|
|
302
|
-
|
|
255
|
+
mapTransportError(err, {
|
|
256
|
+
412: {
|
|
303
257
|
name: 'InvalidStateError',
|
|
304
258
|
message: 'Document update conflict: the stored document changed since it ' +
|
|
305
|
-
'was read. Re-fetch the current document and retry.'
|
|
306
|
-
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
if (httpStatus(err) === 409) {
|
|
310
|
-
throw namedError({
|
|
311
|
-
name: 'DuplicateError',
|
|
312
|
-
message: 'A unique indexed attribute value is already held by another ' +
|
|
313
|
-
'document in this collection.',
|
|
314
|
-
cause: err
|
|
315
|
-
});
|
|
316
|
-
}
|
|
317
|
-
throw err;
|
|
259
|
+
'was read. Re-fetch the current document and retry.'
|
|
260
|
+
},
|
|
261
|
+
409: { name: 'DuplicateError', message: DUPLICATE_ATTRIBUTE_MESSAGE }
|
|
262
|
+
});
|
|
318
263
|
}
|
|
319
264
|
}
|
|
320
265
|
/**
|
|
@@ -339,17 +284,30 @@ export class WasTransport extends Transport {
|
|
|
339
284
|
});
|
|
340
285
|
}
|
|
341
286
|
catch (err) {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
message: 'Document not found.',
|
|
346
|
-
cause: err
|
|
347
|
-
});
|
|
348
|
-
}
|
|
349
|
-
throw err;
|
|
287
|
+
mapTransportError(err, {
|
|
288
|
+
404: { name: 'NotFoundError', message: 'Document not found.' }
|
|
289
|
+
});
|
|
350
290
|
}
|
|
351
291
|
return (await readJsonData(response));
|
|
352
292
|
}
|
|
293
|
+
/**
|
|
294
|
+
* Throws a `NotSupportedError` (the name `EdvClientCore` dispatches on)
|
|
295
|
+
* unless the collection's backend advertises the given affordance token --
|
|
296
|
+
* the shared gate in front of every optional-feature operation.
|
|
297
|
+
*
|
|
298
|
+
* @param feature {string} the affordance token (e.g. `chunked-streams`)
|
|
299
|
+
* @param what {string} the operation name, for the message
|
|
300
|
+
* @returns {Promise<void>}
|
|
301
|
+
*/
|
|
302
|
+
async _requireFeature(feature, what) {
|
|
303
|
+
if (!(await this._features.has(feature))) {
|
|
304
|
+
throw namedError({
|
|
305
|
+
name: 'NotSupportedError',
|
|
306
|
+
message: `${what} is not supported: the collection's backend ` +
|
|
307
|
+
`does not advertise the "${feature}" affordance.`
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
}
|
|
353
311
|
/**
|
|
354
312
|
* Resolves to `true` if a resource exists at the document's path, via a
|
|
355
313
|
* bodiless `HEAD` (the stored envelope is not needed, only its existence). A
|
|
@@ -395,13 +353,7 @@ export class WasTransport extends Transport {
|
|
|
395
353
|
if (!query) {
|
|
396
354
|
throw new TypeError('"query" is required.');
|
|
397
355
|
}
|
|
398
|
-
|
|
399
|
-
throw namedError({
|
|
400
|
-
name: 'NotSupportedError',
|
|
401
|
-
message: "Blinded-index query is not supported: the collection's backend " +
|
|
402
|
-
'does not advertise the "blinded-index-query" affordance.'
|
|
403
|
-
});
|
|
404
|
-
}
|
|
356
|
+
await this._requireFeature('blinded-index-query', 'Blinded-index query');
|
|
405
357
|
// `returnDocuments` is a first-class `IEDVQuery` field, but the WAS profile
|
|
406
358
|
// has no ids-only mode, so it is dropped (whatever its value) and full
|
|
407
359
|
// documents come back -- the best-effort degradation `EdvClientCore.find`
|
|
@@ -416,14 +368,9 @@ export class WasTransport extends Transport {
|
|
|
416
368
|
});
|
|
417
369
|
}
|
|
418
370
|
catch (err) {
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
message: 'Collection not found.',
|
|
423
|
-
cause: err
|
|
424
|
-
});
|
|
425
|
-
}
|
|
426
|
-
throw err;
|
|
371
|
+
mapTransportError(err, {
|
|
372
|
+
404: { name: 'NotFoundError', message: 'Collection not found.' }
|
|
373
|
+
});
|
|
427
374
|
}
|
|
428
375
|
const result = await readJsonData(response);
|
|
429
376
|
if (result === null || typeof result !== 'object') {
|
|
@@ -469,9 +416,11 @@ export class WasTransport extends Transport {
|
|
|
469
416
|
* `PUT` as an opaque binary body ({@link CHUNK_CONTENT_TYPE}) to the chunk's
|
|
470
417
|
* own URL (`.../chunks/{index}`), signed like every other write. The server
|
|
471
418
|
* stores the bytes verbatim -- it never parses the chunk -- so any
|
|
472
|
-
* client-side crypto framing is transparent to it.
|
|
473
|
-
*
|
|
474
|
-
*
|
|
419
|
+
* client-side crypto framing is transparent to it. Requires the backend's
|
|
420
|
+
* `chunked-streams` affordance (throws `NotSupportedError` when it is
|
|
421
|
+
* absent). The parent Resource must already exist
|
|
422
|
+
* (`EdvClientCore.insert`/`update` writes the document envelope before
|
|
423
|
+
* draining the stream), so a 404 here surfaces as a `NotFoundError`.
|
|
475
424
|
*
|
|
476
425
|
* @param options {object}
|
|
477
426
|
* @param options.docId {string} the owning document id (= WAS resource id)
|
|
@@ -485,6 +434,10 @@ export class WasTransport extends Transport {
|
|
|
485
434
|
if (!chunk) {
|
|
486
435
|
throw new TypeError('"chunk" is required.');
|
|
487
436
|
}
|
|
437
|
+
// Gate on the affordance before diagnosing a 404: against a server with no
|
|
438
|
+
// `/chunks/{n}` route at all, the 404 would otherwise be misreported as a
|
|
439
|
+
// missing parent document.
|
|
440
|
+
await this._requireFeature('chunked-streams', 'Chunked encrypted storage');
|
|
488
441
|
try {
|
|
489
442
|
await this._was.request({
|
|
490
443
|
path: this._chunkPath(docId, chunk.index),
|
|
@@ -494,15 +447,13 @@ export class WasTransport extends Transport {
|
|
|
494
447
|
});
|
|
495
448
|
}
|
|
496
449
|
catch (err) {
|
|
497
|
-
|
|
498
|
-
|
|
450
|
+
mapTransportError(err, {
|
|
451
|
+
404: {
|
|
499
452
|
name: 'NotFoundError',
|
|
500
453
|
message: `Cannot store chunk ${chunk.index}: the parent document ` +
|
|
501
|
-
`"${docId}" does not exist. Write the document before its chunks
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
}
|
|
505
|
-
throw err;
|
|
454
|
+
`"${docId}" does not exist. Write the document before its chunks.`
|
|
455
|
+
}
|
|
456
|
+
});
|
|
506
457
|
}
|
|
507
458
|
}
|
|
508
459
|
/**
|
|
@@ -510,9 +461,10 @@ export class WasTransport extends Transport {
|
|
|
510
461
|
*
|
|
511
462
|
* Reads one encrypted chunk back by index, `GET`ting the chunk's own URL and
|
|
512
463
|
* parsing the opaque body (stored as raw bytes, so parsed client-side) back
|
|
513
|
-
* into the EDV chunk object the decrypt stream consumes.
|
|
514
|
-
*
|
|
515
|
-
*
|
|
464
|
+
* into the EDV chunk object the decrypt stream consumes. Requires the
|
|
465
|
+
* backend's `chunked-streams` affordance (throws `NotSupportedError` when it
|
|
466
|
+
* is absent). A missing chunk (404) surfaces as a `NotFoundError` (the name
|
|
467
|
+
* `EdvClientCore` expects), so a reassembling reader can distinguish it.
|
|
516
468
|
*
|
|
517
469
|
* @param options {object}
|
|
518
470
|
* @param options.docId {string} the owning document id
|
|
@@ -526,6 +478,10 @@ export class WasTransport extends Transport {
|
|
|
526
478
|
if (chunkIndex === undefined) {
|
|
527
479
|
throw new TypeError('"chunkIndex" is required.');
|
|
528
480
|
}
|
|
481
|
+
// Gate on the affordance before diagnosing a 404: against a server with no
|
|
482
|
+
// `/chunks/{n}` route at all, the 404 would otherwise surface as a spurious
|
|
483
|
+
// missing-chunk (data corruption) report.
|
|
484
|
+
await this._requireFeature('chunked-streams', 'Chunked encrypted storage');
|
|
529
485
|
let response;
|
|
530
486
|
try {
|
|
531
487
|
response = await this._was.request({
|
|
@@ -534,14 +490,12 @@ export class WasTransport extends Transport {
|
|
|
534
490
|
});
|
|
535
491
|
}
|
|
536
492
|
catch (err) {
|
|
537
|
-
|
|
538
|
-
|
|
493
|
+
mapTransportError(err, {
|
|
494
|
+
404: {
|
|
539
495
|
name: 'NotFoundError',
|
|
540
|
-
message: `Chunk ${chunkIndex} of document "${docId}" not found
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
}
|
|
544
|
-
throw err;
|
|
496
|
+
message: `Chunk ${chunkIndex} of document "${docId}" not found.`
|
|
497
|
+
}
|
|
498
|
+
});
|
|
545
499
|
}
|
|
546
500
|
// The chunk was stored as opaque bytes, so the http-client did not
|
|
547
501
|
// pre-parse it: decode the body text and parse the EDV chunk object back.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WasTransport.js","sourceRoot":"","sources":["../../src/edv/WasTransport.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH
|
|
1
|
+
{"version":3,"file":"WasTransport.js","sourceRoot":"","sources":["../../src/edv/WasTransport.ts"],"names":[],"mappings":"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"}
|
package/dist/edv/constants.d.ts
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* Shared EDV-over-WAS constants: the stored-envelope content types (the portable
|
|
6
|
-
* default and the preferred JOSE marker) and the `TextEncoder` used to serialize
|
|
7
|
-
* envelopes to bytes. Kept in one place so `WasTransport` and `EdvCodec` stay in
|
|
8
|
-
* lockstep instead of each declaring their own copy.
|
|
9
|
-
*/
|
|
10
1
|
/**
|
|
11
2
|
* The content type used by default: plain JSON, which an unmodified WAS server
|
|
12
3
|
* accepts. The stored envelope is still self-identifying by its `jwe` field.
|
|
@@ -22,11 +13,6 @@ export declare const DEFAULT_CONTENT_TYPE = "application/json";
|
|
|
22
13
|
* `contentType` option).
|
|
23
14
|
*/
|
|
24
15
|
export declare const JOSE_CONTENT_TYPE = "application/jose+json";
|
|
25
|
-
/**
|
|
26
|
-
* A shared `TextEncoder` for serializing envelope bytes (stateless, so one
|
|
27
|
-
* instance is reused across every write).
|
|
28
|
-
*/
|
|
29
|
-
export declare const ENCODER: TextEncoder;
|
|
30
16
|
/**
|
|
31
17
|
* Serializes an encrypted envelope to its wire bytes -- the single source of
|
|
32
18
|
* the envelope encoding shared by `EdvCodec` and `WasTransport`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/edv/constants.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/edv/constants.ts"],"names":[],"mappings":"AAWA;;;GAGG;AACH,eAAO,MAAM,oBAAoB,qBAAqB,CAAA;AAEtD;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,0BAA0B,CAAA;AAExD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAE1D"}
|
package/dist/edv/constants.js
CHANGED
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
*/
|
|
4
4
|
/**
|
|
5
5
|
* Shared EDV-over-WAS constants: the stored-envelope content types (the portable
|
|
6
|
-
* default and the preferred JOSE marker) and the
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* default and the preferred JOSE marker) and the envelope byte serialization.
|
|
7
|
+
* Kept in one place so `WasTransport` and `EdvCodec` stay in lockstep instead
|
|
8
|
+
* of each declaring their own copy.
|
|
9
9
|
*/
|
|
10
|
+
import { ENCODER } from '../internal/content.js';
|
|
10
11
|
/**
|
|
11
12
|
* The content type used by default: plain JSON, which an unmodified WAS server
|
|
12
13
|
* accepts. The stored envelope is still self-identifying by its `jwe` field.
|
|
@@ -22,11 +23,6 @@ export const DEFAULT_CONTENT_TYPE = 'application/json';
|
|
|
22
23
|
* `contentType` option).
|
|
23
24
|
*/
|
|
24
25
|
export const JOSE_CONTENT_TYPE = 'application/jose+json';
|
|
25
|
-
/**
|
|
26
|
-
* A shared `TextEncoder` for serializing envelope bytes (stateless, so one
|
|
27
|
-
* instance is reused across every write).
|
|
28
|
-
*/
|
|
29
|
-
export const ENCODER = new TextEncoder();
|
|
30
26
|
/**
|
|
31
27
|
* Serializes an encrypted envelope to its wire bytes -- the single source of
|
|
32
28
|
* the envelope encoding shared by `EdvCodec` and `WasTransport`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/edv/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/edv/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;GAKG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAA;AAEhD;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,kBAAkB,CAAA;AAEtD;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,uBAAuB,CAAA;AAExD;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAA;AACjD,CAAC"}
|