@interop/was-client 0.9.1 → 0.10.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 +27 -1
- 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 +13 -5
- package/dist/Resource.d.ts.map +1 -1
- package/dist/Resource.js +50 -38
- 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 +11 -4
- package/dist/codec.d.ts.map +1 -1
- package/dist/edv/EdvCodec.d.ts +64 -33
- package/dist/edv/EdvCodec.d.ts.map +1 -1
- package/dist/edv/EdvCodec.js +194 -86
- 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 +69 -4
- package/dist/internal/codec.d.ts.map +1 -1
- package/dist/internal/codec.js +93 -5
- 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/edv/index.d.ts
CHANGED
|
@@ -18,5 +18,5 @@
|
|
|
18
18
|
*/
|
|
19
19
|
export { createEdvEncryption, EdvCodec } from './EdvCodec.js';
|
|
20
20
|
export type { EdvKeys } from './EdvCodec.js';
|
|
21
|
-
export { WasTransport,
|
|
21
|
+
export { WasTransport, JOSE_CONTENT_TYPE } from './WasTransport.js';
|
|
22
22
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/edv/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/edv/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAC7D,YAAY,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/edv/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAC7D,YAAY,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA"}
|
package/dist/edv/index.js
CHANGED
|
@@ -17,5 +17,5 @@
|
|
|
17
17
|
* transport, for driving an `EdvClient` directly against WAS.
|
|
18
18
|
*/
|
|
19
19
|
export { createEdvEncryption, EdvCodec } from './EdvCodec.js';
|
|
20
|
-
export { WasTransport,
|
|
20
|
+
export { WasTransport, JOSE_CONTENT_TYPE } from './WasTransport.js';
|
|
21
21
|
//# sourceMappingURL=index.js.map
|
package/dist/edv/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/edv/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAE7D,OAAO,EAAE,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/edv/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAE7D,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA"}
|
package/dist/errors.d.ts
CHANGED
|
@@ -40,7 +40,9 @@ export declare class ValidationError extends WasError {
|
|
|
40
40
|
constructor(message: string, options?: WasErrorOptions);
|
|
41
41
|
}
|
|
42
42
|
/**
|
|
43
|
-
* Authorization headers were missing or could not be verified (HTTP 401)
|
|
43
|
+
* Authorization headers were missing or could not be verified (HTTP 401), or
|
|
44
|
+
* the caller is authenticated but not permitted to act on the target (HTTP
|
|
45
|
+
* 403).
|
|
44
46
|
*/
|
|
45
47
|
export declare class AuthRequiredError extends WasError {
|
|
46
48
|
constructor(message: string, options?: WasErrorOptions);
|
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
|
|
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;;;;GAIG;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;;;;;;;GAOG;AACH,qBAAa,uBAAwB,SAAQ,QAAQ;gBACvC,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;;;;;;;;GAQG;AACH,qBAAa,eAAgB,SAAQ,QAAQ;gBAC/B,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB;CAI3D;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,QAAQ;gBAC9B,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB;CAI3D;AA+ED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAG3D;AAED;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,QAAQ,CAuD/C"}
|
package/dist/errors.js
CHANGED
|
@@ -49,7 +49,9 @@ export class ValidationError extends WasError {
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
/**
|
|
52
|
-
* Authorization headers were missing or could not be verified (HTTP 401)
|
|
52
|
+
* Authorization headers were missing or could not be verified (HTTP 401), or
|
|
53
|
+
* the caller is authenticated but not permitted to act on the target (HTTP
|
|
54
|
+
* 403).
|
|
53
55
|
*/
|
|
54
56
|
export class AuthRequiredError extends WasError {
|
|
55
57
|
constructor(message, options = {}) {
|
|
@@ -217,13 +219,18 @@ export function mapError(err) {
|
|
|
217
219
|
const data = httpError.data;
|
|
218
220
|
const type = data?.type;
|
|
219
221
|
const title = data?.title;
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
222
|
+
// Guard with `Array.isArray`, not just optional chaining: a non-conformant
|
|
223
|
+
// `problem+json` body with `errors` as a non-array (e.g. `"boom"`) is truthy,
|
|
224
|
+
// so `?.map` would throw a `TypeError` and mask the real `WasError`.
|
|
225
|
+
const details = Array.isArray(data?.errors)
|
|
226
|
+
? data.errors
|
|
227
|
+
.map(entry => entry.detail)
|
|
228
|
+
.filter((detail) => typeof detail === 'string')
|
|
229
|
+
: undefined;
|
|
223
230
|
const requestUrl = httpError.requestUrl;
|
|
224
231
|
const message = title ?? httpError.message ?? 'WAS request failed';
|
|
225
232
|
const options = { status, type, title, details, requestUrl, cause: err };
|
|
226
|
-
const kind = typeof type === 'string' ? type
|
|
233
|
+
const kind = typeof type === 'string' ? problemFragment(type) : undefined;
|
|
227
234
|
const byKind = errorForKind(kind, message, options);
|
|
228
235
|
if (byKind !== null) {
|
|
229
236
|
return byKind;
|
|
@@ -232,9 +239,12 @@ export function mapError(err) {
|
|
|
232
239
|
case 400:
|
|
233
240
|
return new ValidationError(message, options);
|
|
234
241
|
case 401:
|
|
242
|
+
case 403:
|
|
235
243
|
return new AuthRequiredError(message, options);
|
|
236
244
|
case 404:
|
|
237
245
|
return new NotFoundError(message, options);
|
|
246
|
+
case 415:
|
|
247
|
+
return new ValidationError(message, options);
|
|
238
248
|
case 409:
|
|
239
249
|
return new ConflictError(message, options);
|
|
240
250
|
case 412:
|
package/dist/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;GAKG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAmBpD;;GAEG;AACH,MAAM,OAAO,QAAS,SAAQ,KAAK;IACjC,MAAM,CAAS;IACf,IAAI,CAAS;IACb,KAAK,CAAS;IACd,OAAO,CAAW;IAClB,UAAU,CAAS;IAEnB,YAAY,OAAe,EAAE,UAA2B,EAAE;QACxD,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,OAAO,CAAA;QACnE,KAAK,CAAC,OAAO,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;QAC3D,IAAI,CAAC,IAAI,GAAG,UAAU,CAAA;QACtB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;QAClB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;IAC9B,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,aAAc,SAAQ,QAAQ;IACzC,YAAY,OAAe,EAAE,UAA2B,EAAE;QACxD,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QACvB,IAAI,CAAC,IAAI,GAAG,eAAe,CAAA;IAC7B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,eAAgB,SAAQ,QAAQ;IAC3C,YAAY,OAAe,EAAE,UAA2B,EAAE;QACxD,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QACvB,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAA;IAC/B,CAAC;CACF;AAED
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -11,5 +11,5 @@ export { Collection } from './Collection.js';
|
|
|
11
11
|
export { Resource } from './Resource.js';
|
|
12
12
|
export { WasError, NotFoundError, ValidationError, AuthRequiredError, NotImplementedError, ConflictError, PreconditionFailedError, PayloadTooLargeError, QuotaExceededError, EncryptionError, WasServerError, mapError } from './errors.js';
|
|
13
13
|
export type { ResourceCodec, EncryptionProvider, EncodedWrite } from './codec.js';
|
|
14
|
-
export type { Json, JsonPrimitive, JsonObject, JsonArray, Action, ActionInput, SpaceDescription, CollectionDescription, CollectionEncryption, CollectionSummary, CollectionsList, SpaceSummary, SpaceListing, ResourceSummary, CollectionResourcesList, ResourceMetadata, ResourceMetadataCustom, AddResult, ImportStats, PolicyDocument, LinkSet, LinkSetEntry, HandleOptions, EncryptionOverride, BackendReference, BackendDescriptor, BackendRegistration, BackendConnectionInput, BackendConnectionPublic, StorageLimit, CollectionUsage, BackendUsage, SpaceQuotaReport, GrantOptions, RequestInput, IZcap, IDelegatedZcap, ISigner } from './types.js';
|
|
14
|
+
export type { Json, JsonPrimitive, JsonObject, JsonArray, ResourceData, Action, ActionInput, SpaceDescription, CollectionDescription, CollectionEncryption, CollectionSummary, CollectionsList, SpaceSummary, SpaceListing, ResourceSummary, CollectionResourcesList, ResourceMetadata, ResourceMetadataCustom, AddResult, ImportStats, PolicyDocument, LinkSet, LinkSetEntry, HandleOptions, EncryptionOverride, BackendReference, BackendDescriptor, BackendRegistration, BackendConnectionInput, BackendConnectionPublic, StorageLimit, CollectionUsage, BackendUsage, SpaceQuotaReport, GrantOptions, RequestInput, IZcap, IDelegatedZcap, ISigner } from './types.js';
|
|
15
15
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;GAGG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAExC,OAAO,EACL,QAAQ,EACR,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,aAAa,EACb,uBAAuB,EACvB,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,QAAQ,EACT,MAAM,aAAa,CAAA;AAEpB,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,YAAY,EACb,MAAM,YAAY,CAAA;AAEnB,YAAY,EACV,IAAI,EACJ,aAAa,EACb,UAAU,EACV,SAAS,EACT,MAAM,EACN,WAAW,EACX,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,uBAAuB,EACvB,gBAAgB,EAChB,sBAAsB,EACtB,SAAS,EACT,WAAW,EACX,cAAc,EACd,OAAO,EACP,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,sBAAsB,EACtB,uBAAuB,EACvB,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,KAAK,EACL,cAAc,EACd,OAAO,EACR,MAAM,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;GAGG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAExC,OAAO,EACL,QAAQ,EACR,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,aAAa,EACb,uBAAuB,EACvB,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,QAAQ,EACT,MAAM,aAAa,CAAA;AAEpB,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,YAAY,EACb,MAAM,YAAY,CAAA;AAEnB,YAAY,EACV,IAAI,EACJ,aAAa,EACb,UAAU,EACV,SAAS,EACT,YAAY,EACZ,MAAM,EACN,WAAW,EACX,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,uBAAuB,EACvB,gBAAgB,EAChB,sBAAsB,EACtB,SAAS,EACT,WAAW,EACX,cAAc,EACd,OAAO,EACP,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,EACnB,sBAAsB,EACtB,uBAAuB,EACvB,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,KAAK,EACL,cAAc,EACd,OAAO,EACR,MAAM,YAAY,CAAA"}
|
package/dist/internal/codec.d.ts
CHANGED
|
@@ -1,6 +1,70 @@
|
|
|
1
1
|
import type { ResourceCodec } from '../codec.js';
|
|
2
2
|
import type { ClientContext } from './request.js';
|
|
3
|
-
import type { CollectionEncryption, EncryptionOverride } from '../types.js';
|
|
3
|
+
import type { CollectionEncryption, EncryptionOverride, IZcap } from '../types.js';
|
|
4
|
+
/**
|
|
5
|
+
* The outcome of a marker read. The distinction is load-bearing: `readable:
|
|
6
|
+
* false` means the Collection Description could not be read at all (a null/404,
|
|
7
|
+
* which WAS also returns for an *unauthorized* read -- e.g. a resource-scoped
|
|
8
|
+
* capability cannot GET the collection description), which is indistinguishable
|
|
9
|
+
* from "absent". That ambiguity must NOT be collapsed into "plaintext", or an
|
|
10
|
+
* encryption-capable client would fail open and write server-visible plaintext
|
|
11
|
+
* into an encrypted collection. `readable: true` means the description was read;
|
|
12
|
+
* its `encryption` is the declared marker (absent for a genuine plaintext
|
|
13
|
+
* collection).
|
|
14
|
+
*/
|
|
15
|
+
export type MarkerReadResult = {
|
|
16
|
+
readable: false;
|
|
17
|
+
} | {
|
|
18
|
+
readable: true;
|
|
19
|
+
encryption?: CollectionEncryption;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Reads a Collection's declared `encryption` marker as a {@link MarkerReadResult},
|
|
23
|
+
* mapping an unreadable description (null/404 -- also what WAS returns for an
|
|
24
|
+
* unauthorized read) to `{ readable: false }`. The lazy `readMarker` thunk both
|
|
25
|
+
* the Collection and the standalone-Resource codec resolution pass to
|
|
26
|
+
* {@link resolveCodec}.
|
|
27
|
+
*
|
|
28
|
+
* @param context {ClientContext}
|
|
29
|
+
* @param options {object}
|
|
30
|
+
* @param options.spaceId {string}
|
|
31
|
+
* @param options.collectionId {string}
|
|
32
|
+
* @param [options.capability] {IZcap}
|
|
33
|
+
* @returns {Promise<MarkerReadResult>}
|
|
34
|
+
*/
|
|
35
|
+
export declare function readCollectionMarker(context: ClientContext, { spaceId, collectionId, capability }: {
|
|
36
|
+
spaceId: string;
|
|
37
|
+
collectionId: string;
|
|
38
|
+
capability?: IZcap;
|
|
39
|
+
}): Promise<MarkerReadResult>;
|
|
40
|
+
/**
|
|
41
|
+
* A per-handle codec cache. Memoizes the in-flight resolution so concurrent
|
|
42
|
+
* callers share one round-trip, but drops it on rejection so a transient
|
|
43
|
+
* failure (e.g. a 500/network error during marker discovery) does not
|
|
44
|
+
* permanently poison the handle, and exposes `reset()` for when a handle's
|
|
45
|
+
* encryption state changes (e.g. `Collection.configure()` adds the marker).
|
|
46
|
+
*/
|
|
47
|
+
export declare class CodecHolder {
|
|
48
|
+
private _promise?;
|
|
49
|
+
private readonly _resolve;
|
|
50
|
+
/**
|
|
51
|
+
* @param resolve {function} resolves a fresh codec; re-invoked after a
|
|
52
|
+
* rejection or a `reset()`, else called at most once
|
|
53
|
+
*/
|
|
54
|
+
constructor(resolve: () => Promise<ResourceCodec>);
|
|
55
|
+
/**
|
|
56
|
+
* Returns the memoized codec, resolving it on first use.
|
|
57
|
+
*
|
|
58
|
+
* @returns {Promise<ResourceCodec>}
|
|
59
|
+
*/
|
|
60
|
+
get(): Promise<ResourceCodec>;
|
|
61
|
+
/**
|
|
62
|
+
* Drops any memoized codec so the next `get()` re-resolves.
|
|
63
|
+
*
|
|
64
|
+
* @returns {void}
|
|
65
|
+
*/
|
|
66
|
+
reset(): void;
|
|
67
|
+
}
|
|
4
68
|
/**
|
|
5
69
|
* The default codec: passes plaintext through unchanged. `encode` echoes the
|
|
6
70
|
* caller's `id` (so `put(id, ...)` is a `PUT` and `add(...)`, with no id, stays
|
|
@@ -23,14 +87,15 @@ export declare const identityCodec: ResourceCodec;
|
|
|
23
87
|
* @param [options.override] {EncryptionOverride} per-handle override; wins
|
|
24
88
|
* over the marker and skips the marker read
|
|
25
89
|
* @param options.readMarker {function} lazily reads the Collection's declared
|
|
26
|
-
* `encryption` marker
|
|
27
|
-
*
|
|
90
|
+
* `encryption` marker, distinguishing a readable description (with or without
|
|
91
|
+
* a marker) from an unreadable one (see {@link MarkerReadResult}); called only
|
|
92
|
+
* when there is no override and the client has a keystore
|
|
28
93
|
* @returns {Promise<ResourceCodec>}
|
|
29
94
|
*/
|
|
30
95
|
export declare function resolveCodec(context: ClientContext, { spaceId, collectionId, override, readMarker }: {
|
|
31
96
|
spaceId: string;
|
|
32
97
|
collectionId: string;
|
|
33
98
|
override?: EncryptionOverride;
|
|
34
|
-
readMarker: () => Promise<
|
|
99
|
+
readMarker: () => Promise<MarkerReadResult>;
|
|
35
100
|
}): Promise<ResourceCodec>;
|
|
36
101
|
//# sourceMappingURL=codec.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codec.d.ts","sourceRoot":"","sources":["../../src/internal/codec.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAgB,aAAa,EAAE,MAAM,aAAa,CAAA;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"codec.d.ts","sourceRoot":"","sources":["../../src/internal/codec.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAgB,aAAa,EAAE,MAAM,aAAa,CAAA;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAIjD,OAAO,KAAK,EACV,oBAAoB,EACpB,kBAAkB,EAClB,KAAK,EAGN,MAAM,aAAa,CAAA;AAEpB;;;;;;;;;;GAUG;AACH,MAAM,MAAM,gBAAgB,GAC1B;IAAE,QAAQ,EAAE,KAAK,CAAA;CAAE,GAAG;IAAE,QAAQ,EAAE,IAAI,CAAC;IAAC,UAAU,CAAC,EAAE,oBAAoB,CAAA;CAAE,CAAA;AAE7E;;;;;;;;;;;;;GAaG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,aAAa,EACtB,EACE,OAAO,EACP,YAAY,EACZ,UAAU,EACX,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,KAAK,CAAA;CAAE,GAC/D,OAAO,CAAC,gBAAgB,CAAC,CAS3B;AAED;;;;;;GAMG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,CAAwB;IACzC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA8B;IAEvD;;;OAGG;gBACS,OAAO,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC;IAIjD;;;;OAIG;IACH,GAAG,IAAI,OAAO,CAAC,aAAa,CAAC;IAiB7B;;;;OAIG;IACH,KAAK,IAAI,IAAI;CAGd;AAED;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,EAAE,aAwB3B,CAAA;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,aAAa,EACtB,EACE,OAAO,EACP,YAAY,EACZ,QAAQ,EACR,UAAU,EACX,EAAE;IACD,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,kBAAkB,CAAA;IAC7B,UAAU,EAAE,MAAM,OAAO,CAAC,gBAAgB,CAAC,CAAA;CAC5C,GACA,OAAO,CAAC,aAAa,CAAC,CA4CxB"}
|
package/dist/internal/codec.js
CHANGED
|
@@ -1,5 +1,77 @@
|
|
|
1
1
|
import { prepareBody, parseResource } from './content.js';
|
|
2
|
+
import { describeCollection } from './describe.js';
|
|
2
3
|
import { EncryptionError } from '../errors.js';
|
|
4
|
+
/**
|
|
5
|
+
* Reads a Collection's declared `encryption` marker as a {@link MarkerReadResult},
|
|
6
|
+
* mapping an unreadable description (null/404 -- also what WAS returns for an
|
|
7
|
+
* unauthorized read) to `{ readable: false }`. The lazy `readMarker` thunk both
|
|
8
|
+
* the Collection and the standalone-Resource codec resolution pass to
|
|
9
|
+
* {@link resolveCodec}.
|
|
10
|
+
*
|
|
11
|
+
* @param context {ClientContext}
|
|
12
|
+
* @param options {object}
|
|
13
|
+
* @param options.spaceId {string}
|
|
14
|
+
* @param options.collectionId {string}
|
|
15
|
+
* @param [options.capability] {IZcap}
|
|
16
|
+
* @returns {Promise<MarkerReadResult>}
|
|
17
|
+
*/
|
|
18
|
+
export async function readCollectionMarker(context, { spaceId, collectionId, capability }) {
|
|
19
|
+
const description = await describeCollection(context, {
|
|
20
|
+
spaceId,
|
|
21
|
+
collectionId,
|
|
22
|
+
capability
|
|
23
|
+
});
|
|
24
|
+
return description === null
|
|
25
|
+
? { readable: false }
|
|
26
|
+
: { readable: true, encryption: description.encryption };
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A per-handle codec cache. Memoizes the in-flight resolution so concurrent
|
|
30
|
+
* callers share one round-trip, but drops it on rejection so a transient
|
|
31
|
+
* failure (e.g. a 500/network error during marker discovery) does not
|
|
32
|
+
* permanently poison the handle, and exposes `reset()` for when a handle's
|
|
33
|
+
* encryption state changes (e.g. `Collection.configure()` adds the marker).
|
|
34
|
+
*/
|
|
35
|
+
export class CodecHolder {
|
|
36
|
+
_promise;
|
|
37
|
+
_resolve;
|
|
38
|
+
/**
|
|
39
|
+
* @param resolve {function} resolves a fresh codec; re-invoked after a
|
|
40
|
+
* rejection or a `reset()`, else called at most once
|
|
41
|
+
*/
|
|
42
|
+
constructor(resolve) {
|
|
43
|
+
this._resolve = resolve;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Returns the memoized codec, resolving it on first use.
|
|
47
|
+
*
|
|
48
|
+
* @returns {Promise<ResourceCodec>}
|
|
49
|
+
*/
|
|
50
|
+
get() {
|
|
51
|
+
if (this._promise) {
|
|
52
|
+
return this._promise;
|
|
53
|
+
}
|
|
54
|
+
const promise = this._resolve();
|
|
55
|
+
// Memoize the in-flight promise so concurrent callers share one round-trip,
|
|
56
|
+
// but drop it on rejection so a transient failure does not permanently
|
|
57
|
+
// poison the handle. The identity guard avoids clobbering a newer promise.
|
|
58
|
+
this._promise = promise;
|
|
59
|
+
promise.catch(() => {
|
|
60
|
+
if (this._promise === promise) {
|
|
61
|
+
this._promise = undefined;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
return promise;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Drops any memoized codec so the next `get()` re-resolves.
|
|
68
|
+
*
|
|
69
|
+
* @returns {void}
|
|
70
|
+
*/
|
|
71
|
+
reset() {
|
|
72
|
+
this._promise = undefined;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
3
75
|
/**
|
|
4
76
|
* The default codec: passes plaintext through unchanged. `encode` echoes the
|
|
5
77
|
* caller's `id` (so `put(id, ...)` is a `PUT` and `add(...)`, with no id, stays
|
|
@@ -36,8 +108,9 @@ export const identityCodec = {
|
|
|
36
108
|
* @param [options.override] {EncryptionOverride} per-handle override; wins
|
|
37
109
|
* over the marker and skips the marker read
|
|
38
110
|
* @param options.readMarker {function} lazily reads the Collection's declared
|
|
39
|
-
* `encryption` marker
|
|
40
|
-
*
|
|
111
|
+
* `encryption` marker, distinguishing a readable description (with or without
|
|
112
|
+
* a marker) from an unreadable one (see {@link MarkerReadResult}); called only
|
|
113
|
+
* when there is no override and the client has a keystore
|
|
41
114
|
* @returns {Promise<ResourceCodec>}
|
|
42
115
|
*/
|
|
43
116
|
export async function resolveCodec(context, { spaceId, collectionId, override, readMarker }) {
|
|
@@ -57,15 +130,30 @@ export async function resolveCodec(context, { spaceId, collectionId, override, r
|
|
|
57
130
|
if (!context.encryption) {
|
|
58
131
|
return identityCodec;
|
|
59
132
|
}
|
|
60
|
-
// 3. Otherwise the Collection's declared marker decides
|
|
133
|
+
// 3. Otherwise the Collection's declared marker decides -- but only if we
|
|
134
|
+
// could actually read it. An unreadable description (a resource-scoped
|
|
135
|
+
// capability cannot GET the collection description, and WAS masks that as a
|
|
136
|
+
// 404) is ambiguous: it is indistinguishable from "absent", so an
|
|
137
|
+
// encryption-capable client fails closed rather than silently downgrading to
|
|
138
|
+
// plaintext and writing the caller's secret as server-visible plaintext into
|
|
139
|
+
// a possibly-encrypted collection.
|
|
61
140
|
const marker = await readMarker();
|
|
62
|
-
if (!marker) {
|
|
141
|
+
if (!marker.readable) {
|
|
142
|
+
throw new EncryptionError(`Cannot determine whether collection ${spaceId}/${collectionId} is ` +
|
|
143
|
+
'encrypted: its description is not readable (a resource-scoped ' +
|
|
144
|
+
'capability cannot read the collection description, and WAS returns ' +
|
|
145
|
+
'404 for both not-found and unauthorized). Refusing to fall back to ' +
|
|
146
|
+
'plaintext. Pass an explicit per-handle encryption override -- ' +
|
|
147
|
+
"`{ encryption: 'plaintext' }` to write plaintext, or a scheme/keys " +
|
|
148
|
+
'override to encrypt.');
|
|
149
|
+
}
|
|
150
|
+
if (!marker.encryption) {
|
|
63
151
|
return identityCodec;
|
|
64
152
|
}
|
|
65
153
|
return buildEncryptingCodec(context, {
|
|
66
154
|
spaceId,
|
|
67
155
|
collectionId,
|
|
68
|
-
scheme: marker.scheme
|
|
156
|
+
scheme: marker.encryption.scheme
|
|
69
157
|
});
|
|
70
158
|
}
|
|
71
159
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codec.js","sourceRoot":"","sources":["../../src/internal/codec.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"codec.js","sourceRoot":"","sources":["../../src/internal/codec.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,7 +10,35 @@
|
|
|
10
10
|
* `application/octet-stream`.
|
|
11
11
|
*/
|
|
12
12
|
import type { HttpResponse } from '@interop/http-client';
|
|
13
|
-
import type { Json } from '../types.js';
|
|
13
|
+
import type { Json, ResourceData } from '../types.js';
|
|
14
|
+
/**
|
|
15
|
+
* Whether a content-type denotes JSON -- `application/json` or any
|
|
16
|
+
* `application/<prefix>+json` structured-suffix variant (e.g.
|
|
17
|
+
* `application/ld+json`, `application/jose+json`), each optionally followed by
|
|
18
|
+
* parameters (`; charset=utf-8`). The `json` token is anchored to the end of the
|
|
19
|
+
* media type, so a non-JSON type that merely contains the substring `json` --
|
|
20
|
+
* `application/jsonl`, `application/json-seq`, `application/json5` -- is NOT
|
|
21
|
+
* treated as JSON and is read back as binary (a `Blob`) instead of being
|
|
22
|
+
* JSON-parsed.
|
|
23
|
+
*
|
|
24
|
+
* @param contentType {string}
|
|
25
|
+
* @returns {boolean}
|
|
26
|
+
*/
|
|
27
|
+
export declare function isJsonContentType(contentType: string): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Whether a content type denotes UTF-8-safe text that should be stored inline as
|
|
30
|
+
* a plain string (legible, no ~33% base64 inflation) rather than as opaque
|
|
31
|
+
* binary -- `text/*`, plus the XML/SVG family that is textual despite an
|
|
32
|
+
* `application/` or `image/` prefix (`application/xml`, any `+xml` structured
|
|
33
|
+
* suffix such as `image/svg+xml` / `application/atom+xml`). Kept deliberately
|
|
34
|
+
* narrow: an unlisted type is treated as binary (base64), which is always
|
|
35
|
+
* byte-safe, and the caller additionally gates on valid UTF-8 before choosing
|
|
36
|
+
* text. Any `; charset=…` parameter is ignored.
|
|
37
|
+
*
|
|
38
|
+
* @param contentType {string}
|
|
39
|
+
* @returns {boolean}
|
|
40
|
+
*/
|
|
41
|
+
export declare function isTextContentType(contentType: string): boolean;
|
|
14
42
|
/**
|
|
15
43
|
* Guesses a content-type from a resource id's file extension, limited to the
|
|
16
44
|
* static-web types in `WEB_CONTENT_TYPES`. Returns `undefined` when the id has
|
|
@@ -31,6 +59,22 @@ export interface PreparedBody {
|
|
|
31
59
|
body?: Uint8Array | Blob;
|
|
32
60
|
contentType?: string;
|
|
33
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Whether a value is a `Blob`, guarding for environments where `Blob` is
|
|
64
|
+
* undefined.
|
|
65
|
+
*
|
|
66
|
+
* @param value {unknown}
|
|
67
|
+
* @returns {boolean}
|
|
68
|
+
*/
|
|
69
|
+
export declare function isBlob(value: unknown): value is Blob;
|
|
70
|
+
/**
|
|
71
|
+
* Coerces a `Uint8Array` (including a Node `Buffer`, which is a subclass) to a
|
|
72
|
+
* plain `Uint8Array` view, as ezcap's `body` type expects.
|
|
73
|
+
*
|
|
74
|
+
* @param bytes {Uint8Array}
|
|
75
|
+
* @returns {Uint8Array}
|
|
76
|
+
*/
|
|
77
|
+
export declare function toPlainBytes(bytes: Uint8Array): Uint8Array;
|
|
34
78
|
/**
|
|
35
79
|
* Inspects write data and resolves it to a JSON or binary payload.
|
|
36
80
|
*
|
|
@@ -40,7 +84,7 @@ export interface PreparedBody {
|
|
|
40
84
|
* with `||` rather than `??` so an empty-string `Blob.type` -- a typeless Blob
|
|
41
85
|
* -- falls through to the guess instead of becoming an empty content-type.)
|
|
42
86
|
*
|
|
43
|
-
* @param data {
|
|
87
|
+
* @param data {ResourceData} the resource content
|
|
44
88
|
* @param options {object}
|
|
45
89
|
* @param [options.contentType] {string} overrides the inferred content-type
|
|
46
90
|
* for binary data
|
|
@@ -48,14 +92,41 @@ export interface PreparedBody {
|
|
|
48
92
|
* content-type by extension when none is given (binary data only)
|
|
49
93
|
* @returns {PreparedBody}
|
|
50
94
|
*/
|
|
51
|
-
export declare function prepareBody(data:
|
|
95
|
+
export declare function prepareBody(data: ResourceData, options?: {
|
|
52
96
|
contentType?: string;
|
|
53
97
|
filename?: string;
|
|
54
98
|
}): PreparedBody;
|
|
99
|
+
/**
|
|
100
|
+
* Extracts the id of a just-created resource from a create response. Prefers
|
|
101
|
+
* the response body's `id`; for a body-less 2xx falls back to the last path
|
|
102
|
+
* segment of the `Location` header (decoded, since the server emits a
|
|
103
|
+
* percent-encoded path). Throws a `WasServerError` when the response carries
|
|
104
|
+
* neither -- a malformed create response -- rather than letting an absent body
|
|
105
|
+
* surface as a raw `TypeError` on `data.id`.
|
|
106
|
+
*
|
|
107
|
+
* @param response {HttpResponse | null}
|
|
108
|
+
* @returns {string}
|
|
109
|
+
*/
|
|
110
|
+
export declare function createdId(response: HttpResponse | null): string;
|
|
111
|
+
/**
|
|
112
|
+
* Unwraps a read response's pre-parsed JSON `data` as `T`, mapping a `null`
|
|
113
|
+
* response (a 404 that a `read` request resolved to `null`) to `null`. Captures
|
|
114
|
+
* the `response === null ? null : response.data as T` idiom shared across the
|
|
115
|
+
* handle read methods.
|
|
116
|
+
*
|
|
117
|
+
* @param response {HttpResponse | null}
|
|
118
|
+
* @returns {T | null}
|
|
119
|
+
*/
|
|
120
|
+
export declare function dataOrNull<T>(response: HttpResponse | null): T | null;
|
|
55
121
|
/**
|
|
56
122
|
* Reads a JSON response body, preferring the http-client's pre-parsed `data`
|
|
57
123
|
* and falling back to `response.json()` when it is absent.
|
|
58
124
|
*
|
|
125
|
+
* `@interop/http-client` pre-consumes the body into `.data` for JSON
|
|
126
|
+
* content-types, so a stored top-level `null` arrives as `.data === null`.
|
|
127
|
+
* Test for `undefined` rather than using `??`; otherwise the nullish fallback
|
|
128
|
+
* would re-invoke `.json()` on the already-consumed stream and throw.
|
|
129
|
+
*
|
|
59
130
|
* @param response {HttpResponse}
|
|
60
131
|
* @returns {Promise<unknown>}
|
|
61
132
|
*/
|
|
@@ -1 +1 @@
|
|
|
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;
|
|
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,YAAY,EAAE,MAAM,aAAa,CAAA;AAIrD;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAO9D;AA6BD;;;;;;;;;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;AAED;;;;;;GAMG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,IAAI,CAEpD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAK1D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,YAAY,EAClB,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GACxD,YAAY,CA4Bd;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,GAAG,MAAM,CAqB/D;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,QAAQ,EAAE,YAAY,GAAG,IAAI,GAAG,CAAC,GAAG,IAAI,CAErE;AAED;;;;;;;;;;;GAWG;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,9 +1,9 @@
|
|
|
1
|
-
import { ValidationError } from '../errors.js';
|
|
1
|
+
import { ValidationError, WasServerError } from '../errors.js';
|
|
2
2
|
const OCTET_STREAM = 'application/octet-stream';
|
|
3
3
|
/**
|
|
4
4
|
* Whether a content-type denotes JSON -- `application/json` or any
|
|
5
5
|
* `application/<prefix>+json` structured-suffix variant (e.g.
|
|
6
|
-
* `application/ld+json`, `application/
|
|
6
|
+
* `application/ld+json`, `application/jose+json`), each optionally followed by
|
|
7
7
|
* parameters (`; charset=utf-8`). The `json` token is anchored to the end of the
|
|
8
8
|
* media type, so a non-JSON type that merely contains the substring `json` --
|
|
9
9
|
* `application/jsonl`, `application/json-seq`, `application/json5` -- is NOT
|
|
@@ -13,9 +13,28 @@ const OCTET_STREAM = 'application/octet-stream';
|
|
|
13
13
|
* @param contentType {string}
|
|
14
14
|
* @returns {boolean}
|
|
15
15
|
*/
|
|
16
|
-
function isJsonContentType(contentType) {
|
|
16
|
+
export function isJsonContentType(contentType) {
|
|
17
17
|
return /^application\/([^+\s;]+\+)?json\s*(;.*)?$/i.test(contentType);
|
|
18
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Whether a content type denotes UTF-8-safe text that should be stored inline as
|
|
21
|
+
* a plain string (legible, no ~33% base64 inflation) rather than as opaque
|
|
22
|
+
* binary -- `text/*`, plus the XML/SVG family that is textual despite an
|
|
23
|
+
* `application/` or `image/` prefix (`application/xml`, any `+xml` structured
|
|
24
|
+
* suffix such as `image/svg+xml` / `application/atom+xml`). Kept deliberately
|
|
25
|
+
* narrow: an unlisted type is treated as binary (base64), which is always
|
|
26
|
+
* byte-safe, and the caller additionally gates on valid UTF-8 before choosing
|
|
27
|
+
* text. Any `; charset=…` parameter is ignored.
|
|
28
|
+
*
|
|
29
|
+
* @param contentType {string}
|
|
30
|
+
* @returns {boolean}
|
|
31
|
+
*/
|
|
32
|
+
export function isTextContentType(contentType) {
|
|
33
|
+
const type = (contentType.split(';')[0] ?? '').trim().toLowerCase();
|
|
34
|
+
return (type.startsWith('text/') ||
|
|
35
|
+
type === 'application/xml' ||
|
|
36
|
+
type.endsWith('+xml'));
|
|
37
|
+
}
|
|
19
38
|
/**
|
|
20
39
|
* Extension-to-content-type fallbacks for the common static-web file types --
|
|
21
40
|
* the only case where guessing a content-type from a resource id pays off
|
|
@@ -60,7 +79,14 @@ export function guessContentTypeFromId(id) {
|
|
|
60
79
|
const extension = id.slice(lastDot + 1).toLowerCase();
|
|
61
80
|
return WEB_CONTENT_TYPES[extension];
|
|
62
81
|
}
|
|
63
|
-
|
|
82
|
+
/**
|
|
83
|
+
* Whether a value is a `Blob`, guarding for environments where `Blob` is
|
|
84
|
+
* undefined.
|
|
85
|
+
*
|
|
86
|
+
* @param value {unknown}
|
|
87
|
+
* @returns {boolean}
|
|
88
|
+
*/
|
|
89
|
+
export function isBlob(value) {
|
|
64
90
|
return typeof Blob !== 'undefined' && value instanceof Blob;
|
|
65
91
|
}
|
|
66
92
|
/**
|
|
@@ -70,7 +96,7 @@ function isBlob(value) {
|
|
|
70
96
|
* @param bytes {Uint8Array}
|
|
71
97
|
* @returns {Uint8Array}
|
|
72
98
|
*/
|
|
73
|
-
function toPlainBytes(bytes) {
|
|
99
|
+
export function toPlainBytes(bytes) {
|
|
74
100
|
if (bytes.constructor === Uint8Array) {
|
|
75
101
|
return bytes;
|
|
76
102
|
}
|
|
@@ -85,7 +111,7 @@ function toPlainBytes(bytes) {
|
|
|
85
111
|
* with `||` rather than `??` so an empty-string `Blob.type` -- a typeless Blob
|
|
86
112
|
* -- falls through to the guess instead of becoming an empty content-type.)
|
|
87
113
|
*
|
|
88
|
-
* @param data {
|
|
114
|
+
* @param data {ResourceData} the resource content
|
|
89
115
|
* @param options {object}
|
|
90
116
|
* @param [options.contentType] {string} overrides the inferred content-type
|
|
91
117
|
* for binary data
|
|
@@ -116,15 +142,60 @@ export function prepareBody(data, options = {}) {
|
|
|
116
142
|
throw new ValidationError('Resource data must be a plain object/array (JSON) or a ' +
|
|
117
143
|
'Blob/Uint8Array (binary).');
|
|
118
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* Extracts the id of a just-created resource from a create response. Prefers
|
|
147
|
+
* the response body's `id`; for a body-less 2xx falls back to the last path
|
|
148
|
+
* segment of the `Location` header (decoded, since the server emits a
|
|
149
|
+
* percent-encoded path). Throws a `WasServerError` when the response carries
|
|
150
|
+
* neither -- a malformed create response -- rather than letting an absent body
|
|
151
|
+
* surface as a raw `TypeError` on `data.id`.
|
|
152
|
+
*
|
|
153
|
+
* @param response {HttpResponse | null}
|
|
154
|
+
* @returns {string}
|
|
155
|
+
*/
|
|
156
|
+
export function createdId(response) {
|
|
157
|
+
const data = response?.data;
|
|
158
|
+
if (data !== null &&
|
|
159
|
+
typeof data === 'object' &&
|
|
160
|
+
typeof data.id === 'string') {
|
|
161
|
+
return data.id;
|
|
162
|
+
}
|
|
163
|
+
const location = response?.headers.get('location');
|
|
164
|
+
const segment = location
|
|
165
|
+
? location.split('/').filter(Boolean).pop()
|
|
166
|
+
: undefined;
|
|
167
|
+
if (segment) {
|
|
168
|
+
return decodeURIComponent(segment);
|
|
169
|
+
}
|
|
170
|
+
throw new WasServerError('Create response carried no resource id: the body has no `id` and there ' +
|
|
171
|
+
'is no `Location` header.');
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Unwraps a read response's pre-parsed JSON `data` as `T`, mapping a `null`
|
|
175
|
+
* response (a 404 that a `read` request resolved to `null`) to `null`. Captures
|
|
176
|
+
* the `response === null ? null : response.data as T` idiom shared across the
|
|
177
|
+
* handle read methods.
|
|
178
|
+
*
|
|
179
|
+
* @param response {HttpResponse | null}
|
|
180
|
+
* @returns {T | null}
|
|
181
|
+
*/
|
|
182
|
+
export function dataOrNull(response) {
|
|
183
|
+
return response === null ? null : response.data;
|
|
184
|
+
}
|
|
119
185
|
/**
|
|
120
186
|
* Reads a JSON response body, preferring the http-client's pre-parsed `data`
|
|
121
187
|
* and falling back to `response.json()` when it is absent.
|
|
122
188
|
*
|
|
189
|
+
* `@interop/http-client` pre-consumes the body into `.data` for JSON
|
|
190
|
+
* content-types, so a stored top-level `null` arrives as `.data === null`.
|
|
191
|
+
* Test for `undefined` rather than using `??`; otherwise the nullish fallback
|
|
192
|
+
* would re-invoke `.json()` on the already-consumed stream and throw.
|
|
193
|
+
*
|
|
123
194
|
* @param response {HttpResponse}
|
|
124
195
|
* @returns {Promise<unknown>}
|
|
125
196
|
*/
|
|
126
197
|
export async function readJsonData(response) {
|
|
127
|
-
return response.data
|
|
198
|
+
return response.data === undefined ? await response.json() : response.data;
|
|
128
199
|
}
|
|
129
200
|
/**
|
|
130
201
|
* Parses a resource GET response: returns the parsed object when the stored
|