memeloop 0.2.8 → 0.2.9
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/{chunk-NVJCRIEK.js → chunk-34B7MUI6.js} +2 -2
- package/dist/{chunk-DACM5AMS.js → chunk-7W4FMKMO.js} +190 -56
- package/dist/chunk-7W4FMKMO.js.map +1 -0
- package/dist/{chunk-OD6U6VAR.js → chunk-GH5RDPLJ.js} +2 -2
- package/dist/{chunk-OD6U6VAR.js.map → chunk-GH5RDPLJ.js.map} +1 -1
- package/dist/device-network/cloudDeviceFetchClient.d.ts +9 -7
- package/dist/device-network/cloudDeviceFetchClient.d.ts.map +1 -1
- package/dist/device-network/deviceCloudConnectionCoordinator.d.ts +5 -5
- package/dist/device-network/deviceCloudConnectionCoordinator.d.ts.map +1 -1
- package/dist/device-network/deviceOrchestrationTransport.d.ts +7 -0
- package/dist/device-network/deviceOrchestrationTransport.d.ts.map +1 -1
- package/dist/device-network/standardDeviceCloudConnectionAdapter.d.ts +16 -8
- package/dist/device-network/standardDeviceCloudConnectionAdapter.d.ts.map +1 -1
- package/dist/device-network/types.d.ts +4 -2
- package/dist/device-network/types.d.ts.map +1 -1
- package/dist/device-network-portable.cjs +190 -55
- package/dist/device-network-portable.cjs.map +1 -1
- package/dist/device-network-portable.js +189 -55
- package/dist/device-network-portable.js.map +1 -1
- package/dist/device-network.cjs +190 -55
- package/dist/device-network.cjs.map +1 -1
- package/dist/device-network.js +4 -2
- package/dist/index.cjs +488 -180
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +302 -127
- package/dist/index.js.map +1 -1
- package/dist/loop-api.cjs +1 -1
- package/dist/loop-api.cjs.map +1 -1
- package/dist/loop-api.js +1 -1
- package/dist/mobile.cjs.map +1 -1
- package/dist/orchestration/externalOrchestrationController.d.ts.map +1 -1
- package/dist/orchestration/workloadExecutionController.d.ts.map +1 -1
- package/dist/plugin/loader.d.ts +1 -1
- package/package.json +2 -1
- package/dist/chunk-DACM5AMS.js.map +0 -1
- /package/dist/{chunk-NVJCRIEK.js.map → chunk-34B7MUI6.js.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DeviceNetworkUnavailableError
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-7W4FMKMO.js";
|
|
4
4
|
|
|
5
5
|
// src/device-network/memoryDeviceNetworkService.ts
|
|
6
6
|
var emptyCapabilities = {
|
|
@@ -197,4 +197,4 @@ export {
|
|
|
197
197
|
MemoryDeviceNetworkService,
|
|
198
198
|
syncCloudDevices
|
|
199
199
|
};
|
|
200
|
-
//# sourceMappingURL=chunk-
|
|
200
|
+
//# sourceMappingURL=chunk-34B7MUI6.js.map
|
|
@@ -1213,14 +1213,28 @@ var MemoryDeviceCloudTokenStorage = class {
|
|
|
1213
1213
|
loadConnectionGrant(input) {
|
|
1214
1214
|
return this.grants.get(connectionGrantCacheKey(input));
|
|
1215
1215
|
}
|
|
1216
|
-
saveConnectionGrant(input, grant) {
|
|
1217
|
-
|
|
1216
|
+
saveConnectionGrant(input, grant, fence) {
|
|
1217
|
+
const write = () => {
|
|
1218
|
+
this.grants.set(connectionGrantCacheKey(input), grant);
|
|
1219
|
+
};
|
|
1220
|
+
if (!fence) {
|
|
1221
|
+
write();
|
|
1222
|
+
return;
|
|
1223
|
+
}
|
|
1224
|
+
if (!fence.commitSynchronous(write)) fence.throwIfStale();
|
|
1218
1225
|
}
|
|
1219
1226
|
loadRelayReservation(peerId) {
|
|
1220
1227
|
return this.relayReservations.get(peerId);
|
|
1221
1228
|
}
|
|
1222
|
-
saveRelayReservation(peerId, token) {
|
|
1223
|
-
|
|
1229
|
+
saveRelayReservation(peerId, token, fence) {
|
|
1230
|
+
const write = () => {
|
|
1231
|
+
this.relayReservations.set(peerId, token);
|
|
1232
|
+
};
|
|
1233
|
+
if (!fence) {
|
|
1234
|
+
write();
|
|
1235
|
+
return;
|
|
1236
|
+
}
|
|
1237
|
+
if (!fence.commitSynchronous(write)) fence.throwIfStale();
|
|
1224
1238
|
}
|
|
1225
1239
|
clear() {
|
|
1226
1240
|
this.grants.clear();
|
|
@@ -1335,13 +1349,16 @@ var CloudDeviceFetchClient = class {
|
|
|
1335
1349
|
}
|
|
1336
1350
|
return { issuer: value.issuer, publicKeyMultibase: value.publicKeyMultibase };
|
|
1337
1351
|
}
|
|
1338
|
-
async createConnectionGrant(input, signal) {
|
|
1352
|
+
async createConnectionGrant(input, signal, fence) {
|
|
1353
|
+
assertFenceSignal(signal, fence);
|
|
1354
|
+
fence?.throwIfStale();
|
|
1339
1355
|
if (!isCanonicalConnectionGrantRequest(input)) {
|
|
1340
1356
|
throw new TypeError("invalid_connection_grant_scope");
|
|
1341
1357
|
}
|
|
1342
1358
|
const cacheInput = normalizedConnectionGrantRequest(input);
|
|
1343
1359
|
const cached = await this.loadCachedGrant(cacheInput);
|
|
1344
1360
|
throwIfAborted(signal);
|
|
1361
|
+
fence?.throwIfStale();
|
|
1345
1362
|
if (isUsableConnectionGrant(cached, cacheInput, this.now() + this.tokenSafetyMarginMs)) {
|
|
1346
1363
|
return cached;
|
|
1347
1364
|
}
|
|
@@ -1350,12 +1367,17 @@ var CloudDeviceFetchClient = class {
|
|
|
1350
1367
|
body: JSON.stringify(input)
|
|
1351
1368
|
}, signal);
|
|
1352
1369
|
if (!isUsableConnectionGrant(value, cacheInput, this.now())) throw invalidShape();
|
|
1353
|
-
|
|
1370
|
+
fence?.throwIfStale();
|
|
1371
|
+
await this.saveCachedGrant(cacheInput, value, fence);
|
|
1372
|
+
fence?.throwIfStale();
|
|
1354
1373
|
return value;
|
|
1355
1374
|
}
|
|
1356
|
-
async createRelayReservation(input, signal) {
|
|
1375
|
+
async createRelayReservation(input, signal, fence) {
|
|
1376
|
+
assertFenceSignal(signal, fence);
|
|
1377
|
+
fence?.throwIfStale();
|
|
1357
1378
|
const cached = await this.loadCachedRelayReservation(input.peerId);
|
|
1358
1379
|
throwIfAborted(signal);
|
|
1380
|
+
fence?.throwIfStale();
|
|
1359
1381
|
if (isUsableRelayReservation(cached, input.peerId, this.now() + this.tokenSafetyMarginMs)) {
|
|
1360
1382
|
return cached;
|
|
1361
1383
|
}
|
|
@@ -1364,7 +1386,9 @@ var CloudDeviceFetchClient = class {
|
|
|
1364
1386
|
body: JSON.stringify(input)
|
|
1365
1387
|
}, signal);
|
|
1366
1388
|
if (!isUsableRelayReservation(value, input.peerId, this.now())) throw invalidShape();
|
|
1367
|
-
|
|
1389
|
+
fence?.throwIfStale();
|
|
1390
|
+
await this.saveCachedRelayReservation(input.peerId, value, fence);
|
|
1391
|
+
fence?.throwIfStale();
|
|
1368
1392
|
return value;
|
|
1369
1393
|
}
|
|
1370
1394
|
async heartbeat(input, signal) {
|
|
@@ -1438,10 +1462,11 @@ var CloudDeviceFetchClient = class {
|
|
|
1438
1462
|
return void 0;
|
|
1439
1463
|
}
|
|
1440
1464
|
}
|
|
1441
|
-
async saveCachedGrant(input, grant) {
|
|
1465
|
+
async saveCachedGrant(input, grant, fence) {
|
|
1442
1466
|
try {
|
|
1443
|
-
await this.tokenStorage.saveConnectionGrant(input, grant);
|
|
1467
|
+
await this.tokenStorage.saveConnectionGrant(input, grant, fence);
|
|
1444
1468
|
} catch (error) {
|
|
1469
|
+
if (fence && !fence.isCurrent()) fence.throwIfStale();
|
|
1445
1470
|
this.options.onTokenStorageError?.("save", error);
|
|
1446
1471
|
}
|
|
1447
1472
|
}
|
|
@@ -1453,14 +1478,20 @@ var CloudDeviceFetchClient = class {
|
|
|
1453
1478
|
return void 0;
|
|
1454
1479
|
}
|
|
1455
1480
|
}
|
|
1456
|
-
async saveCachedRelayReservation(peerId, token) {
|
|
1481
|
+
async saveCachedRelayReservation(peerId, token, fence) {
|
|
1457
1482
|
try {
|
|
1458
|
-
await this.tokenStorage.saveRelayReservation(peerId, token);
|
|
1483
|
+
await this.tokenStorage.saveRelayReservation(peerId, token, fence);
|
|
1459
1484
|
} catch (error) {
|
|
1485
|
+
if (fence && !fence.isCurrent()) fence.throwIfStale();
|
|
1460
1486
|
this.options.onTokenStorageError?.("save", error);
|
|
1461
1487
|
}
|
|
1462
1488
|
}
|
|
1463
1489
|
};
|
|
1490
|
+
function assertFenceSignal(signal, fence) {
|
|
1491
|
+
if (fence && signal && fence.signal !== signal) {
|
|
1492
|
+
throw new TypeError("device_cloud_generation_signal_mismatch");
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1464
1495
|
function normalizeCloudDeviceBaseUrl(value) {
|
|
1465
1496
|
const baseUrl = value.trim();
|
|
1466
1497
|
if (!baseUrl || baseUrl.length > CLOUD_URL_MAX_CHARACTERS) throw new Error("invalid_cloud_url");
|
|
@@ -1887,16 +1918,16 @@ var DeviceCloudConnectionCoordinator = class {
|
|
|
1887
1918
|
try {
|
|
1888
1919
|
if (this.snapshotValue.components.authorizer !== "ready") {
|
|
1889
1920
|
activeComponent = "authorizer";
|
|
1890
|
-
await this.runStep(activeComponent, generation, signal, () => this.options.adapter.ensureAuthorizer(configuration, signal));
|
|
1921
|
+
await this.runStep(activeComponent, generation, signal, (fence) => this.options.adapter.ensureAuthorizer(configuration, signal, fence));
|
|
1891
1922
|
}
|
|
1892
1923
|
if (this.snapshotValue.components.registration !== "ready") {
|
|
1893
1924
|
activeComponent = "registration";
|
|
1894
|
-
await this.runStep(activeComponent, generation, signal, () => this.options.adapter.registerDevice(configuration, signal));
|
|
1925
|
+
await this.runStep(activeComponent, generation, signal, (fence) => this.options.adapter.registerDevice(configuration, signal, fence));
|
|
1895
1926
|
}
|
|
1896
1927
|
let relayFailure;
|
|
1897
1928
|
try {
|
|
1898
1929
|
activeComponent = "relay";
|
|
1899
|
-
await this.runStep(activeComponent, generation, signal, () => this.options.adapter.ensureRelay(configuration, signal));
|
|
1930
|
+
await this.runStep(activeComponent, generation, signal, (fence) => this.options.adapter.ensureRelay(configuration, signal, fence));
|
|
1900
1931
|
} catch (error) {
|
|
1901
1932
|
const classification = this.classify(error);
|
|
1902
1933
|
if (classification === "registration-invalid") throw error;
|
|
@@ -1904,11 +1935,11 @@ var DeviceCloudConnectionCoordinator = class {
|
|
|
1904
1935
|
this.warn("Device Cloud relay maintenance failed", relayFailure);
|
|
1905
1936
|
}
|
|
1906
1937
|
activeComponent = "heartbeat";
|
|
1907
|
-
await this.runStep(activeComponent, generation, signal, () => this.options.adapter.heartbeat(configuration, signal));
|
|
1938
|
+
await this.runStep(activeComponent, generation, signal, (fence) => this.options.adapter.heartbeat(configuration, signal, fence));
|
|
1908
1939
|
let directoryFailure;
|
|
1909
1940
|
try {
|
|
1910
1941
|
activeComponent = "directory";
|
|
1911
|
-
await this.runStep(activeComponent, generation, signal, () => this.options.adapter.syncDirectory(configuration, signal));
|
|
1942
|
+
await this.runStep(activeComponent, generation, signal, (fence) => this.options.adapter.syncDirectory(configuration, signal, fence));
|
|
1912
1943
|
} catch (error) {
|
|
1913
1944
|
const classification = this.classify(error);
|
|
1914
1945
|
if (classification === "registration-invalid") throw error;
|
|
@@ -1948,9 +1979,9 @@ var DeviceCloudConnectionCoordinator = class {
|
|
|
1948
1979
|
if (!this.isCurrent(generation, signal)) return;
|
|
1949
1980
|
await this.setComponent(component, "pending", generation);
|
|
1950
1981
|
try {
|
|
1951
|
-
const result = await operation();
|
|
1952
|
-
if (!this.isCurrent(generation, signal)) return;
|
|
1953
1982
|
const fence = this.createCommitFence(generation, signal);
|
|
1983
|
+
const result = await operation(fence);
|
|
1984
|
+
if (!this.isCurrent(generation, signal)) return;
|
|
1954
1985
|
await result?.commit?.(fence);
|
|
1955
1986
|
if (!this.isCurrent(generation, signal)) return;
|
|
1956
1987
|
await this.setComponent(component, "ready", generation);
|
|
@@ -2414,11 +2445,18 @@ function createJsonFrameReader(source, options) {
|
|
|
2414
2445
|
|
|
2415
2446
|
// src/device-network/deviceOrchestrationTransport.ts
|
|
2416
2447
|
var DEVICE_ORCHESTRATION_PROTOCOL = "/memeloop/orchestration/2.0.0";
|
|
2417
|
-
var
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2448
|
+
var DEVICE_ORCHESTRATION_FRAME_LIMITS = Object.freeze({
|
|
2449
|
+
maxPayloadBytes: 1024 * 1024,
|
|
2450
|
+
requestIdleTimeoutMs: 1e4,
|
|
2451
|
+
requestTotalTimeoutMs: 3e4,
|
|
2452
|
+
watchIdleTimeoutMs: 9e4,
|
|
2453
|
+
watchBookmarkIntervalMs: 3e4
|
|
2454
|
+
});
|
|
2455
|
+
var DEFAULT_MAX_FRAME_BYTES = DEVICE_ORCHESTRATION_FRAME_LIMITS.maxPayloadBytes;
|
|
2456
|
+
var REQUEST_IDLE_TIMEOUT_MS = DEVICE_ORCHESTRATION_FRAME_LIMITS.requestIdleTimeoutMs;
|
|
2457
|
+
var REQUEST_TOTAL_TIMEOUT_MS = DEVICE_ORCHESTRATION_FRAME_LIMITS.requestTotalTimeoutMs;
|
|
2458
|
+
var WATCH_IDLE_TIMEOUT_MS = DEVICE_ORCHESTRATION_FRAME_LIMITS.watchIdleTimeoutMs;
|
|
2459
|
+
var WATCH_BOOKMARK_INTERVAL_MS = DEVICE_ORCHESTRATION_FRAME_LIMITS.watchBookmarkIntervalMs;
|
|
2422
2460
|
function orchestrationTransportError(code, message) {
|
|
2423
2461
|
return new OrchestrationError({
|
|
2424
2462
|
code,
|
|
@@ -2699,6 +2737,13 @@ function createDeviceOrchestrationStreamHandler(options) {
|
|
|
2699
2737
|
assertFrameLimit(maxFrameBytes);
|
|
2700
2738
|
return async ({ remotePeerId, stream, authorize }) => {
|
|
2701
2739
|
const abort = new AbortController();
|
|
2740
|
+
const abortFromStream = () => {
|
|
2741
|
+
if (!abort.signal.aborted) {
|
|
2742
|
+
abort.abort(stream.signal?.reason ?? new Error("device orchestration stream closed"));
|
|
2743
|
+
}
|
|
2744
|
+
};
|
|
2745
|
+
stream.signal?.addEventListener("abort", abortFromStream, { once: true });
|
|
2746
|
+
if (stream.signal?.aborted) abortFromStream();
|
|
2702
2747
|
try {
|
|
2703
2748
|
const envelope = await readSingleRequest(stream, maxFrameBytes);
|
|
2704
2749
|
if (authorize && !await authorize(envelope.grant)) {
|
|
@@ -2722,7 +2767,8 @@ function createDeviceOrchestrationStreamHandler(options) {
|
|
|
2722
2767
|
await stream.sink(encodeJsonFrames([response], maxFrameBytes));
|
|
2723
2768
|
}
|
|
2724
2769
|
} finally {
|
|
2725
|
-
|
|
2770
|
+
stream.signal?.removeEventListener("abort", abortFromStream);
|
|
2771
|
+
if (!abort.signal.aborted) abort.abort();
|
|
2726
2772
|
await stream.close().catch(() => void 0);
|
|
2727
2773
|
}
|
|
2728
2774
|
};
|
|
@@ -3154,6 +3200,23 @@ function sameTrustedDevice(left, right) {
|
|
|
3154
3200
|
|
|
3155
3201
|
// src/device-network/standardDeviceCloudConnectionAdapter.ts
|
|
3156
3202
|
var DEFAULT_RELAY_TOKEN_SAFETY_MARGIN_MS = 2 * 6e4;
|
|
3203
|
+
var REGISTRATION_INVALID_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
3204
|
+
"device_not_found",
|
|
3205
|
+
"device_registration_invalid",
|
|
3206
|
+
"device_registration_not_found",
|
|
3207
|
+
"invalid_device_registration",
|
|
3208
|
+
"registration_invalid"
|
|
3209
|
+
]);
|
|
3210
|
+
var DeviceCloudRegistrationInvalidError = class extends Error {
|
|
3211
|
+
code = "DEVICE_CLOUD_REGISTRATION_INVALID";
|
|
3212
|
+
constructor(cause) {
|
|
3213
|
+
super(
|
|
3214
|
+
"cloud device heartbeat rejected",
|
|
3215
|
+
cause === void 0 ? void 0 : { cause }
|
|
3216
|
+
);
|
|
3217
|
+
this.name = "DeviceCloudRegistrationInvalidError";
|
|
3218
|
+
}
|
|
3219
|
+
};
|
|
3157
3220
|
var StandardDeviceCloudConnectionAdapter = class {
|
|
3158
3221
|
constructor(options) {
|
|
3159
3222
|
this.options = options;
|
|
@@ -3173,9 +3236,9 @@ var StandardDeviceCloudConnectionAdapter = class {
|
|
|
3173
3236
|
}
|
|
3174
3237
|
relayRequiredForOnline(_configuration) {
|
|
3175
3238
|
const addresses = this.options.network.getMultiaddrs();
|
|
3176
|
-
return this.options.relayRequiredForOnline?.(addresses) ?? !hasValidDirectCloudDeviceAddress(addresses);
|
|
3239
|
+
return this.options.relayRequiredForOnline?.(addresses) ?? !hasValidDirectCloudDeviceAddress(addresses, this.options.identity.peerId);
|
|
3177
3240
|
}
|
|
3178
|
-
async ensureAuthorizer(client, signal) {
|
|
3241
|
+
async ensureAuthorizer(client, signal, _fence) {
|
|
3179
3242
|
const publicKey = await client.getConnectionGrantPublicKey(signal);
|
|
3180
3243
|
return {
|
|
3181
3244
|
commit: async (fence) => {
|
|
@@ -3185,7 +3248,7 @@ var StandardDeviceCloudConnectionAdapter = class {
|
|
|
3185
3248
|
}
|
|
3186
3249
|
};
|
|
3187
3250
|
}
|
|
3188
|
-
async registerDevice(client, signal) {
|
|
3251
|
+
async registerDevice(client, signal, _fence) {
|
|
3189
3252
|
const nonce = await client.createBindingNonce(signal);
|
|
3190
3253
|
throwIfAborted3(signal);
|
|
3191
3254
|
const signature = await this.options.signDeviceBinding({
|
|
@@ -3213,27 +3276,28 @@ var StandardDeviceCloudConnectionAdapter = class {
|
|
|
3213
3276
|
}
|
|
3214
3277
|
return void 0;
|
|
3215
3278
|
}
|
|
3216
|
-
async ensureRelay(client, signal) {
|
|
3279
|
+
async ensureRelay(client, signal, fence) {
|
|
3217
3280
|
if (this.relayReservationClient === client && this.relayReservation && this.relayReservation.expiresAt > this.now() + this.relayTokenSafetyMarginMs) {
|
|
3218
3281
|
return void 0;
|
|
3219
3282
|
}
|
|
3220
3283
|
const relayReservation = await client.createRelayReservation(
|
|
3221
3284
|
{ peerId: this.options.identity.peerId },
|
|
3222
|
-
signal
|
|
3285
|
+
signal,
|
|
3286
|
+
fence
|
|
3223
3287
|
);
|
|
3224
3288
|
return {
|
|
3225
|
-
commit: async (
|
|
3226
|
-
|
|
3227
|
-
await this.options.network.configureRelayReservation(relayReservation, signal,
|
|
3228
|
-
|
|
3229
|
-
|
|
3289
|
+
commit: async (fence2) => {
|
|
3290
|
+
fence2.throwIfStale();
|
|
3291
|
+
await this.options.network.configureRelayReservation(relayReservation, signal, fence2);
|
|
3292
|
+
fence2.throwIfStale();
|
|
3293
|
+
fence2.commitSynchronous(() => {
|
|
3230
3294
|
this.relayReservation = relayReservation;
|
|
3231
3295
|
this.relayReservationClient = client;
|
|
3232
3296
|
});
|
|
3233
3297
|
}
|
|
3234
3298
|
};
|
|
3235
3299
|
}
|
|
3236
|
-
async heartbeat(client, signal) {
|
|
3300
|
+
async heartbeat(client, signal, _fence) {
|
|
3237
3301
|
throwIfAborted3(signal);
|
|
3238
3302
|
const capabilities = await this.options.capabilities();
|
|
3239
3303
|
throwIfAborted3(signal);
|
|
@@ -3251,8 +3315,16 @@ var StandardDeviceCloudConnectionAdapter = class {
|
|
|
3251
3315
|
if (!boundedProofSignature(heartbeat.signature)) {
|
|
3252
3316
|
throw new Error("invalid device heartbeat signature");
|
|
3253
3317
|
}
|
|
3254
|
-
|
|
3255
|
-
|
|
3318
|
+
let result;
|
|
3319
|
+
try {
|
|
3320
|
+
result = await client.heartbeat(heartbeat, signal);
|
|
3321
|
+
} catch (error) {
|
|
3322
|
+
if (isHeartbeatRegistrationInvalid(error)) {
|
|
3323
|
+
throw new DeviceCloudRegistrationInvalidError(error);
|
|
3324
|
+
}
|
|
3325
|
+
throw error;
|
|
3326
|
+
}
|
|
3327
|
+
if (!result.ok) throw new DeviceCloudRegistrationInvalidError();
|
|
3256
3328
|
return void 0;
|
|
3257
3329
|
}
|
|
3258
3330
|
async dispose(client, signal) {
|
|
@@ -3288,7 +3360,7 @@ var StandardDeviceCloudConnectionAdapter = class {
|
|
|
3288
3360
|
throw new AggregateError(errors, "device cloud generation cleanup failed");
|
|
3289
3361
|
}
|
|
3290
3362
|
}
|
|
3291
|
-
async syncDirectory(client, signal) {
|
|
3363
|
+
async syncDirectory(client, signal, _fence) {
|
|
3292
3364
|
const cloudDevices = await client.listDevices(signal);
|
|
3293
3365
|
return {
|
|
3294
3366
|
commit: async (fence) => {
|
|
@@ -3316,6 +3388,7 @@ var StandardDeviceCloudConnectionAdapter = class {
|
|
|
3316
3388
|
return this.options.syncDevice(client, peerId, signal);
|
|
3317
3389
|
}
|
|
3318
3390
|
classifyError(error) {
|
|
3391
|
+
if (error instanceof DeviceCloudRegistrationInvalidError) return "registration-invalid";
|
|
3319
3392
|
if (error instanceof CloudDeviceFetchError) {
|
|
3320
3393
|
return error.code === "cloud_request_failed" ? "offline" : "error";
|
|
3321
3394
|
}
|
|
@@ -3326,6 +3399,35 @@ var StandardDeviceCloudConnectionAdapter = class {
|
|
|
3326
3399
|
return active.length > 0 ? [...active] : [...this.relayReservation?.relayMultiaddrs ?? []];
|
|
3327
3400
|
}
|
|
3328
3401
|
};
|
|
3402
|
+
function isHeartbeatRegistrationInvalid(error) {
|
|
3403
|
+
if (!(error instanceof CloudDeviceFetchError) || error.code !== "cloud_http_error") {
|
|
3404
|
+
return false;
|
|
3405
|
+
}
|
|
3406
|
+
if (error.status === 404) return true;
|
|
3407
|
+
return error.status === 401 && hasExplicitRegistrationInvalidCode(error.responseBody);
|
|
3408
|
+
}
|
|
3409
|
+
function hasExplicitRegistrationInvalidCode(responseBody) {
|
|
3410
|
+
const body = responseBody?.trim();
|
|
3411
|
+
if (!body) return false;
|
|
3412
|
+
let value;
|
|
3413
|
+
try {
|
|
3414
|
+
value = JSON.parse(body);
|
|
3415
|
+
} catch {
|
|
3416
|
+
return REGISTRATION_INVALID_ERROR_CODES.has(normalizeErrorCode(body));
|
|
3417
|
+
}
|
|
3418
|
+
return registrationInvalidCodeFromValue(value);
|
|
3419
|
+
}
|
|
3420
|
+
function registrationInvalidCodeFromValue(value) {
|
|
3421
|
+
if (typeof value === "string") {
|
|
3422
|
+
return REGISTRATION_INVALID_ERROR_CODES.has(normalizeErrorCode(value));
|
|
3423
|
+
}
|
|
3424
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
3425
|
+
const record = value;
|
|
3426
|
+
return registrationInvalidCodeFromValue(record.code) || registrationInvalidCodeFromValue(record.errorCode) || registrationInvalidCodeFromValue(record.error);
|
|
3427
|
+
}
|
|
3428
|
+
function normalizeErrorCode(value) {
|
|
3429
|
+
return value.trim().toLowerCase().replaceAll("-", "_");
|
|
3430
|
+
}
|
|
3329
3431
|
function toPublicDeviceIdentity(identity) {
|
|
3330
3432
|
return {
|
|
3331
3433
|
peerId: identity.peerId,
|
|
@@ -3335,21 +3437,42 @@ function toPublicDeviceIdentity(identity) {
|
|
|
3335
3437
|
platform: identity.platform
|
|
3336
3438
|
};
|
|
3337
3439
|
}
|
|
3338
|
-
function hasValidDirectCloudDeviceAddress(addresses) {
|
|
3339
|
-
return addresses.some((address) =>
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3440
|
+
function hasValidDirectCloudDeviceAddress(addresses, expectedPeerId) {
|
|
3441
|
+
return addresses.some((address) => isDialableDirectMultiaddr(address, expectedPeerId));
|
|
3442
|
+
}
|
|
3443
|
+
function isDialableDirectMultiaddr(address, expectedPeerId) {
|
|
3444
|
+
if (address.length === 0 || address.length > 4096 || address !== address.trim() || !address.startsWith("/") || address.endsWith("/") || address.includes("//") || address.includes("/p2p-circuit")) return false;
|
|
3445
|
+
const parts = address.split("/").slice(1);
|
|
3446
|
+
if (parts.some((part) => part.length === 0 || containsAsciiControlOrSpace3(part))) return false;
|
|
3447
|
+
const hostProtocol = parts[0];
|
|
3448
|
+
const host = parts[1]?.toLowerCase();
|
|
3449
|
+
if (host === void 0 || hostProtocol !== "ip4" && hostProtocol !== "ip6" && hostProtocol !== "dns" && hostProtocol !== "dns4" && hostProtocol !== "dns6") return false;
|
|
3450
|
+
const publicHost = hostProtocol === "ip4" ? isPublicIpv4(host) : hostProtocol === "ip6" ? isPublicIpv6(host) : isPlausiblePublicDnsHost(host);
|
|
3451
|
+
if (!publicHost) return false;
|
|
3452
|
+
const transport = parts[2];
|
|
3453
|
+
const port = parsePort(parts[3]);
|
|
3454
|
+
if (transport !== "tcp" || port === void 0) return false;
|
|
3455
|
+
let index = 4;
|
|
3456
|
+
if (parts[index] === "ws" || parts[index] === "wss") index += 1;
|
|
3457
|
+
if (parts[index] === "p2p") {
|
|
3458
|
+
const peerId = parts[index + 1];
|
|
3459
|
+
if (!peerId || containsAsciiControlOrSpace3(peerId)) return false;
|
|
3460
|
+
if (expectedPeerId !== void 0 && peerId !== expectedPeerId) return false;
|
|
3461
|
+
index += 2;
|
|
3462
|
+
}
|
|
3463
|
+
return index === parts.length;
|
|
3464
|
+
}
|
|
3465
|
+
function parsePort(value) {
|
|
3466
|
+
if (value === void 0 || !/^\d{1,5}$/u.test(value)) return void 0;
|
|
3467
|
+
const port = Number(value);
|
|
3468
|
+
return port >= 1 && port <= 65535 ? port : void 0;
|
|
3469
|
+
}
|
|
3470
|
+
function containsAsciiControlOrSpace3(value) {
|
|
3471
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
3472
|
+
const code = value.charCodeAt(index);
|
|
3473
|
+
if (code <= 32 || code === 127) return true;
|
|
3474
|
+
}
|
|
3475
|
+
return false;
|
|
3353
3476
|
}
|
|
3354
3477
|
function isPublicIpv4(host) {
|
|
3355
3478
|
const octets = host.split(".").map((part) => Number(part));
|
|
@@ -3389,7 +3512,17 @@ function isPlausiblePublicDnsHost(host) {
|
|
|
3389
3512
|
const normalized = host.endsWith(".") ? host.slice(0, -1) : host;
|
|
3390
3513
|
if (isIpv4Syntax(normalized)) return isPublicIpv4(normalized);
|
|
3391
3514
|
if (normalized.includes(":")) return isPublicIpv6(normalized);
|
|
3392
|
-
|
|
3515
|
+
const specialUseSuffixes = [
|
|
3516
|
+
"example",
|
|
3517
|
+
"home.arpa",
|
|
3518
|
+
"internal",
|
|
3519
|
+
"invalid",
|
|
3520
|
+
"local",
|
|
3521
|
+
"localhost",
|
|
3522
|
+
"onion",
|
|
3523
|
+
"test"
|
|
3524
|
+
];
|
|
3525
|
+
if (specialUseSuffixes.some((suffix) => normalized === suffix || normalized.endsWith(`.${suffix}`))) return false;
|
|
3393
3526
|
const labels = normalized.split(".");
|
|
3394
3527
|
return labels.length > 1 && labels.every(
|
|
3395
3528
|
(label) => label.length > 0 && label.length <= 63 && /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/u.test(label)
|
|
@@ -3467,6 +3600,7 @@ export {
|
|
|
3467
3600
|
encodeJsonFrames,
|
|
3468
3601
|
createJsonFrameReader,
|
|
3469
3602
|
DEVICE_ORCHESTRATION_PROTOCOL,
|
|
3603
|
+
DEVICE_ORCHESTRATION_FRAME_LIMITS,
|
|
3470
3604
|
createDeviceOrchestrationTransport,
|
|
3471
3605
|
createDeviceOrchestrationStreamHandler,
|
|
3472
3606
|
Libp2pDeviceSyncTransport,
|
|
@@ -3488,4 +3622,4 @@ export {
|
|
|
3488
3622
|
StandardDeviceCloudConnectionAdapter,
|
|
3489
3623
|
hasValidDirectCloudDeviceAddress
|
|
3490
3624
|
};
|
|
3491
|
-
//# sourceMappingURL=chunk-
|
|
3625
|
+
//# sourceMappingURL=chunk-7W4FMKMO.js.map
|