@interop/was-client 0.78.0 → 0.80.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 +23 -11
- package/dist/Resource.d.ts +9 -0
- package/dist/Resource.d.ts.map +1 -1
- package/dist/Resource.js +10 -2
- package/dist/Resource.js.map +1 -1
- package/dist/codec.d.ts +8 -6
- package/dist/codec.d.ts.map +1 -1
- package/dist/codec.js.map +1 -1
- package/dist/edv/EdvCodec.d.ts +55 -4
- package/dist/edv/EdvCodec.d.ts.map +1 -1
- package/dist/edv/EdvCodec.js +255 -55
- package/dist/edv/EdvCodec.js.map +1 -1
- package/dist/edv/WasTransport.d.ts +11 -1
- package/dist/edv/WasTransport.d.ts.map +1 -1
- package/dist/edv/WasTransport.js +18 -3
- package/dist/edv/WasTransport.js.map +1 -1
- package/dist/edv/cipher.d.ts +6 -1
- package/dist/edv/cipher.d.ts.map +1 -1
- package/dist/edv/cipher.js +5 -0
- package/dist/edv/cipher.js.map +1 -1
- package/dist/edv/core.d.ts +2 -2
- package/dist/edv/core.d.ts.map +1 -1
- package/dist/edv/core.js +1 -1
- package/dist/edv/core.js.map +1 -1
- package/dist/edv/docCipher.d.ts +56 -7
- package/dist/edv/docCipher.d.ts.map +1 -1
- package/dist/edv/docCipher.js +17 -10
- package/dist/edv/docCipher.js.map +1 -1
- package/dist/edv/index.d.ts +2 -2
- 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/edv/refreshingDocCipher.d.ts +6 -5
- package/dist/edv/refreshingDocCipher.d.ts.map +1 -1
- package/dist/edv/refreshingDocCipher.js +72 -51
- package/dist/edv/refreshingDocCipher.js.map +1 -1
- package/dist/internal/conditional.d.ts +25 -2
- package/dist/internal/conditional.d.ts.map +1 -1
- package/dist/internal/conditional.js +33 -2
- package/dist/internal/conditional.js.map +1 -1
- package/dist/internal/write.d.ts +14 -4
- package/dist/internal/write.d.ts.map +1 -1
- package/dist/internal/write.js +82 -19
- package/dist/internal/write.js.map +1 -1
- package/dist/sync/index.d.ts +1 -1
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +1 -1
- package/dist/sync/index.js.map +1 -1
- package/dist/sync/port.d.ts +8 -1
- package/dist/sync/port.d.ts.map +1 -1
- package/dist/sync/port.js +31 -13
- package/dist/sync/port.js.map +1 -1
- package/dist/sync/types.d.ts +41 -16
- package/dist/sync/types.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -2,9 +2,10 @@ import { UnknownEpochError } from '../errors.js';
|
|
|
2
2
|
import { createEdvDocCipher } from './docCipher.js';
|
|
3
3
|
import { acquireDescriptor } from './acquire.js';
|
|
4
4
|
/**
|
|
5
|
-
* Builds
|
|
5
|
+
* Builds an {@link EdvDocCipher} whose descriptor is acquired through the
|
|
6
6
|
* source/cache seams and refreshed (once per instance) on an unknown-epoch
|
|
7
|
-
* decrypt
|
|
7
|
+
* decrypt or `isPendingStub`. The metadata last installed with `applyMeta` is
|
|
8
|
+
* re-applied to the rebuilt cipher, so a refresh keeps the index schema.
|
|
8
9
|
*
|
|
9
10
|
* With no `source` the descriptor is served from the cache alone and the
|
|
10
11
|
* refresh path is inert (an unknown-epoch decrypt propagates immediately) --
|
|
@@ -23,9 +24,12 @@ import { acquireDescriptor } from './acquire.js';
|
|
|
23
24
|
* @param options.cache {EncryptionDescriptorCache}
|
|
24
25
|
* @param [options.onFetchError] {function} observes swallowed
|
|
25
26
|
* descriptor-fetch failures
|
|
26
|
-
* @returns {Promise<
|
|
27
|
+
* @returns {Promise<EdvDocCipher>}
|
|
27
28
|
*/
|
|
28
29
|
export async function createRefreshingEdvDocCipher({ keyAgreementKey, keyResolver, collectionId, spaceId, idDerivation, source, cache, onFetchError }) {
|
|
30
|
+
// The `/meta` value last installed with `applyMeta`, replayed onto a rebuilt
|
|
31
|
+
// cipher so a refresh does not drop the collection's index schema.
|
|
32
|
+
let appliedMeta;
|
|
29
33
|
const build = async () => {
|
|
30
34
|
const encryption = await acquireDescriptor({
|
|
31
35
|
source,
|
|
@@ -38,7 +42,7 @@ export async function createRefreshingEdvDocCipher({ keyAgreementKey, keyResolve
|
|
|
38
42
|
'(fetched or cached). Every encrypted collection carries its key ' +
|
|
39
43
|
'epochs from provisioning; refusing to build a cipher without them.');
|
|
40
44
|
}
|
|
41
|
-
|
|
45
|
+
const cipher = await createEdvDocCipher({
|
|
42
46
|
keyAgreementKey,
|
|
43
47
|
keyResolver,
|
|
44
48
|
collectionId,
|
|
@@ -46,12 +50,71 @@ export async function createRefreshingEdvDocCipher({ keyAgreementKey, keyResolve
|
|
|
46
50
|
idDerivation,
|
|
47
51
|
encryption
|
|
48
52
|
});
|
|
53
|
+
if (appliedMeta !== undefined) {
|
|
54
|
+
await cipher.applyMeta(appliedMeta);
|
|
55
|
+
}
|
|
56
|
+
return cipher;
|
|
49
57
|
};
|
|
50
58
|
let inner = await build();
|
|
51
59
|
// The one descriptor refresh this cipher instance (= this collection this
|
|
52
60
|
// session) may spend, shared so concurrent unknown-epoch decrypts ride a
|
|
53
61
|
// single re-read instead of each spending one.
|
|
54
62
|
let refreshed = null;
|
|
63
|
+
/**
|
|
64
|
+
* Runs a read on the current inner cipher, refreshing the descriptor and
|
|
65
|
+
* retrying once when it throws `UnknownEpochError`.
|
|
66
|
+
*
|
|
67
|
+
* @param read {function} the read to run against a cipher
|
|
68
|
+
* @returns {Promise<T>}
|
|
69
|
+
*/
|
|
70
|
+
async function withRefresh(read) {
|
|
71
|
+
try {
|
|
72
|
+
return await read(inner);
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
// `instanceof` is safe here and only here: `inner` is built in this
|
|
76
|
+
// package by `createEdvDocCipher`, which raises this package's own
|
|
77
|
+
// class, so no injected seam is crossed. A caller classifying what
|
|
78
|
+
// THIS cipher throws is crossing one, and uses `isUnknownEpochError` /
|
|
79
|
+
// `isKeyUnwrapError` instead.
|
|
80
|
+
if (!(err instanceof UnknownEpochError) || !source) {
|
|
81
|
+
throw err;
|
|
82
|
+
}
|
|
83
|
+
if (!refreshed) {
|
|
84
|
+
const attempt = build().then(cipher => {
|
|
85
|
+
inner = cipher;
|
|
86
|
+
});
|
|
87
|
+
refreshed = attempt;
|
|
88
|
+
// Only a COMPLETED refresh is spent. A rejected one (the description
|
|
89
|
+
// could not be read and no cached copy answered either) un-arms the
|
|
90
|
+
// guard so a later unknown-epoch decrypt may try again; a successful
|
|
91
|
+
// refresh that still cannot route the envelope stays spent for the
|
|
92
|
+
// session, which is what keeps a genuinely foreign envelope from
|
|
93
|
+
// driving a refetch loop.
|
|
94
|
+
attempt.catch(() => {
|
|
95
|
+
if (refreshed === attempt) {
|
|
96
|
+
refreshed = null;
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
await refreshed;
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// The refresh failed, so nothing was learned about this envelope's
|
|
105
|
+
// epoch: surface the original UnknownEpochError rather than the
|
|
106
|
+
// build failure, so callers classifying on it (the create-loss
|
|
107
|
+
// re-mint) still see the row they exist to repair.
|
|
108
|
+
throw err;
|
|
109
|
+
}
|
|
110
|
+
// One retry under the swapped cipher. If the refresh was already
|
|
111
|
+
// spent before this decrypt began, this re-attempt is a local
|
|
112
|
+
// no-network decrypt that fails the same way -- so a genuinely
|
|
113
|
+
// foreign envelope still surfaces UnknownEpochError, and never a
|
|
114
|
+
// second description read.
|
|
115
|
+
return read(inner);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
55
118
|
return {
|
|
56
119
|
encrypt: options => inner.encrypt(options),
|
|
57
120
|
encryptUpdate: options => {
|
|
@@ -60,53 +123,11 @@ export async function createRefreshingEdvDocCipher({ keyAgreementKey, keyResolve
|
|
|
60
123
|
}
|
|
61
124
|
return inner.encryptUpdate(options);
|
|
62
125
|
},
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
// `instanceof` is safe here and only here: `inner` is built in this
|
|
69
|
-
// package by `createEdvDocCipher`, which raises this package's own
|
|
70
|
-
// class, so no injected seam is crossed. A caller classifying what
|
|
71
|
-
// THIS cipher throws is crossing one, and uses `isUnknownEpochError` /
|
|
72
|
-
// `isKeyUnwrapError` instead.
|
|
73
|
-
if (!(err instanceof UnknownEpochError) || !source) {
|
|
74
|
-
throw err;
|
|
75
|
-
}
|
|
76
|
-
if (!refreshed) {
|
|
77
|
-
const attempt = build().then(cipher => {
|
|
78
|
-
inner = cipher;
|
|
79
|
-
});
|
|
80
|
-
refreshed = attempt;
|
|
81
|
-
// Only a COMPLETED refresh is spent. A rejected one (the description
|
|
82
|
-
// could not be read and no cached copy answered either) un-arms the
|
|
83
|
-
// guard so a later unknown-epoch decrypt may try again; a successful
|
|
84
|
-
// refresh that still cannot route the envelope stays spent for the
|
|
85
|
-
// session, which is what keeps a genuinely foreign envelope from
|
|
86
|
-
// driving a refetch loop.
|
|
87
|
-
attempt.catch(() => {
|
|
88
|
-
if (refreshed === attempt) {
|
|
89
|
-
refreshed = null;
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
try {
|
|
94
|
-
await refreshed;
|
|
95
|
-
}
|
|
96
|
-
catch {
|
|
97
|
-
// The refresh failed, so nothing was learned about this envelope's
|
|
98
|
-
// epoch: surface the original UnknownEpochError rather than the
|
|
99
|
-
// build failure, so callers classifying on it (the create-loss
|
|
100
|
-
// re-mint) still see the row they exist to repair.
|
|
101
|
-
throw err;
|
|
102
|
-
}
|
|
103
|
-
// One retry under the swapped cipher. If the refresh was already
|
|
104
|
-
// spent before this decrypt began, this re-attempt is a local
|
|
105
|
-
// no-network decrypt that fails the same way -- so a genuinely
|
|
106
|
-
// foreign envelope still surfaces UnknownEpochError, and never a
|
|
107
|
-
// second description read.
|
|
108
|
-
return inner.decrypt(options);
|
|
109
|
-
}
|
|
126
|
+
decrypt: options => withRefresh(cipher => cipher.decrypt(options)),
|
|
127
|
+
isPendingStub: options => withRefresh(cipher => cipher.isPendingStub(options)),
|
|
128
|
+
async applyMeta(options) {
|
|
129
|
+
appliedMeta = options;
|
|
130
|
+
return inner.applyMeta(options);
|
|
110
131
|
}
|
|
111
132
|
};
|
|
112
133
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refreshingDocCipher.js","sourceRoot":"","sources":["../../src/edv/refreshingDocCipher.ts"],"names":[],"mappings":"AAqCA,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAChD,OAAO,EAAE,kBAAkB,
|
|
1
|
+
{"version":3,"file":"refreshingDocCipher.js","sourceRoot":"","sources":["../../src/edv/refreshingDocCipher.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,6 +17,13 @@ import { NotSupportedError } from '../errors.js';
|
|
|
17
17
|
* stamp). HTTP header names are case-insensitive; the wire form is `Key-Epoch`.
|
|
18
18
|
*/
|
|
19
19
|
export declare const KEY_EPOCH_HEADER = "Key-Epoch";
|
|
20
|
+
/**
|
|
21
|
+
* The request header a content write or delete declares its writer-attribution
|
|
22
|
+
* label under (spec "Writer attribution"), stamping it onto the Resource
|
|
23
|
+
* Metadata `writerId` property (an absent header clears any prior label). HTTP
|
|
24
|
+
* header names are case-insensitive; the wire form is `Writer-Id`.
|
|
25
|
+
*/
|
|
26
|
+
export declare const WRITER_ID_HEADER = "Writer-Id";
|
|
20
27
|
/**
|
|
21
28
|
* A conditional-write precondition: `ifMatch` is the quoted ETag an
|
|
22
29
|
* update-if-unchanged write must match; `ifNoneMatch` requests a create-if-absent
|
|
@@ -61,12 +68,23 @@ export declare function namedPrecondition(precondition?: WritePrecondition): Wri
|
|
|
61
68
|
* @returns {void}
|
|
62
69
|
*/
|
|
63
70
|
export declare function assertSinglePrecondition(precondition?: WritePrecondition): void;
|
|
71
|
+
/**
|
|
72
|
+
* Throws `ValidationError` when a writer-attribution label is present but
|
|
73
|
+
* empty. Per the spec, `writerId` is an opaque non-empty string; a present but
|
|
74
|
+
* empty value is a caller bug, refused locally rather than sent as an
|
|
75
|
+
* `invalid-request-body` the server would otherwise have to reject.
|
|
76
|
+
*
|
|
77
|
+
* @param [writerId] {string}
|
|
78
|
+
* @returns {void}
|
|
79
|
+
*/
|
|
80
|
+
export declare function assertWriterId(writerId?: string): void;
|
|
64
81
|
/**
|
|
65
82
|
* Builds the headers for a write request: the content-type (when present) and
|
|
66
83
|
* the conditional-write precondition headers (`If-Match` / `If-None-Match: *`).
|
|
67
84
|
* Returns `undefined` when no header is needed, matching the request layer's
|
|
68
85
|
* optional `headers`. Throws `ValidationError` when the precondition names both
|
|
69
|
-
* `ifMatch` and `ifNoneMatch`, a pair no server state can satisfy
|
|
86
|
+
* `ifMatch` and `ifNoneMatch`, a pair no server state can satisfy, or when
|
|
87
|
+
* `writerId` is present but empty.
|
|
70
88
|
*
|
|
71
89
|
* @param options {object}
|
|
72
90
|
* @param [options.contentType] {string} the body content-type, if any
|
|
@@ -76,12 +94,17 @@ export declare function assertSinglePrecondition(precondition?: WritePreconditio
|
|
|
76
94
|
* encrypted this write under; emitted as the `Key-Epoch` header so the
|
|
77
95
|
* server stamps the Resource's epoch. Omitted when absent (which clears any
|
|
78
96
|
* prior stamp on the server).
|
|
97
|
+
* @param [options.writerId] {string} the writer-attribution label this
|
|
98
|
+
* write declares; emitted as the `Writer-Id` header. Omitted when absent
|
|
99
|
+
* (which clears any prior label on the server, per the spec's
|
|
100
|
+
* declare-or-clear rule).
|
|
79
101
|
* @returns {Record<string, string> | undefined}
|
|
80
102
|
*/
|
|
81
|
-
export declare function writeHeaders({ contentType, precondition, epoch }: {
|
|
103
|
+
export declare function writeHeaders({ contentType, precondition, epoch, writerId }: {
|
|
82
104
|
contentType?: string;
|
|
83
105
|
precondition?: WritePrecondition;
|
|
84
106
|
epoch?: string;
|
|
107
|
+
writerId?: string;
|
|
85
108
|
}): Record<string, string> | undefined;
|
|
86
109
|
/**
|
|
87
110
|
* The refusal for a guarded write whose pin the read it is based on never
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conditional.d.ts","sourceRoot":"","sources":["../../src/internal/conditional.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC7D,OAAO,EACL,iBAAiB,EAGlB,MAAM,cAAc,CAAA;AAErB;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,cAAc,CAAA;AAE3C;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,YAAY,GAAG,iBAAiB,CAE5E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,YAAY,CAAC,EAAE,iBAAiB,GAC/B,iBAAiB,GAAG,SAAS,CAK/B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CACtC,YAAY,CAAC,EAAE,iBAAiB,GAC/B,IAAI,CAQN;AAED
|
|
1
|
+
{"version":3,"file":"conditional.d.ts","sourceRoot":"","sources":["../../src/internal/conditional.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC7D,OAAO,EACL,iBAAiB,EAGlB,MAAM,cAAc,CAAA;AAErB;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,cAAc,CAAA;AAE3C;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,cAAc,CAAA;AAE3C;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,YAAY,GAAG,iBAAiB,CAE5E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,YAAY,CAAC,EAAE,iBAAiB,GAC/B,iBAAiB,GAAG,SAAS,CAK/B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CACtC,YAAY,CAAC,EAAE,iBAAiB,GAC/B,IAAI,CAQN;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAOtD;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,YAAY,CAAC,EAC3B,WAAW,EACX,YAAiB,EACjB,KAAK,EACL,QAAQ,EACT,EAAE;IACD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,iBAAiB,CAAA;IAChC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAqBrC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,2BAA2B,CAAC,EAC1C,SAAS,EACV,EAAE;IACD,SAAS,EAAE,MAAM,CAAA;CAClB,GAAG,iBAAiB,CASpB;AAED;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,YAAY,GAAG,IAAI,GAAG,MAAM,GAAG,SAAS,CAE1E;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,gCAAgC,CAAC,EAC/C,IAAI,EACJ,OAAO,EACP,YAAY,EACb,EAAE;IACD,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,YAAY,GAAG,IAAI,CAAA;IAC5B,YAAY,CAAC,EAAE,iBAAiB,CAAA;CACjC,GAAG,IAAI,CAkCP"}
|
|
@@ -5,6 +5,13 @@ import { NotSupportedError, PreconditionFailedError, ValidationError } from '../
|
|
|
5
5
|
* stamp). HTTP header names are case-insensitive; the wire form is `Key-Epoch`.
|
|
6
6
|
*/
|
|
7
7
|
export const KEY_EPOCH_HEADER = 'Key-Epoch';
|
|
8
|
+
/**
|
|
9
|
+
* The request header a content write or delete declares its writer-attribution
|
|
10
|
+
* label under (spec "Writer attribution"), stamping it onto the Resource
|
|
11
|
+
* Metadata `writerId` property (an absent header clears any prior label). HTTP
|
|
12
|
+
* header names are case-insensitive; the wire form is `Writer-Id`.
|
|
13
|
+
*/
|
|
14
|
+
export const WRITER_ID_HEADER = 'Writer-Id';
|
|
8
15
|
/**
|
|
9
16
|
* Extracts the conditional-write precondition a codec attached to its encoded
|
|
10
17
|
* write (`EncodedWrite.ifMatch` / `ifNoneMatch`). The one mapping shared by
|
|
@@ -52,12 +59,28 @@ export function assertSinglePrecondition(precondition) {
|
|
|
52
59
|
'`ifMatch` to update or `ifNoneMatch: true` to create.');
|
|
53
60
|
}
|
|
54
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Throws `ValidationError` when a writer-attribution label is present but
|
|
64
|
+
* empty. Per the spec, `writerId` is an opaque non-empty string; a present but
|
|
65
|
+
* empty value is a caller bug, refused locally rather than sent as an
|
|
66
|
+
* `invalid-request-body` the server would otherwise have to reject.
|
|
67
|
+
*
|
|
68
|
+
* @param [writerId] {string}
|
|
69
|
+
* @returns {void}
|
|
70
|
+
*/
|
|
71
|
+
export function assertWriterId(writerId) {
|
|
72
|
+
if (writerId !== undefined && writerId.length === 0) {
|
|
73
|
+
throw new ValidationError('A `writerId` must be a non-empty string: pass a label to declare it, ' +
|
|
74
|
+
'or omit the option to send no `Writer-Id` header.');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
55
77
|
/**
|
|
56
78
|
* Builds the headers for a write request: the content-type (when present) and
|
|
57
79
|
* the conditional-write precondition headers (`If-Match` / `If-None-Match: *`).
|
|
58
80
|
* Returns `undefined` when no header is needed, matching the request layer's
|
|
59
81
|
* optional `headers`. Throws `ValidationError` when the precondition names both
|
|
60
|
-
* `ifMatch` and `ifNoneMatch`, a pair no server state can satisfy
|
|
82
|
+
* `ifMatch` and `ifNoneMatch`, a pair no server state can satisfy, or when
|
|
83
|
+
* `writerId` is present but empty.
|
|
61
84
|
*
|
|
62
85
|
* @param options {object}
|
|
63
86
|
* @param [options.contentType] {string} the body content-type, if any
|
|
@@ -67,10 +90,15 @@ export function assertSinglePrecondition(precondition) {
|
|
|
67
90
|
* encrypted this write under; emitted as the `Key-Epoch` header so the
|
|
68
91
|
* server stamps the Resource's epoch. Omitted when absent (which clears any
|
|
69
92
|
* prior stamp on the server).
|
|
93
|
+
* @param [options.writerId] {string} the writer-attribution label this
|
|
94
|
+
* write declares; emitted as the `Writer-Id` header. Omitted when absent
|
|
95
|
+
* (which clears any prior label on the server, per the spec's
|
|
96
|
+
* declare-or-clear rule).
|
|
70
97
|
* @returns {Record<string, string> | undefined}
|
|
71
98
|
*/
|
|
72
|
-
export function writeHeaders({ contentType, precondition = {}, epoch }) {
|
|
99
|
+
export function writeHeaders({ contentType, precondition = {}, epoch, writerId }) {
|
|
73
100
|
assertSinglePrecondition(precondition);
|
|
101
|
+
assertWriterId(writerId);
|
|
74
102
|
const headers = {};
|
|
75
103
|
if (contentType) {
|
|
76
104
|
headers['content-type'] = contentType;
|
|
@@ -85,6 +113,9 @@ export function writeHeaders({ contentType, precondition = {}, epoch }) {
|
|
|
85
113
|
// This record keys every header in lower case; the name is case-insensitive.
|
|
86
114
|
headers[KEY_EPOCH_HEADER.toLowerCase()] = epoch;
|
|
87
115
|
}
|
|
116
|
+
if (writerId !== undefined) {
|
|
117
|
+
headers[WRITER_ID_HEADER.toLowerCase()] = writerId;
|
|
118
|
+
}
|
|
88
119
|
return Object.keys(headers).length > 0 ? headers : undefined;
|
|
89
120
|
}
|
|
90
121
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conditional.js","sourceRoot":"","sources":["../../src/internal/conditional.ts"],"names":[],"mappings":"AAYA,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,eAAe,EAChB,MAAM,cAAc,CAAA;AAErB;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,WAAW,CAAA;AAa3C;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAqB;IACvD,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAA;AACvE,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,iBAAiB,CAC/B,YAAgC;IAEhC,OAAO,YAAY,KAAK,SAAS;QAC/B,CAAC,YAAY,CAAC,OAAO,KAAK,SAAS,IAAI,YAAY,CAAC,WAAW,CAAC;QAChE,CAAC,CAAC,YAAY;QACd,CAAC,CAAC,SAAS,CAAA;AACf,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,wBAAwB,CACtC,YAAgC;IAEhC,IAAI,YAAY,EAAE,OAAO,KAAK,SAAS,IAAI,YAAY,CAAC,WAAW,EAAE,CAAC;QACpE,MAAM,IAAI,eAAe,CACvB,yEAAyE;YACvE,gEAAgE;YAChE,uDAAuD,CAC1D,CAAA;IACH,CAAC;AACH,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"conditional.js","sourceRoot":"","sources":["../../src/internal/conditional.ts"],"names":[],"mappings":"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"}
|
package/dist/internal/write.d.ts
CHANGED
|
@@ -15,8 +15,9 @@
|
|
|
15
15
|
*
|
|
16
16
|
* A codec may also answer `encode` with a multi-request `ChunkedWrite` plan
|
|
17
17
|
* rather than an `EncodedWrite`. `insertResource` runs the plan over the
|
|
18
|
-
* signed-request context built here (`codecRequestContext`)
|
|
19
|
-
*
|
|
18
|
+
* signed-request context built here (`codecRequestContext`). `upsertResource`
|
|
19
|
+
* runs one only to create a resource at an id that holds none, and refuses it
|
|
20
|
+
* over an existing document, since a plan cannot replace one.
|
|
20
21
|
*/
|
|
21
22
|
import type { HttpResponse } from '@interop/http-client';
|
|
22
23
|
import type { CodecRequestContext, EncodedWrite, ResourceCodec } from '../codec.js';
|
|
@@ -141,6 +142,13 @@ export declare function insertResource(context: ClientContext, { itemsPath, path
|
|
|
141
142
|
* re-thrown here with a message naming the real cause, instead of surfacing
|
|
142
143
|
* as an inexplicable failed create. Conditional codecs therefore need read
|
|
143
144
|
* access to update an existing document.
|
|
145
|
+
* - A codec may answer with a multi-request `ChunkedWrite` plan (the EDV
|
|
146
|
+
* codec's large binary write). When the pre-read found no document, the
|
|
147
|
+
* plan runs over the handle's signed-request context and creates the
|
|
148
|
+
* resource at this id, guarded like any fresh insert: a 412 surfaces as
|
|
149
|
+
* `PreconditionFailedError`, under the same masked-404 message. Over an
|
|
150
|
+
* existing document the plan is refused with `ValidationError`, since a
|
|
151
|
+
* plan cannot replace a document.
|
|
144
152
|
*
|
|
145
153
|
* @param context {ClientContext}
|
|
146
154
|
* @param options {object}
|
|
@@ -152,7 +160,7 @@ export declare function insertResource(context: ClientContext, { itemsPath, path
|
|
|
152
160
|
* @param [options.capability] {IZcap}
|
|
153
161
|
* @param [options.precondition] {WritePrecondition} the caller's explicit
|
|
154
162
|
* precondition (used only for a non-conditional codec)
|
|
155
|
-
* @returns {Promise<
|
|
163
|
+
* @returns {Promise<{ etag?: string }>} the stored resource's new ETag
|
|
156
164
|
*/
|
|
157
165
|
export declare function upsertResource(context: ClientContext, { path, codec, id, data, contentType, capability, precondition: callerPrecondition }: {
|
|
158
166
|
path: string;
|
|
@@ -162,5 +170,7 @@ export declare function upsertResource(context: ClientContext, { path, codec, id
|
|
|
162
170
|
contentType?: string;
|
|
163
171
|
capability?: IZcap;
|
|
164
172
|
precondition?: WritePrecondition;
|
|
165
|
-
}): Promise<
|
|
173
|
+
}): Promise<{
|
|
174
|
+
etag?: string;
|
|
175
|
+
}>;
|
|
166
176
|
//# sourceMappingURL=write.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/internal/write.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH
|
|
1
|
+
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/internal/write.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACxD,OAAO,KAAK,EAEV,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACd,MAAM,aAAa,CAAA;AAGpB,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAUjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAEzD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,aAAa,EACtB,EACE,IAAI,EACJ,MAAM,EACN,OAAO,EACP,UAAU,EACV,YAAY,EACb,EAAE;IACD,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,YAAY,CAAA;IACrB,UAAU,CAAC,EAAE,KAAK,CAAA;IAClB,YAAY,CAAC,EAAE,iBAAiB,CAAA;CACjC,GACA,OAAO,CAAC,YAAY,CAAC,CAcvB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,aAAa,EACtB,EAAE,UAAU,EAAE,GAAE;IAAE,UAAU,CAAC,EAAE,KAAK,CAAA;CAAO,GAC1C,mBAAmB,CASrB;AAED;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GACrB;IACE,OAAO,CAAC,EAAE,KAAK,CAAA;IACf,OAAO,EAAE,YAAY,CAAA;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,YAAY,CAAA;CACvB,GACD;IACE,OAAO,EAAE,IAAI,CAAA;IACb,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAEL;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,aAAa,EACtB,EACE,SAAS,EACT,SAAS,EACT,KAAK,EACL,IAAI,EACJ,WAAW,EACX,UAAU,EACX,EAAE;IACD,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAA;IACjC,KAAK,EAAE,aAAa,CAAA;IACpB,IAAI,EAAE,YAAY,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,KAAK,CAAA;CACnB,GACA,OAAO,CAAC,aAAa,CAAC,CA2BxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,aAAa,EACtB,EACE,IAAI,EACJ,KAAK,EACL,EAAE,EACF,IAAI,EACJ,WAAW,EACX,UAAU,EACV,YAAY,EAAE,kBAAkB,EACjC,EAAE;IACD,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,aAAa,CAAA;IACpB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,YAAY,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,KAAK,CAAA;IAClB,YAAY,CAAC,EAAE,iBAAiB,CAAA;CACjC,GACA,OAAO,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAiE5B"}
|
package/dist/internal/write.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isChunkedWrite } from '../codec.js';
|
|
2
2
|
import { PreconditionFailedError, ValidationError } from '../errors.js';
|
|
3
3
|
import { send } from './request.js';
|
|
4
|
-
import { assertPreconditionAgainstPreRead, assertSinglePrecondition, encodedPrecondition, writeHeaders, namedPrecondition } from './conditional.js';
|
|
4
|
+
import { assertPreconditionAgainstPreRead, assertSinglePrecondition, encodedPrecondition, readEtag, writeHeaders, namedPrecondition } from './conditional.js';
|
|
5
5
|
/**
|
|
6
6
|
* Sends an encoded write (`PUT`/`POST`) to a resource path, applying the
|
|
7
7
|
* encoded body (`json` or `body`), its content-type, and the conditional-write
|
|
@@ -135,6 +135,13 @@ export async function insertResource(context, { itemsPath, pathForId, codec, dat
|
|
|
135
135
|
* re-thrown here with a message naming the real cause, instead of surfacing
|
|
136
136
|
* as an inexplicable failed create. Conditional codecs therefore need read
|
|
137
137
|
* access to update an existing document.
|
|
138
|
+
* - A codec may answer with a multi-request `ChunkedWrite` plan (the EDV
|
|
139
|
+
* codec's large binary write). When the pre-read found no document, the
|
|
140
|
+
* plan runs over the handle's signed-request context and creates the
|
|
141
|
+
* resource at this id, guarded like any fresh insert: a 412 surfaces as
|
|
142
|
+
* `PreconditionFailedError`, under the same masked-404 message. Over an
|
|
143
|
+
* existing document the plan is refused with `ValidationError`, since a
|
|
144
|
+
* plan cannot replace a document.
|
|
138
145
|
*
|
|
139
146
|
* @param context {ClientContext}
|
|
140
147
|
* @param options {object}
|
|
@@ -146,7 +153,7 @@ export async function insertResource(context, { itemsPath, pathForId, codec, dat
|
|
|
146
153
|
* @param [options.capability] {IZcap}
|
|
147
154
|
* @param [options.precondition] {WritePrecondition} the caller's explicit
|
|
148
155
|
* precondition (used only for a non-conditional codec)
|
|
149
|
-
* @returns {Promise<
|
|
156
|
+
* @returns {Promise<{ etag?: string }>} the stored resource's new ETag
|
|
150
157
|
*/
|
|
151
158
|
export async function upsertResource(context, { path, codec, id, data, contentType, capability, precondition: callerPrecondition }) {
|
|
152
159
|
// An empty precondition object (the handle's default) names no baseline.
|
|
@@ -180,15 +187,12 @@ export async function upsertResource(context, { path, codec, id, data, contentTy
|
|
|
180
187
|
})
|
|
181
188
|
});
|
|
182
189
|
if (isChunkedWrite(write)) {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
'answered with a multi-request write plan, which is only auto-routed ' +
|
|
190
|
-
'on the insert path (add()). Add it as a new resource' +
|
|
191
|
-
(write.guidance === undefined ? '.' : `. ${write.guidance}`));
|
|
190
|
+
return await runChunkedCreate(context, {
|
|
191
|
+
path,
|
|
192
|
+
write,
|
|
193
|
+
capability,
|
|
194
|
+
current
|
|
195
|
+
});
|
|
192
196
|
}
|
|
193
197
|
const encoded = write;
|
|
194
198
|
// A conditional codec computes the precondition itself (from the sequence /
|
|
@@ -198,27 +202,86 @@ export async function upsertResource(context, { path, codec, id, data, contentTy
|
|
|
198
202
|
? encodedPrecondition(encoded)
|
|
199
203
|
: precondition;
|
|
200
204
|
try {
|
|
201
|
-
|
|
205
|
+
const response = await sendEncodedWrite(context, {
|
|
202
206
|
path,
|
|
203
207
|
method: 'PUT',
|
|
204
208
|
capability,
|
|
205
209
|
encoded,
|
|
206
210
|
precondition: chosen
|
|
207
211
|
});
|
|
212
|
+
return { etag: readEtag(response) };
|
|
208
213
|
}
|
|
209
214
|
catch (err) {
|
|
210
215
|
if (err instanceof PreconditionFailedError &&
|
|
211
216
|
codec.conditionalWrites &&
|
|
212
217
|
current === null) {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
218
|
+
throw maskedInsertRejected({ err, path });
|
|
219
|
+
}
|
|
220
|
+
throw err;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Runs a codec's multi-request plan for a write by id, which creates the
|
|
225
|
+
* resource at that id. Only a pre-read that found no document (`current`
|
|
226
|
+
* is `null`) lets it run: over an existing document, and after no pre-read at
|
|
227
|
+
* all, the plan is refused, since a plan writes a fresh document and cannot
|
|
228
|
+
* reconcile an existing one's stored parts with the new payload. The codec
|
|
229
|
+
* supplies the scheme-specific recovery advice; this layer knows nothing
|
|
230
|
+
* about how it stores things.
|
|
231
|
+
*
|
|
232
|
+
* The plan guards its own first write as create-if-absent, so a 412 means
|
|
233
|
+
* the id was taken after the pre-read, or is held by a document the
|
|
234
|
+
* capability cannot read. It surfaces as `PreconditionFailedError` with the
|
|
235
|
+
* masked-404 message of any other fresh insert by id.
|
|
236
|
+
*
|
|
237
|
+
* @param context {ClientContext}
|
|
238
|
+
* @param options {object}
|
|
239
|
+
* @param options.path {string} the resource path the plan writes
|
|
240
|
+
* @param options.write {ChunkedWrite} the codec's plan
|
|
241
|
+
* @param [options.capability] {IZcap}
|
|
242
|
+
* @param options.current {HttpResponse | null | undefined} the pre-read's
|
|
243
|
+
* result, `undefined` when the codec asked for none
|
|
244
|
+
* @returns {Promise<{ etag?: string }>} the stored resource's new ETag
|
|
245
|
+
*/
|
|
246
|
+
async function runChunkedCreate(context, { path, write, capability, current }) {
|
|
247
|
+
if (current !== null) {
|
|
248
|
+
throw new ValidationError(`Cannot write this payload to "${path}": the collection's codec ` +
|
|
249
|
+
'answered with a multi-request write plan, which can only create a ' +
|
|
250
|
+
'resource at an id that holds none, and a document is stored here. ' +
|
|
251
|
+
'Delete the resource first, or add the payload as a new resource ' +
|
|
252
|
+
'(add())' +
|
|
253
|
+
(write.guidance === undefined ? '.' : `. ${write.guidance}`));
|
|
254
|
+
}
|
|
255
|
+
try {
|
|
256
|
+
const { etag } = await write.execute(codecRequestContext(context, { capability }));
|
|
257
|
+
return { etag };
|
|
258
|
+
}
|
|
259
|
+
catch (err) {
|
|
260
|
+
// `current` is `null`, so a conditional codec pre-read and found nothing.
|
|
261
|
+
if (err instanceof PreconditionFailedError) {
|
|
262
|
+
throw maskedInsertRejected({ err, path });
|
|
220
263
|
}
|
|
221
264
|
throw err;
|
|
222
265
|
}
|
|
223
266
|
}
|
|
267
|
+
/**
|
|
268
|
+
* The error for a fresh insert by id the server rejected with 412 after the
|
|
269
|
+
* pre-read found nothing: the document exists, but its current version is not
|
|
270
|
+
* readable with this capability (a masked 404), or it appeared since the
|
|
271
|
+
* pre-read. The server's error is kept as the cause.
|
|
272
|
+
*
|
|
273
|
+
* @param options {object}
|
|
274
|
+
* @param options.err {PreconditionFailedError} the server's 412
|
|
275
|
+
* @param options.path {string} the resource path written
|
|
276
|
+
* @returns {PreconditionFailedError}
|
|
277
|
+
*/
|
|
278
|
+
function maskedInsertRejected({ err, path }) {
|
|
279
|
+
const { status, type, title, details, requestUrl } = err;
|
|
280
|
+
return new PreconditionFailedError(`Cannot update the document at "${path}": it exists, but its current ` +
|
|
281
|
+
'version is not readable with this capability (WAS masks ' +
|
|
282
|
+
'unauthorized reads as 404), so the write was encoded as a fresh ' +
|
|
283
|
+
'insert and the server rejected it. A conditional codec ' +
|
|
284
|
+
'(e.g. the EDV codec) needs read access to update an existing ' +
|
|
285
|
+
'document.', { status, type, title, details, requestUrl, cause: err });
|
|
286
|
+
}
|
|
224
287
|
//# sourceMappingURL=write.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/internal/write.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/internal/write.ts"],"names":[],"mappings":"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"}
|
package/dist/sync/index.d.ts
CHANGED
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
* boundary the predicates are the contract
|
|
56
56
|
* (`decisions/0001-cross-package-errors-match-by-name.md`).
|
|
57
57
|
*/
|
|
58
|
-
export { createWasSyncPort, KEY_EPOCH_HEADER, parseEtag } from './port.js';
|
|
58
|
+
export { createWasSyncPort, KEY_EPOCH_HEADER, parseEtag, WRITER_ID_HEADER } from './port.js';
|
|
59
59
|
export { httpStatus as errorStatus, errorMessage, requireResourceId } from '../errors.js';
|
|
60
60
|
export { contentCid, cidFrom, deriveSpaceId } from './cid.js';
|
|
61
61
|
export { isEncryptedEnvelope } from './envelope.js';
|
package/dist/sync/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,SAAS,EACT,gBAAgB,EACjB,MAAM,WAAW,CAAA;AAIlB,OAAO,EACL,UAAU,IAAI,WAAW,EACzB,YAAY,EACZ,iBAAiB,EAClB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AACnD,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAA;AAC/D,OAAO,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAA;AACzE,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACpB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,eAAe,EACf,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EACrB,MAAM,cAAc,CAAA;AAErB,YAAY,EACV,IAAI,EACJ,cAAc,EACd,OAAO,EACP,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,UAAU,EACV,WAAW,EACX,SAAS,EACV,MAAM,YAAY,CAAA"}
|
package/dist/sync/index.js
CHANGED
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
* boundary the predicates are the contract
|
|
56
56
|
* (`decisions/0001-cross-package-errors-match-by-name.md`).
|
|
57
57
|
*/
|
|
58
|
-
export { createWasSyncPort, KEY_EPOCH_HEADER, parseEtag } from './port.js';
|
|
58
|
+
export { createWasSyncPort, KEY_EPOCH_HEADER, parseEtag, WRITER_ID_HEADER } from './port.js';
|
|
59
59
|
// The sync subpath's names for the client's own error accessors, so a
|
|
60
60
|
// sync-only consumer reads a raw ky/ezcap failure without importing the core
|
|
61
61
|
// entry.
|
package/dist/sync/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,SAAS,EACT,gBAAgB,EACjB,MAAM,WAAW,CAAA;AAClB,sEAAsE;AACtE,6EAA6E;AAC7E,SAAS;AACT,OAAO,EACL,UAAU,IAAI,WAAW,EACzB,YAAY,EACZ,iBAAiB,EAClB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AACnD,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAA;AAC/D,OAAO,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAA;AACzE,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACpB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,eAAe,EACf,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EACrB,MAAM,cAAc,CAAA"}
|
package/dist/sync/port.d.ts
CHANGED
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
* port has no signal for still leaves this subpath as a typed `WasError`.
|
|
39
39
|
*/
|
|
40
40
|
import type { WasClient } from '../WasClient.js';
|
|
41
|
-
import { KEY_EPOCH_HEADER } from '../internal/conditional.js';
|
|
41
|
+
import { KEY_EPOCH_HEADER, WRITER_ID_HEADER } from '../internal/conditional.js';
|
|
42
42
|
import type { IZcap } from '../types.js';
|
|
43
43
|
import type { WasSyncPort } from './types.js';
|
|
44
44
|
/**
|
|
@@ -48,6 +48,13 @@ import type { WasSyncPort } from './types.js';
|
|
|
48
48
|
* of the sync subpath's public surface.
|
|
49
49
|
*/
|
|
50
50
|
export { KEY_EPOCH_HEADER };
|
|
51
|
+
/**
|
|
52
|
+
* The request header a content write or delete declares its writer-attribution
|
|
53
|
+
* label under, stamping it onto the Resource Metadata `writerId` property.
|
|
54
|
+
* Defined next to the header assembly it drives (`internal/conditional.ts`)
|
|
55
|
+
* and re-exported here as part of the sync subpath's public surface.
|
|
56
|
+
*/
|
|
57
|
+
export { WRITER_ID_HEADER };
|
|
51
58
|
/**
|
|
52
59
|
* Parses a quoted strong `ETag` into its numeric revision: the decimal
|
|
53
60
|
* integer after the LAST `.` inside the quotes (`"3mJr7AoUXx2.3"` to `3`).
|
package/dist/sync/port.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"port.d.ts","sourceRoot":"","sources":["../../src/sync/port.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAEhD,OAAO,
|
|
1
|
+
{"version":3,"file":"port.d.ts","sourceRoot":"","sources":["../../src/sync/port.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAEhD,OAAO,EAEL,gBAAgB,EAGhB,gBAAgB,EACjB,MAAM,4BAA4B,CAAA;AAYnC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,KAAK,EAIV,WAAW,EAEZ,MAAM,YAAY,CAAA;AAEnB;;;;;GAKG;AACH,OAAO,EAAE,gBAAgB,EAAE,CAAA;AAE3B;;;;;GAKG;AACH,OAAO,EAAE,gBAAgB,EAAE,CAAA;AAyG3B;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAW7E;AAwBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,GAAG,EACH,OAAO,EACP,YAAY,EACZ,UAAU,EACV,aAAqB,EACtB,EAAE;IACD,GAAG,EAAE,SAAS,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,KAAK,CAAA;IAClB,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB,GAAG,WAAW,CAwPd"}
|