@interop/was-client 0.5.0 → 0.6.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 +72 -0
- package/dist/Resource.d.ts +6 -0
- package/dist/Resource.d.ts.map +1 -1
- package/dist/Resource.js +7 -1
- package/dist/Resource.js.map +1 -1
- package/dist/WasClient.js +2 -2
- package/dist/WasClient.js.map +1 -1
- package/dist/edv/WasTransport.d.ts +178 -0
- package/dist/edv/WasTransport.d.ts.map +1 -0
- package/dist/edv/WasTransport.js +284 -0
- package/dist/edv/WasTransport.js.map +1 -0
- package/dist/edv/index.d.ts +11 -0
- package/dist/edv/index.d.ts.map +1 -0
- package/dist/edv/index.js +11 -0
- package/dist/edv/index.js.map +1 -0
- package/dist/errors.d.ts +8 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +12 -1
- package/dist/errors.js.map +1 -1
- package/dist/internal/content.d.ts +30 -1
- package/dist/internal/content.d.ts.map +1 -1
- package/dist/internal/content.js +68 -3
- package/dist/internal/content.js.map +1 -1
- package/dist/internal/request.d.ts.map +1 -1
- package/dist/internal/request.js +2 -7
- package/dist/internal/request.js.map +1 -1
- package/package.json +11 -1
package/README.md
CHANGED
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
- [Resource metadata](#resource-metadata)
|
|
22
22
|
- [Storage introspection: backends and quotas](#storage-introspection-backends-and-quotas)
|
|
23
23
|
- [Export and import](#export-and-import)
|
|
24
|
+
- [Encrypted collections (EDV-over-WAS)](#encrypted-collections-edv-over-was)
|
|
24
25
|
- [The manual-request escape hatch](#the-manual-request-escape-hatch)
|
|
25
26
|
- [Errors and the 404/null caveat](#errors-and-the-404null-caveat)
|
|
26
27
|
- [Contribute](#contribute)
|
|
@@ -402,6 +403,77 @@ const stats = await otherSpace.import(archive)
|
|
|
402
403
|
// policiesCreated, policiesSkipped }
|
|
403
404
|
```
|
|
404
405
|
|
|
406
|
+
### Encrypted collections (EDV-over-WAS)
|
|
407
|
+
|
|
408
|
+
Client-side end-to-end encryption, where the server stores only opaque
|
|
409
|
+
ciphertext and the keys never leave the client. This is the "EDV-over-WAS"
|
|
410
|
+
layout profile (Layer 1): it maps
|
|
411
|
+
[Encrypted Data Vault](https://digitalbazaar.github.io/encrypted-data-vaults/)
|
|
412
|
+
documents onto ordinary WAS resources, so it works against **any** WAS server
|
|
413
|
+
with no server changes. It is shipped on the opt-in `@interop/was-client/edv`
|
|
414
|
+
subpath so plaintext consumers do not pull the crypto dependencies.
|
|
415
|
+
|
|
416
|
+
`WasTransport` is an `@interop/edv-client` `Transport`: pair it with
|
|
417
|
+
`EdvClientCore`, which does all encryption, decryption, and key handling
|
|
418
|
+
client-side. The WAS Collection is the vault; each encrypted document is one WAS
|
|
419
|
+
resource (its EDV id is used verbatim as the resource id).
|
|
420
|
+
|
|
421
|
+
This example assumes a WAS server is already running and you have created (or
|
|
422
|
+
have access to) a collection to use as the vault:
|
|
423
|
+
|
|
424
|
+
```ts
|
|
425
|
+
import { WasClient } from '@interop/was-client'
|
|
426
|
+
import { WasTransport } from '@interop/was-client/edv'
|
|
427
|
+
import { EdvClientCore } from '@interop/edv-client'
|
|
428
|
+
import { X25519KeyAgreementKey2020 } from '@interop/x25519-key-agreement-key'
|
|
429
|
+
|
|
430
|
+
const was = WasClient.fromSigner({ serverUrl, signer })
|
|
431
|
+
const space = await was.createSpace({ name: 'My Wallet' })
|
|
432
|
+
const collection = await space.createCollection({ id: 'vault', name: 'Vault' })
|
|
433
|
+
|
|
434
|
+
// Client-side key material (never sent to the server). In a real app these come
|
|
435
|
+
// from the wallet's key store; here we generate a key-agreement key.
|
|
436
|
+
const kak = await X25519KeyAgreementKey2020.generate({
|
|
437
|
+
controller: was.controllerDid
|
|
438
|
+
})
|
|
439
|
+
const keyResolver = async ({ id }: { id: string }) => {
|
|
440
|
+
if (id !== kak.id) throw new Error(`Unknown key id "${id}".`)
|
|
441
|
+
return {
|
|
442
|
+
id: kak.id,
|
|
443
|
+
type: kak.type,
|
|
444
|
+
publicKeyMultibase: kak.publicKeyMultibase
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
const edv = new EdvClientCore({ keyAgreementKey: kak, keyResolver })
|
|
449
|
+
const transport = new WasTransport({
|
|
450
|
+
was,
|
|
451
|
+
spaceId: space.id,
|
|
452
|
+
collectionId: collection.id
|
|
453
|
+
})
|
|
454
|
+
|
|
455
|
+
// Encrypt + write: the server stores a JWE envelope, not the cleartext.
|
|
456
|
+
const doc = await edv.insert({ doc: { content: { secret: 42 } }, transport })
|
|
457
|
+
|
|
458
|
+
// Read + decrypt:
|
|
459
|
+
const decrypted = await edv.get({ id: doc.id, transport })
|
|
460
|
+
console.log(decrypted.content) // { secret: 42 }
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
Scope and caveats (this is the first, documents-only increment):
|
|
464
|
+
|
|
465
|
+
- **Documents only.** `insert` / `update` / `get` are supported. Blinded `find`
|
|
466
|
+
/ `count` / index updates and chunked blob streams throw -- they need
|
|
467
|
+
server-side EDV affordances (a blinded `/query` endpoint, the
|
|
468
|
+
`/{id}/chunks/{n}` sub-segment) a plaintext WAS server does not provide.
|
|
469
|
+
- **Advisory `sequence`.** Without server-side conditional writes, a stale
|
|
470
|
+
`update` is not rejected (last-writer-wins). Safe for single-writer use.
|
|
471
|
+
- **Content type.** Envelopes are stored as `application/json` by default so any
|
|
472
|
+
WAS server accepts them. The preferred marker `application/edv+json` (exported
|
|
473
|
+
as `EDV_CONTENT_TYPE`) needs the server to register an `application/*+json`
|
|
474
|
+
content-type parser -- the reference was-teaching-server does; pass
|
|
475
|
+
`contentType: EDV_CONTENT_TYPE` to opt in.
|
|
476
|
+
|
|
405
477
|
### The manual-request escape hatch
|
|
406
478
|
|
|
407
479
|
`was.request(...)` mirrors ezcap's generic `request()` for hand-built calls. As
|
package/dist/Resource.d.ts
CHANGED
|
@@ -49,6 +49,12 @@ export declare class Resource {
|
|
|
49
49
|
* objects/arrays, binary for `Blob`/`Uint8Array`. Throws `NotFoundError` if
|
|
50
50
|
* the parent collection does not exist (WAS does not auto-create parents).
|
|
51
51
|
*
|
|
52
|
+
* For binary data with no explicit `contentType` (and no `Blob.type`), the
|
|
53
|
+
* content-type is guessed from the resource id's file extension for common
|
|
54
|
+
* static-web types -- so `resource('index.html').put(bytes)` is sent as
|
|
55
|
+
* `text/html`. An unrecognized/absent extension sends no content-type, and the
|
|
56
|
+
* server applies its own required-`Content-Type` rule.
|
|
57
|
+
*
|
|
52
58
|
* @param data {Json | Blob | Uint8Array}
|
|
53
59
|
* @param options {object}
|
|
54
60
|
* @param [options.contentType] {string} content-type for binary data
|
package/dist/Resource.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Resource.d.ts","sourceRoot":"","sources":["../src/Resource.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAE1D,OAAO,KAAK,EACV,KAAK,EACL,IAAI,EACJ,cAAc,EACd,gBAAgB,EAChB,sBAAsB,EACvB,MAAM,YAAY,CAAA;AAEnB,qBAAa,QAAQ;IACnB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IAEnB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAO;IAEpC;;;;;;;OAOG;gBACS,EACV,OAAO,EACP,OAAO,EACP,YAAY,EACZ,UAAU,EACV,UAAU,EACX,EAAE;QACD,OAAO,EAAE,aAAa,CAAA;QACtB,OAAO,EAAE,MAAM,CAAA;QACf,YAAY,EAAE,MAAM,CAAA;QACpB,UAAU,EAAE,MAAM,CAAA;QAClB,UAAU,CAAC,EAAE,KAAK,CAAA;KACnB;IAQD,OAAO,KAAK,KAAK,GAEhB;IAED;;;;;;OAMG;IACG,GAAG,IAAI,OAAO,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAUxC;;;;;OAKG;IACG,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAUvC;;;;;OAKG;IACG,QAAQ,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAa5C
|
|
1
|
+
{"version":3,"file":"Resource.d.ts","sourceRoot":"","sources":["../src/Resource.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAE1D,OAAO,KAAK,EACV,KAAK,EACL,IAAI,EACJ,cAAc,EACd,gBAAgB,EAChB,sBAAsB,EACvB,MAAM,YAAY,CAAA;AAEnB,qBAAa,QAAQ;IACnB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IAEnB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAO;IAEpC;;;;;;;OAOG;gBACS,EACV,OAAO,EACP,OAAO,EACP,YAAY,EACZ,UAAU,EACV,UAAU,EACX,EAAE;QACD,OAAO,EAAE,aAAa,CAAA;QACtB,OAAO,EAAE,MAAM,CAAA;QACf,YAAY,EAAE,MAAM,CAAA;QACpB,UAAU,EAAE,MAAM,CAAA;QAClB,UAAU,CAAC,EAAE,KAAK,CAAA;KACnB;IAQD,OAAO,KAAK,KAAK,GAEhB;IAED;;;;;;OAMG;IACG,GAAG,IAAI,OAAO,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAUxC;;;;;OAKG;IACG,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAUvC;;;;;OAKG;IACG,QAAQ,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAa5C;;;;;;;;;;;;;;;OAeG;IACG,GAAG,CACP,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,UAAU,EAC9B,OAAO,GAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAO,GACrC,OAAO,CAAC,IAAI,CAAC;IAehB;;;;OAIG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAS7B,OAAO,KAAK,SAAS,GAEpB;IAED;;;;;;;OAOG;IACG,IAAI,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAU9C;;;;;;;;;;OAUG;IACG,OAAO,CAAC,IAAI,GAAE;QAAE,MAAM,CAAC,EAAE,sBAAsB,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAS5E;;;;;;OAMG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK1C;;;;;;OAMG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAK1D,OAAO,KAAK,WAAW,GAEtB;IAED;;;;;;OAMG;IACG,SAAS,IAAI,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAUjD;;;;;OAKG;IACG,SAAS,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAStD;;;;;OAKG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAIhC;;;;OAIG;IACG,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IAKlC;;;;;OAKG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;CAQnC"}
|
package/dist/Resource.js
CHANGED
|
@@ -88,6 +88,12 @@ export class Resource {
|
|
|
88
88
|
* objects/arrays, binary for `Blob`/`Uint8Array`. Throws `NotFoundError` if
|
|
89
89
|
* the parent collection does not exist (WAS does not auto-create parents).
|
|
90
90
|
*
|
|
91
|
+
* For binary data with no explicit `contentType` (and no `Blob.type`), the
|
|
92
|
+
* content-type is guessed from the resource id's file extension for common
|
|
93
|
+
* static-web types -- so `resource('index.html').put(bytes)` is sent as
|
|
94
|
+
* `text/html`. An unrecognized/absent extension sends no content-type, and the
|
|
95
|
+
* server applies its own required-`Content-Type` rule.
|
|
96
|
+
*
|
|
91
97
|
* @param data {Json | Blob | Uint8Array}
|
|
92
98
|
* @param options {object}
|
|
93
99
|
* @param [options.contentType] {string} content-type for binary data
|
|
@@ -95,7 +101,7 @@ export class Resource {
|
|
|
95
101
|
*/
|
|
96
102
|
async put(data, options = {}) {
|
|
97
103
|
assertNotReserved(this.id, 'resource');
|
|
98
|
-
const prepared = prepareBody(data, options);
|
|
104
|
+
const prepared = prepareBody(data, { ...options, filename: this.id });
|
|
99
105
|
await send(this._context, {
|
|
100
106
|
path: this._path,
|
|
101
107
|
method: 'PUT',
|
package/dist/Resource.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Resource.js","sourceRoot":"","sources":["../src/Resource.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;GAIG;AACH,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAChF,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAE1D,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAA;AAS5C,MAAM,OAAO,QAAQ;IACV,OAAO,CAAQ;IACf,YAAY,CAAQ;IACpB,EAAE,CAAQ;IAEF,QAAQ,CAAe;IACvB,WAAW,CAAQ;IAEpC;;;;;;;OAOG;IACH,YAAY,EACV,OAAO,EACP,OAAO,EACP,YAAY,EACZ,UAAU,EACV,UAAU,EAOX;QACC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAA;QACvB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAA;QAChC,IAAI,CAAC,EAAE,GAAG,UAAU,CAAA;QACpB,IAAI,CAAC,WAAW,GAAG,UAAU,CAAA;IAC/B,CAAC;IAED,IAAY,KAAK;QACf,OAAO,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,EAAE,CAAC,CAAA;IAC/D,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,GAAG;QACP,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YACzC,IAAI,EAAE,IAAI,CAAC,KAAK;YAChB,MAAM,EAAE,KAAK;YACb,UAAU,EAAE,IAAI,CAAC,WAAW;YAC5B,IAAI,EAAE,IAAI;SACX,CAAC,CAAA;QACF,OAAO,aAAa,CAAC,QAAQ,CAAC,CAAA;IAChC,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,OAAO;QACX,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YACzC,IAAI,EAAE,IAAI,CAAC,KAAK;YAChB,MAAM,EAAE,KAAK;YACb,UAAU,EAAE,IAAI,CAAC,WAAW;YAC5B,IAAI,EAAE,IAAI;SACX,CAAC,CAAA;QACF,OAAO,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAA;IACnD,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,QAAQ;QACZ,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YACzC,IAAI,EAAE,IAAI,CAAC,KAAK;YAChB,MAAM,EAAE,KAAK;YACb,UAAU,EAAE,IAAI,CAAC,WAAW;YAC5B,IAAI,EAAE,IAAI;SACX,CAAC,CAAA;QACF,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YACtB,OAAO,IAAI,CAAA;QACb,CAAC;QACD,OAAO,IAAI,UAAU,CAAC,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAA;IACrD,CAAC;IAED
|
|
1
|
+
{"version":3,"file":"Resource.js","sourceRoot":"","sources":["../src/Resource.ts"],"names":[],"mappings":"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"}
|
package/dist/WasClient.js
CHANGED
|
@@ -13,7 +13,7 @@ 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 } from './internal/content.js';
|
|
16
|
+
import { parseResource, readJsonData } from './internal/content.js';
|
|
17
17
|
import { delegateGrant } from './internal/grant.js';
|
|
18
18
|
import { ValidationError } from './errors.js';
|
|
19
19
|
import { Space } from './Space.js';
|
|
@@ -166,7 +166,7 @@ export class WasClient {
|
|
|
166
166
|
if (response === null) {
|
|
167
167
|
return null;
|
|
168
168
|
}
|
|
169
|
-
return (
|
|
169
|
+
return (await readJsonData(response));
|
|
170
170
|
}
|
|
171
171
|
/**
|
|
172
172
|
* Rebuilds an access handle from a received capability, returning a handle at
|
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,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"WasClient.js","sourceRoot":"","sources":["../src/WasClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* An `@interop/edv-client` `Transport` that maps Encrypted Data Vault (EDV)
|
|
6
|
+
* document operations onto ordinary WAS Resource CRUD -- the "EDV-over-WAS"
|
|
7
|
+
* layout profile (Layer 1). It is paired with `EdvClientCore`, which does all
|
|
8
|
+
* encryption, decryption, and index blinding client-side; this transport only
|
|
9
|
+
* moves opaque JWE documents to and from a WAS server, reusing the client's
|
|
10
|
+
* zcap-signed request layer (`WasClient.request()`). Keys never reach the
|
|
11
|
+
* server.
|
|
12
|
+
*
|
|
13
|
+
* Profile decisions encoded here:
|
|
14
|
+
*
|
|
15
|
+
* - **Vault per Collection.** The WAS Collection is the EDV vault; each
|
|
16
|
+
* encrypted document is one WAS Resource.
|
|
17
|
+
* - **Restrict-mode ids.** The WAS resource id IS the EDV document id (the
|
|
18
|
+
* 128-bit multibase value `EdvClientCore.generateId()` produces), which is
|
|
19
|
+
* URL-safe and never a reserved segment.
|
|
20
|
+
* - **Encrypted content type.** Documents are stored as `application/json` by
|
|
21
|
+
* default, so the profile works against an unmodified WAS server. The
|
|
22
|
+
* preferred marker is `application/edv+json` (exported as `EDV_CONTENT_TYPE`),
|
|
23
|
+
* which distinguishes EDV envelopes from plaintext application JSON in
|
|
24
|
+
* listings and metadata -- but the server must register an `application/*+json`
|
|
25
|
+
* content-type parser to accept it (the reference was-teaching-server does; a
|
|
26
|
+
* server that does not will reject it with 415). Pass `contentType:
|
|
27
|
+
* EDV_CONTENT_TYPE` to opt into it where the server supports it.
|
|
28
|
+
*
|
|
29
|
+
* Scope: documents only (`insert` / `update` / `get`). Blinded `find` / `count`
|
|
30
|
+
* / `updateIndex` and chunked streams (`storeChunk` / `getChunk`) require
|
|
31
|
+
* server-side EDV affordances (blinded `/query`, the `/{id}/chunks/{n}`
|
|
32
|
+
* sub-segment, conditional writes) that a plaintext WAS server does not yet
|
|
33
|
+
* provide, so they throw here. Because there are no conditional writes, the EDV
|
|
34
|
+
* `sequence` is advisory (last-writer-wins on `update`).
|
|
35
|
+
*/
|
|
36
|
+
import { Transport } from '@interop/edv-client';
|
|
37
|
+
import type { IEncryptedDocument } from '@interop/data-integrity-core';
|
|
38
|
+
import type { WasClient } from '../WasClient.js';
|
|
39
|
+
/**
|
|
40
|
+
* The preferred content type marking a stored EDV-encrypted document (a JSON
|
|
41
|
+
* envelope whose `jwe` property carries the ciphertext). Requires the server to
|
|
42
|
+
* register an `application/*+json` content-type parser; otherwise use the
|
|
43
|
+
* default `application/json` (see `WasTransport`'s `contentType` option).
|
|
44
|
+
*/
|
|
45
|
+
export declare const EDV_CONTENT_TYPE = "application/edv+json";
|
|
46
|
+
/**
|
|
47
|
+
* The subset of `WasClient` this transport depends on: the signed-request
|
|
48
|
+
* escape hatch. Declared structurally so tests can supply a lightweight stub.
|
|
49
|
+
*/
|
|
50
|
+
type WasRequester = Pick<WasClient, 'request'>;
|
|
51
|
+
export declare class WasTransport extends Transport {
|
|
52
|
+
readonly spaceId: string;
|
|
53
|
+
readonly collectionId: string;
|
|
54
|
+
readonly contentType: string;
|
|
55
|
+
private readonly _was;
|
|
56
|
+
/**
|
|
57
|
+
* @param options {object}
|
|
58
|
+
* @param options.was {WasClient} a WAS client holding the signer
|
|
59
|
+
* @param options.spaceId {string} the vault's Space id
|
|
60
|
+
* @param options.collectionId {string} the vault Collection id
|
|
61
|
+
* @param [options.contentType] {string} content type for stored envelopes;
|
|
62
|
+
* defaults to `application/json` (accepted by an unmodified server). Pass
|
|
63
|
+
* `EDV_CONTENT_TYPE` against a server that registers an `application/*+json`
|
|
64
|
+
* parser.
|
|
65
|
+
*/
|
|
66
|
+
constructor({ was, spaceId, collectionId, contentType }: {
|
|
67
|
+
was: WasRequester;
|
|
68
|
+
spaceId: string;
|
|
69
|
+
collectionId: string;
|
|
70
|
+
contentType?: string;
|
|
71
|
+
});
|
|
72
|
+
/**
|
|
73
|
+
* The WAS resource path for a document id, delegating to was-client's
|
|
74
|
+
* internal `resourcePath` builder so the percent-encoding and trailing-slash
|
|
75
|
+
* rules stay defined in one place (no trailing slash -- get/put/delete by
|
|
76
|
+
* id).
|
|
77
|
+
*
|
|
78
|
+
* @param id {string} the EDV document id (= WAS resource id)
|
|
79
|
+
* @returns {string}
|
|
80
|
+
*/
|
|
81
|
+
private _resourcePath;
|
|
82
|
+
/**
|
|
83
|
+
* Writes an encrypted document to its WAS resource path as
|
|
84
|
+
* `application/edv+json` (the envelope serialized to bytes so the stored
|
|
85
|
+
* content type is exact).
|
|
86
|
+
*
|
|
87
|
+
* @param id {string}
|
|
88
|
+
* @param encrypted {IEncryptedDocument}
|
|
89
|
+
* @returns {Promise<HttpResponse>}
|
|
90
|
+
*/
|
|
91
|
+
private _put;
|
|
92
|
+
/**
|
|
93
|
+
* @inheritdoc
|
|
94
|
+
*
|
|
95
|
+
* Inserts a new encrypted document. WAS `PUT` is an upsert, so to preserve
|
|
96
|
+
* EDV insert semantics (`DuplicateError` if the id already exists) this first
|
|
97
|
+
* checks for an existing resource. The check + write is not atomic -- with no
|
|
98
|
+
* server-side conditional writes yet, this is an advisory, single-writer
|
|
99
|
+
* guard.
|
|
100
|
+
*
|
|
101
|
+
* @param options {object}
|
|
102
|
+
* @param options.encrypted {IEncryptedDocument} the document to insert
|
|
103
|
+
* @returns {Promise<void>}
|
|
104
|
+
*/
|
|
105
|
+
insert({ encrypted }?: {
|
|
106
|
+
encrypted?: IEncryptedDocument;
|
|
107
|
+
}): Promise<void>;
|
|
108
|
+
/**
|
|
109
|
+
* @inheritdoc
|
|
110
|
+
*
|
|
111
|
+
* Updates (upserts) an encrypted document. The EDV `sequence` is advisory
|
|
112
|
+
* here -- without server-side conditional writes, a stale write is not
|
|
113
|
+
* rejected (last-writer-wins).
|
|
114
|
+
*
|
|
115
|
+
* @param options {object}
|
|
116
|
+
* @param options.encrypted {IEncryptedDocument} the document to update
|
|
117
|
+
* @returns {Promise<void>}
|
|
118
|
+
*/
|
|
119
|
+
update({ encrypted }?: {
|
|
120
|
+
encrypted?: IEncryptedDocument;
|
|
121
|
+
}): Promise<void>;
|
|
122
|
+
/**
|
|
123
|
+
* @inheritdoc
|
|
124
|
+
*
|
|
125
|
+
* Reads an encrypted document by id. Throws a `NotFoundError` (the name
|
|
126
|
+
* `EdvClientCore` expects) when the resource is missing or not visible.
|
|
127
|
+
*
|
|
128
|
+
* @param options {object}
|
|
129
|
+
* @param options.id {string} the document id to read
|
|
130
|
+
* @returns {Promise<IEncryptedDocument>}
|
|
131
|
+
*/
|
|
132
|
+
get({ id }?: {
|
|
133
|
+
id?: string;
|
|
134
|
+
}): Promise<IEncryptedDocument>;
|
|
135
|
+
/**
|
|
136
|
+
* Resolves to `true` if a resource exists at the document's path. A 404
|
|
137
|
+
* resolves to `false`; any other error propagates.
|
|
138
|
+
*
|
|
139
|
+
* @param id {string}
|
|
140
|
+
* @returns {Promise<boolean>}
|
|
141
|
+
*/
|
|
142
|
+
private _exists;
|
|
143
|
+
/**
|
|
144
|
+
* @inheritdoc
|
|
145
|
+
*
|
|
146
|
+
* Blinded-index query is not part of the documents-only EDV-over-WAS profile;
|
|
147
|
+
* it needs the server's `/query` affordance.
|
|
148
|
+
*/
|
|
149
|
+
find(): Promise<never>;
|
|
150
|
+
/**
|
|
151
|
+
* @inheritdoc
|
|
152
|
+
*
|
|
153
|
+
* Index updates need the server's `/{id}/index` affordance.
|
|
154
|
+
*/
|
|
155
|
+
updateIndex(): Promise<never>;
|
|
156
|
+
/**
|
|
157
|
+
* @inheritdoc
|
|
158
|
+
*
|
|
159
|
+
* Chunked streams need the reserved `/{id}/chunks/{n}` sub-segment.
|
|
160
|
+
*/
|
|
161
|
+
storeChunk(): Promise<never>;
|
|
162
|
+
/**
|
|
163
|
+
* @inheritdoc
|
|
164
|
+
*
|
|
165
|
+
* Chunked streams need the reserved `/{id}/chunks/{n}` sub-segment.
|
|
166
|
+
*/
|
|
167
|
+
getChunk(): Promise<never>;
|
|
168
|
+
/**
|
|
169
|
+
* Throws a uniform "not supported in this profile" error for EDV operations
|
|
170
|
+
* that depend on server-side affordances absent from a plaintext WAS server.
|
|
171
|
+
*
|
|
172
|
+
* @param operation {string}
|
|
173
|
+
* @returns {never}
|
|
174
|
+
*/
|
|
175
|
+
private _unsupported;
|
|
176
|
+
}
|
|
177
|
+
export {};
|
|
178
|
+
//# sourceMappingURL=WasTransport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WasTransport.d.ts","sourceRoot":"","sources":["../../src/edv/WasTransport.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAE/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAA;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAKhD;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,yBAAyB,CAAA;AAQtD;;;GAGG;AACH,KAAK,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;AAoC9C,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;IAEnC;;;;;;;;;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;IAQD;;;;;;;;OAQG;IACH,OAAO,CAAC,aAAa;IAIrB;;;;;;;;OAQG;YACW,IAAI;IAalB;;;;;;;;;;;;OAYG;IACY,MAAM,CAAC,EACpB,SAAS,EACV,GAAE;QAAE,SAAS,CAAC,EAAE,kBAAkB,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAa1D;;;;;;;;;;OAUG;IACY,MAAM,CAAC,EACpB,SAAS,EACV,GAAE;QAAE,SAAS,CAAC,EAAE,kBAAkB,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB1D;;;;;;;;;OASG;IACY,GAAG,CAAC,EACjB,EAAE,EACH,GAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAuBrD;;;;;;OAMG;YACW,OAAO;IAYrB;;;;;OAKG;IACY,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC;IAIrC;;;;OAIG;IACY,WAAW,IAAI,OAAO,CAAC,KAAK,CAAC;IAI5C;;;;OAIG;IACY,UAAU,IAAI,OAAO,CAAC,KAAK,CAAC;IAI3C;;;;OAIG;IACY,QAAQ,IAAI,OAAO,CAAC,KAAK,CAAC;IAIzC;;;;;;OAMG;IACH,OAAO,CAAC,YAAY;CAQrB"}
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* An `@interop/edv-client` `Transport` that maps Encrypted Data Vault (EDV)
|
|
6
|
+
* document operations onto ordinary WAS Resource CRUD -- the "EDV-over-WAS"
|
|
7
|
+
* layout profile (Layer 1). It is paired with `EdvClientCore`, which does all
|
|
8
|
+
* encryption, decryption, and index blinding client-side; this transport only
|
|
9
|
+
* moves opaque JWE documents to and from a WAS server, reusing the client's
|
|
10
|
+
* zcap-signed request layer (`WasClient.request()`). Keys never reach the
|
|
11
|
+
* server.
|
|
12
|
+
*
|
|
13
|
+
* Profile decisions encoded here:
|
|
14
|
+
*
|
|
15
|
+
* - **Vault per Collection.** The WAS Collection is the EDV vault; each
|
|
16
|
+
* encrypted document is one WAS Resource.
|
|
17
|
+
* - **Restrict-mode ids.** The WAS resource id IS the EDV document id (the
|
|
18
|
+
* 128-bit multibase value `EdvClientCore.generateId()` produces), which is
|
|
19
|
+
* URL-safe and never a reserved segment.
|
|
20
|
+
* - **Encrypted content type.** Documents are stored as `application/json` by
|
|
21
|
+
* default, so the profile works against an unmodified WAS server. The
|
|
22
|
+
* preferred marker is `application/edv+json` (exported as `EDV_CONTENT_TYPE`),
|
|
23
|
+
* which distinguishes EDV envelopes from plaintext application JSON in
|
|
24
|
+
* listings and metadata -- but the server must register an `application/*+json`
|
|
25
|
+
* content-type parser to accept it (the reference was-teaching-server does; a
|
|
26
|
+
* server that does not will reject it with 415). Pass `contentType:
|
|
27
|
+
* EDV_CONTENT_TYPE` to opt into it where the server supports it.
|
|
28
|
+
*
|
|
29
|
+
* Scope: documents only (`insert` / `update` / `get`). Blinded `find` / `count`
|
|
30
|
+
* / `updateIndex` and chunked streams (`storeChunk` / `getChunk`) require
|
|
31
|
+
* server-side EDV affordances (blinded `/query`, the `/{id}/chunks/{n}`
|
|
32
|
+
* sub-segment, conditional writes) that a plaintext WAS server does not yet
|
|
33
|
+
* provide, so they throw here. Because there are no conditional writes, the EDV
|
|
34
|
+
* `sequence` is advisory (last-writer-wins on `update`).
|
|
35
|
+
*/
|
|
36
|
+
import { Transport } from '@interop/edv-client';
|
|
37
|
+
import { httpStatus } from '../errors.js';
|
|
38
|
+
import { readJsonData } from '../internal/content.js';
|
|
39
|
+
import { resourcePath } from '../internal/paths.js';
|
|
40
|
+
/**
|
|
41
|
+
* The preferred content type marking a stored EDV-encrypted document (a JSON
|
|
42
|
+
* envelope whose `jwe` property carries the ciphertext). Requires the server to
|
|
43
|
+
* register an `application/*+json` content-type parser; otherwise use the
|
|
44
|
+
* default `application/json` (see `WasTransport`'s `contentType` option).
|
|
45
|
+
*/
|
|
46
|
+
export const EDV_CONTENT_TYPE = 'application/edv+json';
|
|
47
|
+
/**
|
|
48
|
+
* The content type used by default: plain JSON, which an unmodified WAS server
|
|
49
|
+
* accepts. The stored envelope is still self-identifying by its `jwe` field.
|
|
50
|
+
*/
|
|
51
|
+
const DEFAULT_CONTENT_TYPE = 'application/json';
|
|
52
|
+
/**
|
|
53
|
+
* A shared `TextEncoder` for serializing envelope bytes (stateless, so one
|
|
54
|
+
* instance is reused across every `_put`).
|
|
55
|
+
*/
|
|
56
|
+
const ENCODER = new TextEncoder();
|
|
57
|
+
/**
|
|
58
|
+
* Builds an `Error` carrying the `name` that `EdvClientCore` (and the reference
|
|
59
|
+
* `HttpsTransport`) dispatch on -- `DuplicateError`, `InvalidStateError`,
|
|
60
|
+
* `NotFoundError`.
|
|
61
|
+
*
|
|
62
|
+
* @param options {object}
|
|
63
|
+
* @param options.name {string} the error name to set
|
|
64
|
+
* @param options.message {string} the human-readable message
|
|
65
|
+
* @param [options.cause] {unknown} the underlying error, if any
|
|
66
|
+
* @returns {Error}
|
|
67
|
+
*/
|
|
68
|
+
function namedError({ name, message, cause }) {
|
|
69
|
+
const err = new Error(message);
|
|
70
|
+
err.name = name;
|
|
71
|
+
if (cause !== undefined) {
|
|
72
|
+
err.cause = cause;
|
|
73
|
+
}
|
|
74
|
+
return err;
|
|
75
|
+
}
|
|
76
|
+
export class WasTransport extends Transport {
|
|
77
|
+
spaceId;
|
|
78
|
+
collectionId;
|
|
79
|
+
contentType;
|
|
80
|
+
_was;
|
|
81
|
+
/**
|
|
82
|
+
* @param options {object}
|
|
83
|
+
* @param options.was {WasClient} a WAS client holding the signer
|
|
84
|
+
* @param options.spaceId {string} the vault's Space id
|
|
85
|
+
* @param options.collectionId {string} the vault Collection id
|
|
86
|
+
* @param [options.contentType] {string} content type for stored envelopes;
|
|
87
|
+
* defaults to `application/json` (accepted by an unmodified server). Pass
|
|
88
|
+
* `EDV_CONTENT_TYPE` against a server that registers an `application/*+json`
|
|
89
|
+
* parser.
|
|
90
|
+
*/
|
|
91
|
+
constructor({ was, spaceId, collectionId, contentType = DEFAULT_CONTENT_TYPE }) {
|
|
92
|
+
super();
|
|
93
|
+
this._was = was;
|
|
94
|
+
this.spaceId = spaceId;
|
|
95
|
+
this.collectionId = collectionId;
|
|
96
|
+
this.contentType = contentType;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* The WAS resource path for a document id, delegating to was-client's
|
|
100
|
+
* internal `resourcePath` builder so the percent-encoding and trailing-slash
|
|
101
|
+
* rules stay defined in one place (no trailing slash -- get/put/delete by
|
|
102
|
+
* id).
|
|
103
|
+
*
|
|
104
|
+
* @param id {string} the EDV document id (= WAS resource id)
|
|
105
|
+
* @returns {string}
|
|
106
|
+
*/
|
|
107
|
+
_resourcePath(id) {
|
|
108
|
+
return resourcePath(this.spaceId, this.collectionId, id);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Writes an encrypted document to its WAS resource path as
|
|
112
|
+
* `application/edv+json` (the envelope serialized to bytes so the stored
|
|
113
|
+
* content type is exact).
|
|
114
|
+
*
|
|
115
|
+
* @param id {string}
|
|
116
|
+
* @param encrypted {IEncryptedDocument}
|
|
117
|
+
* @returns {Promise<HttpResponse>}
|
|
118
|
+
*/
|
|
119
|
+
async _put(id, encrypted) {
|
|
120
|
+
const body = ENCODER.encode(JSON.stringify(encrypted));
|
|
121
|
+
return this._was.request({
|
|
122
|
+
path: this._resourcePath(id),
|
|
123
|
+
method: 'PUT',
|
|
124
|
+
body,
|
|
125
|
+
headers: { 'content-type': this.contentType }
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* @inheritdoc
|
|
130
|
+
*
|
|
131
|
+
* Inserts a new encrypted document. WAS `PUT` is an upsert, so to preserve
|
|
132
|
+
* EDV insert semantics (`DuplicateError` if the id already exists) this first
|
|
133
|
+
* checks for an existing resource. The check + write is not atomic -- with no
|
|
134
|
+
* server-side conditional writes yet, this is an advisory, single-writer
|
|
135
|
+
* guard.
|
|
136
|
+
*
|
|
137
|
+
* @param options {object}
|
|
138
|
+
* @param options.encrypted {IEncryptedDocument} the document to insert
|
|
139
|
+
* @returns {Promise<void>}
|
|
140
|
+
*/
|
|
141
|
+
async insert({ encrypted } = {}) {
|
|
142
|
+
if (!encrypted) {
|
|
143
|
+
throw new TypeError('"encrypted" is required.');
|
|
144
|
+
}
|
|
145
|
+
if (await this._exists(encrypted.id)) {
|
|
146
|
+
throw namedError({
|
|
147
|
+
name: 'DuplicateError',
|
|
148
|
+
message: `A document with id "${encrypted.id}" already exists.`
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
await this._put(encrypted.id, encrypted);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* @inheritdoc
|
|
155
|
+
*
|
|
156
|
+
* Updates (upserts) an encrypted document. The EDV `sequence` is advisory
|
|
157
|
+
* here -- without server-side conditional writes, a stale write is not
|
|
158
|
+
* rejected (last-writer-wins).
|
|
159
|
+
*
|
|
160
|
+
* @param options {object}
|
|
161
|
+
* @param options.encrypted {IEncryptedDocument} the document to update
|
|
162
|
+
* @returns {Promise<void>}
|
|
163
|
+
*/
|
|
164
|
+
async update({ encrypted } = {}) {
|
|
165
|
+
if (!encrypted) {
|
|
166
|
+
throw new TypeError('"encrypted" is required.');
|
|
167
|
+
}
|
|
168
|
+
try {
|
|
169
|
+
await this._put(encrypted.id, encrypted);
|
|
170
|
+
}
|
|
171
|
+
catch (err) {
|
|
172
|
+
// A server that DOES enforce conditional writes signals a stale update
|
|
173
|
+
// with 409; surface it the way `EdvClientCore` expects.
|
|
174
|
+
if (httpStatus(err) === 409) {
|
|
175
|
+
throw namedError({
|
|
176
|
+
name: 'InvalidStateError',
|
|
177
|
+
message: 'Conflict error.',
|
|
178
|
+
cause: err
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
throw err;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* @inheritdoc
|
|
186
|
+
*
|
|
187
|
+
* Reads an encrypted document by id. Throws a `NotFoundError` (the name
|
|
188
|
+
* `EdvClientCore` expects) when the resource is missing or not visible.
|
|
189
|
+
*
|
|
190
|
+
* @param options {object}
|
|
191
|
+
* @param options.id {string} the document id to read
|
|
192
|
+
* @returns {Promise<IEncryptedDocument>}
|
|
193
|
+
*/
|
|
194
|
+
async get({ id } = {}) {
|
|
195
|
+
if (!id) {
|
|
196
|
+
throw new TypeError('"id" is required.');
|
|
197
|
+
}
|
|
198
|
+
let response;
|
|
199
|
+
try {
|
|
200
|
+
response = await this._was.request({
|
|
201
|
+
path: this._resourcePath(id),
|
|
202
|
+
method: 'GET'
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
catch (err) {
|
|
206
|
+
if (httpStatus(err) === 404) {
|
|
207
|
+
throw namedError({
|
|
208
|
+
name: 'NotFoundError',
|
|
209
|
+
message: 'Document not found.',
|
|
210
|
+
cause: err
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
throw err;
|
|
214
|
+
}
|
|
215
|
+
return (await readJsonData(response));
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Resolves to `true` if a resource exists at the document's path. A 404
|
|
219
|
+
* resolves to `false`; any other error propagates.
|
|
220
|
+
*
|
|
221
|
+
* @param id {string}
|
|
222
|
+
* @returns {Promise<boolean>}
|
|
223
|
+
*/
|
|
224
|
+
async _exists(id) {
|
|
225
|
+
try {
|
|
226
|
+
await this._was.request({ path: this._resourcePath(id), method: 'GET' });
|
|
227
|
+
return true;
|
|
228
|
+
}
|
|
229
|
+
catch (err) {
|
|
230
|
+
if (httpStatus(err) === 404) {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
throw err;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* @inheritdoc
|
|
238
|
+
*
|
|
239
|
+
* Blinded-index query is not part of the documents-only EDV-over-WAS profile;
|
|
240
|
+
* it needs the server's `/query` affordance.
|
|
241
|
+
*/
|
|
242
|
+
async find() {
|
|
243
|
+
return this._unsupported('find (blinded-index query)');
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* @inheritdoc
|
|
247
|
+
*
|
|
248
|
+
* Index updates need the server's `/{id}/index` affordance.
|
|
249
|
+
*/
|
|
250
|
+
async updateIndex() {
|
|
251
|
+
return this._unsupported('updateIndex');
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* @inheritdoc
|
|
255
|
+
*
|
|
256
|
+
* Chunked streams need the reserved `/{id}/chunks/{n}` sub-segment.
|
|
257
|
+
*/
|
|
258
|
+
async storeChunk() {
|
|
259
|
+
return this._unsupported('storeChunk (chunked streams)');
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* @inheritdoc
|
|
263
|
+
*
|
|
264
|
+
* Chunked streams need the reserved `/{id}/chunks/{n}` sub-segment.
|
|
265
|
+
*/
|
|
266
|
+
async getChunk() {
|
|
267
|
+
return this._unsupported('getChunk (chunked streams)');
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Throws a uniform "not supported in this profile" error for EDV operations
|
|
271
|
+
* that depend on server-side affordances absent from a plaintext WAS server.
|
|
272
|
+
*
|
|
273
|
+
* @param operation {string}
|
|
274
|
+
* @returns {never}
|
|
275
|
+
*/
|
|
276
|
+
_unsupported(operation) {
|
|
277
|
+
throw namedError({
|
|
278
|
+
name: 'NotSupportedError',
|
|
279
|
+
message: `"${operation}" is not supported by the documents-only ` +
|
|
280
|
+
'EDV-over-WAS profile (requires server-side EDV affordances).'
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
//# sourceMappingURL=WasTransport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WasTransport.js","sourceRoot":"","sources":["../../src/edv/WasTransport.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The `@interop/was-client/edv` subpath entry: encrypted (EDV-over-WAS) storage
|
|
6
|
+
* support. Kept off the core `@interop/was-client` entry so plaintext consumers
|
|
7
|
+
* do not pull the `@interop/edv-client` / `@interop/minimal-cipher` crypto graph
|
|
8
|
+
* unless they opt in by importing this subpath.
|
|
9
|
+
*/
|
|
10
|
+
export { WasTransport, EDV_CONTENT_TYPE } from './WasTransport.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/edv/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;GAKG;AACH,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The `@interop/was-client/edv` subpath entry: encrypted (EDV-over-WAS) storage
|
|
6
|
+
* support. Kept off the core `@interop/was-client` entry so plaintext consumers
|
|
7
|
+
* do not pull the `@interop/edv-client` / `@interop/minimal-cipher` crypto graph
|
|
8
|
+
* unless they opt in by importing this subpath.
|
|
9
|
+
*/
|
|
10
|
+
export { WasTransport, EDV_CONTENT_TYPE } from './WasTransport.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/edv/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;GAKG;AACH,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA"}
|
package/dist/errors.d.ts
CHANGED
|
@@ -83,6 +83,14 @@ export declare class QuotaExceededError extends WasError {
|
|
|
83
83
|
export declare class WasServerError extends WasError {
|
|
84
84
|
constructor(message: string, options?: WasErrorOptions);
|
|
85
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Reads the HTTP status from a raw ky/ezcap error, checking both the flat
|
|
88
|
+
* `status` and the nested `response.status` shapes.
|
|
89
|
+
*
|
|
90
|
+
* @param err {unknown} the caught error
|
|
91
|
+
* @returns {number | undefined}
|
|
92
|
+
*/
|
|
93
|
+
export declare function httpStatus(err: unknown): number | undefined;
|
|
86
94
|
/**
|
|
87
95
|
* Translates a thrown ky/ezcap error into the appropriate `WasError` subclass,
|
|
88
96
|
* carrying through the server's `problem+json` fields. Dispatches on the
|
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAWA;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED;;GAEG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;gBAEP,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB;CAU3D;AAED;;;;GAIG;AACH,qBAAa,aAAc,SAAQ,QAAQ;gBAC7B,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB;CAI3D;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,QAAQ;gBAC/B,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB;CAI3D;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,QAAQ;gBACjC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB;CAI3D;AAED;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,QAAQ;gBACnC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB;CAI3D;AAED;;;;;GAKG;AACH,qBAAa,aAAc,SAAQ,QAAQ;gBAC7B,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB;CAI3D;AAED;;;;GAIG;AACH,qBAAa,oBAAqB,SAAQ,QAAQ;gBACpC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB;CAI3D;AAED;;;;GAIG;AACH,qBAAa,kBAAmB,SAAQ,QAAQ;gBAClC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB;CAI3D;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,QAAQ;gBAC9B,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB;CAI3D;AA6ED;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ,CA6C/C"}
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAWA;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED;;GAEG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;gBAEP,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB;CAU3D;AAED;;;;GAIG;AACH,qBAAa,aAAc,SAAQ,QAAQ;gBAC7B,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB;CAI3D;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,QAAQ;gBAC/B,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB;CAI3D;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,QAAQ;gBACjC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB;CAI3D;AAED;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,QAAQ;gBACnC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB;CAI3D;AAED;;;;;GAKG;AACH,qBAAa,aAAc,SAAQ,QAAQ;gBAC7B,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB;CAI3D;AAED;;;;GAIG;AACH,qBAAa,oBAAqB,SAAQ,QAAQ;gBACpC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB;CAI3D;AAED;;;;GAIG;AACH,qBAAa,kBAAmB,SAAQ,QAAQ;gBAClC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB;CAI3D;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,QAAQ;gBAC9B,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB;CAI3D;AA6ED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAG3D;AAED;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ,CA6C/C"}
|
package/dist/errors.js
CHANGED
|
@@ -157,6 +157,17 @@ function errorForKind(kind, message, options) {
|
|
|
157
157
|
const ErrorClass = kind === undefined ? undefined : ERROR_CLASS_BY_KIND[kind];
|
|
158
158
|
return ErrorClass ? new ErrorClass(message, options) : null;
|
|
159
159
|
}
|
|
160
|
+
/**
|
|
161
|
+
* Reads the HTTP status from a raw ky/ezcap error, checking both the flat
|
|
162
|
+
* `status` and the nested `response.status` shapes.
|
|
163
|
+
*
|
|
164
|
+
* @param err {unknown} the caught error
|
|
165
|
+
* @returns {number | undefined}
|
|
166
|
+
*/
|
|
167
|
+
export function httpStatus(err) {
|
|
168
|
+
const raw = err;
|
|
169
|
+
return raw?.status ?? raw?.response?.status;
|
|
170
|
+
}
|
|
160
171
|
/**
|
|
161
172
|
* Translates a thrown ky/ezcap error into the appropriate `WasError` subclass,
|
|
162
173
|
* carrying through the server's `problem+json` fields. Dispatches on the
|
|
@@ -171,7 +182,7 @@ export function mapError(err) {
|
|
|
171
182
|
return err;
|
|
172
183
|
}
|
|
173
184
|
const httpError = (err ?? {});
|
|
174
|
-
const status = httpError
|
|
185
|
+
const status = httpStatus(httpError);
|
|
175
186
|
const data = httpError.data;
|
|
176
187
|
const type = data?.type;
|
|
177
188
|
const title = data?.title;
|
package/dist/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,11 +5,23 @@
|
|
|
5
5
|
* JSON-vs-binary detection and body coercion for resource writes, plus
|
|
6
6
|
* content-type-aware parsing for resource reads. A plain object/array is sent
|
|
7
7
|
* as JSON; a `Blob`/`Uint8Array`/`Buffer` is sent as binary, with the
|
|
8
|
-
* content-type taken from `options.contentType`, the `Blob.type`,
|
|
8
|
+
* content-type taken from `options.contentType`, the `Blob.type`, a guess from
|
|
9
|
+
* the resource id's file extension (`options.filename`), or
|
|
9
10
|
* `application/octet-stream`.
|
|
10
11
|
*/
|
|
11
12
|
import type { HttpResponse } from '@interop/http-client';
|
|
12
13
|
import type { Json } from '../types.js';
|
|
14
|
+
/**
|
|
15
|
+
* Guesses a content-type from a resource id's file extension, limited to the
|
|
16
|
+
* static-web types in `WEB_CONTENT_TYPES`. Returns `undefined` when the id has
|
|
17
|
+
* no extension, is a leading-dot dotfile (e.g. `.gitignore`), or carries an
|
|
18
|
+
* unrecognized extension -- never a generic fallback, so the caller stays in
|
|
19
|
+
* control of a miss.
|
|
20
|
+
*
|
|
21
|
+
* @param id {string} the resource id (often a filename like `index.html`)
|
|
22
|
+
* @returns {string | undefined}
|
|
23
|
+
*/
|
|
24
|
+
export declare function guessContentTypeFromId(id: string): string | undefined;
|
|
13
25
|
/**
|
|
14
26
|
* A write body resolved into either a JSON payload (passed to ezcap as `json`)
|
|
15
27
|
* or a binary payload with its content-type (passed as `body` + header).
|
|
@@ -22,15 +34,32 @@ export interface PreparedBody {
|
|
|
22
34
|
/**
|
|
23
35
|
* Inspects write data and resolves it to a JSON or binary payload.
|
|
24
36
|
*
|
|
37
|
+
* The binary content-type resolves in precedence order: an explicit
|
|
38
|
+
* `options.contentType`, then a non-empty `Blob.type`, then a guess from
|
|
39
|
+
* `options.filename`'s extension, then `application/octet-stream`. (Coalescing
|
|
40
|
+
* with `||` rather than `??` so an empty-string `Blob.type` -- a typeless Blob
|
|
41
|
+
* -- falls through to the guess instead of becoming an empty content-type.)
|
|
42
|
+
*
|
|
25
43
|
* @param data {Json | Blob | Uint8Array} the resource content
|
|
26
44
|
* @param options {object}
|
|
27
45
|
* @param [options.contentType] {string} overrides the inferred content-type
|
|
28
46
|
* for binary data
|
|
47
|
+
* @param [options.filename] {string} resource id used to guess a
|
|
48
|
+
* content-type by extension when none is given (binary data only)
|
|
29
49
|
* @returns {PreparedBody}
|
|
30
50
|
*/
|
|
31
51
|
export declare function prepareBody(data: Json | Blob | Uint8Array, options?: {
|
|
32
52
|
contentType?: string;
|
|
53
|
+
filename?: string;
|
|
33
54
|
}): PreparedBody;
|
|
55
|
+
/**
|
|
56
|
+
* Reads a JSON response body, preferring the http-client's pre-parsed `data`
|
|
57
|
+
* and falling back to `response.json()` when it is absent.
|
|
58
|
+
*
|
|
59
|
+
* @param response {HttpResponse}
|
|
60
|
+
* @returns {Promise<unknown>}
|
|
61
|
+
*/
|
|
62
|
+
export declare function readJsonData(response: HttpResponse): Promise<unknown>;
|
|
34
63
|
/**
|
|
35
64
|
* Parses a resource GET response: returns the parsed object when the stored
|
|
36
65
|
* content-type is JSON, otherwise a `Blob` whose `.type` carries the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/internal/content.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH
|
|
1
|
+
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/internal/content.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAExD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AA+BvC;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAOrE;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI,CAAA;IACxB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAoBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,UAAU,EAC9B,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GACxD,YAAY,CA4Bd;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CAE3E;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,YAAY,GAAG,IAAI,GAC5B,OAAO,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,CAS7B"}
|
package/dist/internal/content.js
CHANGED
|
@@ -1,5 +1,49 @@
|
|
|
1
1
|
import { ValidationError } from '../errors.js';
|
|
2
2
|
const OCTET_STREAM = 'application/octet-stream';
|
|
3
|
+
/**
|
|
4
|
+
* Extension-to-content-type fallbacks for the common static-web file types --
|
|
5
|
+
* the only case where guessing a content-type from a resource id pays off
|
|
6
|
+
* (e.g. serving an HTML site out of a public Collection). Deliberately tiny and
|
|
7
|
+
* inline: an explicit `contentType` (or a non-empty `Blob.type`) always wins,
|
|
8
|
+
* and an unknown extension yields no guess -- so this never needs the breadth
|
|
9
|
+
* (or the `mime-db`-sized weight) of a full media-type library. `.js`/`.mjs`
|
|
10
|
+
* are pinned to `text/javascript` (the WHATWG-preferred form).
|
|
11
|
+
*/
|
|
12
|
+
const WEB_CONTENT_TYPES = {
|
|
13
|
+
html: 'text/html',
|
|
14
|
+
css: 'text/css',
|
|
15
|
+
js: 'text/javascript',
|
|
16
|
+
mjs: 'text/javascript',
|
|
17
|
+
json: 'application/json',
|
|
18
|
+
svg: 'image/svg+xml',
|
|
19
|
+
png: 'image/png',
|
|
20
|
+
jpg: 'image/jpeg',
|
|
21
|
+
jpeg: 'image/jpeg',
|
|
22
|
+
gif: 'image/gif',
|
|
23
|
+
webp: 'image/webp',
|
|
24
|
+
ico: 'image/x-icon',
|
|
25
|
+
woff2: 'font/woff2',
|
|
26
|
+
txt: 'text/plain',
|
|
27
|
+
wasm: 'application/wasm'
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Guesses a content-type from a resource id's file extension, limited to the
|
|
31
|
+
* static-web types in `WEB_CONTENT_TYPES`. Returns `undefined` when the id has
|
|
32
|
+
* no extension, is a leading-dot dotfile (e.g. `.gitignore`), or carries an
|
|
33
|
+
* unrecognized extension -- never a generic fallback, so the caller stays in
|
|
34
|
+
* control of a miss.
|
|
35
|
+
*
|
|
36
|
+
* @param id {string} the resource id (often a filename like `index.html`)
|
|
37
|
+
* @returns {string | undefined}
|
|
38
|
+
*/
|
|
39
|
+
export function guessContentTypeFromId(id) {
|
|
40
|
+
const lastDot = id.lastIndexOf('.');
|
|
41
|
+
if (lastDot < 1) {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
const extension = id.slice(lastDot + 1).toLowerCase();
|
|
45
|
+
return WEB_CONTENT_TYPES[extension];
|
|
46
|
+
}
|
|
3
47
|
function isBlob(value) {
|
|
4
48
|
return typeof Blob !== 'undefined' && value instanceof Blob;
|
|
5
49
|
}
|
|
@@ -19,23 +63,34 @@ function toPlainBytes(bytes) {
|
|
|
19
63
|
/**
|
|
20
64
|
* Inspects write data and resolves it to a JSON or binary payload.
|
|
21
65
|
*
|
|
66
|
+
* The binary content-type resolves in precedence order: an explicit
|
|
67
|
+
* `options.contentType`, then a non-empty `Blob.type`, then a guess from
|
|
68
|
+
* `options.filename`'s extension, then `application/octet-stream`. (Coalescing
|
|
69
|
+
* with `||` rather than `??` so an empty-string `Blob.type` -- a typeless Blob
|
|
70
|
+
* -- falls through to the guess instead of becoming an empty content-type.)
|
|
71
|
+
*
|
|
22
72
|
* @param data {Json | Blob | Uint8Array} the resource content
|
|
23
73
|
* @param options {object}
|
|
24
74
|
* @param [options.contentType] {string} overrides the inferred content-type
|
|
25
75
|
* for binary data
|
|
76
|
+
* @param [options.filename] {string} resource id used to guess a
|
|
77
|
+
* content-type by extension when none is given (binary data only)
|
|
26
78
|
* @returns {PreparedBody}
|
|
27
79
|
*/
|
|
28
80
|
export function prepareBody(data, options = {}) {
|
|
81
|
+
const guessed = options.filename
|
|
82
|
+
? guessContentTypeFromId(options.filename)
|
|
83
|
+
: undefined;
|
|
29
84
|
if (isBlob(data)) {
|
|
30
85
|
return {
|
|
31
86
|
body: data,
|
|
32
|
-
contentType: options.contentType
|
|
87
|
+
contentType: options.contentType || data.type || guessed || OCTET_STREAM
|
|
33
88
|
};
|
|
34
89
|
}
|
|
35
90
|
if (data instanceof Uint8Array) {
|
|
36
91
|
return {
|
|
37
92
|
body: toPlainBytes(data),
|
|
38
|
-
contentType: options.contentType
|
|
93
|
+
contentType: options.contentType || guessed || OCTET_STREAM
|
|
39
94
|
};
|
|
40
95
|
}
|
|
41
96
|
if (data !== null && typeof data === 'object') {
|
|
@@ -45,6 +100,16 @@ export function prepareBody(data, options = {}) {
|
|
|
45
100
|
throw new ValidationError('Resource data must be a plain object/array (JSON) or a ' +
|
|
46
101
|
'Blob/Uint8Array (binary).');
|
|
47
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* Reads a JSON response body, preferring the http-client's pre-parsed `data`
|
|
105
|
+
* and falling back to `response.json()` when it is absent.
|
|
106
|
+
*
|
|
107
|
+
* @param response {HttpResponse}
|
|
108
|
+
* @returns {Promise<unknown>}
|
|
109
|
+
*/
|
|
110
|
+
export async function readJsonData(response) {
|
|
111
|
+
return response.data ?? (await response.json());
|
|
112
|
+
}
|
|
48
113
|
/**
|
|
49
114
|
* Parses a resource GET response: returns the parsed object when the stored
|
|
50
115
|
* content-type is JSON, otherwise a `Blob` whose `.type` carries the
|
|
@@ -59,7 +124,7 @@ export async function parseResource(response) {
|
|
|
59
124
|
}
|
|
60
125
|
const contentType = response.headers.get('content-type') ?? '';
|
|
61
126
|
if (contentType.includes('json')) {
|
|
62
|
-
return (
|
|
127
|
+
return (await readJsonData(response));
|
|
63
128
|
}
|
|
64
129
|
return response.blob();
|
|
65
130
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content.js","sourceRoot":"","sources":["../../src/internal/content.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"content.js","sourceRoot":"","sources":["../../src/internal/content.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/internal/request.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAGxD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAExC;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,UAAU,CAAA;IACtB,aAAa,EAAE,MAAM,CAAA;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS;IAExB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,MAAM,CAAA;IAEZ,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,IAAI,GAAG,UAAU,CAAA;IACxB,UAAU,CAAC,EAAE,KAAK,CAAA;IAClB,wEAAwE;IACxE,IAAI,CAAC,EAAE,OAAO,CAAA;IACd;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAYD;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,SAAS,GACf,OAAO,CAAC,YAAY,CAAC,CAavB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE;IAC3C,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,IAAI,CAAC,EAAE,OAAO,CAAA;CACf,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAwB/B;AAED;;;;;;;;GAQG;AACH,wBAAsB,IAAI,CACxB,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,SAAS,GACf,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/internal/request.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAGxD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAExC;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,UAAU,CAAA;IACtB,aAAa,EAAE,MAAM,CAAA;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS;IAExB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,MAAM,CAAA;IAEZ,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,IAAI,GAAG,UAAU,CAAA;IACxB,UAAU,CAAC,EAAE,KAAK,CAAA;IAClB,wEAAwE;IACxE,IAAI,CAAC,EAAE,OAAO,CAAA;IACd;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAYD;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,SAAS,GACf,OAAO,CAAC,YAAY,CAAC,CAavB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE;IAC3C,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,IAAI,CAAC,EAAE,OAAO,CAAA;CACf,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAwB/B;AAED;;;;;;;;GAQG;AACH,wBAAsB,IAAI,CACxB,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,SAAS,GACf,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAS9B"}
|
package/dist/internal/request.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mapError } from '../errors.js';
|
|
1
|
+
import { mapError, httpStatus } from '../errors.js';
|
|
2
2
|
import { toUrl } from './paths.js';
|
|
3
3
|
function resolveRequestUrl(context, input) {
|
|
4
4
|
if (input.url !== undefined) {
|
|
@@ -87,12 +87,7 @@ export async function send(context, input) {
|
|
|
87
87
|
return await rawRequest(context, input);
|
|
88
88
|
}
|
|
89
89
|
catch (err) {
|
|
90
|
-
|
|
91
|
-
?.status;
|
|
92
|
-
const responseStatus = err?.response
|
|
93
|
-
?.status;
|
|
94
|
-
if ((input.read || input.idempotent) &&
|
|
95
|
-
(status === 404 || responseStatus === 404)) {
|
|
90
|
+
if ((input.read || input.idempotent) && httpStatus(err) === 404) {
|
|
96
91
|
return null;
|
|
97
92
|
}
|
|
98
93
|
throw mapError(err);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/internal/request.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/internal/request.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAuClC,SAAS,iBAAiB,CAAC,OAAsB,EAAE,KAAgB;IACjE,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAC,GAAG,CAAA;IAClB,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,IAAI,SAAS,CAAC,qCAAqC,CAAC,CAAA;IAC5D,CAAC;IACD,OAAO,KAAK,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAA;AAClE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,OAAsB,EACtB,KAAgB;IAEhB,MAAM,GAAG,GAAG,iBAAiB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;IAC7C,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAA;IACpC,OAAO,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC;QAChC,GAAG;QACH,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,MAAM;QACN,2EAA2E;QAC3E,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,MAAM;QAC9B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;KACjB,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,KAKrC;IACC,IAAI,QAAkB,CAAA;IACtB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE;YAChC,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,KAAK;YAC7B,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAC,CAAA;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAA;IACrB,CAAC;IACD,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;QAChB,OAAO,QAAwB,CAAA;IACjC,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC1C,OAAO,IAAI,CAAA;IACb,CAAC;IACD,0EAA0E;IAC1E,IAAI,IAAa,CAAA;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,GAAG,SAAS,CAAA;IAClB,CAAC;IACD,MAAM,QAAQ,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAA;AAC1E,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI,CACxB,OAAsB,EACtB,KAAgB;IAEhB,IAAI,CAAC;QACH,OAAO,MAAM,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;IACzC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC;YAChE,OAAO,IAAI,CAAA;QACb,CAAC;QACD,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAA;IACrB,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@interop/was-client",
|
|
3
3
|
"description": "A developer-friendly client for Wallet Attached Storage (WAS) servers.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.6.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"build": "pnpm run clear && tsc",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"test": "pnpm run fix && pnpm run lint && pnpm run test:node && pnpm run test:browser",
|
|
16
16
|
"test:browser": "playwright test",
|
|
17
17
|
"test:node": "vitest run",
|
|
18
|
+
"test:integration": "vitest run --config vitest.integration.config.ts",
|
|
18
19
|
"test:coverage": "vitest run --coverage"
|
|
19
20
|
},
|
|
20
21
|
"files": [
|
|
@@ -28,6 +29,12 @@
|
|
|
28
29
|
"react-native": "./dist/index.js",
|
|
29
30
|
"import": "./dist/index.js",
|
|
30
31
|
"default": "./dist/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./edv": {
|
|
34
|
+
"types": "./dist/edv/index.d.ts",
|
|
35
|
+
"react-native": "./dist/edv/index.js",
|
|
36
|
+
"import": "./dist/edv/index.js",
|
|
37
|
+
"default": "./dist/edv/index.js"
|
|
31
38
|
}
|
|
32
39
|
},
|
|
33
40
|
"module": "dist/index.js",
|
|
@@ -37,12 +44,15 @@
|
|
|
37
44
|
"dependencies": {
|
|
38
45
|
"@interop/data-integrity-core": "^8.0.0",
|
|
39
46
|
"@interop/ed25519-signature": "^7.1.2",
|
|
47
|
+
"@interop/edv-client": "^17.2.0",
|
|
40
48
|
"@interop/ezcap": "^7.2.1",
|
|
41
49
|
"@interop/http-client": "^1.0.3",
|
|
42
50
|
"@interop/storage-core": "^0.1.0"
|
|
43
51
|
},
|
|
44
52
|
"devDependencies": {
|
|
45
53
|
"@eslint/js": "^10.0.1",
|
|
54
|
+
"@interop/ed25519-verification-key": "^8.0.0",
|
|
55
|
+
"@interop/x25519-key-agreement-key": "^5.1.0",
|
|
46
56
|
"@playwright/test": "^1.60.0",
|
|
47
57
|
"@types/node": "^25.9.1",
|
|
48
58
|
"@vitest/coverage-v8": "^4.1.7",
|