@metalabel/dfos-client 0.46.0 → 0.47.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/LICENSE +1 -1
- package/README.md +28 -0
- package/dist/api-auth.d.ts +1 -1
- package/dist/{chunk-63XCFYOE.js → chunk-KY632J74.js} +3 -0
- package/dist/index.d.ts +49 -4
- package/dist/index.js +58 -7
- package/dist/{memory-CL1DM6Ud.d.ts → memory-BuTsEPZI.d.ts} +1 -1
- package/dist/siwd.d.ts +1 -1
- package/dist/store/index.d.ts +2 -2
- package/dist/store/index.js +9 -1
- package/dist/{types-ByxTj1u-.d.ts → types-BfzEg_gw.d.ts} +18 -0
- package/package.json +6 -6
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -57,6 +57,34 @@ createClient({ relays: [...], quorum: 2 }); // require 2 relays to return the sa
|
|
|
57
57
|
|
|
58
58
|
`quorum: 1` (default) is first-wins with failover. `provenance.agreed` reports whether the threshold was met.
|
|
59
59
|
|
|
60
|
+
### Divergence — and the way out of it
|
|
61
|
+
|
|
62
|
+
The cached prefix is a **pin**: once a chain's first N operations have verified here, a later read has to extend them. A relay answering with a _different_ operation at a position the pin covers is contradicting proof rather than carrying news, so the read fails with a `DivergenceError`.
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import { divergenceErrorFrom } from '@metalabel/dfos-client';
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
await client.identity(did);
|
|
69
|
+
} catch (err) {
|
|
70
|
+
const d = divergenceErrorFrom(err); // walks `cause` — the fan-out wraps its candidate's failure
|
|
71
|
+
if (d) {
|
|
72
|
+
d.chainType; // 'identity' | 'content' — a content read can diverge on its CREATOR's chain
|
|
73
|
+
d.chainId;
|
|
74
|
+
d.cachedHeadCID; // the tip this client proved
|
|
75
|
+
d.liveHeadCID; // the tip the relays serve now
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**Nothing is discarded automatically.** A client that healed itself would erase the only evidence a rewrite happened, which is the reason the prefix is pinned at all. The undo is explicit and per-chain:
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
await client.discardCachedChain('identity', did); // this chain's prefix only; nothing else, nowhere else
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The next read of that chain folds cold from genesis and recomputes every signature and CID. Deleting is local: no relay is touched and no operation is destroyed. It is idempotent, safe for a chain that was never cached, and answers `false` only when the configured `Store` exposes no `delete` (both bundled stores do).
|
|
87
|
+
|
|
60
88
|
### The free floor
|
|
61
89
|
|
|
62
90
|
```typescript
|
package/dist/api-auth.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { ApiRequestVerifyError, DEFAULT_PROOF_SKEW_SECONDS, DEFAULT_PROOF_WINDOW_SECONDS, DFOS_AUTH_SCHEME, EMPTY_BODY_SHA256, IDENTITY_PROOF_JWS_TYP, IdentityProofPayload, MAX_BODY_BYTES, MAX_PROOF_FRESHNESS_SPAN_SECONDS, MAX_REQUEST_PROOF_SIZE, ProofExtraMembers, REQUEST_PROOF_JWS_TYP, RequestProofFailurePhase, RequestProofFailureReason, RequestProofPayload, SignApiIdentityRequestInput, SignApiRequestInput, apiIdentitySigningInput, apiRequestSigningInput, assertProofVerifierConfig, buildApiAuthHeaders, buildApiIdentityHeaders, parseDfosAuthorization, sha256BodyHash, signApiIdentityRequest, signApiRequest } from '@metalabel/dfos-protocol/credentials';
|
|
2
|
-
import { a as Client } from './types-
|
|
2
|
+
import { a as Client } from './types-BfzEg_gw.js';
|
|
3
3
|
import '@metalabel/dfos-protocol/chain';
|
|
4
4
|
import '@metalabel/dfos-web-relay/peer-client';
|
|
5
5
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { C as ClientConfig, a as Client, b as Callbacks, R as RevChecker } from './types-
|
|
2
|
-
export { c as CallOptions, D as DocumentBlob, G as GlobalLogOptions, d as GlobalLogPage, e as GlobalLogResult, I as IndexCapabilities, f as IndexContentPage, g as IndexContentRow, h as IndexCountersignatureRow, i as IndexCountersignaturesPage, j as IndexCredentialRow, k as IndexCredentialsPage, l as IndexIdentitiesPage, m as IndexIdentityProfile, n as IndexIdentityRow, o as IndexOrder, p as IndexRecencyOrder, L as LogOp, P as Provenance, q as RelayHealth, r as RelayResponse, s as Resolution, t as Resolved, u as ResolvedContent, v as ResolvedCredential, S as Store, T as Trust, U as UnverifiableAxis, V as VerifyResult } from './types-
|
|
3
|
-
export { m as memoryStore } from './memory-
|
|
1
|
+
import { C as ClientConfig, a as Client, b as Callbacks, R as RevChecker } from './types-BfzEg_gw.js';
|
|
2
|
+
export { c as CallOptions, D as DocumentBlob, G as GlobalLogOptions, d as GlobalLogPage, e as GlobalLogResult, I as IndexCapabilities, f as IndexContentPage, g as IndexContentRow, h as IndexCountersignatureRow, i as IndexCountersignaturesPage, j as IndexCredentialRow, k as IndexCredentialsPage, l as IndexIdentitiesPage, m as IndexIdentityProfile, n as IndexIdentityRow, o as IndexOrder, p as IndexRecencyOrder, L as LogOp, P as Provenance, q as RelayHealth, r as RelayResponse, s as Resolution, t as Resolved, u as ResolvedContent, v as ResolvedCredential, S as Store, T as Trust, U as UnverifiableAxis, V as VerifyResult } from './types-BfzEg_gw.js';
|
|
3
|
+
export { m as memoryStore } from './memory-BuTsEPZI.js';
|
|
4
4
|
import '@metalabel/dfos-protocol/chain';
|
|
5
5
|
import '@metalabel/dfos-protocol/credentials';
|
|
6
6
|
import '@metalabel/dfos-web-relay/peer-client';
|
|
@@ -12,6 +12,51 @@ declare const createClient: (config: ClientConfig) => Client;
|
|
|
12
12
|
*/
|
|
13
13
|
declare const resolvers: (relays: string[]) => Callbacks;
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* The relays' log for a chain disagrees with the verified prefix this client
|
|
17
|
+
* cached: at a position the cache already covers, the operation served is not
|
|
18
|
+
* the operation this client proved. Distinct from `StaleAnswerError` (a relay
|
|
19
|
+
* merely behind) and from a failed proof (a chain that does not verify) — here
|
|
20
|
+
* two histories contradict each other about what already happened, so verifying
|
|
21
|
+
* forward from the trusted prefix is not a thing that can be done.
|
|
22
|
+
*
|
|
23
|
+
* NOTHING IS DISCARDED HERE. Dropping a verified prefix is a decision about
|
|
24
|
+
* trust, not an error path: a client that healed itself silently would erase the
|
|
25
|
+
* only evidence that a rewrite happened, which is the whole reason the prefix is
|
|
26
|
+
* pinned. `client.discardCachedChain()` is the explicit undo, and it is the
|
|
27
|
+
* caller's to call.
|
|
28
|
+
*
|
|
29
|
+
* The error is thrown as a CANDIDATE FILTER, inside the fan-out. A fan-out where
|
|
30
|
+
* every relay diverges surfaces its own error carrying this one as `cause`, so
|
|
31
|
+
* callers reach it with `divergenceErrorFrom(err)` rather than a bare
|
|
32
|
+
* `instanceof` on what they caught.
|
|
33
|
+
*/
|
|
34
|
+
declare class DivergenceError extends Error {
|
|
35
|
+
readonly chainType: 'identity' | 'content';
|
|
36
|
+
readonly chainId: string;
|
|
37
|
+
/** Head CID of the verified prefix this client holds. */
|
|
38
|
+
readonly cachedHeadCID: string;
|
|
39
|
+
/**
|
|
40
|
+
* Head CID of the log the relays served, as that operation's own JWS header
|
|
41
|
+
* names it — orientation for a human, never a proof. Empty when the served log
|
|
42
|
+
* was empty or its head named no CID.
|
|
43
|
+
*/
|
|
44
|
+
readonly liveHeadCID: string;
|
|
45
|
+
constructor(input: {
|
|
46
|
+
chainType: 'identity' | 'content';
|
|
47
|
+
chainId: string;
|
|
48
|
+
cachedHeadCID: string;
|
|
49
|
+
liveHeadCID: string;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Find the `DivergenceError` behind a caught error, walking the `cause` chain —
|
|
54
|
+
* the fan-out wraps a candidate's verification failure, and a content read wraps
|
|
55
|
+
* the identity read inside it. Returns `undefined` when the failure was anything
|
|
56
|
+
* else, so a caller can branch on the answer instead of matching message text.
|
|
57
|
+
*/
|
|
58
|
+
declare const divergenceErrorFrom: (err: unknown) => DivergenceError | undefined;
|
|
59
|
+
|
|
15
60
|
/**
|
|
16
61
|
* Build the default revocation checker over an ordered relay set.
|
|
17
62
|
*
|
|
@@ -29,4 +74,4 @@ declare const resolvers: (relays: string[]) => Callbacks;
|
|
|
29
74
|
*/
|
|
30
75
|
declare const createRevocationChecker: (relays: string[], fetchImpl: typeof fetch, resolveKey: (kid: string) => Promise<Uint8Array>) => RevChecker;
|
|
31
76
|
|
|
32
|
-
export { Callbacks, Client, ClientConfig, RevChecker, createClient, createRevocationChecker, resolvers };
|
|
77
|
+
export { Callbacks, Client, ClientConfig, DivergenceError, RevChecker, createClient, createRevocationChecker, divergenceErrorFrom, resolvers };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
memoryStore
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-KY632J74.js";
|
|
4
4
|
|
|
5
5
|
// src/client.ts
|
|
6
6
|
import {
|
|
@@ -111,7 +111,9 @@ var fanOutLog = async (fetchPage, relays, quorum, verifyCandidate) => {
|
|
|
111
111
|
}
|
|
112
112
|
if (lastVerifyError !== void 0) {
|
|
113
113
|
const message = lastVerifyError instanceof Error ? lastVerifyError.message : "unknown error";
|
|
114
|
-
throw new Error(`all candidate logs failed verification: ${message}
|
|
114
|
+
throw new Error(`all candidate logs failed verification: ${message}`, {
|
|
115
|
+
cause: lastVerifyError
|
|
116
|
+
});
|
|
115
117
|
}
|
|
116
118
|
return {
|
|
117
119
|
outcome: "unreachable",
|
|
@@ -238,6 +240,36 @@ import {
|
|
|
238
240
|
} from "@metalabel/dfos-protocol/chain";
|
|
239
241
|
import { decodeJwsUnsafe } from "@metalabel/dfos-protocol/crypto";
|
|
240
242
|
var DID_PREFIX = "did:dfos";
|
|
243
|
+
var cacheKey = (kind, id) => `${kind}:${id}`;
|
|
244
|
+
var DivergenceError = class extends Error {
|
|
245
|
+
chainType;
|
|
246
|
+
chainId;
|
|
247
|
+
/** Head CID of the verified prefix this client holds. */
|
|
248
|
+
cachedHeadCID;
|
|
249
|
+
/**
|
|
250
|
+
* Head CID of the log the relays served, as that operation's own JWS header
|
|
251
|
+
* names it — orientation for a human, never a proof. Empty when the served log
|
|
252
|
+
* was empty or its head named no CID.
|
|
253
|
+
*/
|
|
254
|
+
liveHeadCID;
|
|
255
|
+
constructor(input) {
|
|
256
|
+
super(`${input.chainType} log diverges from the verified cached prefix: ${input.chainId}`);
|
|
257
|
+
this.name = "DivergenceError";
|
|
258
|
+
this.chainType = input.chainType;
|
|
259
|
+
this.chainId = input.chainId;
|
|
260
|
+
this.cachedHeadCID = input.cachedHeadCID;
|
|
261
|
+
this.liveHeadCID = input.liveHeadCID;
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
var CAUSE_DEPTH = 8;
|
|
265
|
+
var divergenceErrorFrom = (err) => {
|
|
266
|
+
let cursor = err;
|
|
267
|
+
for (let depth = 0; depth < CAUSE_DEPTH && cursor instanceof Error; depth++) {
|
|
268
|
+
if (cursor instanceof DivergenceError) return cursor;
|
|
269
|
+
cursor = cursor.cause;
|
|
270
|
+
}
|
|
271
|
+
return void 0;
|
|
272
|
+
};
|
|
241
273
|
var opMeta = (jws) => {
|
|
242
274
|
const decoded = decodeJwsUnsafe(jws);
|
|
243
275
|
const cid = typeof decoded?.header.cid === "string" ? decoded.header.cid : "";
|
|
@@ -263,7 +295,7 @@ var keyBytesFor = (state, keyId) => {
|
|
|
263
295
|
var createResolvers = (deps) => {
|
|
264
296
|
const relaysFor = (o) => normalizeRelays(o?.relays ?? deps.relays);
|
|
265
297
|
const getIdentityChain = async (did, options) => {
|
|
266
|
-
const key =
|
|
298
|
+
const key = cacheKey("identity", did);
|
|
267
299
|
const cached = options?.fresh ? void 0 : await deps.store.get(key);
|
|
268
300
|
const verifyCandidate = async (entries) => {
|
|
269
301
|
if (!cached) {
|
|
@@ -277,7 +309,12 @@ var createResolvers = (deps) => {
|
|
|
277
309
|
return { state: state2, log: log2, headCID: last.cid, lastCreatedAt: last.createdAt };
|
|
278
310
|
}
|
|
279
311
|
if (cached.log.some((jws, index) => index < entries.length && entries[index].jwsToken !== jws)) {
|
|
280
|
-
throw new
|
|
312
|
+
throw new DivergenceError({
|
|
313
|
+
chainType: "identity",
|
|
314
|
+
chainId: did,
|
|
315
|
+
cachedHeadCID: cached.headCID,
|
|
316
|
+
liveHeadCID: opMeta(entries[entries.length - 1]?.jwsToken ?? "").cid
|
|
317
|
+
});
|
|
281
318
|
}
|
|
282
319
|
if (entries.length < cached.log.length) {
|
|
283
320
|
throw new StaleAnswerError(`identity log is behind the verified cached prefix: ${did}`);
|
|
@@ -358,7 +395,7 @@ var createResolvers = (deps) => {
|
|
|
358
395
|
isRevoked: deps.isRevoked
|
|
359
396
|
});
|
|
360
397
|
const getContentChain = async (contentId, options) => {
|
|
361
|
-
const key =
|
|
398
|
+
const key = cacheKey("content", contentId);
|
|
362
399
|
const cached = options?.fresh ? void 0 : await deps.store.get(key);
|
|
363
400
|
const verifyCandidate = async (entries) => {
|
|
364
401
|
if (!cached) {
|
|
@@ -380,7 +417,12 @@ var createResolvers = (deps) => {
|
|
|
380
417
|
return { state: state2, log: log2, headCID: last.cid, lastCreatedAt: last.createdAt };
|
|
381
418
|
}
|
|
382
419
|
if (cached.log.some((jws, index) => index < entries.length && entries[index].jwsToken !== jws)) {
|
|
383
|
-
throw new
|
|
420
|
+
throw new DivergenceError({
|
|
421
|
+
chainType: "content",
|
|
422
|
+
chainId: contentId,
|
|
423
|
+
cachedHeadCID: cached.headCID,
|
|
424
|
+
liveHeadCID: opMeta(entries[entries.length - 1]?.jwsToken ?? "").cid
|
|
425
|
+
});
|
|
384
426
|
}
|
|
385
427
|
if (entries.length < cached.log.length) {
|
|
386
428
|
throw new StaleAnswerError(
|
|
@@ -439,7 +481,13 @@ var createResolvers = (deps) => {
|
|
|
439
481
|
tipUnverified: cached !== void 0 && candidate.log.length === cached.log.length
|
|
440
482
|
};
|
|
441
483
|
};
|
|
442
|
-
|
|
484
|
+
const discardCachedChain = async (kind, id) => {
|
|
485
|
+
const remove = deps.store.delete?.bind(deps.store);
|
|
486
|
+
if (!remove) return false;
|
|
487
|
+
await remove(cacheKey(kind, id));
|
|
488
|
+
return true;
|
|
489
|
+
};
|
|
490
|
+
return { getIdentityChain, getContentChain, discardCachedChain, callbacks };
|
|
443
491
|
};
|
|
444
492
|
|
|
445
493
|
// src/revocation.ts
|
|
@@ -690,6 +738,7 @@ var createClient = (config) => {
|
|
|
690
738
|
return {
|
|
691
739
|
callbacks,
|
|
692
740
|
resolve,
|
|
741
|
+
discardCachedChain: resolvers2.discardCachedChain,
|
|
693
742
|
identity,
|
|
694
743
|
content,
|
|
695
744
|
credential,
|
|
@@ -721,8 +770,10 @@ var fetchBlob = async (contentId, relays, fetchImpl) => {
|
|
|
721
770
|
};
|
|
722
771
|
var resolvers = (relays) => createClient({ relays }).callbacks();
|
|
723
772
|
export {
|
|
773
|
+
DivergenceError,
|
|
724
774
|
createClient,
|
|
725
775
|
createRevocationChecker,
|
|
776
|
+
divergenceErrorFrom,
|
|
726
777
|
memoryStore,
|
|
727
778
|
resolvers
|
|
728
779
|
};
|
package/dist/siwd.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Signer, VerifiedIdentity, VerifiedSignRequest } from '@metalabel/dfos-protocol/chain';
|
|
2
|
-
import { a as Client, V as VerifyResult } from './types-
|
|
2
|
+
import { a as Client, V as VerifyResult } from './types-BfzEg_gw.js';
|
|
3
3
|
import '@metalabel/dfos-protocol/credentials';
|
|
4
4
|
import '@metalabel/dfos-web-relay/peer-client';
|
|
5
5
|
|
package/dist/store/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { m as memoryStore } from '../memory-
|
|
2
|
-
import { S as Store } from '../types-
|
|
1
|
+
export { m as memoryStore } from '../memory-BuTsEPZI.js';
|
|
2
|
+
import { S as Store } from '../types-BfzEg_gw.js';
|
|
3
3
|
import '@metalabel/dfos-protocol/chain';
|
|
4
4
|
import '@metalabel/dfos-protocol/credentials';
|
|
5
5
|
import '@metalabel/dfos-web-relay/peer-client';
|
package/dist/store/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
memoryStore
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-KY632J74.js";
|
|
4
4
|
|
|
5
5
|
// src/store/indexeddb.ts
|
|
6
6
|
var STORE_NAME = "dfos-cache";
|
|
@@ -40,6 +40,14 @@ var indexedDbStore = (dbName = "dfos-client") => {
|
|
|
40
40
|
const db = await open();
|
|
41
41
|
const store = db.transaction(STORE_NAME, "readwrite").objectStore(STORE_NAME);
|
|
42
42
|
await promisify(store.put(value, key));
|
|
43
|
+
},
|
|
44
|
+
// IndexedDB's own delete succeeds on a key that is not there, which is
|
|
45
|
+
// exactly the idempotence the caller wants: discarding a chain that was
|
|
46
|
+
// never cached is not a failure, it is already the requested state.
|
|
47
|
+
async delete(key) {
|
|
48
|
+
const db = await open();
|
|
49
|
+
const store = db.transaction(STORE_NAME, "readwrite").objectStore(STORE_NAME);
|
|
50
|
+
await promisify(store.delete(key));
|
|
43
51
|
}
|
|
44
52
|
};
|
|
45
53
|
};
|
|
@@ -104,6 +104,13 @@ interface Callbacks {
|
|
|
104
104
|
interface Store {
|
|
105
105
|
get(key: string): Promise<unknown | undefined>;
|
|
106
106
|
set(key: string, value: unknown): Promise<void>;
|
|
107
|
+
/**
|
|
108
|
+
* Forget one key. Idempotent, and absent keys are not an error. Optional so a
|
|
109
|
+
* store written against the two-method shape still satisfies this interface;
|
|
110
|
+
* a store without it makes `client.discardCachedChain()` answer `false`
|
|
111
|
+
* instead of quietly doing nothing. Both bundled stores implement it.
|
|
112
|
+
*/
|
|
113
|
+
delete?(key: string): Promise<void>;
|
|
107
114
|
}
|
|
108
115
|
/** A raw JWS operation from a relay log — cid + token, unverified until folded. */
|
|
109
116
|
interface LogOp {
|
|
@@ -275,6 +282,17 @@ interface Client {
|
|
|
275
282
|
document(contentId: string, options?: CallOptions): Promise<Resolved<DocumentBlob>>;
|
|
276
283
|
/** No-throw, self-routing "is this legit". */
|
|
277
284
|
verify(jws: string, options?: CallOptions): Promise<VerifyResult<unknown>>;
|
|
285
|
+
/**
|
|
286
|
+
* Forget the verified prefix cached for ONE chain, so the next read of it
|
|
287
|
+
* folds cold from genesis. The explicit way out of a `DivergenceError`: the
|
|
288
|
+
* client never discards a pinned prefix on its own, because a contradiction
|
|
289
|
+
* that heals itself is a contradiction nobody sees. Narrow (this chain only),
|
|
290
|
+
* idempotent, and local — no relay is touched and no operation is destroyed.
|
|
291
|
+
*
|
|
292
|
+
* `false` means the configured store exposes no `delete` and nothing was
|
|
293
|
+
* forgotten; both bundled stores return `true`.
|
|
294
|
+
*/
|
|
295
|
+
discardCachedChain(kind: 'identity' | 'content', id: string): Promise<boolean>;
|
|
278
296
|
/** Raw floor. */
|
|
279
297
|
log(kind: 'identity' | 'content', id: string, options?: CallOptions): Promise<Resolved<LogOp[]>>;
|
|
280
298
|
globalLog(after?: string, options?: GlobalLogOptions): Promise<GlobalLogResult>;
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metalabel/dfos-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.47.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "DFOS Client — the client-side kit for participating in the protocol: resolve, verify, prove. Fetch, resolve, verify-orchestration and cache over untrusted relays, plus the SIWD and API-AUTH proof surfaces. Holds no keys; all crypto truth comes from @metalabel/dfos-protocol",
|
|
6
6
|
"license": "MIT",
|
|
7
|
-
"author": "
|
|
7
|
+
"author": "DFOS Inc (https://dfos.com)",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
10
10
|
"url": "https://github.com/metalabel/dfos.git",
|
|
@@ -47,16 +47,16 @@
|
|
|
47
47
|
"README.md"
|
|
48
48
|
],
|
|
49
49
|
"peerDependencies": {
|
|
50
|
-
"@metalabel/dfos-protocol": "^0.
|
|
51
|
-
"@metalabel/dfos-web-relay": "^0.
|
|
50
|
+
"@metalabel/dfos-protocol": "^0.47.0",
|
|
51
|
+
"@metalabel/dfos-web-relay": "^0.47.0"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@types/node": "^24.10.4",
|
|
55
55
|
"tsup": "^8.5.1",
|
|
56
56
|
"typescript": "^5.9.3",
|
|
57
57
|
"vitest": "^4.1.8",
|
|
58
|
-
"@metalabel/dfos-
|
|
59
|
-
"@metalabel/dfos-
|
|
58
|
+
"@metalabel/dfos-protocol": "0.47.0",
|
|
59
|
+
"@metalabel/dfos-web-relay": "0.47.0"
|
|
60
60
|
},
|
|
61
61
|
"scripts": {
|
|
62
62
|
"build": "tsup",
|