@tinycloud/sdk-services 3.1.0-beta.9 → 3.1.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/dist/index.cjs +551 -171
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +103 -12
- package/dist/index.d.ts +103 -12
- package/dist/index.js +551 -171
- package/dist/index.js.map +1 -1
- package/dist/kv/index.cjs +56 -11
- package/dist/kv/index.cjs.map +1 -1
- package/dist/kv/index.d.cts +12 -2
- package/dist/kv/index.d.ts +12 -2
- package/dist/kv/index.js +56 -11
- package/dist/kv/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1713,6 +1713,24 @@ var MAX_KV_BATCH_READ_ITEMS = 100;
|
|
|
1713
1713
|
function isJsonObject(value) {
|
|
1714
1714
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1715
1715
|
}
|
|
1716
|
+
var pathByteEncoder = new TextEncoder();
|
|
1717
|
+
function comparePathsByBytes(a, b) {
|
|
1718
|
+
const left = pathByteEncoder.encode(a);
|
|
1719
|
+
const right = pathByteEncoder.encode(b);
|
|
1720
|
+
const length = Math.min(left.length, right.length);
|
|
1721
|
+
for (let index = 0; index < length; index++) {
|
|
1722
|
+
if (left[index] !== right[index]) {
|
|
1723
|
+
return left[index] - right[index];
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
return left.length - right.length;
|
|
1727
|
+
}
|
|
1728
|
+
var REVOKED_BODY = /^(?:Invalid invocation: )?delegation-(?:(revoked): [A-Za-z0-9]+|(ancestor-revoked): ancestor=[A-Za-z0-9]+ invoked=[A-Za-z0-9]+)$/;
|
|
1729
|
+
function revocationCodeOf(body) {
|
|
1730
|
+
const match = REVOKED_BODY.exec(body.trim());
|
|
1731
|
+
if (match === null) return void 0;
|
|
1732
|
+
return match[1] !== void 0 ? ErrorCodes.AUTH_DELEGATION_REVOKED : ErrorCodes.AUTH_DELEGATION_ANCESTOR_REVOKED;
|
|
1733
|
+
}
|
|
1716
1734
|
function encodeKvBatchPartName(path) {
|
|
1717
1735
|
return encodeURIComponent(path).replace(
|
|
1718
1736
|
/[!'()*]/g,
|
|
@@ -1940,15 +1958,25 @@ var KVService = class extends BaseService {
|
|
|
1940
1958
|
)?.[1];
|
|
1941
1959
|
return contentType?.includes("application/json") ? JSON.parse(text) : text;
|
|
1942
1960
|
}
|
|
1961
|
+
/**
|
|
1962
|
+
* Validate a batch read response and return its items in the caller's
|
|
1963
|
+
* request order. The node flattens invocation abilities from a `BTreeMap`,
|
|
1964
|
+
* so results arrive sorted by UTF-8 byte order of the path, not in request
|
|
1965
|
+
* order. Items that carry their path in `key` are matched by path; if no
|
|
1966
|
+
* item carries a key, items are assumed to be in the node's byte-sorted
|
|
1967
|
+
* order and the request is aligned the same way. Any mix of keyed and
|
|
1968
|
+
* keyless items, a missing requested path, an unrequested path, or a
|
|
1969
|
+
* malformed item fails closed (returns undefined).
|
|
1970
|
+
*/
|
|
1943
1971
|
normalizeBatchReadResponse(data, paths, requireData) {
|
|
1944
1972
|
if (!data || typeof data !== "object") return void 0;
|
|
1945
1973
|
const response = data;
|
|
1946
|
-
|
|
1974
|
+
const items = response.results;
|
|
1975
|
+
if (!Array.isArray(items) || items.length !== paths.length) {
|
|
1947
1976
|
return void 0;
|
|
1948
1977
|
}
|
|
1949
|
-
for (
|
|
1950
|
-
|
|
1951
|
-
if (!item || typeof item !== "object" || item.key !== paths[index] || typeof item.ok !== "boolean") {
|
|
1978
|
+
for (const item of items) {
|
|
1979
|
+
if (!item || typeof item !== "object" || typeof item.ok !== "boolean") {
|
|
1952
1980
|
return void 0;
|
|
1953
1981
|
}
|
|
1954
1982
|
if (item.ok && (!item.headers || typeof item.headers !== "object" || Object.values(item.headers).some((value) => typeof value !== "string") || requireData && typeof item.dataBase64 !== "string")) {
|
|
@@ -1958,7 +1986,24 @@ var KVService = class extends BaseService {
|
|
|
1958
1986
|
return void 0;
|
|
1959
1987
|
}
|
|
1960
1988
|
}
|
|
1961
|
-
|
|
1989
|
+
if (items.every((item) => typeof item.key === "string")) {
|
|
1990
|
+
const byPath = new Map(items.map((item) => [item.key, item]));
|
|
1991
|
+
if (byPath.size !== items.length) return void 0;
|
|
1992
|
+
const aligned2 = [];
|
|
1993
|
+
for (const path of paths) {
|
|
1994
|
+
const item = byPath.get(path);
|
|
1995
|
+
if (!item) return void 0;
|
|
1996
|
+
aligned2.push(item);
|
|
1997
|
+
}
|
|
1998
|
+
return aligned2;
|
|
1999
|
+
}
|
|
2000
|
+
if (items.some((item) => item.key !== void 0)) return void 0;
|
|
2001
|
+
const requestOrder = paths.map((_, index) => index).sort((a, b) => comparePathsByBytes(paths[a], paths[b]));
|
|
2002
|
+
const aligned = new Array(items.length);
|
|
2003
|
+
for (let position = 0; position < requestOrder.length; position++) {
|
|
2004
|
+
aligned[requestOrder[position]] = items[position];
|
|
2005
|
+
}
|
|
2006
|
+
return aligned;
|
|
1962
2007
|
}
|
|
1963
2008
|
async batchRead(keys, action, options) {
|
|
1964
2009
|
if (!this.requireAuth()) return err(authRequiredError("kv"));
|
|
@@ -2051,19 +2096,19 @@ var KVService = class extends BaseService {
|
|
|
2051
2096
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2052
2097
|
));
|
|
2053
2098
|
}
|
|
2054
|
-
const
|
|
2099
|
+
const items = this.normalizeBatchReadResponse(
|
|
2055
2100
|
await response.json(),
|
|
2056
2101
|
paths,
|
|
2057
2102
|
action === KVAction.GET
|
|
2058
2103
|
);
|
|
2059
|
-
if (!
|
|
2104
|
+
if (!items) {
|
|
2060
2105
|
return err(serviceError(
|
|
2061
2106
|
ErrorCodes.NETWORK_ERROR,
|
|
2062
2107
|
"KV batch read response did not match the requested keys",
|
|
2063
2108
|
"kv"
|
|
2064
2109
|
));
|
|
2065
2110
|
}
|
|
2066
|
-
const results =
|
|
2111
|
+
const results = items.map((item, index) => {
|
|
2067
2112
|
if (!item.ok) {
|
|
2068
2113
|
return {
|
|
2069
2114
|
key: keys[index],
|
|
@@ -2697,8 +2742,8 @@ var KVService = class extends BaseService {
|
|
|
2697
2742
|
}
|
|
2698
2743
|
/**
|
|
2699
2744
|
* Map a failed `kv/sync` response. 410 and the retention 403 carry
|
|
2700
|
-
* `{"error":{"code","reason"}}`; a revoked grant is a 401 whose
|
|
2701
|
-
*
|
|
2745
|
+
* `{"error":{"code","reason"}}`; a revoked grant is a 401 whose whole body
|
|
2746
|
+
* is the node's revocation error (see REVOKED_BODY). A body read that
|
|
2702
2747
|
* fails because the request was cancelled or timed out rethrows, so the
|
|
2703
2748
|
* caller sees `ABORTED`/`TIMEOUT` rather than a mapped status.
|
|
2704
2749
|
*/
|
|
@@ -2743,7 +2788,7 @@ var KVService = class extends BaseService {
|
|
|
2743
2788
|
));
|
|
2744
2789
|
}
|
|
2745
2790
|
if (response.status === 401) {
|
|
2746
|
-
const revoked =
|
|
2791
|
+
const revoked = revocationCodeOf(errorText);
|
|
2747
2792
|
if (revoked !== void 0) {
|
|
2748
2793
|
return err(serviceError(revoked, `${context}: 401 - ${errorText}`, "kv", { meta }));
|
|
2749
2794
|
}
|
|
@@ -3990,7 +4035,7 @@ var AsyncQueue = class {
|
|
|
3990
4035
|
}
|
|
3991
4036
|
const waiter = this.waiters.shift();
|
|
3992
4037
|
if (waiter) {
|
|
3993
|
-
waiter({ value, done: false });
|
|
4038
|
+
waiter.resolve({ value, done: false });
|
|
3994
4039
|
return;
|
|
3995
4040
|
}
|
|
3996
4041
|
this.values.push(value);
|
|
@@ -4002,7 +4047,22 @@ var AsyncQueue = class {
|
|
|
4002
4047
|
this.closed = true;
|
|
4003
4048
|
while (this.waiters.length > 0) {
|
|
4004
4049
|
const waiter = this.waiters.shift();
|
|
4005
|
-
waiter?.({ value: void 0, done: true });
|
|
4050
|
+
waiter?.resolve({ value: void 0, done: true });
|
|
4051
|
+
}
|
|
4052
|
+
}
|
|
4053
|
+
/**
|
|
4054
|
+
* Fail the queue: pending and future `next()` calls reject with `error`,
|
|
4055
|
+
* so a `for await` consumer sees the iterator throw.
|
|
4056
|
+
*/
|
|
4057
|
+
fail(error) {
|
|
4058
|
+
if (this.closed) {
|
|
4059
|
+
return;
|
|
4060
|
+
}
|
|
4061
|
+
this.closed = true;
|
|
4062
|
+
this.failure = error;
|
|
4063
|
+
while (this.waiters.length > 0) {
|
|
4064
|
+
const waiter = this.waiters.shift();
|
|
4065
|
+
waiter?.reject(error);
|
|
4006
4066
|
}
|
|
4007
4067
|
}
|
|
4008
4068
|
next() {
|
|
@@ -4010,20 +4070,28 @@ var AsyncQueue = class {
|
|
|
4010
4070
|
const value = this.values.shift();
|
|
4011
4071
|
return Promise.resolve({ value, done: false });
|
|
4012
4072
|
}
|
|
4073
|
+
if (this.failure !== void 0) {
|
|
4074
|
+
return Promise.reject(this.failure);
|
|
4075
|
+
}
|
|
4013
4076
|
if (this.closed) {
|
|
4014
4077
|
return Promise.resolve({ value: void 0, done: true });
|
|
4015
4078
|
}
|
|
4016
|
-
return new Promise((resolve) => {
|
|
4017
|
-
this.waiters.push(resolve);
|
|
4079
|
+
return new Promise((resolve, reject) => {
|
|
4080
|
+
this.waiters.push({ resolve, reject });
|
|
4018
4081
|
});
|
|
4019
4082
|
}
|
|
4020
4083
|
};
|
|
4084
|
+
var HOOK_STREAM_RETRY_BASE_DELAY_MS = 250;
|
|
4085
|
+
var HOOK_STREAM_RETRY_MAX_DELAY_MS = 3e4;
|
|
4086
|
+
var HOOK_STREAM_HEALTHY_MS = 5e3;
|
|
4021
4087
|
var HooksService = class extends BaseService {
|
|
4022
4088
|
constructor(config = {}) {
|
|
4023
4089
|
super();
|
|
4024
4090
|
this._subscribers = /* @__PURE__ */ new Set();
|
|
4025
|
-
|
|
4026
|
-
this.
|
|
4091
|
+
/** True while the one supervisor loop runs. Set only by wake(), cleared only at loop exit. */
|
|
4092
|
+
this._supervising = false;
|
|
4093
|
+
/** Bumped on every session change; part of the plan key. */
|
|
4094
|
+
this._sessionGeneration = 0;
|
|
4027
4095
|
this._config = config;
|
|
4028
4096
|
}
|
|
4029
4097
|
get config() {
|
|
@@ -4039,35 +4107,32 @@ var HooksService = class extends BaseService {
|
|
|
4039
4107
|
if (subscriptions.length === 0) {
|
|
4040
4108
|
throw new Error("At least one hook subscription is required");
|
|
4041
4109
|
}
|
|
4042
|
-
const
|
|
4110
|
+
const requested = subscriptions.map(normalizeSubscription);
|
|
4043
4111
|
const subscriber = {
|
|
4044
|
-
requested
|
|
4112
|
+
requested,
|
|
4113
|
+
signatures: requested.map(subscriptionSignature),
|
|
4045
4114
|
ttlSeconds: options.ttlSeconds,
|
|
4046
4115
|
queue: new AsyncQueue()
|
|
4047
4116
|
};
|
|
4048
|
-
|
|
4049
|
-
const abortHandler = () => {
|
|
4117
|
+
const leave = () => {
|
|
4050
4118
|
this._subscribers.delete(subscriber);
|
|
4051
4119
|
subscriber.queue.close();
|
|
4052
|
-
|
|
4120
|
+
this.wake();
|
|
4053
4121
|
};
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
} else {
|
|
4058
|
-
options.signal.addEventListener("abort", abortHandler, { once: true });
|
|
4059
|
-
}
|
|
4122
|
+
const { signal } = options;
|
|
4123
|
+
if (signal?.aborted) {
|
|
4124
|
+
return;
|
|
4060
4125
|
}
|
|
4061
|
-
|
|
4126
|
+
signal?.addEventListener("abort", leave, { once: true });
|
|
4127
|
+
this._subscribers.add(subscriber);
|
|
4128
|
+
this.wake();
|
|
4062
4129
|
try {
|
|
4063
4130
|
for await (const event of subscriber.queue) {
|
|
4064
4131
|
yield event;
|
|
4065
4132
|
}
|
|
4066
4133
|
} finally {
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
}
|
|
4070
|
-
abortHandler();
|
|
4134
|
+
signal?.removeEventListener("abort", leave);
|
|
4135
|
+
leave();
|
|
4071
4136
|
}
|
|
4072
4137
|
}
|
|
4073
4138
|
async register(webhook) {
|
|
@@ -4208,146 +4273,292 @@ var HooksService = class extends BaseService {
|
|
|
4208
4273
|
return err(wrapError("hooks", error));
|
|
4209
4274
|
}
|
|
4210
4275
|
}
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
if (state.signature !== this._activeSignature) {
|
|
4223
|
-
this._activeSignature = state.signature;
|
|
4224
|
-
this.abortSharedStream();
|
|
4276
|
+
/**
|
|
4277
|
+
* Called after anything that may change what the supervisor should do:
|
|
4278
|
+
* subscribe, unsubscribe, session change, sign-out. Interrupts the running
|
|
4279
|
+
* step if the plan moved away from it, and starts the supervisor if none
|
|
4280
|
+
* runs. Touches only SDK-owned state, so it never throws into callers such
|
|
4281
|
+
* as `ServiceContext.setSession`.
|
|
4282
|
+
*/
|
|
4283
|
+
wake() {
|
|
4284
|
+
const phase = this._phase;
|
|
4285
|
+
if (phase && phase.key !== this.plan()?.key) {
|
|
4286
|
+
phase.interrupt.abort();
|
|
4225
4287
|
}
|
|
4226
|
-
if (
|
|
4227
|
-
|
|
4228
|
-
if (!isAbortError(error)) {
|
|
4229
|
-
throw error;
|
|
4230
|
-
}
|
|
4231
|
-
}).finally(() => {
|
|
4232
|
-
this._sharedStreamTask = void 0;
|
|
4233
|
-
this._sharedStreamAbort = void 0;
|
|
4234
|
-
if (this._subscribers.size > 0) {
|
|
4235
|
-
void this.scheduleSharedStreamRefresh();
|
|
4236
|
-
}
|
|
4237
|
-
});
|
|
4288
|
+
if (this._supervising || this._subscribers.size === 0) {
|
|
4289
|
+
return;
|
|
4238
4290
|
}
|
|
4291
|
+
this._supervising = true;
|
|
4292
|
+
this.supervise().catch(() => this.collapse());
|
|
4239
4293
|
}
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4294
|
+
/**
|
|
4295
|
+
* The only owner of the shared stream. Each iteration is one attempt
|
|
4296
|
+
* (mint → open → drain), then a classification and, unless the attempt was
|
|
4297
|
+
* superseded or released its subscribers, a backoff. Every await is a
|
|
4298
|
+
* `phase` that wake() can interrupt; an interrupted phase yields
|
|
4299
|
+
* `undefined`, so a superseded mint can never act. Outside `attempt` and
|
|
4300
|
+
* `pause`, which each own one catch, the loop touches only SDK state.
|
|
4301
|
+
*/
|
|
4302
|
+
async supervise() {
|
|
4303
|
+
let streak = 0;
|
|
4304
|
+
for (; ; ) {
|
|
4305
|
+
const plan = this.plan();
|
|
4306
|
+
if (!plan) {
|
|
4307
|
+
this._supervising = false;
|
|
4308
|
+
return;
|
|
4309
|
+
}
|
|
4310
|
+
const health = { openedAt: 0, delivered: false };
|
|
4311
|
+
const outcome = await this.phase(
|
|
4312
|
+
plan.key,
|
|
4313
|
+
(signal) => this.attempt(plan, signal, health)
|
|
4314
|
+
);
|
|
4315
|
+
if (health.delivered || health.openedAt > 0 && performance.now() - health.openedAt >= HOOK_STREAM_HEALTHY_MS) {
|
|
4316
|
+
streak = 0;
|
|
4317
|
+
}
|
|
4318
|
+
if (!outcome) {
|
|
4319
|
+
continue;
|
|
4320
|
+
}
|
|
4321
|
+
if (this.plan()?.key !== plan.key) {
|
|
4322
|
+
continue;
|
|
4246
4323
|
}
|
|
4247
|
-
|
|
4248
|
-
|
|
4324
|
+
if (outcome.kind === "stopped") {
|
|
4325
|
+
this.release();
|
|
4326
|
+
continue;
|
|
4327
|
+
}
|
|
4328
|
+
if (outcome.kind === "refused" && outcome.terminal) {
|
|
4329
|
+
this.release(outcome.error);
|
|
4330
|
+
this.report(outcome.error);
|
|
4331
|
+
continue;
|
|
4249
4332
|
}
|
|
4333
|
+
if (outcome.kind !== "ended") {
|
|
4334
|
+
this.report(outcome.error);
|
|
4335
|
+
}
|
|
4336
|
+
streak += 1;
|
|
4337
|
+
await this.phase(
|
|
4338
|
+
plan.key,
|
|
4339
|
+
(signal) => this.pause(streak, signal)
|
|
4340
|
+
);
|
|
4341
|
+
}
|
|
4342
|
+
}
|
|
4343
|
+
/**
|
|
4344
|
+
* Run one step under an interrupt that wake() fires when the plan key moves
|
|
4345
|
+
* on. An interrupted step's result is discarded. The interrupt is also
|
|
4346
|
+
* fired when the step returns, which releases whatever it left open: the
|
|
4347
|
+
* request signal and its listeners, an unread response body, a timer.
|
|
4348
|
+
*/
|
|
4349
|
+
async phase(key, step) {
|
|
4350
|
+
const interrupt = new AbortController();
|
|
4351
|
+
this._phase = { key, interrupt };
|
|
4352
|
+
try {
|
|
4353
|
+
if (this.plan()?.key !== key) {
|
|
4354
|
+
interrupt.abort();
|
|
4355
|
+
}
|
|
4356
|
+
const result = await step(interrupt.signal);
|
|
4357
|
+
return interrupt.signal.aborted ? void 0 : result;
|
|
4358
|
+
} finally {
|
|
4359
|
+
this._phase = void 0;
|
|
4360
|
+
interrupt.abort();
|
|
4250
4361
|
}
|
|
4251
|
-
const subscriptions = [...merged.values()].sort(
|
|
4252
|
-
(left, right) => subscriptionSignature(left).localeCompare(subscriptionSignature(right))
|
|
4253
|
-
);
|
|
4254
|
-
const ttlSeconds = ttlCandidates.length > 0 ? Math.min(...ttlCandidates) : void 0;
|
|
4255
|
-
const signature = JSON.stringify({
|
|
4256
|
-
subscriptions: subscriptions.map(subscriptionSignature),
|
|
4257
|
-
ttlSeconds
|
|
4258
|
-
});
|
|
4259
|
-
return {
|
|
4260
|
-
subscriptions,
|
|
4261
|
-
ttlSeconds,
|
|
4262
|
-
signature
|
|
4263
|
-
};
|
|
4264
4362
|
}
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4363
|
+
/**
|
|
4364
|
+
* One mint → open → drain. The single catch site for everything the
|
|
4365
|
+
* attempt touches that the SDK does not own: context accessors, invoke,
|
|
4366
|
+
* fetch, response bodies, the SSE parser. Never rejects.
|
|
4367
|
+
*/
|
|
4368
|
+
async attempt(plan, signal, health) {
|
|
4369
|
+
let phase = "mint";
|
|
4370
|
+
let request;
|
|
4371
|
+
const owns = () => !signal.aborted && !request?.signal.aborted && this.plan()?.key === plan.key;
|
|
4268
4372
|
try {
|
|
4269
|
-
const
|
|
4270
|
-
const
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4373
|
+
const context = this.context;
|
|
4374
|
+
const contextSignal = context.abortSignal;
|
|
4375
|
+
this._lastContextSignal = contextSignal;
|
|
4376
|
+
if (!context.isAuthenticated || contextSignal?.aborted) {
|
|
4377
|
+
return { kind: "stopped" };
|
|
4378
|
+
}
|
|
4379
|
+
request = this.createRequestSignal(signal, 0);
|
|
4380
|
+
const host = this.host;
|
|
4381
|
+
const minted = await awaitOwned(
|
|
4382
|
+
request.signal,
|
|
4383
|
+
() => context.fetch(`${host}/hooks/tickets`, {
|
|
4384
|
+
method: "POST",
|
|
4385
|
+
headers: {
|
|
4386
|
+
...serviceHeadersToRecord(this.createInvokeHeaders(plan.subscriptions)),
|
|
4387
|
+
"content-type": "application/json"
|
|
4388
|
+
},
|
|
4389
|
+
body: JSON.stringify({
|
|
4390
|
+
subscriptions: plan.subscriptions,
|
|
4391
|
+
ttlSeconds: plan.ttlSeconds
|
|
4392
|
+
}),
|
|
4393
|
+
signal: request.signal
|
|
4394
|
+
})
|
|
4274
4395
|
);
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4396
|
+
if (!owns()) return { kind: "stopped" };
|
|
4397
|
+
if (!minted.ok) {
|
|
4398
|
+
const status = minted.status;
|
|
4399
|
+
const error = await awaitOwned(
|
|
4400
|
+
request.signal,
|
|
4401
|
+
() => responseError("hooks", "failed to mint hook ticket", minted)
|
|
4402
|
+
);
|
|
4403
|
+
if (!owns()) return { kind: "stopped" };
|
|
4404
|
+
return { kind: "refused", terminal: isTerminalMintRefusal(status), error };
|
|
4405
|
+
}
|
|
4406
|
+
const body = await awaitOwned(request.signal, () => minted.json());
|
|
4407
|
+
if (!owns()) return { kind: "stopped" };
|
|
4408
|
+
const ticket = body !== null && typeof body === "object" && "ticket" in body ? body.ticket : void 0;
|
|
4409
|
+
if (typeof ticket !== "string" || ticket.length === 0) {
|
|
4410
|
+
throw new Error("Hook ticket response did not include a ticket");
|
|
4411
|
+
}
|
|
4412
|
+
phase = "open";
|
|
4413
|
+
if (!owns()) return { kind: "stopped" };
|
|
4414
|
+
const stream = await awaitOwned(
|
|
4415
|
+
request.signal,
|
|
4416
|
+
() => context.fetch(`${host}/hooks/events?ticket=${encodeURIComponent(ticket)}`, {
|
|
4417
|
+
method: "GET",
|
|
4418
|
+
headers: { accept: "text/event-stream" },
|
|
4419
|
+
signal: request.signal
|
|
4420
|
+
})
|
|
4279
4421
|
);
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
if (
|
|
4290
|
-
|
|
4291
|
-
|
|
4422
|
+
if (!owns()) return { kind: "stopped" };
|
|
4423
|
+
if (!stream.ok) {
|
|
4424
|
+
return { kind: "refused", terminal: false, error: hookStreamRefusal(stream.status) };
|
|
4425
|
+
}
|
|
4426
|
+
health.openedAt = performance.now();
|
|
4427
|
+
const iterator = parseSseStream(stream.body, request.signal)[Symbol.asyncIterator]();
|
|
4428
|
+
try {
|
|
4429
|
+
for (; ; ) {
|
|
4430
|
+
const next = await awaitOwned(request.signal, () => iterator.next());
|
|
4431
|
+
if (!owns()) return { kind: "stopped" };
|
|
4432
|
+
if (next.done) break;
|
|
4433
|
+
const message = next.value;
|
|
4434
|
+
if (!message.data) continue;
|
|
4435
|
+
const event = parseHookEvent(message);
|
|
4436
|
+
if (!owns()) return { kind: "stopped" };
|
|
4437
|
+
this.dispatch(event);
|
|
4438
|
+
health.delivered = true;
|
|
4292
4439
|
}
|
|
4440
|
+
} finally {
|
|
4441
|
+
const closing = iterator.return?.();
|
|
4442
|
+
if (closing) void Promise.resolve(closing).then(() => void 0, () => void 0);
|
|
4293
4443
|
}
|
|
4444
|
+
return owns() ? { kind: "ended" } : { kind: "stopped" };
|
|
4445
|
+
} catch (thrown) {
|
|
4446
|
+
return request?.signal.aborted || thrown === SUPERSEDED ? { kind: "stopped" } : { kind: "failed", error: hookStreamFailure(phase, thrown) };
|
|
4447
|
+
}
|
|
4448
|
+
}
|
|
4449
|
+
/**
|
|
4450
|
+
* Back off before the next attempt. `config.streamRetry` overrides the
|
|
4451
|
+
* delay and the clock; whatever they do, the pause ends by the delay or the
|
|
4452
|
+
* interrupt, then yields one timer turn so an instant clock cannot starve
|
|
4453
|
+
* due timers or the process.
|
|
4454
|
+
*/
|
|
4455
|
+
async pause(attempt, signal) {
|
|
4456
|
+
try {
|
|
4457
|
+
this._lastContextSignal = this.context.abortSignal;
|
|
4458
|
+
} catch {
|
|
4459
|
+
}
|
|
4460
|
+
const contextSignal = this._lastContextSignal;
|
|
4461
|
+
const waits = [];
|
|
4462
|
+
const aborts = [];
|
|
4463
|
+
try {
|
|
4464
|
+
const retry = this._config.streamRetry;
|
|
4465
|
+
const delayMs = retry?.delay?.(attempt) ?? hookStreamRetryDelay(attempt);
|
|
4466
|
+
waits.push((retry?.wait ?? sleep)(delayMs, attempt, signal));
|
|
4467
|
+
} catch {
|
|
4468
|
+
waits.push(Promise.resolve());
|
|
4469
|
+
}
|
|
4470
|
+
aborts.push(abortPromise(signal));
|
|
4471
|
+
if (contextSignal) aborts.push(abortPromise(contextSignal));
|
|
4472
|
+
try {
|
|
4473
|
+
await Promise.race([...waits, ...aborts.map(({ promise }) => promise)]);
|
|
4474
|
+
} catch {
|
|
4294
4475
|
} finally {
|
|
4295
|
-
|
|
4296
|
-
|
|
4476
|
+
for (const abort of aborts) abort.dispose();
|
|
4477
|
+
}
|
|
4478
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
4479
|
+
}
|
|
4480
|
+
/** The stream the current subscribers need, or undefined when none remain. */
|
|
4481
|
+
plan() {
|
|
4482
|
+
if (this._subscribers.size === 0) {
|
|
4483
|
+
return void 0;
|
|
4484
|
+
}
|
|
4485
|
+
const merged = /* @__PURE__ */ new Map();
|
|
4486
|
+
let ttlSeconds;
|
|
4487
|
+
for (const subscriber of this._subscribers) {
|
|
4488
|
+
subscriber.requested.forEach(
|
|
4489
|
+
(subscription, index) => merged.set(subscriber.signatures[index], subscription)
|
|
4490
|
+
);
|
|
4491
|
+
if (typeof subscriber.ttlSeconds === "number") {
|
|
4492
|
+
ttlSeconds = Math.min(subscriber.ttlSeconds, ttlSeconds ?? Infinity);
|
|
4297
4493
|
}
|
|
4298
4494
|
}
|
|
4495
|
+
const signatures = [...merged.keys()].sort();
|
|
4496
|
+
return {
|
|
4497
|
+
key: JSON.stringify([this._sessionGeneration, signatures, ttlSeconds ?? null]),
|
|
4498
|
+
subscriptions: signatures.map((signature) => merged.get(signature)),
|
|
4499
|
+
ttlSeconds
|
|
4500
|
+
};
|
|
4299
4501
|
}
|
|
4300
|
-
|
|
4301
|
-
this.
|
|
4502
|
+
dispatch(event) {
|
|
4503
|
+
for (const subscriber of this._subscribers) {
|
|
4504
|
+
if (matchesAnySubscription(event, subscriber.requested)) {
|
|
4505
|
+
subscriber.queue.push(event);
|
|
4506
|
+
}
|
|
4507
|
+
}
|
|
4302
4508
|
}
|
|
4303
|
-
|
|
4304
|
-
|
|
4509
|
+
/**
|
|
4510
|
+
* Detach every subscriber. With `error`, their iterators throw it after
|
|
4511
|
+
* draining buffered events; without, they complete.
|
|
4512
|
+
*/
|
|
4513
|
+
release(error) {
|
|
4514
|
+
const subscribers = [...this._subscribers];
|
|
4515
|
+
this._subscribers.clear();
|
|
4516
|
+
for (const { queue } of subscribers) {
|
|
4517
|
+
if (error) {
|
|
4518
|
+
queue.fail(error);
|
|
4519
|
+
} else {
|
|
4520
|
+
queue.close();
|
|
4521
|
+
}
|
|
4522
|
+
}
|
|
4305
4523
|
}
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
const ticketResponse = await this.context.fetch(`${host}/hooks/tickets`, {
|
|
4310
|
-
method: "POST",
|
|
4311
|
-
headers: {
|
|
4312
|
-
...serviceHeadersToRecord(headers),
|
|
4313
|
-
"content-type": "application/json"
|
|
4314
|
-
},
|
|
4315
|
-
body: JSON.stringify({
|
|
4316
|
-
subscriptions,
|
|
4317
|
-
ttlSeconds
|
|
4318
|
-
}),
|
|
4319
|
-
signal
|
|
4320
|
-
});
|
|
4321
|
-
if (!ticketResponse.ok) {
|
|
4322
|
-
throw await responseError(
|
|
4323
|
-
"hooks",
|
|
4324
|
-
"failed to mint hook ticket",
|
|
4325
|
-
ticketResponse
|
|
4326
|
-
);
|
|
4524
|
+
report(error) {
|
|
4525
|
+
if (error.meta && typeof error.meta === "object") {
|
|
4526
|
+
Object.freeze(error.meta);
|
|
4327
4527
|
}
|
|
4328
|
-
|
|
4329
|
-
|
|
4330
|
-
|
|
4528
|
+
Object.freeze(error);
|
|
4529
|
+
try {
|
|
4530
|
+
this.emitError(error, "stream");
|
|
4531
|
+
} catch {
|
|
4331
4532
|
}
|
|
4332
|
-
return ticketJson;
|
|
4333
4533
|
}
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4534
|
+
/**
|
|
4535
|
+
* Unreachable by construction. If the loop ever rejects anyway, fail its
|
|
4536
|
+
* subscribers visibly instead of stranding them or crashing the process.
|
|
4537
|
+
*/
|
|
4538
|
+
collapse() {
|
|
4539
|
+
this._supervising = false;
|
|
4540
|
+
this._phase?.interrupt.abort();
|
|
4541
|
+
this._phase = void 0;
|
|
4542
|
+
const error = serviceError(
|
|
4543
|
+
ErrorCodes.NETWORK_ERROR,
|
|
4544
|
+
"hook stream supervisor stopped unexpectedly",
|
|
4545
|
+
"hooks"
|
|
4342
4546
|
);
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4547
|
+
this.report(error);
|
|
4548
|
+
this.release(error);
|
|
4549
|
+
}
|
|
4550
|
+
onSessionChange(session) {
|
|
4551
|
+
super.onSessionChange(session);
|
|
4552
|
+
this._sessionGeneration += 1;
|
|
4553
|
+
this.wake();
|
|
4554
|
+
}
|
|
4555
|
+
onSignOut() {
|
|
4556
|
+
super.onSignOut();
|
|
4557
|
+
this.release();
|
|
4558
|
+
this.wake();
|
|
4559
|
+
}
|
|
4560
|
+
createHookHeaders(action, path) {
|
|
4561
|
+
return this.context.invoke(this.session, "hooks", path, action);
|
|
4351
4562
|
}
|
|
4352
4563
|
createInvokeHeaders(subscriptions) {
|
|
4353
4564
|
const entries = subscriptions.map((subscription) => ({
|
|
@@ -4378,11 +4589,168 @@ function buildScopePath(service, pathPrefix) {
|
|
|
4378
4589
|
const normalized = normalizePathPrefix(pathPrefix);
|
|
4379
4590
|
return normalized ? `${service}/${normalized}` : service;
|
|
4380
4591
|
}
|
|
4592
|
+
function hookStreamRetryDelay(attempt) {
|
|
4593
|
+
const cap = Math.min(
|
|
4594
|
+
HOOK_STREAM_RETRY_BASE_DELAY_MS * 2 ** Math.max(0, attempt - 1),
|
|
4595
|
+
HOOK_STREAM_RETRY_MAX_DELAY_MS
|
|
4596
|
+
);
|
|
4597
|
+
return cap / 2 + Math.random() * (cap / 2);
|
|
4598
|
+
}
|
|
4599
|
+
function isTerminalMintRefusal(status) {
|
|
4600
|
+
return typeof status === "number" && status >= 400 && status < 500 && status !== 408 && status !== 429;
|
|
4601
|
+
}
|
|
4602
|
+
var SUPERSEDED = /* @__PURE__ */ Symbol("hooks attempt superseded");
|
|
4603
|
+
async function awaitOwned(signal, operation) {
|
|
4604
|
+
if (signal.aborted) {
|
|
4605
|
+
if (typeof operation !== "function") {
|
|
4606
|
+
void operation.then(cancelLateResponse, () => void 0);
|
|
4607
|
+
}
|
|
4608
|
+
throw SUPERSEDED;
|
|
4609
|
+
}
|
|
4610
|
+
const promise = typeof operation === "function" ? operation() : operation;
|
|
4611
|
+
return new Promise((resolve, reject) => {
|
|
4612
|
+
let settled = false;
|
|
4613
|
+
const cleanup = () => signal.removeEventListener("abort", onAbort);
|
|
4614
|
+
const onAbort = () => {
|
|
4615
|
+
if (settled) return;
|
|
4616
|
+
settled = true;
|
|
4617
|
+
cleanup();
|
|
4618
|
+
reject(SUPERSEDED);
|
|
4619
|
+
};
|
|
4620
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
4621
|
+
promise.then(
|
|
4622
|
+
(value) => {
|
|
4623
|
+
if (settled) {
|
|
4624
|
+
cancelLateResponse(value);
|
|
4625
|
+
return;
|
|
4626
|
+
}
|
|
4627
|
+
settled = true;
|
|
4628
|
+
cleanup();
|
|
4629
|
+
resolve(value);
|
|
4630
|
+
},
|
|
4631
|
+
(error) => {
|
|
4632
|
+
if (settled) return;
|
|
4633
|
+
settled = true;
|
|
4634
|
+
cleanup();
|
|
4635
|
+
reject(error);
|
|
4636
|
+
}
|
|
4637
|
+
);
|
|
4638
|
+
});
|
|
4639
|
+
}
|
|
4640
|
+
function cancelLateResponse(value) {
|
|
4641
|
+
if (!(value instanceof Response) || !value.body) return;
|
|
4642
|
+
try {
|
|
4643
|
+
const cancellation = value.body.cancel();
|
|
4644
|
+
void cancellation.then(() => void 0, () => void 0);
|
|
4645
|
+
} catch {
|
|
4646
|
+
}
|
|
4647
|
+
}
|
|
4648
|
+
function hookStreamRefusal(status) {
|
|
4649
|
+
const code = typeof status === "number" ? status : void 0;
|
|
4650
|
+
return serviceError(
|
|
4651
|
+
ErrorCodes.NETWORK_ERROR,
|
|
4652
|
+
`hook stream open refused: ${code ?? "unknown status"}`,
|
|
4653
|
+
"hooks",
|
|
4654
|
+
{ meta: { phase: "open", status: code } }
|
|
4655
|
+
);
|
|
4656
|
+
}
|
|
4657
|
+
var STREAM_ERROR_NAMES = /* @__PURE__ */ new Set([
|
|
4658
|
+
"Error",
|
|
4659
|
+
"TypeError",
|
|
4660
|
+
"AbortError",
|
|
4661
|
+
"TimeoutError",
|
|
4662
|
+
"SyntaxError",
|
|
4663
|
+
"RangeError",
|
|
4664
|
+
"NetworkError"
|
|
4665
|
+
]);
|
|
4666
|
+
function hookStreamFailure(phase, thrown) {
|
|
4667
|
+
const candidateName = readProperty(thrown, "name");
|
|
4668
|
+
const name = typeof candidateName === "string" && STREAM_ERROR_NAMES.has(candidateName) ? candidateName : "Error";
|
|
4669
|
+
const code = identifier(readProperty(thrown, "code")) ?? identifier(readProperty(readProperty(thrown, "cause"), "code"));
|
|
4670
|
+
return serviceError(
|
|
4671
|
+
ErrorCodes.NETWORK_ERROR,
|
|
4672
|
+
`hook stream ${phase} failed: ${name}${code ? ` (${code})` : ""}`,
|
|
4673
|
+
"hooks",
|
|
4674
|
+
{ meta: { phase, errorName: name, ...code ? { errorCode: code } : {} } }
|
|
4675
|
+
);
|
|
4676
|
+
}
|
|
4677
|
+
var STREAM_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
4678
|
+
"ECONNREFUSED",
|
|
4679
|
+
"ECONNRESET",
|
|
4680
|
+
"ECONNABORTED",
|
|
4681
|
+
"ETIMEDOUT",
|
|
4682
|
+
"EPIPE",
|
|
4683
|
+
"ENOTFOUND",
|
|
4684
|
+
"EAI_AGAIN",
|
|
4685
|
+
"EHOSTUNREACH",
|
|
4686
|
+
"ENETUNREACH",
|
|
4687
|
+
"ENETDOWN",
|
|
4688
|
+
"EADDRNOTAVAIL",
|
|
4689
|
+
"UND_ERR_SOCKET",
|
|
4690
|
+
"UND_ERR_CONNECT_TIMEOUT",
|
|
4691
|
+
"UND_ERR_HEADERS_TIMEOUT",
|
|
4692
|
+
"UND_ERR_BODY_TIMEOUT",
|
|
4693
|
+
"UND_ERR_CLOSED",
|
|
4694
|
+
"UND_ERR_ABORTED",
|
|
4695
|
+
"UND_ERR_RESPONSE_STATUS_CODE",
|
|
4696
|
+
"ERR_TLS_CERT_ALTNAME_INVALID",
|
|
4697
|
+
"CERT_HAS_EXPIRED",
|
|
4698
|
+
"DEPTH_ZERO_SELF_SIGNED_CERT",
|
|
4699
|
+
"UNABLE_TO_VERIFY_LEAF_SIGNATURE",
|
|
4700
|
+
"SELF_SIGNED_CERT_IN_CHAIN",
|
|
4701
|
+
"ERR_SSL_WRONG_VERSION_NUMBER"
|
|
4702
|
+
]);
|
|
4703
|
+
function identifier(value) {
|
|
4704
|
+
return typeof value === "string" && STREAM_ERROR_CODES.has(value) ? value : void 0;
|
|
4705
|
+
}
|
|
4706
|
+
function readProperty(value, key) {
|
|
4707
|
+
if (value === null || typeof value !== "object" && typeof value !== "function") {
|
|
4708
|
+
return void 0;
|
|
4709
|
+
}
|
|
4710
|
+
try {
|
|
4711
|
+
return Reflect.get(value, key);
|
|
4712
|
+
} catch {
|
|
4713
|
+
return void 0;
|
|
4714
|
+
}
|
|
4715
|
+
}
|
|
4716
|
+
function sleep(delayMs, _attempt, signal) {
|
|
4717
|
+
return new Promise((resolve) => {
|
|
4718
|
+
const finish = () => {
|
|
4719
|
+
clearTimeout(timer);
|
|
4720
|
+
signal.removeEventListener("abort", stop);
|
|
4721
|
+
resolve();
|
|
4722
|
+
};
|
|
4723
|
+
const timer = setTimeout(finish, delayMs);
|
|
4724
|
+
timer.unref?.();
|
|
4725
|
+
const stop = () => finish();
|
|
4726
|
+
if (signal.aborted) {
|
|
4727
|
+
finish();
|
|
4728
|
+
} else {
|
|
4729
|
+
signal.addEventListener("abort", stop, { once: true });
|
|
4730
|
+
}
|
|
4731
|
+
});
|
|
4732
|
+
}
|
|
4733
|
+
function abortPromise(signal) {
|
|
4734
|
+
let resolve;
|
|
4735
|
+
const promise = new Promise((done) => {
|
|
4736
|
+
resolve = done;
|
|
4737
|
+
});
|
|
4738
|
+
const onAbort = () => resolve();
|
|
4739
|
+
if (signal.aborted) {
|
|
4740
|
+
resolve();
|
|
4741
|
+
} else {
|
|
4742
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
4743
|
+
}
|
|
4744
|
+
return {
|
|
4745
|
+
promise,
|
|
4746
|
+
dispose: () => signal.removeEventListener("abort", onAbort)
|
|
4747
|
+
};
|
|
4748
|
+
}
|
|
4381
4749
|
function normalizeSubscription(subscription) {
|
|
4382
4750
|
return {
|
|
4383
4751
|
...subscription,
|
|
4384
4752
|
pathPrefix: normalizePathPrefix(subscription.pathPrefix),
|
|
4385
|
-
abilities: subscription.abilities
|
|
4753
|
+
abilities: subscription.abilities ? [...subscription.abilities] : []
|
|
4386
4754
|
};
|
|
4387
4755
|
}
|
|
4388
4756
|
function subscriptionSignature(subscription) {
|
|
@@ -4448,9 +4816,6 @@ async function responseError(service, message, response) {
|
|
|
4448
4816
|
meta: { ...error.meta, status: response.status, statusText: response.statusText }
|
|
4449
4817
|
};
|
|
4450
4818
|
}
|
|
4451
|
-
function isAbortError(error) {
|
|
4452
|
-
return error instanceof DOMException && error.name === "AbortError";
|
|
4453
|
-
}
|
|
4454
4819
|
async function* parseSseStream(body, signal) {
|
|
4455
4820
|
if (!body) {
|
|
4456
4821
|
throw new Error("Hook stream response does not expose a readable body");
|
|
@@ -4479,11 +4844,24 @@ async function* parseSseStream(body, signal) {
|
|
|
4479
4844
|
async function* readBodyChunks(body, signal) {
|
|
4480
4845
|
const asyncIterable = body;
|
|
4481
4846
|
if (typeof asyncIterable?.[Symbol.asyncIterator] === "function") {
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4847
|
+
const iterator = asyncIterable[Symbol.asyncIterator]();
|
|
4848
|
+
const cancel = () => {
|
|
4849
|
+
try {
|
|
4850
|
+
const closing = iterator.return?.();
|
|
4851
|
+
if (closing) void Promise.resolve(closing).then(() => void 0, () => void 0);
|
|
4852
|
+
} catch {
|
|
4853
|
+
}
|
|
4854
|
+
};
|
|
4855
|
+
signal?.addEventListener("abort", cancel, { once: true });
|
|
4856
|
+
try {
|
|
4857
|
+
while (!signal?.aborted) {
|
|
4858
|
+
const next = await iterator.next();
|
|
4859
|
+
if (next.done) break;
|
|
4860
|
+
yield next.value;
|
|
4485
4861
|
}
|
|
4486
|
-
|
|
4862
|
+
} finally {
|
|
4863
|
+
signal?.removeEventListener("abort", cancel);
|
|
4864
|
+
cancel();
|
|
4487
4865
|
}
|
|
4488
4866
|
return;
|
|
4489
4867
|
}
|
|
@@ -4492,21 +4870,23 @@ async function* readBodyChunks(body, signal) {
|
|
|
4492
4870
|
throw new Error("Unsupported hook stream body type");
|
|
4493
4871
|
}
|
|
4494
4872
|
const reader = stream.getReader();
|
|
4873
|
+
const cancelReader = () => {
|
|
4874
|
+
try {
|
|
4875
|
+
const cancellation = reader.cancel?.();
|
|
4876
|
+
if (cancellation) void cancellation.then(() => void 0, () => void 0);
|
|
4877
|
+
} catch {
|
|
4878
|
+
}
|
|
4879
|
+
};
|
|
4880
|
+
signal?.addEventListener("abort", cancelReader, { once: true });
|
|
4495
4881
|
try {
|
|
4496
4882
|
while (!signal?.aborted) {
|
|
4497
4883
|
const { done, value } = await reader.read();
|
|
4498
|
-
if (done)
|
|
4499
|
-
|
|
4500
|
-
}
|
|
4501
|
-
if (value) {
|
|
4502
|
-
yield value;
|
|
4503
|
-
}
|
|
4884
|
+
if (done) break;
|
|
4885
|
+
if (value) yield value;
|
|
4504
4886
|
}
|
|
4505
4887
|
} finally {
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
} catch {
|
|
4509
|
-
}
|
|
4888
|
+
signal?.removeEventListener("abort", cancelReader);
|
|
4889
|
+
cancelReader();
|
|
4510
4890
|
reader.releaseLock?.();
|
|
4511
4891
|
}
|
|
4512
4892
|
}
|
|
@@ -7150,10 +7530,10 @@ var EncryptionService = class extends BaseService {
|
|
|
7150
7530
|
get crypto() {
|
|
7151
7531
|
return this._config.crypto;
|
|
7152
7532
|
}
|
|
7153
|
-
async discoverNetwork(
|
|
7533
|
+
async discoverNetwork(identifier2, ownerDid) {
|
|
7154
7534
|
this.assertActive();
|
|
7155
7535
|
const result = await discoverNetwork({
|
|
7156
|
-
identifier,
|
|
7536
|
+
identifier: identifier2,
|
|
7157
7537
|
...ownerDid !== void 0 ? { ownerDid } : {},
|
|
7158
7538
|
...this._config.node !== void 0 ? { node: this._config.node } : {},
|
|
7159
7539
|
...this._config.wellKnown !== void 0 ? { wellKnown: this._config.wellKnown } : {}
|