@interop/was-client 0.9.2 → 0.11.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 +32 -4
- package/dist/Collection.d.ts +49 -10
- package/dist/Collection.d.ts.map +1 -1
- package/dist/Collection.js +161 -61
- package/dist/Collection.js.map +1 -1
- package/dist/Resource.d.ts +41 -12
- package/dist/Resource.d.ts.map +1 -1
- package/dist/Resource.js +87 -54
- package/dist/Resource.js.map +1 -1
- package/dist/Space.d.ts +1 -0
- package/dist/Space.d.ts.map +1 -1
- package/dist/Space.js +24 -27
- package/dist/Space.js.map +1 -1
- package/dist/WasClient.d.ts +43 -2
- package/dist/WasClient.d.ts.map +1 -1
- package/dist/WasClient.js +90 -14
- package/dist/WasClient.js.map +1 -1
- package/dist/codec.d.ts +48 -9
- package/dist/codec.d.ts.map +1 -1
- package/dist/edv/EdvCodec.d.ts +96 -37
- package/dist/edv/EdvCodec.d.ts.map +1 -1
- package/dist/edv/EdvCodec.js +245 -90
- package/dist/edv/EdvCodec.js.map +1 -1
- package/dist/edv/WasTransport.d.ts +6 -12
- package/dist/edv/WasTransport.d.ts.map +1 -1
- package/dist/edv/WasTransport.js +6 -21
- package/dist/edv/WasTransport.js.map +1 -1
- package/dist/edv/constants.d.ts +30 -0
- package/dist/edv/constants.d.ts.map +1 -0
- package/dist/edv/constants.js +30 -0
- package/dist/edv/constants.js.map +1 -0
- package/dist/edv/index.d.ts +1 -1
- package/dist/edv/index.d.ts.map +1 -1
- package/dist/edv/index.js +1 -1
- package/dist/edv/index.js.map +1 -1
- package/dist/errors.d.ts +3 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +15 -5
- package/dist/errors.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 +71 -5
- package/dist/internal/codec.d.ts.map +1 -1
- package/dist/internal/codec.js +102 -7
- package/dist/internal/codec.js.map +1 -1
- package/dist/internal/content.d.ts +74 -3
- package/dist/internal/content.d.ts.map +1 -1
- package/dist/internal/content.js +78 -7
- package/dist/internal/content.js.map +1 -1
- package/dist/internal/describe.d.ts.map +1 -1
- package/dist/internal/describe.js +2 -1
- package/dist/internal/describe.js.map +1 -1
- package/dist/internal/pagination.d.ts +45 -0
- package/dist/internal/pagination.d.ts.map +1 -0
- package/dist/internal/pagination.js +53 -0
- package/dist/internal/pagination.js.map +1 -0
- package/dist/internal/paths.d.ts +4 -0
- package/dist/internal/paths.d.ts.map +1 -1
- package/dist/internal/paths.js +10 -1
- package/dist/internal/paths.js.map +1 -1
- package/dist/internal/policy.d.ts +54 -0
- package/dist/internal/policy.d.ts.map +1 -0
- package/dist/internal/policy.js +58 -0
- package/dist/internal/policy.js.map +1 -0
- package/dist/internal/request.d.ts +4 -2
- package/dist/internal/request.d.ts.map +1 -1
- package/dist/internal/request.js +9 -2
- package/dist/internal/request.js.map +1 -1
- package/dist/internal/reserved.d.ts +3 -8
- package/dist/internal/reserved.d.ts.map +1 -1
- package/dist/internal/reserved.js +10 -20
- package/dist/internal/reserved.js.map +1 -1
- package/dist/internal/write.d.ts +37 -0
- package/dist/internal/write.d.ts.map +1 -0
- package/dist/internal/write.js +29 -0
- package/dist/internal/write.js.map +1 -0
- package/dist/types.d.ts +14 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +6 -6
package/dist/WasClient.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ import type { EncryptionProvider } from './codec.js';
|
|
|
15
15
|
import { Space } from './Space.js';
|
|
16
16
|
import { Collection } from './Collection.js';
|
|
17
17
|
import { Resource } from './Resource.js';
|
|
18
|
-
import type { GrantOptions, HandleOptions, IDelegatedZcap, ISigner, IZcap, Json, RequestInput, CollectionResourcesList, SpaceListing } from './types.js';
|
|
18
|
+
import type { GrantOptions, HandleOptions, IDelegatedZcap, ISigner, IZcap, Json, RequestInput, CollectionResourcesList, ResourceSummary, SpaceListing } from './types.js';
|
|
19
19
|
export declare class WasClient {
|
|
20
20
|
readonly serverUrl: string;
|
|
21
21
|
readonly zcapClient: ZcapClient;
|
|
@@ -110,10 +110,24 @@ export declare class WasClient {
|
|
|
110
110
|
publicRead({ resourceUrl }: {
|
|
111
111
|
resourceUrl: string;
|
|
112
112
|
}): Promise<Json | Blob | null>;
|
|
113
|
+
/**
|
|
114
|
+
* Reads the first page of a public (`PublicCanRead`) collection listing with an
|
|
115
|
+
* unsigned `GET` and packages the means to follow its `next` links. Returns
|
|
116
|
+
* `null` if the collection is missing or not publicly readable (404 conflation
|
|
117
|
+
* caveat).
|
|
118
|
+
*
|
|
119
|
+
* @param collectionUrl {string} the absolute collection URL
|
|
120
|
+
* @returns {Promise<PageWalk | null>}
|
|
121
|
+
*/
|
|
122
|
+
private _publicListWalk;
|
|
113
123
|
/**
|
|
114
124
|
* Lists a public (`PublicCanRead`) collection by its URL with no authorization
|
|
115
125
|
* -- an unsigned `GET` -- e.g. to browse a blog published as a public-read
|
|
116
|
-
* collection.
|
|
126
|
+
* collection. Transparently follows the server's `next` pagination links,
|
|
127
|
+
* buffering every page into a single list (the returned envelope omits `next`).
|
|
128
|
+
* For a large collection prefer `publicListCollectionPages()` or
|
|
129
|
+
* `publicListCollectionItems()`, which stream one page at a time and allow
|
|
130
|
+
* stopping early. Returns `null` if the collection is missing or not publicly
|
|
117
131
|
* readable (404 conflation caveat).
|
|
118
132
|
*
|
|
119
133
|
* @param options {object}
|
|
@@ -123,6 +137,33 @@ export declare class WasClient {
|
|
|
123
137
|
publicListCollection({ collectionUrl }: {
|
|
124
138
|
collectionUrl: string;
|
|
125
139
|
}): Promise<CollectionResourcesList | null>;
|
|
140
|
+
/**
|
|
141
|
+
* Lazily yields a public collection listing one page at a time, following the
|
|
142
|
+
* server's `next` links on demand with unsigned `GET`s. Use this to stream a
|
|
143
|
+
* large public collection in constant memory or to stop early. Yields nothing
|
|
144
|
+
* if the collection is missing or not publicly readable (404 conflation
|
|
145
|
+
* caveat).
|
|
146
|
+
*
|
|
147
|
+
* @param options {object}
|
|
148
|
+
* @param options.collectionUrl {string} the absolute collection URL
|
|
149
|
+
* @returns {AsyncGenerator<CollectionResourcesList>}
|
|
150
|
+
*/
|
|
151
|
+
publicListCollectionPages({ collectionUrl }: {
|
|
152
|
+
collectionUrl: string;
|
|
153
|
+
}): AsyncGenerator<CollectionResourcesList>;
|
|
154
|
+
/**
|
|
155
|
+
* Lazily yields each item of a public collection across every page, flattening
|
|
156
|
+
* `publicListCollectionPages()`. Yields the listing's `ResourceSummary` entries
|
|
157
|
+
* (id / url / contentType / name), not the resource bodies. Yields nothing if
|
|
158
|
+
* the collection is missing or not publicly readable (404 conflation caveat).
|
|
159
|
+
*
|
|
160
|
+
* @param options {object}
|
|
161
|
+
* @param options.collectionUrl {string} the absolute collection URL
|
|
162
|
+
* @returns {AsyncGenerator<ResourceSummary>}
|
|
163
|
+
*/
|
|
164
|
+
publicListCollectionItems({ collectionUrl }: {
|
|
165
|
+
collectionUrl: string;
|
|
166
|
+
}): AsyncGenerator<ResourceSummary>;
|
|
126
167
|
/**
|
|
127
168
|
* Rebuilds an access handle from a received capability, returning a handle at
|
|
128
169
|
* the depth implied by the capability's `invocationTarget` (space /
|
package/dist/WasClient.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WasClient.d.ts","sourceRoot":"","sources":["../src/WasClient.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;GAOG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAE3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"WasClient.d.ts","sourceRoot":"","sources":["../src/WasClient.ts"],"names":[],"mappings":"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"}
|
package/dist/WasClient.js
CHANGED
|
@@ -13,7 +13,8 @@ import { ZcapClient } from '@interop/ezcap';
|
|
|
13
13
|
import { Ed25519Signature2020 } from '@interop/ed25519-signature';
|
|
14
14
|
import { spacesRoot } from './internal/paths.js';
|
|
15
15
|
import { send, rawRequest, unsignedRequest } from './internal/request.js';
|
|
16
|
-
import { parseResource, readJsonData } from './internal/content.js';
|
|
16
|
+
import { createdId, parseResource, readJsonData } from './internal/content.js';
|
|
17
|
+
import { collectPages, walkPages } from './internal/pagination.js';
|
|
17
18
|
import { delegateGrant } from './internal/grant.js';
|
|
18
19
|
import { ValidationError } from './errors.js';
|
|
19
20
|
import { Space } from './Space.js';
|
|
@@ -120,8 +121,7 @@ export class WasClient {
|
|
|
120
121
|
method: 'POST',
|
|
121
122
|
json: body
|
|
122
123
|
});
|
|
123
|
-
|
|
124
|
-
return this.space(created.id);
|
|
124
|
+
return this.space(createdId(response));
|
|
125
125
|
}
|
|
126
126
|
/**
|
|
127
127
|
* Lists the spaces in the repository visible to the wrapped signer, as a
|
|
@@ -159,16 +159,15 @@ export class WasClient {
|
|
|
159
159
|
return parseResource(response);
|
|
160
160
|
}
|
|
161
161
|
/**
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
162
|
+
* Reads the first page of a public (`PublicCanRead`) collection listing with an
|
|
163
|
+
* unsigned `GET` and packages the means to follow its `next` links. Returns
|
|
164
|
+
* `null` if the collection is missing or not publicly readable (404 conflation
|
|
165
|
+
* caveat).
|
|
166
166
|
*
|
|
167
|
-
* @param
|
|
168
|
-
* @
|
|
169
|
-
* @returns {Promise<CollectionResourcesList | null>}
|
|
167
|
+
* @param collectionUrl {string} the absolute collection URL
|
|
168
|
+
* @returns {Promise<PageWalk | null>}
|
|
170
169
|
*/
|
|
171
|
-
async
|
|
170
|
+
async _publicListWalk(collectionUrl) {
|
|
172
171
|
// The collection listing endpoint is the trailing-slash items URL.
|
|
173
172
|
const url = collectionUrl.endsWith('/')
|
|
174
173
|
? collectionUrl
|
|
@@ -177,7 +176,73 @@ export class WasClient {
|
|
|
177
176
|
if (response === null) {
|
|
178
177
|
return null;
|
|
179
178
|
}
|
|
180
|
-
return
|
|
179
|
+
return {
|
|
180
|
+
first: (await readJsonData(response)),
|
|
181
|
+
firstUrl: url,
|
|
182
|
+
fetchPage: async (pageUrl) => {
|
|
183
|
+
const pageResponse = await unsignedRequest({
|
|
184
|
+
url: pageUrl,
|
|
185
|
+
method: 'GET',
|
|
186
|
+
read: true
|
|
187
|
+
});
|
|
188
|
+
return pageResponse === null
|
|
189
|
+
? null
|
|
190
|
+
: (await readJsonData(pageResponse));
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Lists a public (`PublicCanRead`) collection by its URL with no authorization
|
|
196
|
+
* -- an unsigned `GET` -- e.g. to browse a blog published as a public-read
|
|
197
|
+
* collection. Transparently follows the server's `next` pagination links,
|
|
198
|
+
* buffering every page into a single list (the returned envelope omits `next`).
|
|
199
|
+
* For a large collection prefer `publicListCollectionPages()` or
|
|
200
|
+
* `publicListCollectionItems()`, which stream one page at a time and allow
|
|
201
|
+
* stopping early. Returns `null` if the collection is missing or not publicly
|
|
202
|
+
* readable (404 conflation caveat).
|
|
203
|
+
*
|
|
204
|
+
* @param options {object}
|
|
205
|
+
* @param options.collectionUrl {string} the absolute collection URL
|
|
206
|
+
* @returns {Promise<CollectionResourcesList | null>}
|
|
207
|
+
*/
|
|
208
|
+
async publicListCollection({ collectionUrl }) {
|
|
209
|
+
const walk = await this._publicListWalk(collectionUrl);
|
|
210
|
+
return walk === null ? null : collectPages(walk);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Lazily yields a public collection listing one page at a time, following the
|
|
214
|
+
* server's `next` links on demand with unsigned `GET`s. Use this to stream a
|
|
215
|
+
* large public collection in constant memory or to stop early. Yields nothing
|
|
216
|
+
* if the collection is missing or not publicly readable (404 conflation
|
|
217
|
+
* caveat).
|
|
218
|
+
*
|
|
219
|
+
* @param options {object}
|
|
220
|
+
* @param options.collectionUrl {string} the absolute collection URL
|
|
221
|
+
* @returns {AsyncGenerator<CollectionResourcesList>}
|
|
222
|
+
*/
|
|
223
|
+
async *publicListCollectionPages({ collectionUrl }) {
|
|
224
|
+
const walk = await this._publicListWalk(collectionUrl);
|
|
225
|
+
if (walk === null) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
yield* walkPages(walk);
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Lazily yields each item of a public collection across every page, flattening
|
|
232
|
+
* `publicListCollectionPages()`. Yields the listing's `ResourceSummary` entries
|
|
233
|
+
* (id / url / contentType / name), not the resource bodies. Yields nothing if
|
|
234
|
+
* the collection is missing or not publicly readable (404 conflation caveat).
|
|
235
|
+
*
|
|
236
|
+
* @param options {object}
|
|
237
|
+
* @param options.collectionUrl {string} the absolute collection URL
|
|
238
|
+
* @returns {AsyncGenerator<ResourceSummary>}
|
|
239
|
+
*/
|
|
240
|
+
async *publicListCollectionItems({ collectionUrl }) {
|
|
241
|
+
for await (const page of this.publicListCollectionPages({
|
|
242
|
+
collectionUrl
|
|
243
|
+
})) {
|
|
244
|
+
yield* page.items;
|
|
245
|
+
}
|
|
181
246
|
}
|
|
182
247
|
/**
|
|
183
248
|
* Rebuilds an access handle from a received capability, returning a handle at
|
|
@@ -188,8 +253,19 @@ export class WasClient {
|
|
|
188
253
|
* @returns {Space | Collection | Resource}
|
|
189
254
|
*/
|
|
190
255
|
fromCapability(zcap) {
|
|
191
|
-
|
|
192
|
-
|
|
256
|
+
let pathname;
|
|
257
|
+
try {
|
|
258
|
+
;
|
|
259
|
+
({ pathname } = new URL(zcap.invocationTarget));
|
|
260
|
+
}
|
|
261
|
+
catch (err) {
|
|
262
|
+
throw new ValidationError(`invocationTarget "${zcap.invocationTarget}" is not a valid ` +
|
|
263
|
+
'absolute URL.', { cause: err });
|
|
264
|
+
}
|
|
265
|
+
// Decode each path segment before splitting it back into handle ids: the
|
|
266
|
+
// path builders re-encode every id with encodeURIComponent, so passing a
|
|
267
|
+
// still-encoded segment through would double-encode it.
|
|
268
|
+
const segments = pathname.split('/').filter(Boolean).map(decodeURIComponent);
|
|
193
269
|
if (segments[0] !== 'space') {
|
|
194
270
|
throw new ValidationError(`Cannot derive a handle from invocationTarget "${zcap.invocationTarget}".`);
|
|
195
271
|
}
|
package/dist/WasClient.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WasClient.js","sourceRoot":"","sources":["../src/WasClient.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;GAOG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AAEjE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAEhD,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACzE,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"WasClient.js","sourceRoot":"","sources":["../src/WasClient.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;GAOG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AAEjE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAEhD,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACzE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAC9E,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAElE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAE7C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAcxC,MAAM,OAAO,SAAS;IACX,SAAS,CAAQ;IACjB,UAAU,CAAY;IACtB,UAAU,CAAqB;IAExC;;;;;;;;;;;;OAYG;IACH,YAAY,EACV,SAAS,EACT,UAAU,EACV,UAAU,EAKX;QACC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;QAC1B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;QAC5B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;IAC9B,CAAC;IAED;;;;;;;;;OASG;IACH,MAAM,CAAC,UAAU,CAAC,EAChB,SAAS,EACT,MAAM,EACN,UAAU,EAKX;QACC,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC;YAChC,UAAU,EAAE,oBAAoB;YAChC,gBAAgB,EAAE,MAAM;YACxB,gBAAgB,EAAE,MAAM;SACzB,CAAC,CAAA;QACF,OAAO,IAAI,SAAS,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAA;IAC7D,CAAC;IAED;;;;;OAKG;IACH,IAAI,aAAa;QACf,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAA;QAC/C,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC;YAChB,MAAM,IAAI,eAAe,CACvB,oDAAoD,CACrD,CAAA;QACH,CAAC;QACD,OAAO,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAW,CAAA;IAC1C,CAAC;IAED,IAAY,QAAQ;QAClB,OAAO;YACL,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,UAAU,EAAE,IAAI,CAAC,UAAU;SAC5B,CAAA;IACH,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,OAAe,EAAE,UAAyB,EAAE;QAChD,OAAO,IAAI,KAAK,CAAC;YACf,OAAO,EAAE,IAAI,CAAC,QAAQ;YACtB,OAAO;YACP,UAAU,EAAE,OAAO,CAAC,UAAU;SAC/B,CAAC,CAAA;IACJ,CAAC;IAED;;;;;;;;;;OAUG;IACH,KAAK,CAAC,WAAW,CACf,OAA4D,EAAE;QAE9D,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,aAAa,CAAA;QACxD,MAAM,IAAI,GAA4B,EAAE,UAAU,EAAE,CAAA;QACpD,IAAI,IAAI,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;YAC1B,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAA;QACnB,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC5B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA;QACvB,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YACzC,IAAI,EAAE,UAAU,EAAE;YAClB,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI;SACX,CAAC,CAAA;QACF,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAA;IACxC,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,UAAU;QACd,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YACzC,IAAI,EAAE,UAAU,EAAE;YAClB,MAAM,EAAE,KAAK;SACd,CAAC,CAAA;QACF,OAAQ,QAA+B,CAAC,IAAoB,CAAA;IAC9D,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,UAAU,CAAC,EACf,WAAW,EAGZ;QACC,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC;YACrC,GAAG,EAAE,WAAW;YAChB,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,IAAI;SACX,CAAC,CAAA;QACF,OAAO,aAAa,CAAC,QAAQ,CAAC,CAAA;IAChC,CAAC;IAED;;;;;;;;OAQG;IACK,KAAK,CAAC,eAAe,CAC3B,aAAqB;QAErB,mEAAmE;QACnE,MAAM,GAAG,GAAG,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC;YACrC,CAAC,CAAC,aAAa;YACf,CAAC,CAAC,GAAG,aAAa,GAAG,CAAA;QACvB,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;QAC1E,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YACtB,OAAO,IAAI,CAAA;QACb,CAAC;QACD,OAAO;YACL,KAAK,EAAE,CAAC,MAAM,YAAY,CAAC,QAAQ,CAAC,CAA4B;YAChE,QAAQ,EAAE,GAAG;YACb,SAAS,EAAE,KAAK,EAAC,OAAO,EAAC,EAAE;gBACzB,MAAM,YAAY,GAAG,MAAM,eAAe,CAAC;oBACzC,GAAG,EAAE,OAAO;oBACZ,MAAM,EAAE,KAAK;oBACb,IAAI,EAAE,IAAI;iBACX,CAAC,CAAA;gBACF,OAAO,YAAY,KAAK,IAAI;oBAC1B,CAAC,CAAC,IAAI;oBACN,CAAC,CAAE,CAAC,MAAM,YAAY,CAAC,YAAY,CAAC,CAA6B,CAAA;YACrE,CAAC;SACF,CAAA;IACH,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,oBAAoB,CAAC,EACzB,aAAa,EAGd;QACC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,CAAA;QACtD,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAA;IAClD,CAAC;IAED;;;;;;;;;;OAUG;IACH,KAAK,CAAC,CAAC,yBAAyB,CAAC,EAC/B,aAAa,EAGd;QACC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,CAAA;QACtD,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,OAAM;QACR,CAAC;QACD,KAAK,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;IACxB,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,CAAC,yBAAyB,CAAC,EAC/B,aAAa,EAGd;QACC,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,IAAI,CAAC,yBAAyB,CAAC;YACtD,aAAa;SACd,CAAC,EAAE,CAAC;YACH,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAA;QACnB,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACH,cAAc,CAAC,IAAW;QACxB,IAAI,QAAgB,CAAA;QACpB,IAAI,CAAC;YACH,CAAC;YAAA,CAAC,EAAE,QAAQ,EAAE,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAA;QAClD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,eAAe,CACvB,qBAAqB,IAAI,CAAC,gBAAgB,mBAAmB;gBAC3D,eAAe,EACjB,EAAE,KAAK,EAAE,GAAG,EAAE,CACf,CAAA;QACH,CAAC;QACD,yEAAyE;QACzE,yEAAyE;QACzE,wDAAwD;QACxD,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAA;QAC5E,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC;YAC5B,MAAM,IAAI,eAAe,CACvB,iDAAiD,IAAI,CAAC,gBAAgB,IAAI,CAC3E,CAAA;QACH,CAAC;QACD,MAAM,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAA;QACtD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,eAAe,CACvB,qBAAqB,IAAI,CAAC,gBAAgB,oBAAoB,CAC/D,CAAA;QACH,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAA;QAC7B,IAAI,UAAU,EAAE,CAAC;YACf,OAAO,IAAI,QAAQ,CAAC;gBAClB,OAAO;gBACP,OAAO;gBACP,YAAY,EAAE,YAAsB;gBACpC,UAAU;gBACV,UAAU,EAAE,IAAI;aACjB,CAAC,CAAA;QACJ,CAAC;QACD,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,IAAI,UAAU,CAAC;gBACpB,OAAO;gBACP,OAAO;gBACP,YAAY;gBACZ,UAAU,EAAE,IAAI;aACjB,CAAC,CAAA;QACJ,CAAC;QACD,OAAO,IAAI,KAAK,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAA;IAC1D,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,KAAK,CAAC,OAAqB;QAC/B,OAAO,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAC9C,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,OAAO,CAAC,OAAqB;QACjC,OAAO,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAC3C,CAAC;CACF"}
|
package/dist/codec.d.ts
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
* silently writing plaintext.
|
|
32
32
|
*/
|
|
33
33
|
import type { HttpResponse } from '@interop/http-client';
|
|
34
|
-
import type { Json } from './types.js';
|
|
34
|
+
import type { Json, ResourceData, ResourceMetadataCustom } from './types.js';
|
|
35
35
|
/**
|
|
36
36
|
* The result of {@link ResourceCodec.encode}: the stored representation of a
|
|
37
37
|
* write, plus the id to store it under.
|
|
@@ -43,7 +43,13 @@ import type { Json } from './types.js';
|
|
|
43
43
|
* - `json` / `body` -- mutually exclusive payloads, mirroring the request
|
|
44
44
|
* layer: `json` for a structured body, `body` for raw bytes.
|
|
45
45
|
* - `contentType` -- the content type to send for a `body` write (e.g.
|
|
46
|
-
* `application/
|
|
46
|
+
* `application/jose+json` for an encrypted envelope).
|
|
47
|
+
* - `resourceContentType` -- the plaintext content type of the resource, when it
|
|
48
|
+
* differs from the stored `contentType`. An encrypting codec sets this to the
|
|
49
|
+
* caller's resolved type (e.g. `image/png`) while `contentType` stays the
|
|
50
|
+
* opaque envelope type, so `add()` can report the real type in
|
|
51
|
+
* {@link AddResult.contentType}. Absent for the identity codec (its
|
|
52
|
+
* `contentType` already is the resource type).
|
|
47
53
|
* - `ifMatch` / `ifNoneMatch` -- an optional conditional-write precondition the
|
|
48
54
|
* codec computed (e.g. the EDV codec maps its `sequence` onto an `If-Match`
|
|
49
55
|
* ETag for lost-update-safe updates, or `If-None-Match: *` for a fresh
|
|
@@ -55,6 +61,7 @@ export interface EncodedWrite {
|
|
|
55
61
|
json?: object;
|
|
56
62
|
body?: Uint8Array | Blob;
|
|
57
63
|
contentType?: string;
|
|
64
|
+
resourceContentType?: string;
|
|
58
65
|
ifMatch?: string;
|
|
59
66
|
ifNoneMatch?: boolean;
|
|
60
67
|
}
|
|
@@ -65,12 +72,15 @@ export interface EncodedWrite {
|
|
|
65
72
|
*/
|
|
66
73
|
export interface ResourceCodec {
|
|
67
74
|
/**
|
|
68
|
-
*
|
|
69
|
-
* `
|
|
70
|
-
*
|
|
71
|
-
*
|
|
75
|
+
* How this codec stores a Resource's user-writable metadata (`custom`:
|
|
76
|
+
* `name` / `tags`, set via `resource.setName` / `setTags` / `setMeta`). The
|
|
77
|
+
* identity codec stores it as server-visible plaintext (`'plaintext'`); an
|
|
78
|
+
* encrypting codec stores it as an opaque envelope (`'encrypted'`) -- the same
|
|
79
|
+
* way it stores content -- so `name` / `tags` never reach the server in the
|
|
80
|
+
* clear. A mode rather than a boolean so a future scheme that stores metadata
|
|
81
|
+
* differently can extend the union.
|
|
72
82
|
*/
|
|
73
|
-
readonly
|
|
83
|
+
readonly metadataMode: 'plaintext' | 'encrypted';
|
|
74
84
|
/**
|
|
75
85
|
* Whether this codec drives optimistic-concurrency (conditional) writes. When
|
|
76
86
|
* `true`, the write path pre-reads the current stored resource and passes it
|
|
@@ -88,7 +98,7 @@ export interface ResourceCodec {
|
|
|
88
98
|
*
|
|
89
99
|
* @param input {object}
|
|
90
100
|
* @param [input.id] {string} resource id (absent on add)
|
|
91
|
-
* @param input.data {
|
|
101
|
+
* @param input.data {ResourceData} the plaintext value
|
|
92
102
|
* @param [input.contentType] {string} caller-supplied content type
|
|
93
103
|
* @param [input.current] {HttpResponse | null} the current stored response
|
|
94
104
|
* (or `null` if absent), supplied only when {@link conditionalWrites} is set,
|
|
@@ -97,7 +107,7 @@ export interface ResourceCodec {
|
|
|
97
107
|
*/
|
|
98
108
|
encode(input: {
|
|
99
109
|
id?: string;
|
|
100
|
-
data:
|
|
110
|
+
data: ResourceData;
|
|
101
111
|
contentType?: string;
|
|
102
112
|
current?: HttpResponse | null;
|
|
103
113
|
}): Promise<EncodedWrite>;
|
|
@@ -110,6 +120,35 @@ export interface ResourceCodec {
|
|
|
110
120
|
* @returns {Promise<Json | Blob>}
|
|
111
121
|
*/
|
|
112
122
|
decode(response: HttpResponse): Promise<Json | Blob>;
|
|
123
|
+
/**
|
|
124
|
+
* Transforms a caller's user-writable metadata (`custom`) into the value to
|
|
125
|
+
* store under `custom` on a `PUT .../meta` write. The identity codec returns
|
|
126
|
+
* `custom` unchanged (server-visible plaintext `{ name, tags }`); an
|
|
127
|
+
* encrypting codec returns an opaque encryption envelope, so `name` / `tags`
|
|
128
|
+
* are never server-visible.
|
|
129
|
+
*
|
|
130
|
+
* @param input {object}
|
|
131
|
+
* @param input.custom {ResourceMetadataCustom} the plaintext user metadata
|
|
132
|
+
* @returns {Promise<{ custom: object }>} the value to store under `custom`
|
|
133
|
+
*/
|
|
134
|
+
encodeMeta(input: {
|
|
135
|
+
custom: ResourceMetadataCustom;
|
|
136
|
+
}): Promise<{
|
|
137
|
+
custom: object;
|
|
138
|
+
}>;
|
|
139
|
+
/**
|
|
140
|
+
* Inverts {@link encodeMeta}: transforms the stored `custom` value read from
|
|
141
|
+
* `.../meta` back into the caller's plaintext `{ name, tags }`. The identity
|
|
142
|
+
* codec returns `stored.custom ?? {}` unchanged; an encrypting codec decrypts
|
|
143
|
+
* the envelope. An absent `custom` (no metadata written) decodes to `{}`.
|
|
144
|
+
*
|
|
145
|
+
* @param stored {object}
|
|
146
|
+
* @param [stored.custom] {unknown} the stored `custom` value from `/meta`
|
|
147
|
+
* @returns {Promise<ResourceMetadataCustom>}
|
|
148
|
+
*/
|
|
149
|
+
decodeMeta(stored: {
|
|
150
|
+
custom?: unknown;
|
|
151
|
+
}): Promise<ResourceMetadataCustom>;
|
|
113
152
|
}
|
|
114
153
|
/**
|
|
115
154
|
* The keystore + codec factory for encrypted collections. Injected into
|
package/dist/codec.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codec.d.ts","sourceRoot":"","sources":["../src/codec.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACxD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"codec.d.ts","sourceRoot":"","sources":["../src/codec.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACxD,OAAO,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAE5E;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,WAAW,YAAY;IAC3B,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI,CAAA;IACxB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;;;;;OAQG;IACH,QAAQ,CAAC,YAAY,EAAE,WAAW,GAAG,WAAW,CAAA;IAEhD;;;;;;;;OAQG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAEpC;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,KAAK,EAAE;QACZ,EAAE,CAAC,EAAE,MAAM,CAAA;QACX,IAAI,EAAE,YAAY,CAAA;QAClB,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI,CAAA;KAC9B,GAAG,OAAO,CAAC,YAAY,CAAC,CAAA;IAEzB;;;;;;;OAOG;IACH,MAAM,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAA;IAEpD;;;;;;;;;;OAUG;IACH,UAAU,CAAC,KAAK,EAAE;QAChB,MAAM,EAAE,sBAAsB,CAAA;KAC/B,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAE/B;;;;;;;;;OASG;IACH,UAAU,CAAC,MAAM,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAA;CAC1E;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,KAAK,EAAE;QACd,OAAO,EAAE,MAAM,CAAA;QACf,YAAY,EAAE,MAAM,CAAA;QACpB,MAAM,EAAE,MAAM,CAAA;QACd,IAAI,CAAC,EAAE,OAAO,CAAA;KACf,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAA;CAClC"}
|
package/dist/edv/EdvCodec.d.ts
CHANGED
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
* app's `resolveKeys`; they never reach the server, which stores only opaque
|
|
12
12
|
* JWE envelopes.
|
|
13
13
|
*
|
|
14
|
-
* This reuses `EdvClientCore`'s
|
|
15
|
-
*
|
|
16
|
-
* the
|
|
17
|
-
* I/O, so the codec is a
|
|
18
|
-
* its own.
|
|
14
|
+
* This reuses `EdvClientCore`'s transport-free `documentCipher` (its public
|
|
15
|
+
* `EdvDocumentCipher` -- the same JWE machinery as the standalone
|
|
16
|
+
* `WasTransport`), but here the WAS Resource CRUD -- the transport role -- is
|
|
17
|
+
* played by core was-client's `Collection`/`Resource` I/O, so the codec is a
|
|
18
|
+
* pure encode/decode transform and needs no transport of its own.
|
|
19
19
|
*
|
|
20
20
|
* Scope (documents-only):
|
|
21
21
|
*
|
|
@@ -24,9 +24,12 @@
|
|
|
24
24
|
* a human-readable id is rejected (it would leak onto the URL). Carry a
|
|
25
25
|
* human-readable label inside the encrypted content instead. (Blind-derived
|
|
26
26
|
* ids are a deferred future item.)
|
|
27
|
-
* - **
|
|
28
|
-
* is
|
|
29
|
-
* (
|
|
27
|
+
* - **Inline non-JSON as a single JWE.** A `Blob`/`Uint8Array` under the size cap
|
|
28
|
+
* is encrypted as one document -- stored as a legible UTF-8 string for a
|
|
29
|
+
* text-family type (else base64) -- with the plaintext content type and the
|
|
30
|
+
* encoding carried in the document `meta`. An oversized one is
|
|
31
|
+
* rejected (large chunked encrypted blobs need the server's `chunked-streams`
|
|
32
|
+
* affordance).
|
|
30
33
|
* - **Enforced sequence (conditional writes).** The codec sets
|
|
31
34
|
* `conditionalWrites`, so the write path pre-reads the current envelope and
|
|
32
35
|
* hands it to `encode`: an update advances `sequence` from its prior value and
|
|
@@ -35,23 +38,25 @@
|
|
|
35
38
|
* surfaces as a `PreconditionFailedError` (412) -- the lost-update guard --
|
|
36
39
|
* rather than the old advisory last-writer-wins. Against a backend that does
|
|
37
40
|
* not advertise `conditional-writes` (no ETag) it degrades to advisory.
|
|
38
|
-
* - **
|
|
39
|
-
* `
|
|
40
|
-
*
|
|
41
|
+
* - **Encrypted metadata.** `metadataMode` is `'encrypted'`, so a Resource's
|
|
42
|
+
* user-writable `custom` (`name`/`tags`, via `setName`/`setTags`/`setMeta`) is
|
|
43
|
+
* encrypted into an EDV Document envelope with the same `documentCipher` used
|
|
44
|
+
* for content and stored opaquely under `/meta`; the server never sees
|
|
45
|
+
* plaintext `name`/`tags`. A reader with the keys decrypts it back
|
|
46
|
+
* transparently via `meta()`.
|
|
41
47
|
*/
|
|
42
48
|
import { EdvClientCore } from '@interop/edv-client';
|
|
43
49
|
import type { HttpResponse } from '@interop/http-client';
|
|
44
50
|
import type { IKeyAgreementKey, IKeyResolver } from '@interop/data-integrity-core';
|
|
45
51
|
import type { EncodedWrite, EncryptionProvider, ResourceCodec } from '../codec.js';
|
|
46
|
-
import type { Json } from '../types.js';
|
|
47
|
-
import { EDV_CONTENT_TYPE } from './WasTransport.js';
|
|
52
|
+
import type { Json, ResourceData, ResourceMetadataCustom } from '../types.js';
|
|
48
53
|
/**
|
|
49
54
|
* A {@link ResourceCodec} that encrypts on write and decrypts on read using an
|
|
50
|
-
* `EdvClientCore`'s
|
|
55
|
+
* `EdvClientCore`'s public `documentCipher`. One instance is bound per encrypted
|
|
51
56
|
* collection handle.
|
|
52
57
|
*/
|
|
53
58
|
export declare class EdvCodec implements ResourceCodec {
|
|
54
|
-
readonly
|
|
59
|
+
readonly metadataMode: "encrypted";
|
|
55
60
|
readonly conditionalWrites = true;
|
|
56
61
|
private readonly _edv;
|
|
57
62
|
private readonly _keyAgreementKey;
|
|
@@ -75,7 +80,7 @@ export declare class EdvCodec implements ResourceCodec {
|
|
|
75
80
|
*/
|
|
76
81
|
encode({ id, data, contentType, current }: {
|
|
77
82
|
id?: string;
|
|
78
|
-
data:
|
|
83
|
+
data: ResourceData;
|
|
79
84
|
contentType?: string;
|
|
80
85
|
current?: HttpResponse | null;
|
|
81
86
|
}): Promise<EncodedWrite>;
|
|
@@ -87,35 +92,90 @@ export declare class EdvCodec implements ResourceCodec {
|
|
|
87
92
|
json(): Promise<unknown>;
|
|
88
93
|
}): Promise<Json | Blob>;
|
|
89
94
|
/**
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
* `
|
|
95
|
+
* @inheritdoc
|
|
96
|
+
*
|
|
97
|
+
* Encrypts the user-writable `custom` into an EDV Document envelope
|
|
98
|
+
* (`{ jwe, ... }`) with the same `documentCipher.encrypt` used for content --
|
|
99
|
+
* `custom` becomes the document `content`. The envelope's own `sequence` is
|
|
100
|
+
* inert (metadata concurrency is the server's plaintext `metaVersion`, not the
|
|
101
|
+
* envelope), so each write re-encrypts fresh with no `update`.
|
|
102
|
+
*/
|
|
103
|
+
encodeMeta({ custom }: {
|
|
104
|
+
custom: ResourceMetadataCustom;
|
|
105
|
+
}): Promise<{
|
|
106
|
+
custom: object;
|
|
107
|
+
}>;
|
|
108
|
+
/**
|
|
109
|
+
* @inheritdoc
|
|
110
|
+
*
|
|
111
|
+
* Decrypts the stored `custom` envelope back to plaintext `{ name, tags }`. An
|
|
112
|
+
* absent `custom` (no metadata written yet, or cleared) decodes to `{}`; a
|
|
113
|
+
* present value must be an EDV envelope (else {@link EncryptionError}, the
|
|
114
|
+
* `_assertEnvelope` guard), so a foreign plaintext `custom` fails closed.
|
|
115
|
+
*/
|
|
116
|
+
decodeMeta({ custom }: {
|
|
117
|
+
custom?: unknown;
|
|
118
|
+
}): Promise<ResourceMetadataCustom>;
|
|
119
|
+
/**
|
|
120
|
+
* Asserts that a document read from an encrypted collection is an EDV envelope
|
|
121
|
+
* (`{ jwe, ... }`) before it is handed to the cipher. A plaintext or foreign
|
|
122
|
+
* resource -- one written without this codec -- carries no `jwe`, which would
|
|
123
|
+
* otherwise make the EDV core throw a raw `TypeError`. Surfacing a typed
|
|
124
|
+
* `EncryptionError` keeps the fail-closed contract legible to callers.
|
|
94
125
|
*
|
|
95
|
-
* @param
|
|
96
|
-
* @param
|
|
97
|
-
*
|
|
126
|
+
* @param doc {unknown}
|
|
127
|
+
* @param context {string} the operation in progress (`read` / `update`),
|
|
128
|
+
* for the message
|
|
129
|
+
* @returns {asserts doc is IEncryptedDocument}
|
|
98
130
|
*/
|
|
99
|
-
private
|
|
131
|
+
private _assertEnvelope;
|
|
100
132
|
/**
|
|
101
|
-
*
|
|
102
|
-
*
|
|
133
|
+
* Splits a caller value into a decrypted EDV document `{ content, meta }`,
|
|
134
|
+
* carrying the plaintext content type and inline-encoding discriminator in
|
|
135
|
+
* `meta`. Three cases:
|
|
136
|
+
*
|
|
137
|
+
* 1. JSON object/array to `content` verbatim, `meta = { contentType }` (no
|
|
138
|
+
* `encoding`); the shape of `content` is never inspected on read, so a
|
|
139
|
+
* caller object shaped like `{ text }` / `{ bytes }` round-trips as itself.
|
|
140
|
+
* 2. Text (`Blob`/`Uint8Array` of a text-family type that is valid UTF-8)
|
|
141
|
+
* to `content = { text }`, `meta = { contentType, encoding: 'utf-8' }`;
|
|
142
|
+
* stored legibly with no base64 inflation.
|
|
143
|
+
* 3. Binary (any other `Blob`/`Uint8Array`) to `content = { bytes: base64 }`,
|
|
144
|
+
* `meta = { contentType, encoding: 'base64' }`.
|
|
103
145
|
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
146
|
+
* A bare primitive is rejected (mirroring the plaintext `prepareBody`
|
|
147
|
+
* contract). The binary/text content type resolves as
|
|
148
|
+
* `contentType || blob.type || guessContentTypeFromId(id) || octet-stream`,
|
|
149
|
+
* mirroring `prepareBody`.
|
|
150
|
+
*
|
|
151
|
+
* @param data {ResourceData}
|
|
152
|
+
* @param [contentType] {string} caller-supplied content type
|
|
153
|
+
* @param [id] {string} resource id, for the extension guess
|
|
154
|
+
* @returns {Promise<{ content: Record<string, unknown>; meta:
|
|
155
|
+
* Record<string, unknown> }>}
|
|
107
156
|
*/
|
|
108
|
-
private
|
|
157
|
+
private _toDocument;
|
|
109
158
|
/**
|
|
110
|
-
* Reconstructs a caller value from decrypted EDV document
|
|
111
|
-
*
|
|
159
|
+
* Reconstructs a caller value from a decrypted EDV document, discriminating
|
|
160
|
+
* on `meta.encoding`:
|
|
161
|
+
*
|
|
162
|
+
* - `'utf-8'` to a `Blob` typed `meta.contentType` from `content.text`.
|
|
163
|
+
* - `'base64'` to a `Blob` typed `meta.contentType` from `content.bytes`.
|
|
164
|
+
* - absent (or `meta` absent) to `content` returned verbatim as JSON.
|
|
165
|
+
*
|
|
166
|
+
* A malformed inner shape (an encoding that does not match its container key's
|
|
167
|
+
* type) throws {@link EncryptionError} -- the decrypted-document analogue of
|
|
168
|
+
* `_assertEnvelope`'s outer guard.
|
|
112
169
|
*
|
|
113
170
|
* @param content {unknown}
|
|
171
|
+
* @param [meta] {Record<string, unknown>}
|
|
114
172
|
* @returns {Json | Blob}
|
|
115
173
|
*/
|
|
116
|
-
private
|
|
174
|
+
private _fromDocument;
|
|
117
175
|
}
|
|
118
|
-
/**
|
|
176
|
+
/**
|
|
177
|
+
* The per-collection key material an EDV codec is built from.
|
|
178
|
+
*/
|
|
119
179
|
export interface EdvKeys {
|
|
120
180
|
keyAgreementKey: IKeyAgreementKey;
|
|
121
181
|
keyResolver: IKeyResolver;
|
|
@@ -139,8 +199,8 @@ export interface EdvKeys {
|
|
|
139
199
|
* `{ keyAgreementKey, keyResolver }`, or `null` if this client holds no keys
|
|
140
200
|
* for it (fail-closed -- not a plaintext signal)
|
|
141
201
|
* @param [options.contentType] {string} stored envelope content type;
|
|
142
|
-
* defaults to `application/json`. Pass `
|
|
143
|
-
* (`application/
|
|
202
|
+
* defaults to `application/json`. Pass `JOSE_CONTENT_TYPE`
|
|
203
|
+
* (`application/jose+json`) against a server that registers an
|
|
144
204
|
* `application/*+json` parser.
|
|
145
205
|
* @param [options.maxBlobBytes] {number} single-document binary cap (default
|
|
146
206
|
* 1 MiB)
|
|
@@ -154,5 +214,4 @@ export declare function createEdvEncryption({ resolveKeys, contentType, maxBlobB
|
|
|
154
214
|
contentType?: string;
|
|
155
215
|
maxBlobBytes?: number;
|
|
156
216
|
}): EncryptionProvider;
|
|
157
|
-
export { EDV_CONTENT_TYPE };
|
|
158
217
|
//# sourceMappingURL=EdvCodec.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EdvCodec.d.ts","sourceRoot":"","sources":["../../src/edv/EdvCodec.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH
|
|
1
|
+
{"version":3,"file":"EdvCodec.d.ts","sourceRoot":"","sources":["../../src/edv/EdvCodec.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACxD,OAAO,KAAK,EAEV,gBAAgB,EAChB,YAAY,EACb,MAAM,8BAA8B,CAAA;AACrC,OAAO,KAAK,EACV,YAAY,EACZ,kBAAkB,EAClB,aAAa,EACd,MAAM,aAAa,CAAA;AAQpB,OAAO,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AA0D7E;;;;GAIG;AACH,qBAAa,QAAS,YAAW,aAAa;IAC5C,QAAQ,CAAC,YAAY,EAAG,WAAW,CAAS;IAC5C,QAAQ,CAAC,iBAAiB,QAAO;IAEjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAe;IACpC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAkB;IACnD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAQ;IACrC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAQ;IAEtC;;;;;;OAMG;gBACS,EACV,GAAG,EACH,eAAe,EACf,WAAW,EACX,YAAY,EACb,EAAE;QACD,GAAG,EAAE,aAAa,CAAA;QAClB,eAAe,EAAE,gBAAgB,CAAA;QACjC,WAAW,EAAE,MAAM,CAAA;QACnB,YAAY,EAAE,MAAM,CAAA;KACrB;IAOD;;OAEG;IACG,MAAM,CAAC,EACX,EAAE,EACF,IAAI,EACJ,WAAW,EACX,OAAO,EACR,EAAE;QACD,EAAE,CAAC,EAAE,MAAM,CAAA;QACX,IAAI,EAAE,YAAY,CAAA;QAClB,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI,CAAA;KAC9B,GAAG,OAAO,CAAC,YAAY,CAAC;IAiEzB;;OAEG;IACG,MAAM,CAAC,QAAQ,EAAE;QACrB,IAAI,CAAC,EAAE,OAAO,CAAA;QACd,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;KACzB,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAYxB;;;;;;;;OAQG;IACG,UAAU,CAAC,EACf,MAAM,EACP,EAAE;QACD,MAAM,EAAE,sBAAsB,CAAA;KAC/B,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAmB/B;;;;;;;OAOG;IACG,UAAU,CAAC,EACf,MAAM,EACP,EAAE;QACD,MAAM,CAAC,EAAE,OAAO,CAAA;KACjB,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAYnC;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,eAAe;IAkBvB;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;YACW,WAAW;IAoEzB;;;;;;;;;;;;;;;OAeG;IACH,OAAO,CAAC,aAAa;CA+BtB;AAsBD;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,eAAe,EAAE,gBAAgB,CAAA;IACjC,WAAW,EAAE,YAAY,CAAA;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,WAAW,EACX,WAAkC,EAClC,YAAqC,EACtC,EAAE;IACD,WAAW,EAAE,CAAC,GAAG,EAAE;QACjB,OAAO,EAAE,MAAM,CAAA;QACf,YAAY,EAAE,MAAM,CAAA;KACrB,KAAK,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAA;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,GAAG,kBAAkB,CAyBrB"}
|