@opendatalabs/personal-server-ts-server 1.7.0 → 1.8.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/app.d.ts +3 -1
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +1 -0
- package/dist/app.js.map +1 -1
- package/dist/bootstrap.d.ts +7 -0
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +37 -2
- package/dist/bootstrap.js.map +1 -1
- package/dist/logging/access-log.d.ts +1 -1
- package/dist/logging/access-log.d.ts.map +1 -1
- package/dist/pending-blob-deletions.d.ts +10 -0
- package/dist/pending-blob-deletions.d.ts.map +1 -0
- package/dist/pending-blob-deletions.js +38 -0
- package/dist/pending-blob-deletions.js.map +1 -0
- package/dist/routes/data.d.ts +3 -1
- package/dist/routes/data.d.ts.map +1 -1
- package/dist/routes/data.js +1 -0
- package/dist/routes/data.js.map +1 -1
- package/dist/storage/index-manager.d.ts.map +1 -1
- package/dist/storage/index-manager.js +4 -2
- package/dist/storage/index-manager.js.map +1 -1
- package/dist/storage/index-schema.d.ts +1 -1
- package/dist/storage/index-schema.d.ts.map +1 -1
- package/dist/storage/index-schema.js +9 -2
- package/dist/storage/index-schema.js.map +1 -1
- package/dist/storage/node-data-storage.d.ts.map +1 -1
- package/dist/storage/node-data-storage.js +10 -0
- package/dist/storage/node-data-storage.js.map +1 -1
- package/dist/ui/ps-lite-debug.js +1388 -129
- package/package.json +3 -3
package/dist/ui/ps-lite-debug.js
CHANGED
|
@@ -105729,7 +105729,7 @@ var LineageGatewayError = class extends ProtocolError {
|
|
|
105729
105729
|
};
|
|
105730
105730
|
var LineageCascadeUnavailableError = class extends ProtocolError {
|
|
105731
105731
|
constructor(details) {
|
|
105732
|
-
super(501, "LINEAGE_CASCADE_UNAVAILABLE", "DELETE ?cascade=lineage is specified but not implemented yet:
|
|
105732
|
+
super(501, "LINEAGE_CASCADE_UNAVAILABLE", "DELETE ?cascade=lineage is specified but not implemented yet: the lineage walk that finds every derivative is missing. Delete scopes one at a time; each single-scope delete is durable.", details);
|
|
105733
105733
|
}
|
|
105734
105734
|
};
|
|
105735
105735
|
var InvalidCascadeError = class extends ProtocolError {
|
|
@@ -105737,6 +105737,16 @@ var InvalidCascadeError = class extends ProtocolError {
|
|
|
105737
105737
|
super(400, "INVALID_CASCADE", 'Unsupported cascade mode; the only supported value is "lineage"', details);
|
|
105738
105738
|
}
|
|
105739
105739
|
};
|
|
105740
|
+
var DeleteTombstoneFailedError = class extends ProtocolError {
|
|
105741
|
+
constructor(details) {
|
|
105742
|
+
super(502, "DELETE_TOMBSTONE_FAILED", "Gateway did not acknowledge the deletion tombstone; nothing was deleted", details);
|
|
105743
|
+
}
|
|
105744
|
+
};
|
|
105745
|
+
var DataDeletedError = class extends ProtocolError {
|
|
105746
|
+
constructor(details) {
|
|
105747
|
+
super(410, "DATA_DELETED", "Data point has been deleted", details);
|
|
105748
|
+
}
|
|
105749
|
+
};
|
|
105740
105750
|
|
|
105741
105751
|
// ../core/dist/sync/data-point-id.js
|
|
105742
105752
|
function computeDataPointId(ownerAddress, scope) {
|
|
@@ -109344,6 +109354,7 @@ async function createPersistentPsLiteStorage(adapter, persistence = createIndexe
|
|
|
109344
109354
|
schemaId: entry.schemaId ?? null,
|
|
109345
109355
|
version: version4,
|
|
109346
109356
|
dataPointId: entry.dataPointId ?? null,
|
|
109357
|
+
afterTombstoneVersion: entry.afterTombstoneVersion ?? null,
|
|
109347
109358
|
id: state.nextId,
|
|
109348
109359
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
109349
109360
|
};
|
|
@@ -109437,25 +109448,34 @@ async function createPersistentPsLiteStorage(adapter, persistence = createIndexe
|
|
|
109437
109448
|
await persist();
|
|
109438
109449
|
return deleted;
|
|
109439
109450
|
},
|
|
109451
|
+
async deleteVersion(scope, collectedAt2) {
|
|
109452
|
+
const entry = state.entries.find((e10) => e10.scope === scope && e10.collectedAt === collectedAt2);
|
|
109453
|
+
if (!entry)
|
|
109454
|
+
return false;
|
|
109455
|
+
return removeEntry(entry);
|
|
109456
|
+
},
|
|
109440
109457
|
async deleteByFileId(fileId) {
|
|
109441
109458
|
const entry = state.entries.find((e10) => e10.fileId === fileId);
|
|
109442
109459
|
if (!entry)
|
|
109443
109460
|
return false;
|
|
109444
|
-
|
|
109445
|
-
await Promise.all([
|
|
109446
|
-
fileStore.deleteEnvelope(blobPath),
|
|
109447
|
-
fallbackStore.deleteEnvelope(blobPath),
|
|
109448
|
-
fileStore.deleteBlockTree?.(blockTreePath(entry.scope, entry.collectedAt)) ?? Promise.resolve(),
|
|
109449
|
-
fallbackStore.deleteBlockTree?.(blockTreePath(entry.scope, entry.collectedAt)) ?? Promise.resolve()
|
|
109450
|
-
]);
|
|
109451
|
-
state = {
|
|
109452
|
-
...state,
|
|
109453
|
-
entries: state.entries.filter((e10) => e10 !== entry)
|
|
109454
|
-
};
|
|
109455
|
-
await persist();
|
|
109456
|
-
return true;
|
|
109461
|
+
return removeEntry(entry);
|
|
109457
109462
|
}
|
|
109458
109463
|
};
|
|
109464
|
+
async function removeEntry(entry) {
|
|
109465
|
+
const blobPath = envelopePath(entry.scope, entry.collectedAt);
|
|
109466
|
+
await Promise.all([
|
|
109467
|
+
fileStore.deleteEnvelope(blobPath),
|
|
109468
|
+
fallbackStore.deleteEnvelope(blobPath),
|
|
109469
|
+
fileStore.deleteBlockTree?.(blockTreePath(entry.scope, entry.collectedAt)) ?? Promise.resolve(),
|
|
109470
|
+
fallbackStore.deleteBlockTree?.(blockTreePath(entry.scope, entry.collectedAt)) ?? Promise.resolve()
|
|
109471
|
+
]);
|
|
109472
|
+
state = {
|
|
109473
|
+
...state,
|
|
109474
|
+
entries: state.entries.filter((e10) => e10 !== entry)
|
|
109475
|
+
};
|
|
109476
|
+
await persist();
|
|
109477
|
+
return true;
|
|
109478
|
+
}
|
|
109459
109479
|
if (fileStore.readEnvelopePreview) {
|
|
109460
109480
|
storagePort.readEnvelopePreview = async (scope, collectedAt2, { maxBytes }) => {
|
|
109461
109481
|
const path = envelopePath(scope, collectedAt2);
|
|
@@ -110743,15 +110763,44 @@ function normalizeOffset(value) {
|
|
|
110743
110763
|
function isRecord3(value) {
|
|
110744
110764
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
110745
110765
|
}
|
|
110766
|
+
var VISIBILITY_PAGE_SIZE = 200;
|
|
110746
110767
|
async function listDataScopesContract(input) {
|
|
110747
110768
|
const limit = normalizeLimit(input.limit);
|
|
110748
110769
|
const offset = normalizeOffset(input.offset);
|
|
110749
|
-
|
|
110750
|
-
|
|
110751
|
-
|
|
110752
|
-
|
|
110753
|
-
|
|
110754
|
-
|
|
110770
|
+
let page;
|
|
110771
|
+
let total;
|
|
110772
|
+
if (input.isVisible) {
|
|
110773
|
+
const visible = [];
|
|
110774
|
+
for (let scan = 0; ; scan += VISIBILITY_PAGE_SIZE) {
|
|
110775
|
+
const batch = input.storage.listScopes({
|
|
110776
|
+
scopePrefix: input.scopePrefix,
|
|
110777
|
+
limit: VISIBILITY_PAGE_SIZE,
|
|
110778
|
+
offset: scan
|
|
110779
|
+
});
|
|
110780
|
+
for (const summary of batch.scopes) {
|
|
110781
|
+
const latest = input.storage.findEntry({
|
|
110782
|
+
scope: summary.scope,
|
|
110783
|
+
at: summary.latestCollectedAt
|
|
110784
|
+
});
|
|
110785
|
+
if (!latest || await input.isVisible(summary.scope, latest)) {
|
|
110786
|
+
visible.push(summary);
|
|
110787
|
+
}
|
|
110788
|
+
}
|
|
110789
|
+
if (batch.scopes.length < VISIBILITY_PAGE_SIZE)
|
|
110790
|
+
break;
|
|
110791
|
+
}
|
|
110792
|
+
total = visible.length;
|
|
110793
|
+
page = visible.slice(offset, offset + limit);
|
|
110794
|
+
} else {
|
|
110795
|
+
const result = input.storage.listScopes({
|
|
110796
|
+
scopePrefix: input.scopePrefix,
|
|
110797
|
+
limit,
|
|
110798
|
+
offset
|
|
110799
|
+
});
|
|
110800
|
+
page = result.scopes;
|
|
110801
|
+
total = result.total;
|
|
110802
|
+
}
|
|
110803
|
+
const scopes = await Promise.all(page.map(async (summary) => {
|
|
110755
110804
|
const entry = input.storage.findEntry({
|
|
110756
110805
|
scope: summary.scope,
|
|
110757
110806
|
at: summary.latestCollectedAt
|
|
@@ -110759,7 +110808,7 @@ async function listDataScopesContract(input) {
|
|
|
110759
110808
|
if (!entry) {
|
|
110760
110809
|
return summary;
|
|
110761
110810
|
}
|
|
110762
|
-
const hasBlocks = typeof input.storage.
|
|
110811
|
+
const hasBlocks = typeof input.storage.hasScopeBlocks === "function" ? await input.storage.hasScopeBlocks(summary.scope, summary.latestCollectedAt) : false;
|
|
110763
110812
|
return {
|
|
110764
110813
|
...summary,
|
|
110765
110814
|
dataStatus: hasBlocks ? "ready" : "indexing",
|
|
@@ -110770,33 +110819,52 @@ async function listDataScopesContract(input) {
|
|
|
110770
110819
|
ok: true,
|
|
110771
110820
|
response: {
|
|
110772
110821
|
scopes,
|
|
110773
|
-
total
|
|
110822
|
+
total,
|
|
110774
110823
|
limit,
|
|
110775
110824
|
offset
|
|
110776
110825
|
}
|
|
110777
110826
|
};
|
|
110778
110827
|
}
|
|
110779
|
-
function listDataVersionsContract(input) {
|
|
110828
|
+
async function listDataVersionsContract(input) {
|
|
110780
110829
|
const scopeResult = parseDataScopeContract(input.scopeParam);
|
|
110781
110830
|
if (!scopeResult.ok)
|
|
110782
110831
|
return scopeResult;
|
|
110783
110832
|
const limit = normalizeLimit(input.limit);
|
|
110784
110833
|
const offset = normalizeOffset(input.offset);
|
|
110785
|
-
|
|
110786
|
-
|
|
110787
|
-
|
|
110788
|
-
|
|
110834
|
+
let page;
|
|
110835
|
+
let total;
|
|
110836
|
+
if (input.isVisible) {
|
|
110837
|
+
const visible = [];
|
|
110838
|
+
for (let scan = 0; ; scan += VISIBILITY_PAGE_SIZE) {
|
|
110839
|
+
const batch = input.storage.listVersions(scopeResult.scope, {
|
|
110840
|
+
limit: VISIBILITY_PAGE_SIZE,
|
|
110841
|
+
offset: scan
|
|
110842
|
+
});
|
|
110843
|
+
for (const entry of batch) {
|
|
110844
|
+
if (await input.isVisible(scopeResult.scope, entry)) {
|
|
110845
|
+
visible.push(entry);
|
|
110846
|
+
}
|
|
110847
|
+
}
|
|
110848
|
+
if (batch.length < VISIBILITY_PAGE_SIZE)
|
|
110849
|
+
break;
|
|
110850
|
+
}
|
|
110851
|
+
total = visible.length;
|
|
110852
|
+
page = visible.slice(offset, offset + limit);
|
|
110853
|
+
} else {
|
|
110854
|
+
page = input.storage.listVersions(scopeResult.scope, { limit, offset });
|
|
110855
|
+
total = input.storage.countVersions(scopeResult.scope);
|
|
110856
|
+
}
|
|
110789
110857
|
return {
|
|
110790
110858
|
ok: true,
|
|
110791
110859
|
scope: scopeResult.scope,
|
|
110792
110860
|
response: {
|
|
110793
110861
|
scope: scopeResult.scope,
|
|
110794
|
-
versions:
|
|
110862
|
+
versions: page.map((entry) => ({
|
|
110795
110863
|
fileId: entry.fileId,
|
|
110796
110864
|
schemaId: entry.schemaId,
|
|
110797
110865
|
collectedAt: entry.collectedAt
|
|
110798
110866
|
})),
|
|
110799
|
-
total
|
|
110867
|
+
total,
|
|
110800
110868
|
limit,
|
|
110801
110869
|
offset
|
|
110802
110870
|
}
|
|
@@ -110873,7 +110941,8 @@ async function ingestDataContract(input) {
|
|
|
110873
110941
|
path: writeResult.relativePath,
|
|
110874
110942
|
scope: scopeResult.scope,
|
|
110875
110943
|
collectedAt: input.collectedAt,
|
|
110876
|
-
sizeBytes: writeResult.sizeBytes
|
|
110944
|
+
sizeBytes: writeResult.sizeBytes,
|
|
110945
|
+
afterTombstoneVersion: input.afterTombstoneVersion ?? null
|
|
110877
110946
|
});
|
|
110878
110947
|
return {
|
|
110879
110948
|
ok: true,
|
|
@@ -110944,7 +111013,8 @@ async function ingestBinaryDataContract(input) {
|
|
|
110944
111013
|
path: writeResult.relativePath,
|
|
110945
111014
|
scope: scopeResult.scope,
|
|
110946
111015
|
collectedAt: input.collectedAt,
|
|
110947
|
-
sizeBytes: input.bytes.length
|
|
111016
|
+
sizeBytes: input.bytes.length,
|
|
111017
|
+
afterTombstoneVersion: input.afterTombstoneVersion ?? null
|
|
110948
111018
|
});
|
|
110949
111019
|
return {
|
|
110950
111020
|
ok: true,
|
|
@@ -110954,15 +111024,6 @@ async function ingestBinaryDataContract(input) {
|
|
|
110954
111024
|
writeResult
|
|
110955
111025
|
};
|
|
110956
111026
|
}
|
|
110957
|
-
async function deleteDataScopeContract(input) {
|
|
110958
|
-
const scopeResult = parseDataScopeContract(input.scopeParam);
|
|
110959
|
-
if (!scopeResult.ok)
|
|
110960
|
-
return scopeResult;
|
|
110961
|
-
return {
|
|
110962
|
-
ok: true,
|
|
110963
|
-
deletedCount: await input.storage.deleteScope(scopeResult.scope)
|
|
110964
|
-
};
|
|
110965
|
-
}
|
|
110966
111027
|
async function writeBlockSidecars(storage, envelope) {
|
|
110967
111028
|
if (!storage.writeBlockManifest)
|
|
110968
111029
|
return;
|
|
@@ -111548,6 +111609,548 @@ async function syncFileContract(input) {
|
|
|
111548
111609
|
return contractOk({ fileId: input.fileId, status: "started" }, 202);
|
|
111549
111610
|
}
|
|
111550
111611
|
|
|
111612
|
+
// ../core/dist/sync/tombstone.js
|
|
111613
|
+
var TOMBSTONE_DATA_HASH_LABEL = "vana.data-point.tombstone.v1";
|
|
111614
|
+
var TOMBSTONE_METADATA_HASH_LABEL = "vana.data-point.tombstone.metadata.v1";
|
|
111615
|
+
var TOMBSTONE_DATA_HASH = keccak256(stringToHex(TOMBSTONE_DATA_HASH_LABEL));
|
|
111616
|
+
var TOMBSTONE_METADATA_HASH = keccak256(stringToHex(TOMBSTONE_METADATA_HASH_LABEL));
|
|
111617
|
+
function isTombstoneRecord(record2) {
|
|
111618
|
+
return record2.dataHash.toLowerCase() === TOMBSTONE_DATA_HASH && record2.metadataHash.toLowerCase() === TOMBSTONE_METADATA_HASH;
|
|
111619
|
+
}
|
|
111620
|
+
|
|
111621
|
+
// ../core/dist/sync/scope-deletions.js
|
|
111622
|
+
var DEFAULT_SCOPE_DELETION_MAX_STALENESS_MS = 12e4;
|
|
111623
|
+
var DEFAULT_SCOPE_DELETION_GATEWAY_RETRY_MS = 15e3;
|
|
111624
|
+
var DEFAULT_MAX_LIVE_ENTRIES = 1e4;
|
|
111625
|
+
function createScopeDeletionTracker(options = {}) {
|
|
111626
|
+
const maxStalenessMs = options.maxStalenessMs ?? DEFAULT_SCOPE_DELETION_MAX_STALENESS_MS;
|
|
111627
|
+
const gatewayRetryMs = options.gatewayRetryMs ?? DEFAULT_SCOPE_DELETION_GATEWAY_RETRY_MS;
|
|
111628
|
+
const maxLiveEntries = options.maxLiveEntries ?? DEFAULT_MAX_LIVE_ENTRIES;
|
|
111629
|
+
const now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
111630
|
+
const nowMs = () => now().getTime();
|
|
111631
|
+
const deleted = /* @__PURE__ */ new Map();
|
|
111632
|
+
const live = /* @__PURE__ */ new Map();
|
|
111633
|
+
let lastFeedSyncMs = null;
|
|
111634
|
+
let lastGatewayFailureMs = null;
|
|
111635
|
+
const inflight = /* @__PURE__ */ new Map();
|
|
111636
|
+
function rememberLive(scope, at3) {
|
|
111637
|
+
deleted.delete(scope);
|
|
111638
|
+
live.delete(scope);
|
|
111639
|
+
live.set(scope, at3);
|
|
111640
|
+
while (live.size > maxLiveEntries) {
|
|
111641
|
+
const oldest = live.keys().next().value;
|
|
111642
|
+
if (oldest === void 0)
|
|
111643
|
+
break;
|
|
111644
|
+
live.delete(oldest);
|
|
111645
|
+
}
|
|
111646
|
+
}
|
|
111647
|
+
function rememberDeleted(scope, tombstone, source) {
|
|
111648
|
+
deleted.set(scope, {
|
|
111649
|
+
deletedAt: tombstone.deletedAt,
|
|
111650
|
+
version: normalizeVersion(tombstone.version),
|
|
111651
|
+
source,
|
|
111652
|
+
verifiedAtMs: nowMs()
|
|
111653
|
+
});
|
|
111654
|
+
live.delete(scope);
|
|
111655
|
+
}
|
|
111656
|
+
function isFresh(at3) {
|
|
111657
|
+
return at3 !== null && nowMs() - at3 <= maxStalenessMs;
|
|
111658
|
+
}
|
|
111659
|
+
function verdictFromRecord(scope, record2) {
|
|
111660
|
+
const deletedAt = deletionTimestamp(record2);
|
|
111661
|
+
if (deletedAt !== null) {
|
|
111662
|
+
const version4 = tombstoneVersion(record2);
|
|
111663
|
+
rememberDeleted(scope, { deletedAt, version: version4 }, "gateway");
|
|
111664
|
+
return {
|
|
111665
|
+
deleted: true,
|
|
111666
|
+
deletedAt,
|
|
111667
|
+
version: version4,
|
|
111668
|
+
source: "gateway",
|
|
111669
|
+
verified: true
|
|
111670
|
+
};
|
|
111671
|
+
}
|
|
111672
|
+
rememberLive(scope, nowMs());
|
|
111673
|
+
return { deleted: false, source: "gateway", verified: true };
|
|
111674
|
+
}
|
|
111675
|
+
async function lookup2(scope) {
|
|
111676
|
+
const feed = options.feed;
|
|
111677
|
+
const owner = options.serverOwner;
|
|
111678
|
+
if (!feed || !owner)
|
|
111679
|
+
return null;
|
|
111680
|
+
if (lastGatewayFailureMs !== null && nowMs() - lastGatewayFailureMs < gatewayRetryMs) {
|
|
111681
|
+
return null;
|
|
111682
|
+
}
|
|
111683
|
+
const pending = inflight.get(scope);
|
|
111684
|
+
if (pending)
|
|
111685
|
+
return pending;
|
|
111686
|
+
const request2 = (async () => {
|
|
111687
|
+
try {
|
|
111688
|
+
const record2 = await feed.getDataPoint({
|
|
111689
|
+
ownerAddress: owner,
|
|
111690
|
+
scope
|
|
111691
|
+
});
|
|
111692
|
+
lastGatewayFailureMs = null;
|
|
111693
|
+
return verdictFromRecord(scope, record2);
|
|
111694
|
+
} catch (err2) {
|
|
111695
|
+
lastGatewayFailureMs = nowMs();
|
|
111696
|
+
options.logger?.warn?.({
|
|
111697
|
+
scope,
|
|
111698
|
+
error: err2 instanceof Error ? err2.message : String(err2),
|
|
111699
|
+
retryAfterMs: gatewayRetryMs
|
|
111700
|
+
}, "Could not check gateway deletion state; serving last known state");
|
|
111701
|
+
return null;
|
|
111702
|
+
} finally {
|
|
111703
|
+
inflight.delete(scope);
|
|
111704
|
+
}
|
|
111705
|
+
})();
|
|
111706
|
+
inflight.set(scope, request2);
|
|
111707
|
+
return request2;
|
|
111708
|
+
}
|
|
111709
|
+
return {
|
|
111710
|
+
maxStalenessMs,
|
|
111711
|
+
markDeleted(scope, tombstone, source = "feed") {
|
|
111712
|
+
rememberDeleted(scope, tombstone, source);
|
|
111713
|
+
},
|
|
111714
|
+
markLive(scope) {
|
|
111715
|
+
rememberLive(scope, nowMs());
|
|
111716
|
+
},
|
|
111717
|
+
noteFeedSynced(at3, options2) {
|
|
111718
|
+
lastFeedSyncMs = (at3 ?? now()).getTime();
|
|
111719
|
+
if (!options2?.full)
|
|
111720
|
+
return;
|
|
111721
|
+
for (const tombstone of deleted.values()) {
|
|
111722
|
+
tombstone.verifiedAtMs = Math.max(tombstone.verifiedAtMs, lastFeedSyncMs);
|
|
111723
|
+
}
|
|
111724
|
+
},
|
|
111725
|
+
knownDeletion(scope) {
|
|
111726
|
+
const known = deleted.get(scope);
|
|
111727
|
+
return known === void 0 ? null : { deletedAt: known.deletedAt, version: known.version };
|
|
111728
|
+
},
|
|
111729
|
+
feedAgeMs() {
|
|
111730
|
+
return lastFeedSyncMs === null ? null : nowMs() - lastFeedSyncMs;
|
|
111731
|
+
},
|
|
111732
|
+
async resolve(scope, resolveOptions) {
|
|
111733
|
+
const known = deleted.get(scope);
|
|
111734
|
+
if (known !== void 0) {
|
|
111735
|
+
if (isFresh(known.verifiedAtMs)) {
|
|
111736
|
+
return {
|
|
111737
|
+
deleted: true,
|
|
111738
|
+
deletedAt: known.deletedAt,
|
|
111739
|
+
version: known.version,
|
|
111740
|
+
source: known.source,
|
|
111741
|
+
verified: true
|
|
111742
|
+
};
|
|
111743
|
+
}
|
|
111744
|
+
const rechecked = await lookup2(scope);
|
|
111745
|
+
if (rechecked !== null)
|
|
111746
|
+
return rechecked;
|
|
111747
|
+
return {
|
|
111748
|
+
deleted: true,
|
|
111749
|
+
deletedAt: known.deletedAt,
|
|
111750
|
+
version: known.version,
|
|
111751
|
+
source: known.source,
|
|
111752
|
+
verified: false
|
|
111753
|
+
};
|
|
111754
|
+
}
|
|
111755
|
+
if (isFresh(live.get(scope) ?? null)) {
|
|
111756
|
+
return { deleted: false, source: "gateway", verified: true };
|
|
111757
|
+
}
|
|
111758
|
+
const consult = resolveOptions?.consultGateway ?? "if-stale";
|
|
111759
|
+
if (consult === "if-stale" && isFresh(lastFeedSyncMs)) {
|
|
111760
|
+
return { deleted: false, source: "feed", verified: true };
|
|
111761
|
+
}
|
|
111762
|
+
return await lookup2(scope) ?? {
|
|
111763
|
+
deleted: false,
|
|
111764
|
+
source: "assumed-live",
|
|
111765
|
+
verified: false
|
|
111766
|
+
};
|
|
111767
|
+
}
|
|
111768
|
+
};
|
|
111769
|
+
}
|
|
111770
|
+
function deletionTimestamp(record2) {
|
|
111771
|
+
if (!record2)
|
|
111772
|
+
return null;
|
|
111773
|
+
if (record2.deletedAt)
|
|
111774
|
+
return record2.deletedAt;
|
|
111775
|
+
return isTombstoneRecord(record2) ? record2.addedAt : null;
|
|
111776
|
+
}
|
|
111777
|
+
function tombstoneVersion(record2) {
|
|
111778
|
+
return normalizeVersion(record2?.expectedVersion ?? null);
|
|
111779
|
+
}
|
|
111780
|
+
function normalizeVersion(value) {
|
|
111781
|
+
if (typeof value !== "string" || !/^\d+$/.test(value))
|
|
111782
|
+
return null;
|
|
111783
|
+
return BigInt(value) > 0n ? BigInt(value).toString() : null;
|
|
111784
|
+
}
|
|
111785
|
+
function isEntryCoveredByTombstone(entry, tombstone) {
|
|
111786
|
+
const version4 = normalizeVersion(tombstone.version);
|
|
111787
|
+
if (version4 === null)
|
|
111788
|
+
return true;
|
|
111789
|
+
const tombstoned = BigInt(version4);
|
|
111790
|
+
if (entry.dataPointId !== null)
|
|
111791
|
+
return BigInt(entry.version) <= tombstoned;
|
|
111792
|
+
const marker = entry.afterTombstoneVersion;
|
|
111793
|
+
if (marker === null || marker === void 0 || !Number.isSafeInteger(marker)) {
|
|
111794
|
+
return true;
|
|
111795
|
+
}
|
|
111796
|
+
return BigInt(marker) < tombstoned;
|
|
111797
|
+
}
|
|
111798
|
+
|
|
111799
|
+
// ../core/dist/sync/workers/delete.js
|
|
111800
|
+
var BLOB_DELETE_BATCH_SIZE = 15;
|
|
111801
|
+
function planBlobDeletions(storage, scope, tombstoneVersionValue) {
|
|
111802
|
+
const tombstone = { version: tombstoneVersionValue };
|
|
111803
|
+
const last2 = tombstoneVersionValue === null ? null : BigInt(tombstoneVersionValue);
|
|
111804
|
+
const keys = /* @__PURE__ */ new Set();
|
|
111805
|
+
const PAGE_SIZE = 500;
|
|
111806
|
+
for (let offset = 0; ; offset += PAGE_SIZE) {
|
|
111807
|
+
const entries = storage.listVersions(scope, { limit: PAGE_SIZE, offset });
|
|
111808
|
+
for (const entry of entries) {
|
|
111809
|
+
if (!isEntryCoveredByTombstone(entry, tombstone))
|
|
111810
|
+
continue;
|
|
111811
|
+
const version4 = BigInt(entry.version);
|
|
111812
|
+
if (last2 !== null && version4 >= 1n && version4 <= last2)
|
|
111813
|
+
continue;
|
|
111814
|
+
keys.add(version4.toString());
|
|
111815
|
+
}
|
|
111816
|
+
if (entries.length < PAGE_SIZE)
|
|
111817
|
+
break;
|
|
111818
|
+
}
|
|
111819
|
+
return {
|
|
111820
|
+
keys: [...keys].sort((a10, b10) => BigInt(a10) < BigInt(b10) ? -1 : 1),
|
|
111821
|
+
range: last2 === null || last2 < 1n ? null : { from: "1", to: last2.toString() }
|
|
111822
|
+
};
|
|
111823
|
+
}
|
|
111824
|
+
function takeFromRange(range, count) {
|
|
111825
|
+
const from = BigInt(range.from);
|
|
111826
|
+
const to3 = BigInt(range.to);
|
|
111827
|
+
const versions = [];
|
|
111828
|
+
let cursor = from;
|
|
111829
|
+
while (cursor <= to3 && versions.length < count) {
|
|
111830
|
+
versions.push(cursor.toString());
|
|
111831
|
+
cursor += 1n;
|
|
111832
|
+
}
|
|
111833
|
+
return {
|
|
111834
|
+
versions,
|
|
111835
|
+
rest: cursor <= to3 ? { from: cursor.toString(), to: range.to } : null
|
|
111836
|
+
};
|
|
111837
|
+
}
|
|
111838
|
+
function rangeSize(range) {
|
|
111839
|
+
return BigInt(range.to) - BigInt(range.from) + 1n;
|
|
111840
|
+
}
|
|
111841
|
+
function countPendingKeys(markers) {
|
|
111842
|
+
let total = 0n;
|
|
111843
|
+
for (const marker of markers) {
|
|
111844
|
+
if (marker.version !== null)
|
|
111845
|
+
total += 1n;
|
|
111846
|
+
else if (marker.range)
|
|
111847
|
+
total += rangeSize(marker.range);
|
|
111848
|
+
else
|
|
111849
|
+
total += 1n;
|
|
111850
|
+
}
|
|
111851
|
+
return total > BigInt(Number.MAX_SAFE_INTEGER) ? Number.MAX_SAFE_INTEGER : Number(total);
|
|
111852
|
+
}
|
|
111853
|
+
async function deleteScope(deps, scope) {
|
|
111854
|
+
const { storage, deleteData, pendingBlobDeletions, scopeDeletions, logger } = deps;
|
|
111855
|
+
const now = deps.now ?? (() => /* @__PURE__ */ new Date());
|
|
111856
|
+
const dataPointId = deps.serverOwner ? computeDataPointId(deps.serverOwner, scope) : null;
|
|
111857
|
+
const result = {
|
|
111858
|
+
scope,
|
|
111859
|
+
dataPointId,
|
|
111860
|
+
durable: false,
|
|
111861
|
+
steps: {
|
|
111862
|
+
gateway: { status: "skipped", reason: "sync-disabled" },
|
|
111863
|
+
storage: { status: "skipped", reason: "sync-disabled" },
|
|
111864
|
+
local: { status: "skipped" }
|
|
111865
|
+
},
|
|
111866
|
+
pendingBlobDeletion: false
|
|
111867
|
+
};
|
|
111868
|
+
if (deleteData) {
|
|
111869
|
+
let tombstoneVersionValue = null;
|
|
111870
|
+
let tombstoneKnown = false;
|
|
111871
|
+
try {
|
|
111872
|
+
let outcome = await deleteData.tombstone(scope);
|
|
111873
|
+
if (outcome.status === "not-registered") {
|
|
111874
|
+
let registry2 = await registryState(deps, scope);
|
|
111875
|
+
if (registry2.status === "live") {
|
|
111876
|
+
outcome = await deleteData.tombstone(scope);
|
|
111877
|
+
registry2 = await registryState(deps, scope);
|
|
111878
|
+
}
|
|
111879
|
+
if (outcome.status === "not-registered" && registry2.status !== "deleted-or-absent") {
|
|
111880
|
+
throw registry2.status === "unknown" ? registry2.error : new Error("Scope was registered concurrently while it was being deleted; retry the delete");
|
|
111881
|
+
}
|
|
111882
|
+
}
|
|
111883
|
+
if (outcome.status === "not-registered") {
|
|
111884
|
+
result.steps.gateway = { status: "skipped", reason: "not-registered" };
|
|
111885
|
+
} else {
|
|
111886
|
+
tombstoneKnown = true;
|
|
111887
|
+
tombstoneVersionValue = outcome.version === null ? null : tombstoneVersion({ expectedVersion: outcome.version });
|
|
111888
|
+
result.steps.gateway = {
|
|
111889
|
+
status: "ok",
|
|
111890
|
+
...outcome.status === "already-deleted" && {
|
|
111891
|
+
reason: "already-deleted"
|
|
111892
|
+
},
|
|
111893
|
+
version: outcome.version,
|
|
111894
|
+
deletedAt: outcome.deletedAt
|
|
111895
|
+
};
|
|
111896
|
+
scopeDeletions?.markDeleted(scope, {
|
|
111897
|
+
deletedAt: outcome.deletedAt ?? now().toISOString(),
|
|
111898
|
+
version: outcome.version
|
|
111899
|
+
}, "local-delete");
|
|
111900
|
+
}
|
|
111901
|
+
result.durable = true;
|
|
111902
|
+
} catch (err2) {
|
|
111903
|
+
const message = errorMessage2(err2);
|
|
111904
|
+
result.steps.gateway = { status: "failed", error: message };
|
|
111905
|
+
result.steps.storage = { status: "skipped", reason: "gateway-failed" };
|
|
111906
|
+
result.steps.local = { status: "skipped", reason: "gateway-failed" };
|
|
111907
|
+
logger.error({ scope, dataPointId, error: message }, "Gateway tombstone failed; scope NOT deleted (local copy kept so sync cannot resurrect a half-deleted scope)");
|
|
111908
|
+
return result;
|
|
111909
|
+
}
|
|
111910
|
+
const plan = planBlobDeletions(storage, scope, tombstoneVersionValue);
|
|
111911
|
+
const batch = plan.keys.slice(0, BLOB_DELETE_BATCH_SIZE);
|
|
111912
|
+
const leftovers = plan.keys.slice(BLOB_DELETE_BATCH_SIZE).map((version4) => ({ scope, version: version4 }));
|
|
111913
|
+
if (plan.range) {
|
|
111914
|
+
const taken = takeFromRange(plan.range, BLOB_DELETE_BATCH_SIZE - batch.length);
|
|
111915
|
+
batch.push(...taken.versions);
|
|
111916
|
+
if (taken.rest)
|
|
111917
|
+
leftovers.push({ scope, version: null, range: taken.rest });
|
|
111918
|
+
}
|
|
111919
|
+
if (tombstoneKnown && tombstoneVersionValue === null) {
|
|
111920
|
+
leftovers.push({ scope, version: null });
|
|
111921
|
+
}
|
|
111922
|
+
const storageStep = await deleteBlobKeys({ deleteData, pendingBlobDeletions, logger }, scope, batch, leftovers);
|
|
111923
|
+
result.steps.storage = storageStep.step;
|
|
111924
|
+
result.pendingBlobDeletion = storageStep.pending > 0;
|
|
111925
|
+
}
|
|
111926
|
+
try {
|
|
111927
|
+
const deletedCount = await storage.deleteScope(scope);
|
|
111928
|
+
result.steps.local = { status: "ok", deletedCount };
|
|
111929
|
+
} catch (err2) {
|
|
111930
|
+
const message = errorMessage2(err2);
|
|
111931
|
+
result.steps.local = { status: "failed", error: message };
|
|
111932
|
+
logger.error({ scope, error: message }, "Local scope deletion failed");
|
|
111933
|
+
}
|
|
111934
|
+
logger.info({
|
|
111935
|
+
scope,
|
|
111936
|
+
dataPointId,
|
|
111937
|
+
durable: result.durable,
|
|
111938
|
+
gateway: result.steps.gateway.status,
|
|
111939
|
+
storage: result.steps.storage.status,
|
|
111940
|
+
local: result.steps.local.status
|
|
111941
|
+
}, "Scope deletion finished");
|
|
111942
|
+
return result;
|
|
111943
|
+
}
|
|
111944
|
+
async function deleteBlobKeys(deps, scope, batch, leftovers) {
|
|
111945
|
+
const { deleteData, pendingBlobDeletions, logger } = deps;
|
|
111946
|
+
let outcome;
|
|
111947
|
+
try {
|
|
111948
|
+
outcome = batch.length > 0 && deleteData ? await deleteData.deleteBlobVersions(scope, batch) : { deleted: [], missing: [], failed: [] };
|
|
111949
|
+
} catch (err2) {
|
|
111950
|
+
outcome = {
|
|
111951
|
+
deleted: [],
|
|
111952
|
+
missing: [],
|
|
111953
|
+
failed: batch.map((version4) => ({ version: version4, error: errorMessage2(err2) }))
|
|
111954
|
+
};
|
|
111955
|
+
}
|
|
111956
|
+
const completed = [...outcome.deleted, ...outcome.missing].map((version4) => ({ scope, version: version4 }));
|
|
111957
|
+
const remaining = [
|
|
111958
|
+
...outcome.failed.map(({ version: version4 }) => ({ scope, version: version4 })),
|
|
111959
|
+
...leftovers
|
|
111960
|
+
];
|
|
111961
|
+
const remainingKeys = countPendingKeys(remaining);
|
|
111962
|
+
let recorded = remainingKeys;
|
|
111963
|
+
if (pendingBlobDeletions) {
|
|
111964
|
+
try {
|
|
111965
|
+
if (completed.length > 0)
|
|
111966
|
+
await pendingBlobDeletions.remove(completed);
|
|
111967
|
+
if (remaining.length > 0)
|
|
111968
|
+
await pendingBlobDeletions.add(remaining);
|
|
111969
|
+
} catch (markerErr) {
|
|
111970
|
+
recorded = 0;
|
|
111971
|
+
logger.error({ scope, error: errorMessage2(markerErr), keys: remainingKeys }, "Could not record pending blob deletion markers");
|
|
111972
|
+
}
|
|
111973
|
+
} else if (remaining.length > 0) {
|
|
111974
|
+
recorded = 0;
|
|
111975
|
+
logger.error({ scope, keys: remainingKeys }, "Blob deletions left unfinished with no marker store to retry them");
|
|
111976
|
+
}
|
|
111977
|
+
const counts = {
|
|
111978
|
+
blobsDeleted: outcome.deleted.length,
|
|
111979
|
+
blobsMissing: outcome.missing.length,
|
|
111980
|
+
blobsPending: remainingKeys
|
|
111981
|
+
};
|
|
111982
|
+
if (outcome.failed.length > 0) {
|
|
111983
|
+
const first = outcome.failed[0];
|
|
111984
|
+
logger.warn({
|
|
111985
|
+
scope,
|
|
111986
|
+
failed: outcome.failed.length,
|
|
111987
|
+
pending: recorded,
|
|
111988
|
+
error: first.error
|
|
111989
|
+
}, "Storage blob deletion failed for some keys after gateway tombstone; will retry");
|
|
111990
|
+
return {
|
|
111991
|
+
step: {
|
|
111992
|
+
status: "failed",
|
|
111993
|
+
error: `${outcome.failed.length} blob delete(s) failed: ${first.error}`,
|
|
111994
|
+
...counts
|
|
111995
|
+
},
|
|
111996
|
+
pending: recorded
|
|
111997
|
+
};
|
|
111998
|
+
}
|
|
111999
|
+
if (remaining.length > 0) {
|
|
112000
|
+
logger.info({ scope, ...counts }, "Storage blob deletion continues on later sync cycles (rate-limited batch)");
|
|
112001
|
+
return { step: { status: "deferred", ...counts }, pending: recorded };
|
|
112002
|
+
}
|
|
112003
|
+
return { step: { status: "ok", ...counts }, pending: 0 };
|
|
112004
|
+
}
|
|
112005
|
+
async function retryPendingBlobDeletions(deps) {
|
|
112006
|
+
const { deleteData, pendingBlobDeletions, logger } = deps;
|
|
112007
|
+
const result = {
|
|
112008
|
+
completed: [],
|
|
112009
|
+
superseded: [],
|
|
112010
|
+
failed: [],
|
|
112011
|
+
remaining: 0
|
|
112012
|
+
};
|
|
112013
|
+
if (!deleteData || !pendingBlobDeletions)
|
|
112014
|
+
return result;
|
|
112015
|
+
let markers = await pendingBlobDeletions.list();
|
|
112016
|
+
if (markers.length === 0)
|
|
112017
|
+
return result;
|
|
112018
|
+
for (const marker of markers.filter((key) => key.version === null && !key.range)) {
|
|
112019
|
+
const registry2 = await registryState(deps, marker.scope);
|
|
112020
|
+
if (registry2.status === "unknown") {
|
|
112021
|
+
result.failed.push({
|
|
112022
|
+
scope: marker.scope,
|
|
112023
|
+
version: null,
|
|
112024
|
+
error: registry2.error.message
|
|
112025
|
+
});
|
|
112026
|
+
continue;
|
|
112027
|
+
}
|
|
112028
|
+
if (registry2.status === "live") {
|
|
112029
|
+
await pendingBlobDeletions.remove([marker]);
|
|
112030
|
+
result.superseded.push(marker.scope);
|
|
112031
|
+
logger.warn({
|
|
112032
|
+
scope: marker.scope,
|
|
112033
|
+
dataPointId: registry2.record.id,
|
|
112034
|
+
version: registry2.record.expectedVersion
|
|
112035
|
+
}, "Scope was re-added after its tombstone; dropping the unexpanded blob deletion marker so the live version's ciphertext survives");
|
|
112036
|
+
continue;
|
|
112037
|
+
}
|
|
112038
|
+
const plan = planBlobDeletions(deps.storage ?? { listVersions: () => [] }, marker.scope, registry2.status === "deleted" ? registry2.version : null);
|
|
112039
|
+
const expanded = plan.keys.map((version4) => ({
|
|
112040
|
+
scope: marker.scope,
|
|
112041
|
+
version: version4
|
|
112042
|
+
}));
|
|
112043
|
+
if (plan.range) {
|
|
112044
|
+
expanded.push({ scope: marker.scope, version: null, range: plan.range });
|
|
112045
|
+
}
|
|
112046
|
+
await pendingBlobDeletions.remove([marker]);
|
|
112047
|
+
await pendingBlobDeletions.add(expanded);
|
|
112048
|
+
}
|
|
112049
|
+
markers = await pendingBlobDeletions.list();
|
|
112050
|
+
let budget = BLOB_DELETE_BATCH_SIZE;
|
|
112051
|
+
const byScope = /* @__PURE__ */ new Map();
|
|
112052
|
+
const exactOrigin = /* @__PURE__ */ new Set();
|
|
112053
|
+
const advancedRanges = [];
|
|
112054
|
+
const enqueue = (scope, version4) => {
|
|
112055
|
+
const versions = byScope.get(scope) ?? [];
|
|
112056
|
+
versions.push(version4);
|
|
112057
|
+
byScope.set(scope, versions);
|
|
112058
|
+
};
|
|
112059
|
+
for (const marker of markers) {
|
|
112060
|
+
if (budget === 0)
|
|
112061
|
+
break;
|
|
112062
|
+
if (marker.version !== null) {
|
|
112063
|
+
enqueue(marker.scope, marker.version);
|
|
112064
|
+
exactOrigin.add(`${marker.scope}\0${marker.version}`);
|
|
112065
|
+
budget -= 1;
|
|
112066
|
+
}
|
|
112067
|
+
}
|
|
112068
|
+
for (const marker of markers) {
|
|
112069
|
+
if (budget === 0)
|
|
112070
|
+
break;
|
|
112071
|
+
if (marker.version === null && marker.range) {
|
|
112072
|
+
const taken = takeFromRange(marker.range, budget);
|
|
112073
|
+
for (const version4 of taken.versions)
|
|
112074
|
+
enqueue(marker.scope, version4);
|
|
112075
|
+
budget -= taken.versions.length;
|
|
112076
|
+
advancedRanges.push({
|
|
112077
|
+
old: marker,
|
|
112078
|
+
next: taken.rest ? { scope: marker.scope, version: null, range: taken.rest } : null
|
|
112079
|
+
});
|
|
112080
|
+
}
|
|
112081
|
+
}
|
|
112082
|
+
for (const [scope, versions] of byScope) {
|
|
112083
|
+
let outcome;
|
|
112084
|
+
try {
|
|
112085
|
+
outcome = await deleteData.deleteBlobVersions(scope, versions);
|
|
112086
|
+
} catch (err2) {
|
|
112087
|
+
const message = errorMessage2(err2);
|
|
112088
|
+
outcome = {
|
|
112089
|
+
deleted: [],
|
|
112090
|
+
missing: [],
|
|
112091
|
+
failed: versions.map((version4) => ({ version: version4, error: message }))
|
|
112092
|
+
};
|
|
112093
|
+
}
|
|
112094
|
+
const completed = [...outcome.deleted, ...outcome.missing].filter((version4) => exactOrigin.has(`${scope}\0${version4}`)).map((version4) => ({ scope, version: version4 }));
|
|
112095
|
+
if (completed.length > 0)
|
|
112096
|
+
await pendingBlobDeletions.remove(completed);
|
|
112097
|
+
result.completed.push(...[...outcome.deleted, ...outcome.missing].map((version4) => ({ scope, version: version4 })));
|
|
112098
|
+
const failedFromRange = outcome.failed.filter(({ version: version4 }) => !exactOrigin.has(`${scope}\0${version4}`)).map(({ version: version4 }) => ({ scope, version: version4 }));
|
|
112099
|
+
if (failedFromRange.length > 0) {
|
|
112100
|
+
await pendingBlobDeletions.add(failedFromRange);
|
|
112101
|
+
}
|
|
112102
|
+
for (const failure of outcome.failed) {
|
|
112103
|
+
result.failed.push({ scope, ...failure });
|
|
112104
|
+
}
|
|
112105
|
+
if (outcome.deleted.length + outcome.missing.length > 0) {
|
|
112106
|
+
logger.info({
|
|
112107
|
+
scope,
|
|
112108
|
+
deleted: outcome.deleted.length,
|
|
112109
|
+
missing: outcome.missing.length
|
|
112110
|
+
}, "Completed pending blob deletions");
|
|
112111
|
+
}
|
|
112112
|
+
if (outcome.failed.length > 0) {
|
|
112113
|
+
logger.warn({
|
|
112114
|
+
scope,
|
|
112115
|
+
failed: outcome.failed.length,
|
|
112116
|
+
error: outcome.failed[0].error
|
|
112117
|
+
}, "Pending blob deletion failed again");
|
|
112118
|
+
}
|
|
112119
|
+
}
|
|
112120
|
+
for (const { old, next } of advancedRanges) {
|
|
112121
|
+
await pendingBlobDeletions.remove([old]);
|
|
112122
|
+
if (next)
|
|
112123
|
+
await pendingBlobDeletions.add([next]);
|
|
112124
|
+
}
|
|
112125
|
+
result.remaining = (await pendingBlobDeletions.list()).length;
|
|
112126
|
+
return result;
|
|
112127
|
+
}
|
|
112128
|
+
async function registryState(deps, scope) {
|
|
112129
|
+
if (!deps.dataPointFeed || !deps.serverOwner) {
|
|
112130
|
+
return { status: "deleted-or-absent" };
|
|
112131
|
+
}
|
|
112132
|
+
let record2;
|
|
112133
|
+
try {
|
|
112134
|
+
record2 = await deps.dataPointFeed.getDataPoint({
|
|
112135
|
+
ownerAddress: deps.serverOwner,
|
|
112136
|
+
scope
|
|
112137
|
+
});
|
|
112138
|
+
} catch (err2) {
|
|
112139
|
+
return {
|
|
112140
|
+
status: "unknown",
|
|
112141
|
+
error: err2 instanceof Error ? err2 : new Error(String(err2))
|
|
112142
|
+
};
|
|
112143
|
+
}
|
|
112144
|
+
if (record2 === null)
|
|
112145
|
+
return { status: "deleted-or-absent" };
|
|
112146
|
+
if (deletionTimestamp(record2) === null)
|
|
112147
|
+
return { status: "live", record: record2 };
|
|
112148
|
+
return { status: "deleted", version: tombstoneVersion(record2) };
|
|
112149
|
+
}
|
|
112150
|
+
function errorMessage2(err2) {
|
|
112151
|
+
return err2 instanceof Error ? err2.message : String(err2);
|
|
112152
|
+
}
|
|
112153
|
+
|
|
111551
112154
|
// ../core/dist/payment/x402.js
|
|
111552
112155
|
function generateRecordId() {
|
|
111553
112156
|
const bytes2 = new Uint8Array(32);
|
|
@@ -112028,6 +112631,51 @@ async function handleX402Cycle(input) {
|
|
|
112028
112631
|
function collectedAt(now) {
|
|
112029
112632
|
return now().toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
112030
112633
|
}
|
|
112634
|
+
async function resolveReadDeletion(deps, scope, entry) {
|
|
112635
|
+
if (!deps.scopeDeletions)
|
|
112636
|
+
return null;
|
|
112637
|
+
const verdict = await deps.scopeDeletions.resolve(scope, {
|
|
112638
|
+
consultGateway: entry ? "if-stale" : "always"
|
|
112639
|
+
});
|
|
112640
|
+
if (!verdict.deleted)
|
|
112641
|
+
return null;
|
|
112642
|
+
if (entry && !isEntryCoveredByTombstone(entry, verdict)) {
|
|
112643
|
+
return null;
|
|
112644
|
+
}
|
|
112645
|
+
return {
|
|
112646
|
+
scope,
|
|
112647
|
+
dataPointId: deps.serverOwner ? computeDataPointId(deps.serverOwner, scope) : null,
|
|
112648
|
+
deletedAt: verdict.deletedAt
|
|
112649
|
+
};
|
|
112650
|
+
}
|
|
112651
|
+
async function assertScopeNotDeleted(deps, scope, entry) {
|
|
112652
|
+
const deletion = await resolveReadDeletion(deps, scope, entry);
|
|
112653
|
+
if (deletion)
|
|
112654
|
+
throw new DataDeletedError(deletion);
|
|
112655
|
+
}
|
|
112656
|
+
function discoveryVisibility(deps) {
|
|
112657
|
+
if (!deps.scopeDeletions)
|
|
112658
|
+
return void 0;
|
|
112659
|
+
return async (scope, entry) => await resolveReadDeletion(deps, scope, entry) === null;
|
|
112660
|
+
}
|
|
112661
|
+
async function ingestTombstoneMarker(deps, scope) {
|
|
112662
|
+
if (!deps.scopeDeletions)
|
|
112663
|
+
return null;
|
|
112664
|
+
const verdict = await deps.scopeDeletions.resolve(scope);
|
|
112665
|
+
if (!verdict.deleted || verdict.version === null)
|
|
112666
|
+
return null;
|
|
112667
|
+
const version4 = Number(verdict.version);
|
|
112668
|
+
return Number.isSafeInteger(version4) ? version4 : null;
|
|
112669
|
+
}
|
|
112670
|
+
function apiLoggerAsLogger(logger) {
|
|
112671
|
+
const noop = () => void 0;
|
|
112672
|
+
return {
|
|
112673
|
+
debug: (payload, message) => (logger?.debug ?? noop)(payload, message ?? ""),
|
|
112674
|
+
info: (payload, message) => (logger?.info ?? noop)(payload, message ?? ""),
|
|
112675
|
+
warn: (payload, message) => (logger?.warn ?? noop)(payload, message ?? ""),
|
|
112676
|
+
error: (payload, message) => (logger?.error ?? noop)(payload, message ?? "")
|
|
112677
|
+
};
|
|
112678
|
+
}
|
|
112031
112679
|
function notifyNewData(syncManager) {
|
|
112032
112680
|
if (!syncManager)
|
|
112033
112681
|
return;
|
|
@@ -112083,24 +112731,6 @@ function resolveLineageGrantView(authResult) {
|
|
|
112083
112731
|
}
|
|
112084
112732
|
return { grantId };
|
|
112085
112733
|
}
|
|
112086
|
-
async function deleteOneScope(deps, scope) {
|
|
112087
|
-
if (deps.syncManager?.deleteScopeRemote) {
|
|
112088
|
-
try {
|
|
112089
|
-
await deps.syncManager.deleteScopeRemote(scope);
|
|
112090
|
-
} catch (err2) {
|
|
112091
|
-
deps.logger?.info?.({ scope, error: err2.message }, "Remote scope deletion failed; proceeding with local delete");
|
|
112092
|
-
}
|
|
112093
|
-
}
|
|
112094
|
-
const result = await deleteDataScopeContract({
|
|
112095
|
-
storage: deps.storage,
|
|
112096
|
-
scopeParam: scope
|
|
112097
|
-
});
|
|
112098
|
-
if (!result.ok) {
|
|
112099
|
-
throw new ProtocolError(result.status, result.body.error, result.body.message);
|
|
112100
|
-
}
|
|
112101
|
-
deps.logger?.info?.({ scope, deletedCount: result.deletedCount }, "Scope deleted");
|
|
112102
|
-
return result.deletedCount;
|
|
112103
|
-
}
|
|
112104
112734
|
async function handlePersonalServerDataRequest(request2, deps, options = {}) {
|
|
112105
112735
|
return withApiErrors(async () => {
|
|
112106
112736
|
const url2 = new URL(request2.url);
|
|
@@ -112113,7 +112743,8 @@ async function handlePersonalServerDataRequest(request2, deps, options = {}) {
|
|
|
112113
112743
|
storage: deps.storage,
|
|
112114
112744
|
scopePrefix: url2.searchParams.get("scopePrefix") ?? void 0,
|
|
112115
112745
|
limit: normalizeLimit2(url2.searchParams.get("limit"), 20),
|
|
112116
|
-
offset: normalizeLimit2(url2.searchParams.get("offset"), 0)
|
|
112746
|
+
offset: normalizeLimit2(url2.searchParams.get("offset"), 0),
|
|
112747
|
+
isVisible: discoveryVisibility(deps)
|
|
112117
112748
|
});
|
|
112118
112749
|
return jsonResponse(result.response);
|
|
112119
112750
|
}
|
|
@@ -112122,14 +112753,18 @@ async function handlePersonalServerDataRequest(request2, deps, options = {}) {
|
|
|
112122
112753
|
if (request2.method !== "GET")
|
|
112123
112754
|
return methodNotAllowed();
|
|
112124
112755
|
await deps.auth.authorizeBuilderList(request2);
|
|
112125
|
-
const result = listDataVersionsContract({
|
|
112756
|
+
const result = await listDataVersionsContract({
|
|
112126
112757
|
storage: deps.storage,
|
|
112127
112758
|
scopeParam: decodePathPart(parts[0]),
|
|
112128
112759
|
limit: normalizeLimit2(url2.searchParams.get("limit"), 20),
|
|
112129
|
-
offset: normalizeLimit2(url2.searchParams.get("offset"), 0)
|
|
112760
|
+
offset: normalizeLimit2(url2.searchParams.get("offset"), 0),
|
|
112761
|
+
isVisible: discoveryVisibility(deps)
|
|
112130
112762
|
});
|
|
112131
112763
|
if (!result.ok)
|
|
112132
112764
|
return contractErrorResponse(result);
|
|
112765
|
+
if (result.response.total === 0) {
|
|
112766
|
+
await assertScopeNotDeleted(deps, result.scope, void 0);
|
|
112767
|
+
}
|
|
112133
112768
|
return jsonResponse(result.response);
|
|
112134
112769
|
}
|
|
112135
112770
|
if ((parts.length === 2 || parts.length === 3) && parts[1] === "lineage") {
|
|
@@ -112211,6 +112846,7 @@ async function handlePersonalServerDataRequest(request2, deps, options = {}) {
|
|
|
112211
112846
|
fileId: url2.searchParams.get("fileId") ?? selectedEntry?.fileId ?? void 0,
|
|
112212
112847
|
at: url2.searchParams.get("at") ?? void 0
|
|
112213
112848
|
});
|
|
112849
|
+
await assertScopeNotDeleted(deps, scopeResult.scope, selectedEntry);
|
|
112214
112850
|
const isOwnerSignal = authResult?.grantId === "owner" || authResult?.grantId === "policy-bypass";
|
|
112215
112851
|
const builder = authResult?.builder;
|
|
112216
112852
|
const resolvedGrantId = !isOwnerSignal && authResult?.grantId ? authResult.grantId : void 0;
|
|
@@ -112265,8 +112901,12 @@ async function handlePersonalServerDataRequest(request2, deps, options = {}) {
|
|
|
112265
112901
|
fileId: url2.searchParams.get("fileId") ?? void 0,
|
|
112266
112902
|
at: url2.searchParams.get("at") ?? void 0
|
|
112267
112903
|
});
|
|
112268
|
-
if (!result.ok)
|
|
112904
|
+
if (!result.ok) {
|
|
112905
|
+
if (result.status === 404) {
|
|
112906
|
+
await assertScopeNotDeleted(deps, scopeResult.scope, void 0);
|
|
112907
|
+
}
|
|
112269
112908
|
return contractErrorResponse(result);
|
|
112909
|
+
}
|
|
112270
112910
|
const logId = deps.createLogId?.() ?? crypto.randomUUID();
|
|
112271
112911
|
const timestamp = (deps.now ?? (() => /* @__PURE__ */ new Date()))().toISOString();
|
|
112272
112912
|
const ipAddress = request2.headers.get("x-forwarded-for") ?? request2.headers.get("x-real-ip") ?? "unknown";
|
|
@@ -112346,6 +112986,7 @@ async function handlePersonalServerDataRequest(request2, deps, options = {}) {
|
|
|
112346
112986
|
return failWrite(contractErrorResponse(scopeResult));
|
|
112347
112987
|
const collectedAtValue = collectedAt(deps.now ?? (() => /* @__PURE__ */ new Date()));
|
|
112348
112988
|
const status2 = deps.syncManager ? "syncing" : "stored";
|
|
112989
|
+
const afterTombstoneVersion = await ingestTombstoneMarker(deps, scopeResult.scope);
|
|
112349
112990
|
const logBuilderWrite = async () => {
|
|
112350
112991
|
if (!writeAuth)
|
|
112351
112992
|
return;
|
|
@@ -112383,7 +113024,8 @@ async function handlePersonalServerDataRequest(request2, deps, options = {}) {
|
|
|
112383
113024
|
collectedAt: collectedAtValue,
|
|
112384
113025
|
status: status2,
|
|
112385
113026
|
attribution: writeAuth?.attribution,
|
|
112386
|
-
lineage: lineage2
|
|
113027
|
+
lineage: lineage2,
|
|
113028
|
+
afterTombstoneVersion
|
|
112387
113029
|
});
|
|
112388
113030
|
if (!result2.ok)
|
|
112389
113031
|
return failWrite(contractErrorResponse(result2));
|
|
@@ -112411,7 +113053,8 @@ async function handlePersonalServerDataRequest(request2, deps, options = {}) {
|
|
|
112411
113053
|
collectedAt: collectedAtValue,
|
|
112412
113054
|
status: status2,
|
|
112413
113055
|
attribution: writeAuth?.attribution,
|
|
112414
|
-
lineage
|
|
113056
|
+
lineage,
|
|
113057
|
+
afterTombstoneVersion
|
|
112415
113058
|
});
|
|
112416
113059
|
if (!result.ok)
|
|
112417
113060
|
return failWrite(contractErrorResponse(result));
|
|
@@ -112450,8 +113093,44 @@ async function handlePersonalServerDataRequest(request2, deps, options = {}) {
|
|
|
112450
113093
|
if (cascade === "lineage") {
|
|
112451
113094
|
throw new LineageCascadeUnavailableError({ scope: parsed.scope });
|
|
112452
113095
|
}
|
|
112453
|
-
await
|
|
112454
|
-
|
|
113096
|
+
const result = deps.syncManager?.deleteScope ? await deps.syncManager.deleteScope(parsed.scope) : await deleteScope({
|
|
113097
|
+
storage: deps.storage,
|
|
113098
|
+
serverOwner: deps.serverOwner,
|
|
113099
|
+
deleteData: null,
|
|
113100
|
+
logger: apiLoggerAsLogger(deps.logger)
|
|
113101
|
+
}, parsed.scope);
|
|
113102
|
+
if (result.steps.gateway.status === "failed") {
|
|
113103
|
+
throw new DeleteTombstoneFailedError({
|
|
113104
|
+
scope: parsed.scope,
|
|
113105
|
+
result
|
|
113106
|
+
});
|
|
113107
|
+
}
|
|
113108
|
+
try {
|
|
113109
|
+
await deps.accessLogWriter.write({
|
|
113110
|
+
logId: deps.createLogId?.() ?? crypto.randomUUID(),
|
|
113111
|
+
grantId: "owner",
|
|
113112
|
+
builder: deps.serverOwner ?? "owner",
|
|
113113
|
+
action: "delete",
|
|
113114
|
+
scope: parsed.scope,
|
|
113115
|
+
timestamp: (deps.now ?? (() => /* @__PURE__ */ new Date()))().toISOString(),
|
|
113116
|
+
ipAddress: request2.headers.get("x-forwarded-for") ?? request2.headers.get("x-real-ip") ?? "unknown",
|
|
113117
|
+
userAgent: request2.headers.get("user-agent") ?? "unknown"
|
|
113118
|
+
});
|
|
113119
|
+
} catch (err2) {
|
|
113120
|
+
deps.logger?.warn?.({
|
|
113121
|
+
scope: parsed.scope,
|
|
113122
|
+
error: err2 instanceof Error ? err2.message : String(err2)
|
|
113123
|
+
}, "Delete access-log entry failed; scope already deleted");
|
|
113124
|
+
}
|
|
113125
|
+
deps.logger?.info?.({
|
|
113126
|
+
scope: parsed.scope,
|
|
113127
|
+
durable: result.durable,
|
|
113128
|
+
gateway: result.steps.gateway.status,
|
|
113129
|
+
storage: result.steps.storage.status,
|
|
113130
|
+
local: result.steps.local.status,
|
|
113131
|
+
deletedCount: result.steps.local.deletedCount
|
|
113132
|
+
}, "Scope deleted");
|
|
113133
|
+
return jsonResponse(result, { status: 200 });
|
|
112455
113134
|
}
|
|
112456
113135
|
return methodNotAllowed();
|
|
112457
113136
|
});
|
|
@@ -112761,6 +113440,16 @@ var McpDataReadError = class extends Error {
|
|
|
112761
113440
|
};
|
|
112762
113441
|
function createMcpDataReadClient(options) {
|
|
112763
113442
|
const basePath = options.basePath ?? "/v1/data";
|
|
113443
|
+
async function assertScopeReadable(scope, entry) {
|
|
113444
|
+
try {
|
|
113445
|
+
await assertScopeNotDeleted(options.dataApiDeps, scope, entry);
|
|
113446
|
+
} catch (err2) {
|
|
113447
|
+
if (err2 instanceof ProtocolError) {
|
|
113448
|
+
throw new McpDataReadError(err2.code, err2.toJSON());
|
|
113449
|
+
}
|
|
113450
|
+
throw err2;
|
|
113451
|
+
}
|
|
113452
|
+
}
|
|
112764
113453
|
async function authorizeScopeRead(params) {
|
|
112765
113454
|
const safeScope = encodeURIComponent(params.scope);
|
|
112766
113455
|
const signingUri = `${basePath}/${safeScope}`;
|
|
@@ -112848,6 +113537,9 @@ function createMcpDataReadClient(options) {
|
|
|
112848
113537
|
const entry = storage.findEntry({ scope });
|
|
112849
113538
|
if (!entry)
|
|
112850
113539
|
return null;
|
|
113540
|
+
if (await resolveReadDeletion(options.dataApiDeps, scope, entry)) {
|
|
113541
|
+
return null;
|
|
113542
|
+
}
|
|
112851
113543
|
const hasBlocks = typeof storage.hasScopeBlocks === "function" ? await storage.hasScopeBlocks(scope, entry.collectedAt) : false;
|
|
112852
113544
|
return {
|
|
112853
113545
|
scope,
|
|
@@ -112876,6 +113568,7 @@ function createMcpDataReadClient(options) {
|
|
|
112876
113568
|
message: `No data found for scope "${scope}"`
|
|
112877
113569
|
});
|
|
112878
113570
|
}
|
|
113571
|
+
await assertScopeReadable(scope, selectedEntry);
|
|
112879
113572
|
const { request: request2, authResult } = await authorizeScopeRead({
|
|
112880
113573
|
scope,
|
|
112881
113574
|
grantId,
|
|
@@ -112933,6 +113626,7 @@ function createMcpDataReadClient(options) {
|
|
|
112933
113626
|
message: `No data found for scope "${scope}"`
|
|
112934
113627
|
});
|
|
112935
113628
|
}
|
|
113629
|
+
await assertScopeReadable(scope, selectedEntry);
|
|
112936
113630
|
const { request: request2, authResult } = await authorizeScopeRead({
|
|
112937
113631
|
scope,
|
|
112938
113632
|
grantId,
|
|
@@ -116596,15 +117290,15 @@ var makeIssue = (params) => {
|
|
|
116596
117290
|
message: issueData.message
|
|
116597
117291
|
};
|
|
116598
117292
|
}
|
|
116599
|
-
let
|
|
117293
|
+
let errorMessage3 = "";
|
|
116600
117294
|
const maps = errorMaps.filter((m10) => !!m10).slice().reverse();
|
|
116601
117295
|
for (const map2 of maps) {
|
|
116602
|
-
|
|
117296
|
+
errorMessage3 = map2(fullIssue, { data, defaultError: errorMessage3 }).message;
|
|
116603
117297
|
}
|
|
116604
117298
|
return {
|
|
116605
117299
|
...issueData,
|
|
116606
117300
|
path: fullPath,
|
|
116607
|
-
message:
|
|
117301
|
+
message: errorMessage3
|
|
116608
117302
|
};
|
|
116609
117303
|
};
|
|
116610
117304
|
function addIssueToContext(ctx, issueData) {
|
|
@@ -121884,19 +122578,19 @@ var getRefs = (options) => {
|
|
|
121884
122578
|
};
|
|
121885
122579
|
|
|
121886
122580
|
// ../../node_modules/zod-to-json-schema/dist/esm/errorMessages.js
|
|
121887
|
-
function addErrorMessage(res, key,
|
|
122581
|
+
function addErrorMessage(res, key, errorMessage3, refs) {
|
|
121888
122582
|
if (!refs?.errorMessages)
|
|
121889
122583
|
return;
|
|
121890
|
-
if (
|
|
122584
|
+
if (errorMessage3) {
|
|
121891
122585
|
res.errorMessage = {
|
|
121892
122586
|
...res.errorMessage,
|
|
121893
|
-
[key]:
|
|
122587
|
+
[key]: errorMessage3
|
|
121894
122588
|
};
|
|
121895
122589
|
}
|
|
121896
122590
|
}
|
|
121897
|
-
function setResponseValueAndErrors(res, key, value,
|
|
122591
|
+
function setResponseValueAndErrors(res, key, value, errorMessage3, refs) {
|
|
121898
122592
|
res[key] = value;
|
|
121899
|
-
addErrorMessage(res, key,
|
|
122593
|
+
addErrorMessage(res, key, errorMessage3, refs);
|
|
121900
122594
|
}
|
|
121901
122595
|
|
|
121902
122596
|
// ../../node_modules/zod-to-json-schema/dist/esm/getRelativePath.js
|
|
@@ -123207,8 +123901,8 @@ var Protocol = class {
|
|
|
123207
123901
|
if (queuedMessage.type === "response") {
|
|
123208
123902
|
resolver(message);
|
|
123209
123903
|
} else {
|
|
123210
|
-
const
|
|
123211
|
-
const error51 = new McpError(
|
|
123904
|
+
const errorMessage3 = message;
|
|
123905
|
+
const error51 = new McpError(errorMessage3.error.code, errorMessage3.error.message, errorMessage3.error.data);
|
|
123212
123906
|
resolver(error51);
|
|
123213
123907
|
}
|
|
123214
123908
|
} else {
|
|
@@ -124508,23 +125202,23 @@ var Server = class extends Protocol {
|
|
|
124508
125202
|
const wrappedHandler = async (request2, extra) => {
|
|
124509
125203
|
const validatedRequest = safeParse3(CallToolRequestSchema, request2);
|
|
124510
125204
|
if (!validatedRequest.success) {
|
|
124511
|
-
const
|
|
124512
|
-
throw new McpError(ErrorCode.InvalidParams, `Invalid tools/call request: ${
|
|
125205
|
+
const errorMessage3 = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
|
|
125206
|
+
throw new McpError(ErrorCode.InvalidParams, `Invalid tools/call request: ${errorMessage3}`);
|
|
124513
125207
|
}
|
|
124514
125208
|
const { params } = validatedRequest.data;
|
|
124515
125209
|
const result = await Promise.resolve(handler(request2, extra));
|
|
124516
125210
|
if (params.task) {
|
|
124517
125211
|
const taskValidationResult = safeParse3(CreateTaskResultSchema, result);
|
|
124518
125212
|
if (!taskValidationResult.success) {
|
|
124519
|
-
const
|
|
124520
|
-
throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${
|
|
125213
|
+
const errorMessage3 = taskValidationResult.error instanceof Error ? taskValidationResult.error.message : String(taskValidationResult.error);
|
|
125214
|
+
throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${errorMessage3}`);
|
|
124521
125215
|
}
|
|
124522
125216
|
return taskValidationResult.data;
|
|
124523
125217
|
}
|
|
124524
125218
|
const validationResult = safeParse3(CallToolResultSchema, result);
|
|
124525
125219
|
if (!validationResult.success) {
|
|
124526
|
-
const
|
|
124527
|
-
throw new McpError(ErrorCode.InvalidParams, `Invalid tools/call result: ${
|
|
125220
|
+
const errorMessage3 = validationResult.error instanceof Error ? validationResult.error.message : String(validationResult.error);
|
|
125221
|
+
throw new McpError(ErrorCode.InvalidParams, `Invalid tools/call result: ${errorMessage3}`);
|
|
124528
125222
|
}
|
|
124529
125223
|
return validationResult.data;
|
|
124530
125224
|
};
|
|
@@ -125240,12 +125934,12 @@ var McpServer = class {
|
|
|
125240
125934
|
* @param errorMessage - The error message.
|
|
125241
125935
|
* @returns The tool error result.
|
|
125242
125936
|
*/
|
|
125243
|
-
createToolError(
|
|
125937
|
+
createToolError(errorMessage3) {
|
|
125244
125938
|
return {
|
|
125245
125939
|
content: [
|
|
125246
125940
|
{
|
|
125247
125941
|
type: "text",
|
|
125248
|
-
text:
|
|
125942
|
+
text: errorMessage3
|
|
125249
125943
|
}
|
|
125250
125944
|
],
|
|
125251
125945
|
isError: true
|
|
@@ -125263,8 +125957,8 @@ var McpServer = class {
|
|
|
125263
125957
|
const parseResult = await safeParseAsync3(schemaToParse, args);
|
|
125264
125958
|
if (!parseResult.success) {
|
|
125265
125959
|
const error51 = "error" in parseResult ? parseResult.error : "Unknown error";
|
|
125266
|
-
const
|
|
125267
|
-
throw new McpError(ErrorCode.InvalidParams, `Input validation error: Invalid arguments for tool ${toolName}: ${
|
|
125960
|
+
const errorMessage3 = getParseErrorMessage(error51);
|
|
125961
|
+
throw new McpError(ErrorCode.InvalidParams, `Input validation error: Invalid arguments for tool ${toolName}: ${errorMessage3}`);
|
|
125268
125962
|
}
|
|
125269
125963
|
return parseResult.data;
|
|
125270
125964
|
}
|
|
@@ -125288,8 +125982,8 @@ var McpServer = class {
|
|
|
125288
125982
|
const parseResult = await safeParseAsync3(outputObj, result.structuredContent);
|
|
125289
125983
|
if (!parseResult.success) {
|
|
125290
125984
|
const error51 = "error" in parseResult ? parseResult.error : "Unknown error";
|
|
125291
|
-
const
|
|
125292
|
-
throw new McpError(ErrorCode.InvalidParams, `Output validation error: Invalid structured content for tool ${toolName}: ${
|
|
125985
|
+
const errorMessage3 = getParseErrorMessage(error51);
|
|
125986
|
+
throw new McpError(ErrorCode.InvalidParams, `Output validation error: Invalid structured content for tool ${toolName}: ${errorMessage3}`);
|
|
125293
125987
|
}
|
|
125294
125988
|
}
|
|
125295
125989
|
/**
|
|
@@ -125501,8 +126195,8 @@ var McpServer = class {
|
|
|
125501
126195
|
const parseResult = await safeParseAsync3(argsObj, request2.params.arguments);
|
|
125502
126196
|
if (!parseResult.success) {
|
|
125503
126197
|
const error51 = "error" in parseResult ? parseResult.error : "Unknown error";
|
|
125504
|
-
const
|
|
125505
|
-
throw new McpError(ErrorCode.InvalidParams, `Invalid arguments for prompt ${request2.params.name}: ${
|
|
126198
|
+
const errorMessage3 = getParseErrorMessage(error51);
|
|
126199
|
+
throw new McpError(ErrorCode.InvalidParams, `Invalid arguments for prompt ${request2.params.name}: ${errorMessage3}`);
|
|
125506
126200
|
}
|
|
125507
126201
|
const args = parseResult.data;
|
|
125508
126202
|
const cb2 = prompt.callback;
|
|
@@ -127598,6 +128292,7 @@ function createPsLiteRuntime(options) {
|
|
|
127598
128292
|
accessLogWriter,
|
|
127599
128293
|
readFulfillmentReporter: options.readFulfillmentReporter,
|
|
127600
128294
|
syncManager: options.syncManager ?? null,
|
|
128295
|
+
scopeDeletions: options.scopeDeletions,
|
|
127601
128296
|
now,
|
|
127602
128297
|
createLogId,
|
|
127603
128298
|
// x402 payment enforcement for builder reads. Only engages with a
|
|
@@ -128074,6 +128769,45 @@ var OrphanedEntryError = class extends Error {
|
|
|
128074
128769
|
this.name = "OrphanedEntryError";
|
|
128075
128770
|
}
|
|
128076
128771
|
};
|
|
128772
|
+
var DeletedScopeEntryError = class extends Error {
|
|
128773
|
+
constructor(path, deletedAt) {
|
|
128774
|
+
super(`Dropped local entry for a scope deleted at ${deletedAt}: ${path}`);
|
|
128775
|
+
this.name = "DeletedScopeEntryError";
|
|
128776
|
+
}
|
|
128777
|
+
};
|
|
128778
|
+
async function dropIfCoveredByDeletion(deps, entry, tombstone, deletedAt, uploaded) {
|
|
128779
|
+
const version4 = tombstoneVersion(tombstone);
|
|
128780
|
+
if (!isEntryCoveredByTombstone(entry, { version: version4 }))
|
|
128781
|
+
return;
|
|
128782
|
+
if (uploaded) {
|
|
128783
|
+
try {
|
|
128784
|
+
await deps.storageAdapter.delete(uploaded.url);
|
|
128785
|
+
} catch (err2) {
|
|
128786
|
+
const message = err2 instanceof Error ? err2.message : String(err2);
|
|
128787
|
+
if (deps.pendingBlobDeletions) {
|
|
128788
|
+
await deps.pendingBlobDeletions.add([
|
|
128789
|
+
{ scope: entry.scope, version: String(entry.version) }
|
|
128790
|
+
]);
|
|
128791
|
+
}
|
|
128792
|
+
deps.logger.warn({
|
|
128793
|
+
scope: entry.scope,
|
|
128794
|
+
url: uploaded.url,
|
|
128795
|
+
error: message,
|
|
128796
|
+
queuedForCleanup: Boolean(deps.pendingBlobDeletions)
|
|
128797
|
+
}, "Could not delete the ciphertext uploaded for an entry the tombstone covers");
|
|
128798
|
+
}
|
|
128799
|
+
}
|
|
128800
|
+
await deps.storage.deleteVersion(entry.scope, entry.collectedAt);
|
|
128801
|
+
deps.logger.warn({
|
|
128802
|
+
path: entry.path,
|
|
128803
|
+
scope: entry.scope,
|
|
128804
|
+
deletedAt,
|
|
128805
|
+
tombstoneVersion: version4,
|
|
128806
|
+
entryVersion: entry.version,
|
|
128807
|
+
afterTombstoneVersion: entry.afterTombstoneVersion ?? null
|
|
128808
|
+
}, "Dropped unsynced local entry: the gateway reports its scope as deleted");
|
|
128809
|
+
throw new DeletedScopeEntryError(entry.path, deletedAt);
|
|
128810
|
+
}
|
|
128077
128811
|
function isMissingPayloadError(err2) {
|
|
128078
128812
|
return err2 instanceof Error && err2.code === "ENOENT";
|
|
128079
128813
|
}
|
|
@@ -128092,6 +128826,20 @@ async function uploadOne(deps, entry) {
|
|
|
128092
128826
|
}
|
|
128093
128827
|
throw err2;
|
|
128094
128828
|
}
|
|
128829
|
+
let registerVersion = BigInt(entry.version);
|
|
128830
|
+
if (!entry.dataPointId && deps.dataPointFeed) {
|
|
128831
|
+
const remote = await deps.dataPointFeed.getDataPoint({
|
|
128832
|
+
ownerAddress: serverOwner,
|
|
128833
|
+
scope: entry.scope
|
|
128834
|
+
});
|
|
128835
|
+
const deletedAt = deletionTimestamp(remote);
|
|
128836
|
+
if (remote && deletedAt !== null) {
|
|
128837
|
+
await dropIfCoveredByDeletion(deps, entry, remote, deletedAt);
|
|
128838
|
+
const afterTombstone = BigInt(remote.expectedVersion) + 1n;
|
|
128839
|
+
if (afterTombstone > registerVersion)
|
|
128840
|
+
registerVersion = afterTombstone;
|
|
128841
|
+
}
|
|
128842
|
+
}
|
|
128095
128843
|
const scopeKey = deriveScopeKey(masterKey, entry.scope);
|
|
128096
128844
|
const scopeKeyHex = uint8ToHex(scopeKey);
|
|
128097
128845
|
const plaintext = new TextEncoder().encode(JSON.stringify(envelope));
|
|
@@ -128102,7 +128850,7 @@ async function uploadOne(deps, entry) {
|
|
|
128102
128850
|
collectedAt: entry.collectedAt,
|
|
128103
128851
|
sizeBytes: encrypted.byteLength
|
|
128104
128852
|
})));
|
|
128105
|
-
const storageKey = `${entry.scope}/${
|
|
128853
|
+
const storageKey = `${entry.scope}/${registerVersion}`;
|
|
128106
128854
|
let url2 = await storageAdapter.upload(storageKey, encrypted);
|
|
128107
128855
|
let dataPointId;
|
|
128108
128856
|
if (entry.dataPointId) {
|
|
@@ -128152,11 +128900,23 @@ async function uploadOne(deps, entry) {
|
|
|
128152
128900
|
return id2;
|
|
128153
128901
|
};
|
|
128154
128902
|
try {
|
|
128155
|
-
dataPointId = await registerAt(
|
|
128903
|
+
dataPointId = await registerAt(registerVersion);
|
|
128904
|
+
if (registerVersion !== BigInt(entry.version)) {
|
|
128905
|
+
await storage.updateEntryVersion(entry.path, Number(registerVersion));
|
|
128906
|
+
}
|
|
128156
128907
|
} catch (err2) {
|
|
128157
128908
|
if (!isStaleVersionConflict(err2))
|
|
128158
128909
|
throw err2;
|
|
128159
|
-
const record2 = await
|
|
128910
|
+
const record2 = deps.dataPointFeed ? await deps.dataPointFeed.getDataPoint({
|
|
128911
|
+
ownerAddress: serverOwner,
|
|
128912
|
+
scope: entry.scope
|
|
128913
|
+
}) : await gateway.getDataPoint(computeDataPointId(serverOwner, entry.scope));
|
|
128914
|
+
const conflictDeletedAt = record2 ? deletionTimestamp(record2) : null;
|
|
128915
|
+
if (record2 && conflictDeletedAt !== null) {
|
|
128916
|
+
await dropIfCoveredByDeletion(deps, entry, record2, conflictDeletedAt, {
|
|
128917
|
+
url: url2
|
|
128918
|
+
});
|
|
128919
|
+
}
|
|
128160
128920
|
if (record2 && record2.dataHash.toLowerCase() === dataHash.toLowerCase()) {
|
|
128161
128921
|
dataPointId = record2.id;
|
|
128162
128922
|
const adoptedVersion = Number(record2.expectedVersion);
|
|
@@ -128182,6 +128942,7 @@ async function uploadOne(deps, entry) {
|
|
|
128182
128942
|
}
|
|
128183
128943
|
}
|
|
128184
128944
|
await storage.updateDataPointId(entry.path, dataPointId);
|
|
128945
|
+
deps.scopeDeletions?.markLive(entry.scope);
|
|
128185
128946
|
}
|
|
128186
128947
|
logger.info({
|
|
128187
128948
|
path: entry.path,
|
|
@@ -128201,7 +128962,7 @@ async function uploadAll(deps, options) {
|
|
|
128201
128962
|
const result = await uploadOne(deps, entry);
|
|
128202
128963
|
results.push(result);
|
|
128203
128964
|
} catch (err2) {
|
|
128204
|
-
if (err2 instanceof OrphanedEntryError) {
|
|
128965
|
+
if (err2 instanceof OrphanedEntryError || err2 instanceof DeletedScopeEntryError) {
|
|
128205
128966
|
continue;
|
|
128206
128967
|
}
|
|
128207
128968
|
const error51 = err2;
|
|
@@ -128230,6 +128991,101 @@ function parseGatewayNextVersion(message) {
|
|
|
128230
128991
|
return null;
|
|
128231
128992
|
}
|
|
128232
128993
|
|
|
128994
|
+
// ../core/dist/sync/data-point-feed.js
|
|
128995
|
+
function createGatewayDataPointFeed(options) {
|
|
128996
|
+
const base = options.gatewayUrl.replace(/\/+$/, "");
|
|
128997
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
128998
|
+
const now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
128999
|
+
return {
|
|
129000
|
+
async listDataPointsByOwner(owner, cursor, listOptions) {
|
|
129001
|
+
const params = new URLSearchParams({ user: owner });
|
|
129002
|
+
if (cursor !== null)
|
|
129003
|
+
params.set("cursor", cursor);
|
|
129004
|
+
if (listOptions?.since)
|
|
129005
|
+
params.set("since", listOptions.since);
|
|
129006
|
+
if (listOptions?.limit !== void 0) {
|
|
129007
|
+
params.set("limit", String(listOptions.limit));
|
|
129008
|
+
}
|
|
129009
|
+
if (listOptions?.includeDeleted)
|
|
129010
|
+
params.set("includeDeleted", "true");
|
|
129011
|
+
const res = await fetchImpl(`${base}/v1/data?${params.toString()}`);
|
|
129012
|
+
if (!res.ok) {
|
|
129013
|
+
throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
|
|
129014
|
+
}
|
|
129015
|
+
const envelope = await res.json();
|
|
129016
|
+
const nextCursor = envelope.pagination?.hasMore === false ? null : envelope.pagination?.nextCursor ?? null;
|
|
129017
|
+
const rows = envelope.data?.dataPoints ?? [];
|
|
129018
|
+
return {
|
|
129019
|
+
dataPoints: rows.map((row) => normalizeRecord(row)),
|
|
129020
|
+
cursor: nextCursor
|
|
129021
|
+
};
|
|
129022
|
+
},
|
|
129023
|
+
async getDataPoint(input) {
|
|
129024
|
+
const dataPointId = computeDataPointId(input.ownerAddress, input.scope);
|
|
129025
|
+
const res = await fetchImpl(`${base}/v1/data/${dataPointId}?includeDeleted=true`);
|
|
129026
|
+
if (res.status === 404)
|
|
129027
|
+
return null;
|
|
129028
|
+
if (res.status === 410) {
|
|
129029
|
+
const body2 = await res.json().catch(() => null);
|
|
129030
|
+
const echoed = unwrap(body2);
|
|
129031
|
+
const deletedAt = stringField(echoed, "deletedAt") ?? now().toISOString();
|
|
129032
|
+
return {
|
|
129033
|
+
id: dataPointId,
|
|
129034
|
+
ownerAddress: input.ownerAddress,
|
|
129035
|
+
scope: input.scope,
|
|
129036
|
+
dataHash: stringField(echoed, "dataHash") ?? TOMBSTONE_DATA_HASH,
|
|
129037
|
+
metadataHash: stringField(echoed, "metadataHash") ?? TOMBSTONE_METADATA_HASH,
|
|
129038
|
+
expectedVersion: stringField(echoed, "expectedVersion") ?? "0",
|
|
129039
|
+
addedAt: stringField(echoed, "addedAt") ?? deletedAt,
|
|
129040
|
+
deletedAt
|
|
129041
|
+
};
|
|
129042
|
+
}
|
|
129043
|
+
if (!res.ok) {
|
|
129044
|
+
throw new Error(`Gateway error: ${res.status} ${res.statusText}`);
|
|
129045
|
+
}
|
|
129046
|
+
const body = await res.json();
|
|
129047
|
+
return normalizeRecord(unwrap(body));
|
|
129048
|
+
}
|
|
129049
|
+
};
|
|
129050
|
+
}
|
|
129051
|
+
function unwrap(body) {
|
|
129052
|
+
if (typeof body !== "object" || body === null)
|
|
129053
|
+
return null;
|
|
129054
|
+
const record2 = body;
|
|
129055
|
+
if (typeof record2.data === "object" && record2.data !== null) {
|
|
129056
|
+
return record2.data;
|
|
129057
|
+
}
|
|
129058
|
+
return record2;
|
|
129059
|
+
}
|
|
129060
|
+
function stringField(record2, key) {
|
|
129061
|
+
const value = record2?.[key];
|
|
129062
|
+
return typeof value === "string" ? value : void 0;
|
|
129063
|
+
}
|
|
129064
|
+
function normalizeRecord(row) {
|
|
129065
|
+
const record2 = row ?? {};
|
|
129066
|
+
const deletedAt = record2.deletedAt;
|
|
129067
|
+
return {
|
|
129068
|
+
...record2,
|
|
129069
|
+
deletedAt: typeof deletedAt === "string" ? deletedAt : null
|
|
129070
|
+
};
|
|
129071
|
+
}
|
|
129072
|
+
function feedFromGatewayClient(gateway) {
|
|
129073
|
+
return {
|
|
129074
|
+
async listDataPointsByOwner(owner, cursor, listOptions) {
|
|
129075
|
+
const { includeDeleted: _includeDeleted, ...sdkOptions } = listOptions ?? {};
|
|
129076
|
+
const result = Object.keys(sdkOptions).length > 0 ? await gateway.listDataPointsByOwner(owner, cursor, sdkOptions) : await gateway.listDataPointsByOwner(owner, cursor);
|
|
129077
|
+
return {
|
|
129078
|
+
dataPoints: result.dataPoints.map((row) => normalizeRecord(row)),
|
|
129079
|
+
cursor: result.cursor
|
|
129080
|
+
};
|
|
129081
|
+
},
|
|
129082
|
+
async getDataPoint(input) {
|
|
129083
|
+
const row = await gateway.getDataPoint(computeDataPointId(input.ownerAddress, input.scope));
|
|
129084
|
+
return row === null ? null : normalizeRecord(row);
|
|
129085
|
+
}
|
|
129086
|
+
};
|
|
129087
|
+
}
|
|
129088
|
+
|
|
128233
129089
|
// ../core/dist/sync/issues.js
|
|
128234
129090
|
var DETERMINISTIC_STAGES = /* @__PURE__ */ new Set([
|
|
128235
129091
|
"openpgp_parse",
|
|
@@ -128567,10 +129423,43 @@ async function downloadAll(deps, options = {}) {
|
|
|
128567
129423
|
if (options.fullReconcile || repairSummary.missingEnvelopeEntries > 0) {
|
|
128568
129424
|
options.retryMemory?.onListingReset();
|
|
128569
129425
|
}
|
|
128570
|
-
const
|
|
129426
|
+
const feed = deps.dataPointFeed ?? feedFromGatewayClient(gateway);
|
|
129427
|
+
const { dataPoints, cursor: nextCursor } = await feed.listDataPointsByOwner(serverOwner, lastCursor, { includeDeleted: true });
|
|
129428
|
+
if (deps.scopeDeletions) {
|
|
129429
|
+
for (const dataPoint of dataPoints) {
|
|
129430
|
+
const deletedAt = deletionTimestamp(dataPoint);
|
|
129431
|
+
if (deletedAt !== null) {
|
|
129432
|
+
deps.scopeDeletions.markDeleted(dataPoint.scope, {
|
|
129433
|
+
deletedAt,
|
|
129434
|
+
version: tombstoneVersion(dataPoint)
|
|
129435
|
+
});
|
|
129436
|
+
} else {
|
|
129437
|
+
deps.scopeDeletions.markLive(dataPoint.scope);
|
|
129438
|
+
}
|
|
129439
|
+
}
|
|
129440
|
+
if (nextCursor === null) {
|
|
129441
|
+
deps.scopeDeletions.noteFeedSynced(void 0, {
|
|
129442
|
+
full: lastCursor === null
|
|
129443
|
+
});
|
|
129444
|
+
}
|
|
129445
|
+
}
|
|
128571
129446
|
const results = [];
|
|
128572
129447
|
let failed = false;
|
|
128573
129448
|
for (const dataPoint of dataPoints) {
|
|
129449
|
+
const deletedAt = deletionTimestamp(dataPoint);
|
|
129450
|
+
if (deletedAt !== null) {
|
|
129451
|
+
try {
|
|
129452
|
+
await reconcileDeletedDataPoint(deps, dataPoint, deletedAt);
|
|
129453
|
+
} catch (err2) {
|
|
129454
|
+
logger.error({
|
|
129455
|
+
dataPointId: dataPoint.id,
|
|
129456
|
+
scope: dataPoint.scope,
|
|
129457
|
+
error: err2.message
|
|
129458
|
+
}, "Failed to reconcile deleted data point locally");
|
|
129459
|
+
failed = true;
|
|
129460
|
+
}
|
|
129461
|
+
continue;
|
|
129462
|
+
}
|
|
128574
129463
|
const retryKey = downloadRetryKey(dataPoint);
|
|
128575
129464
|
const decision = options.retryMemory?.decide(retryKey) ?? "attempt";
|
|
128576
129465
|
if (decision === "give-up") {
|
|
@@ -128626,6 +129515,49 @@ async function downloadAll(deps, options = {}) {
|
|
|
128626
129515
|
}
|
|
128627
129516
|
return results;
|
|
128628
129517
|
}
|
|
129518
|
+
async function reconcileDeletedDataPoint(deps, record2, deletedAt) {
|
|
129519
|
+
const tombstone = { version: tombstoneVersion(record2) };
|
|
129520
|
+
const tombstoned = tombstone.version === null ? null : BigInt(tombstone.version);
|
|
129521
|
+
const orphanKeys = [];
|
|
129522
|
+
const { storage, logger } = deps;
|
|
129523
|
+
const PAGE_SIZE = 500;
|
|
129524
|
+
const stale = [];
|
|
129525
|
+
let kept = 0;
|
|
129526
|
+
for (let offset = 0; ; offset += PAGE_SIZE) {
|
|
129527
|
+
const entries = storage.listVersions(record2.scope, {
|
|
129528
|
+
limit: PAGE_SIZE,
|
|
129529
|
+
offset
|
|
129530
|
+
});
|
|
129531
|
+
for (const entry of entries) {
|
|
129532
|
+
if (isEntryCoveredByTombstone(entry, tombstone)) {
|
|
129533
|
+
stale.push({ scope: entry.scope, collectedAt: entry.collectedAt });
|
|
129534
|
+
if (entry.dataPointId === null && (tombstoned === null || BigInt(entry.version) > tombstoned)) {
|
|
129535
|
+
orphanKeys.push({
|
|
129536
|
+
scope: entry.scope,
|
|
129537
|
+
version: String(entry.version)
|
|
129538
|
+
});
|
|
129539
|
+
}
|
|
129540
|
+
} else {
|
|
129541
|
+
kept += 1;
|
|
129542
|
+
}
|
|
129543
|
+
}
|
|
129544
|
+
if (entries.length < PAGE_SIZE)
|
|
129545
|
+
break;
|
|
129546
|
+
}
|
|
129547
|
+
let removed = 0;
|
|
129548
|
+
for (const version4 of stale) {
|
|
129549
|
+
if (await storage.deleteVersion(version4.scope, version4.collectedAt)) {
|
|
129550
|
+
removed += 1;
|
|
129551
|
+
}
|
|
129552
|
+
}
|
|
129553
|
+
if (orphanKeys.length > 0 && deps.pendingBlobDeletions) {
|
|
129554
|
+
await deps.pendingBlobDeletions.add(orphanKeys);
|
|
129555
|
+
}
|
|
129556
|
+
if (removed > 0 || kept > 0) {
|
|
129557
|
+
logger.info({ dataPointId: record2.id, scope: record2.scope, deletedAt, removed, kept }, "Reconciled gateway deletion against local index");
|
|
129558
|
+
}
|
|
129559
|
+
return { scope: record2.scope, deletedAt, removed, kept };
|
|
129560
|
+
}
|
|
128629
129561
|
async function repairLocalMissingBlockSidecars(deps) {
|
|
128630
129562
|
const { storage, logger, diagnostics } = deps;
|
|
128631
129563
|
if (!storage.writeBlockManifest || !storage.hasScopeBlocks) {
|
|
@@ -128784,28 +129716,6 @@ async function repairMissingBlockSidecars(storage, logger, ctx, entry, diagnosti
|
|
|
128784
129716
|
}
|
|
128785
129717
|
}
|
|
128786
129718
|
|
|
128787
|
-
// ../core/dist/sync/workers/delete.js
|
|
128788
|
-
async function deleteScopeRemote(deps, scope) {
|
|
128789
|
-
const { storage, logger } = deps;
|
|
128790
|
-
let syncedVersions = 0;
|
|
128791
|
-
const PAGE_SIZE = 1e3;
|
|
128792
|
-
for (let offset = 0; ; offset += PAGE_SIZE) {
|
|
128793
|
-
const entries = storage.listVersions(scope, { limit: PAGE_SIZE, offset });
|
|
128794
|
-
syncedVersions += entries.filter((e10) => e10.dataPointId !== null).length;
|
|
128795
|
-
if (entries.length < PAGE_SIZE)
|
|
128796
|
-
break;
|
|
128797
|
-
}
|
|
128798
|
-
if (syncedVersions > 0) {
|
|
128799
|
-
logger.warn({ scope, syncedVersions }, "Remote scope deletion is not supported on the DPv2 gateway (no de-registration endpoint); local data was removed but the remote data point(s) and ciphertext blob(s) remain");
|
|
128800
|
-
}
|
|
128801
|
-
return {
|
|
128802
|
-
scope,
|
|
128803
|
-
filesDeregistered: 0,
|
|
128804
|
-
blobsDeleted: 0,
|
|
128805
|
-
errors: []
|
|
128806
|
-
};
|
|
128807
|
-
}
|
|
128808
|
-
|
|
128809
129719
|
// ../core/dist/sync/engine/sync-manager.js
|
|
128810
129720
|
var MAX_ERRORS = 10;
|
|
128811
129721
|
function createSyncManager(uploadDeps, downloadDeps, options) {
|
|
@@ -128823,12 +129733,28 @@ function createSyncManager(uploadDeps, downloadDeps, options) {
|
|
|
128823
129733
|
let rerunRequested = false;
|
|
128824
129734
|
let needsFullReconcile = true;
|
|
128825
129735
|
const downloadRetryMemory = createDownloadRetryMemory();
|
|
129736
|
+
const dataPointFeed = downloadDeps.dataPointFeed ?? uploadDeps.dataPointFeed;
|
|
129737
|
+
const scopeDeletions = uploadDeps.scopeDeletions ?? downloadDeps.scopeDeletions;
|
|
129738
|
+
const workerUploadDeps = {
|
|
129739
|
+
...uploadDeps,
|
|
129740
|
+
pendingBlobDeletions: uploadDeps.pendingBlobDeletions ?? options?.pendingBlobDeletions
|
|
129741
|
+
};
|
|
129742
|
+
const workerDownloadDeps = {
|
|
129743
|
+
...downloadDeps,
|
|
129744
|
+
pendingBlobDeletions: downloadDeps.pendingBlobDeletions ?? options?.pendingBlobDeletions
|
|
129745
|
+
};
|
|
129746
|
+
let mutationQueue = Promise.resolve();
|
|
129747
|
+
function exclusive(operation) {
|
|
129748
|
+
const run = mutationQueue.then(operation, operation);
|
|
129749
|
+
mutationQueue = run.catch(() => void 0);
|
|
129750
|
+
return run;
|
|
129751
|
+
}
|
|
128826
129752
|
async function runCycle() {
|
|
128827
129753
|
if (cycleInFlight) {
|
|
128828
129754
|
rerunRequested = true;
|
|
128829
129755
|
return cycleInFlight;
|
|
128830
129756
|
}
|
|
128831
|
-
cycleInFlight = (async () => {
|
|
129757
|
+
cycleInFlight = exclusive(async () => {
|
|
128832
129758
|
do {
|
|
128833
129759
|
rerunRequested = false;
|
|
128834
129760
|
const canRun = await (options?.canSync?.() ?? { ok: true });
|
|
@@ -128839,7 +129765,19 @@ function createSyncManager(uploadDeps, downloadDeps, options) {
|
|
|
128839
129765
|
}
|
|
128840
129766
|
blocked = null;
|
|
128841
129767
|
try {
|
|
128842
|
-
|
|
129768
|
+
await retryPendingBlobDeletions({
|
|
129769
|
+
deleteData: options?.deleteData,
|
|
129770
|
+
pendingBlobDeletions: options?.pendingBlobDeletions,
|
|
129771
|
+
dataPointFeed,
|
|
129772
|
+
serverOwner: uploadDeps.serverOwner,
|
|
129773
|
+
storage: uploadDeps.storage,
|
|
129774
|
+
logger: uploadDeps.logger
|
|
129775
|
+
});
|
|
129776
|
+
} catch (err2) {
|
|
129777
|
+
uploadDeps.logger.warn({ error: err2.message }, "Pending blob deletion retry failed");
|
|
129778
|
+
}
|
|
129779
|
+
try {
|
|
129780
|
+
const uploadResults = await uploadAll(workerUploadDeps, {
|
|
128843
129781
|
batchSize: uploadBatchSize,
|
|
128844
129782
|
onError(entry, error51) {
|
|
128845
129783
|
pushError({
|
|
@@ -128863,7 +129801,7 @@ function createSyncManager(uploadDeps, downloadDeps, options) {
|
|
|
128863
129801
|
}
|
|
128864
129802
|
try {
|
|
128865
129803
|
const fullReconcile = needsFullReconcile;
|
|
128866
|
-
const downloadResults = await downloadAll(
|
|
129804
|
+
const downloadResults = await downloadAll(workerDownloadDeps, {
|
|
128867
129805
|
fullReconcile,
|
|
128868
129806
|
retryMemory: downloadRetryMemory
|
|
128869
129807
|
});
|
|
@@ -128885,7 +129823,7 @@ function createSyncManager(uploadDeps, downloadDeps, options) {
|
|
|
128885
129823
|
}
|
|
128886
129824
|
lastSync = (/* @__PURE__ */ new Date()).toISOString();
|
|
128887
129825
|
} while (rerunRequested && isRunning);
|
|
128888
|
-
})
|
|
129826
|
+
});
|
|
128889
129827
|
try {
|
|
128890
129828
|
await cycleInFlight;
|
|
128891
129829
|
} finally {
|
|
@@ -128974,13 +129912,291 @@ function createSyncManager(uploadDeps, downloadDeps, options) {
|
|
|
128974
129912
|
uploadDeps.logger.debug("New data notification received");
|
|
128975
129913
|
scheduleNotifiedCycle();
|
|
128976
129914
|
},
|
|
128977
|
-
|
|
128978
|
-
|
|
129915
|
+
deleteScope(scope) {
|
|
129916
|
+
return exclusive(() => deleteScope({
|
|
129917
|
+
storage: uploadDeps.storage,
|
|
129918
|
+
serverOwner: uploadDeps.serverOwner,
|
|
129919
|
+
deleteData: options?.deleteData,
|
|
129920
|
+
pendingBlobDeletions: options?.pendingBlobDeletions,
|
|
129921
|
+
scopeDeletions,
|
|
129922
|
+
dataPointFeed,
|
|
129923
|
+
logger: uploadDeps.logger
|
|
129924
|
+
}, scope));
|
|
128979
129925
|
}
|
|
128980
129926
|
};
|
|
128981
129927
|
return manager;
|
|
128982
129928
|
}
|
|
128983
129929
|
|
|
129930
|
+
// ../core/dist/sync/delete-data-port.js
|
|
129931
|
+
function createGatewayDeleteDataPort(options) {
|
|
129932
|
+
const gatewayBase = options.gatewayUrl.replace(/\/+$/, "");
|
|
129933
|
+
const storageBase = options.storage.endpoint.replace(/\/+$/, "");
|
|
129934
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
129935
|
+
const owner = options.serverOwner.toLowerCase();
|
|
129936
|
+
async function sendTombstone(scope, dataPointId, version4) {
|
|
129937
|
+
const signature = await options.signer.signAddData({
|
|
129938
|
+
ownerAddress: options.serverOwner,
|
|
129939
|
+
scope,
|
|
129940
|
+
dataHash: TOMBSTONE_DATA_HASH,
|
|
129941
|
+
metadataHash: TOMBSTONE_METADATA_HASH,
|
|
129942
|
+
expectedVersion: version4
|
|
129943
|
+
});
|
|
129944
|
+
return fetchImpl(`${gatewayBase}/v1/data/${dataPointId}`, {
|
|
129945
|
+
method: "DELETE",
|
|
129946
|
+
headers: {
|
|
129947
|
+
"Content-Type": "application/json",
|
|
129948
|
+
Authorization: `Web3Signed ${signature}`
|
|
129949
|
+
},
|
|
129950
|
+
body: JSON.stringify({
|
|
129951
|
+
ownerAddress: options.serverOwner,
|
|
129952
|
+
scope,
|
|
129953
|
+
expectedVersion: String(version4),
|
|
129954
|
+
signature
|
|
129955
|
+
})
|
|
129956
|
+
});
|
|
129957
|
+
}
|
|
129958
|
+
return {
|
|
129959
|
+
async tombstone(scope) {
|
|
129960
|
+
const dataPointId = computeDataPointId(options.serverOwner, scope);
|
|
129961
|
+
const current = await options.dataPointFeed.getDataPoint({
|
|
129962
|
+
ownerAddress: options.serverOwner,
|
|
129963
|
+
scope
|
|
129964
|
+
});
|
|
129965
|
+
if (current === null) {
|
|
129966
|
+
return { status: "not-registered", dataPointId };
|
|
129967
|
+
}
|
|
129968
|
+
if (current.deletedAt !== null) {
|
|
129969
|
+
return {
|
|
129970
|
+
status: "already-deleted",
|
|
129971
|
+
dataPointId,
|
|
129972
|
+
version: current.expectedVersion,
|
|
129973
|
+
deletedAt: current.deletedAt
|
|
129974
|
+
};
|
|
129975
|
+
}
|
|
129976
|
+
let version4 = BigInt(current.expectedVersion) + 1n;
|
|
129977
|
+
let res = await sendTombstone(scope, dataPointId, version4);
|
|
129978
|
+
if (res.status === 409) {
|
|
129979
|
+
const body2 = await res.json().catch(() => null);
|
|
129980
|
+
const conflict = unwrap2(body2);
|
|
129981
|
+
const nextExplicit = integerField(conflict, "nextExpectedVersion") ?? integerField(body2, "nextExpectedVersion");
|
|
129982
|
+
const currentExpected = integerField(conflict, "currentExpectedVersion") ?? integerField(body2, "currentExpectedVersion");
|
|
129983
|
+
const legacyNext = parseGatewayNextVersion(detailFromBody(body2, res.statusText));
|
|
129984
|
+
const next = nextExplicit !== null ? nextExplicit : currentExpected !== null ? currentExpected + 1n : legacyNext !== null ? BigInt(legacyNext) : null;
|
|
129985
|
+
if (next === null) {
|
|
129986
|
+
throw new Error(`Gateway error: 409 ${detailFromBody(body2, res.statusText)}`);
|
|
129987
|
+
}
|
|
129988
|
+
version4 = next;
|
|
129989
|
+
res = await sendTombstone(scope, dataPointId, version4);
|
|
129990
|
+
}
|
|
129991
|
+
if (res.status === 404) {
|
|
129992
|
+
return { status: "not-registered", dataPointId };
|
|
129993
|
+
}
|
|
129994
|
+
if (res.status === 410) {
|
|
129995
|
+
const body2 = await res.json().catch(() => null);
|
|
129996
|
+
const echoed = unwrap2(body2);
|
|
129997
|
+
let winning = normalizeVersionString(stringField2(echoed, "expectedVersion"));
|
|
129998
|
+
let deletedAt = stringField2(echoed, "deletedAt");
|
|
129999
|
+
if (winning === null) {
|
|
130000
|
+
const reread = await options.dataPointFeed.getDataPoint({ ownerAddress: options.serverOwner, scope }).catch(() => null);
|
|
130001
|
+
if (reread && reread.deletedAt !== null) {
|
|
130002
|
+
winning = normalizeVersionString(reread.expectedVersion);
|
|
130003
|
+
deletedAt = deletedAt ?? reread.deletedAt;
|
|
130004
|
+
}
|
|
130005
|
+
}
|
|
130006
|
+
return {
|
|
130007
|
+
status: "already-deleted",
|
|
130008
|
+
dataPointId,
|
|
130009
|
+
version: winning,
|
|
130010
|
+
deletedAt
|
|
130011
|
+
};
|
|
130012
|
+
}
|
|
130013
|
+
if (!res.ok) {
|
|
130014
|
+
throw new Error(`Gateway error: ${res.status} ${await errorDetail(res)}`);
|
|
130015
|
+
}
|
|
130016
|
+
const body = await res.json().catch(() => null);
|
|
130017
|
+
const row = unwrap2(body);
|
|
130018
|
+
return {
|
|
130019
|
+
status: "tombstoned",
|
|
130020
|
+
dataPointId: stringField2(row, "dataPointId") ?? dataPointId,
|
|
130021
|
+
version: stringField2(row, "expectedVersion") ?? String(version4),
|
|
130022
|
+
deletedAt: stringField2(row, "deletedAt")
|
|
130023
|
+
};
|
|
130024
|
+
},
|
|
130025
|
+
async deleteBlobVersions(scope, versions) {
|
|
130026
|
+
const outcome = {
|
|
130027
|
+
deleted: [],
|
|
130028
|
+
missing: [],
|
|
130029
|
+
failed: []
|
|
130030
|
+
};
|
|
130031
|
+
for (const version4 of versions) {
|
|
130032
|
+
const path = `/v1/chains/${options.storage.chainId}/blobs/${owner}/${encodeURIComponent(scope)}/${encodeURIComponent(version4)}`;
|
|
130033
|
+
try {
|
|
130034
|
+
const authorization = await buildWeb3SignedHeader({
|
|
130035
|
+
signMessage: (message) => options.storage.signMessage(message),
|
|
130036
|
+
aud: storageBase,
|
|
130037
|
+
method: "DELETE",
|
|
130038
|
+
uri: path
|
|
130039
|
+
});
|
|
130040
|
+
const res = await fetchImpl(`${storageBase}${path}`, {
|
|
130041
|
+
method: "DELETE",
|
|
130042
|
+
headers: { authorization }
|
|
130043
|
+
});
|
|
130044
|
+
if (res.status === 404) {
|
|
130045
|
+
outcome.missing.push(version4);
|
|
130046
|
+
} else if (res.ok) {
|
|
130047
|
+
outcome.deleted.push(version4);
|
|
130048
|
+
} else {
|
|
130049
|
+
outcome.failed.push({
|
|
130050
|
+
version: version4,
|
|
130051
|
+
error: `vana-storage delete failed: ${res.status} ${res.statusText}`
|
|
130052
|
+
});
|
|
130053
|
+
}
|
|
130054
|
+
} catch (err2) {
|
|
130055
|
+
outcome.failed.push({
|
|
130056
|
+
version: version4,
|
|
130057
|
+
error: err2 instanceof Error ? err2.message : String(err2)
|
|
130058
|
+
});
|
|
130059
|
+
}
|
|
130060
|
+
}
|
|
130061
|
+
return outcome;
|
|
130062
|
+
}
|
|
130063
|
+
};
|
|
130064
|
+
}
|
|
130065
|
+
async function errorDetail(res) {
|
|
130066
|
+
const body = await res.json().catch(() => null);
|
|
130067
|
+
return detailFromBody(body, res.statusText);
|
|
130068
|
+
}
|
|
130069
|
+
function detailFromBody(body, fallback) {
|
|
130070
|
+
if (typeof body === "object" && body !== null) {
|
|
130071
|
+
const record2 = body;
|
|
130072
|
+
if (typeof record2.error === "string")
|
|
130073
|
+
return record2.error;
|
|
130074
|
+
if (typeof record2.message === "string")
|
|
130075
|
+
return record2.message;
|
|
130076
|
+
if (typeof record2.error === "object" && record2.error !== null) {
|
|
130077
|
+
const nested = record2.error;
|
|
130078
|
+
if (typeof nested.message === "string")
|
|
130079
|
+
return nested.message;
|
|
130080
|
+
}
|
|
130081
|
+
}
|
|
130082
|
+
return fallback;
|
|
130083
|
+
}
|
|
130084
|
+
function normalizeVersionString(value) {
|
|
130085
|
+
if (value === null || !/^\d+$/.test(value))
|
|
130086
|
+
return null;
|
|
130087
|
+
const parsed = BigInt(value);
|
|
130088
|
+
return parsed > 0n ? parsed.toString() : null;
|
|
130089
|
+
}
|
|
130090
|
+
function integerField(record2, key) {
|
|
130091
|
+
if (typeof record2 !== "object" || record2 === null)
|
|
130092
|
+
return null;
|
|
130093
|
+
const value = record2[key];
|
|
130094
|
+
if (typeof value === "number" && Number.isSafeInteger(value)) {
|
|
130095
|
+
return BigInt(value);
|
|
130096
|
+
}
|
|
130097
|
+
if (typeof value === "string" && /^\d+$/.test(value))
|
|
130098
|
+
return BigInt(value);
|
|
130099
|
+
return null;
|
|
130100
|
+
}
|
|
130101
|
+
function unwrap2(body) {
|
|
130102
|
+
if (typeof body !== "object" || body === null)
|
|
130103
|
+
return null;
|
|
130104
|
+
const record2 = body;
|
|
130105
|
+
if (typeof record2.data === "object" && record2.data !== null) {
|
|
130106
|
+
return record2.data;
|
|
130107
|
+
}
|
|
130108
|
+
return record2;
|
|
130109
|
+
}
|
|
130110
|
+
function stringField2(record2, key) {
|
|
130111
|
+
const value = record2?.[key];
|
|
130112
|
+
return typeof value === "string" ? value : null;
|
|
130113
|
+
}
|
|
130114
|
+
|
|
130115
|
+
// ../core/dist/sync/pending-blob-deletions.js
|
|
130116
|
+
function markerId(key) {
|
|
130117
|
+
const range = key.range ? `${key.range.from}-${key.range.to}` : "";
|
|
130118
|
+
return `${key.scope}\0${key.version ?? ""}\0${range}`;
|
|
130119
|
+
}
|
|
130120
|
+
function normalizeRange(value) {
|
|
130121
|
+
if (typeof value !== "object" || value === null)
|
|
130122
|
+
return void 0;
|
|
130123
|
+
const { from, to: to3 } = value;
|
|
130124
|
+
if (typeof from !== "string" || typeof to3 !== "string" || !/^\d+$/.test(from) || !/^\d+$/.test(to3) || BigInt(from) > BigInt(to3)) {
|
|
130125
|
+
return void 0;
|
|
130126
|
+
}
|
|
130127
|
+
return { from, to: to3 };
|
|
130128
|
+
}
|
|
130129
|
+
function normalizePendingBlobDeletions(stored) {
|
|
130130
|
+
if (!Array.isArray(stored))
|
|
130131
|
+
return [];
|
|
130132
|
+
const keys = [];
|
|
130133
|
+
for (const item of stored) {
|
|
130134
|
+
if (typeof item === "string") {
|
|
130135
|
+
keys.push({ scope: item, version: null });
|
|
130136
|
+
} else if (typeof item === "object" && item !== null && typeof item.scope === "string") {
|
|
130137
|
+
const version4 = item.version;
|
|
130138
|
+
const range = typeof version4 === "string" ? void 0 : normalizeRange(item.range);
|
|
130139
|
+
keys.push({
|
|
130140
|
+
scope: item.scope,
|
|
130141
|
+
version: typeof version4 === "string" ? version4 : null,
|
|
130142
|
+
...range ? { range } : {}
|
|
130143
|
+
});
|
|
130144
|
+
}
|
|
130145
|
+
}
|
|
130146
|
+
return keys;
|
|
130147
|
+
}
|
|
130148
|
+
function createPendingBlobDeletionStore(kv) {
|
|
130149
|
+
let queue = Promise.resolve();
|
|
130150
|
+
function serialized(operation) {
|
|
130151
|
+
const run = queue.then(operation, operation);
|
|
130152
|
+
queue = run.catch(() => void 0);
|
|
130153
|
+
return run;
|
|
130154
|
+
}
|
|
130155
|
+
async function current() {
|
|
130156
|
+
return normalizePendingBlobDeletions(await kv.read());
|
|
130157
|
+
}
|
|
130158
|
+
return {
|
|
130159
|
+
list() {
|
|
130160
|
+
return serialized(current);
|
|
130161
|
+
},
|
|
130162
|
+
add(keys) {
|
|
130163
|
+
return serialized(async () => {
|
|
130164
|
+
if (keys.length === 0)
|
|
130165
|
+
return;
|
|
130166
|
+
const existing = await current();
|
|
130167
|
+
const known = new Set(existing.map(markerId));
|
|
130168
|
+
const next = [...existing];
|
|
130169
|
+
for (const key of keys) {
|
|
130170
|
+
const id2 = markerId(key);
|
|
130171
|
+
if (known.has(id2))
|
|
130172
|
+
continue;
|
|
130173
|
+
known.add(id2);
|
|
130174
|
+
next.push({
|
|
130175
|
+
scope: key.scope,
|
|
130176
|
+
version: key.version,
|
|
130177
|
+
...key.range ? { range: { ...key.range } } : {}
|
|
130178
|
+
});
|
|
130179
|
+
}
|
|
130180
|
+
if (next.length === existing.length)
|
|
130181
|
+
return;
|
|
130182
|
+
await kv.write(next);
|
|
130183
|
+
});
|
|
130184
|
+
},
|
|
130185
|
+
remove(keys) {
|
|
130186
|
+
return serialized(async () => {
|
|
130187
|
+
if (keys.length === 0)
|
|
130188
|
+
return;
|
|
130189
|
+
const existing = await current();
|
|
130190
|
+
const gone = new Set(keys.map(markerId));
|
|
130191
|
+
const next = existing.filter((key) => !gone.has(markerId(key)));
|
|
130192
|
+
if (next.length === existing.length)
|
|
130193
|
+
return;
|
|
130194
|
+
await kv.write(next);
|
|
130195
|
+
});
|
|
130196
|
+
}
|
|
130197
|
+
};
|
|
130198
|
+
}
|
|
130199
|
+
|
|
128984
130200
|
// ../core/dist/storage/adapters/sdk.js
|
|
128985
130201
|
function createSdkStorageAdapter(providerOrFactory, options) {
|
|
128986
130202
|
let cachedProvider;
|
|
@@ -129041,8 +130257,11 @@ function copyBytes(data) {
|
|
|
129041
130257
|
|
|
129042
130258
|
// ../core/dist/storage/adapters/vana.js
|
|
129043
130259
|
var DEFAULT_VANA_STORAGE_ENDPOINT = "https://storage.vana.org";
|
|
130260
|
+
function resolveVanaStorageEndpoint(config2) {
|
|
130261
|
+
return (config2.storage.config.vana?.apiUrl ?? DEFAULT_VANA_STORAGE_ENDPOINT).replace(/\/+$/, "");
|
|
130262
|
+
}
|
|
129044
130263
|
function createVanaSyncStorageAdapter(params) {
|
|
129045
|
-
const endpoint = (params.config
|
|
130264
|
+
const endpoint = resolveVanaStorageEndpoint(params.config);
|
|
129046
130265
|
const owner = params.serverOwner.toLowerCase();
|
|
129047
130266
|
const chainId = params.config.gateway.chainId;
|
|
129048
130267
|
return createSdkStorageAdapter(createVanaStorageProvider({
|
|
@@ -129097,6 +130316,7 @@ async function resolvePsLiteOwner(input) {
|
|
|
129097
130316
|
|
|
129098
130317
|
// ../lite/dist/sync.js
|
|
129099
130318
|
var SYNC_CURSOR_KEY = "sync-cursor-v1";
|
|
130319
|
+
var PENDING_BLOB_DELETIONS_KEY = "pending-blob-deletions-v1";
|
|
129100
130320
|
function createBrowserLogger(logger) {
|
|
129101
130321
|
const fallback = {
|
|
129102
130322
|
info: console.info.bind(console),
|
|
@@ -129127,6 +130347,19 @@ function createPsLiteSyncCursor(stateStore) {
|
|
|
129127
130347
|
}
|
|
129128
130348
|
};
|
|
129129
130349
|
}
|
|
130350
|
+
function createPsLitePendingBlobDeletionStore(stateStore) {
|
|
130351
|
+
return createPendingBlobDeletionStore({
|
|
130352
|
+
async read() {
|
|
130353
|
+
const state = await stateStore.get(PENDING_BLOB_DELETIONS_KEY);
|
|
130354
|
+
if (!state)
|
|
130355
|
+
return null;
|
|
130356
|
+
return normalizePendingBlobDeletions(state.keys ?? state.scopes);
|
|
130357
|
+
},
|
|
130358
|
+
async write(keys) {
|
|
130359
|
+
await stateStore.set(PENDING_BLOB_DELETIONS_KEY, { keys });
|
|
130360
|
+
}
|
|
130361
|
+
});
|
|
130362
|
+
}
|
|
129130
130363
|
function buildDownloadDiagnosticsHook(recorder) {
|
|
129131
130364
|
return {
|
|
129132
130365
|
onDownloadStart(fileId) {
|
|
@@ -129212,6 +130445,20 @@ async function createPsLiteSyncManager(options) {
|
|
|
129212
130445
|
});
|
|
129213
130446
|
const cursor = createPsLiteSyncCursor(options.stateStore);
|
|
129214
130447
|
const logger = createBrowserLogger(options.logger);
|
|
130448
|
+
const dataPointFeed = options.dataPointFeed ?? createGatewayDataPointFeed({ gatewayUrl: options.config.gateway.url });
|
|
130449
|
+
const scopeDeletions = options.scopeDeletions ?? createScopeDeletionTracker({ feed: dataPointFeed, serverOwner, logger });
|
|
130450
|
+
const deleteData = createGatewayDeleteDataPort({
|
|
130451
|
+
gatewayUrl: options.config.gateway.url,
|
|
130452
|
+
dataPointFeed,
|
|
130453
|
+
serverOwner,
|
|
130454
|
+
signer,
|
|
130455
|
+
storage: {
|
|
130456
|
+
endpoint: resolveVanaStorageEndpoint(options.config),
|
|
130457
|
+
chainId: options.config.gateway.chainId,
|
|
130458
|
+
signMessage: (message) => options.serverAccount.signMessage(message)
|
|
130459
|
+
}
|
|
130460
|
+
});
|
|
130461
|
+
const pendingBlobDeletions = createPsLitePendingBlobDeletionStore(options.stateStore);
|
|
129215
130462
|
const downloadDiagnostics = options.diagnostics ? buildDownloadDiagnosticsHook(options.diagnostics) : void 0;
|
|
129216
130463
|
const syncManager = createSyncManager({
|
|
129217
130464
|
storage: options.storage,
|
|
@@ -129221,7 +130468,9 @@ async function createPsLiteSyncManager(options) {
|
|
|
129221
130468
|
masterKey,
|
|
129222
130469
|
serverOwner,
|
|
129223
130470
|
logger,
|
|
129224
|
-
lineageGateway: options.lineageGateway
|
|
130471
|
+
lineageGateway: options.lineageGateway,
|
|
130472
|
+
dataPointFeed,
|
|
130473
|
+
scopeDeletions
|
|
129225
130474
|
}, {
|
|
129226
130475
|
storage: options.storage,
|
|
129227
130476
|
storageAdapter,
|
|
@@ -129230,8 +130479,12 @@ async function createPsLiteSyncManager(options) {
|
|
|
129230
130479
|
masterKey,
|
|
129231
130480
|
serverOwner,
|
|
129232
130481
|
logger,
|
|
129233
|
-
diagnostics: downloadDiagnostics
|
|
130482
|
+
diagnostics: downloadDiagnostics,
|
|
130483
|
+
dataPointFeed,
|
|
130484
|
+
scopeDeletions
|
|
129234
130485
|
}, {
|
|
130486
|
+
deleteData,
|
|
130487
|
+
pendingBlobDeletions,
|
|
129235
130488
|
async canSync() {
|
|
129236
130489
|
try {
|
|
129237
130490
|
const serverInfo = await gateway.getServer(options.serverAccount.address);
|
|
@@ -129253,7 +130506,7 @@ async function createPsLiteSyncManager(options) {
|
|
|
129253
130506
|
}
|
|
129254
130507
|
});
|
|
129255
130508
|
syncManager.start();
|
|
129256
|
-
return { syncManager, serverOwner };
|
|
130509
|
+
return { syncManager, serverOwner, dataPointFeed, scopeDeletions };
|
|
129257
130510
|
}
|
|
129258
130511
|
|
|
129259
130512
|
// ../lite/dist/persistence.js
|
|
@@ -129319,8 +130572,9 @@ async function createIndexedDbPsLiteRuntime(options) {
|
|
|
129319
130572
|
requestSigner: createRequestSigner(identity.account)
|
|
129320
130573
|
});
|
|
129321
130574
|
let syncManager = options.syncManager ?? null;
|
|
130575
|
+
let scopeDeletions = options.scopeDeletions;
|
|
129322
130576
|
if (!syncManager && config2.sync.enabled) {
|
|
129323
|
-
|
|
130577
|
+
const sync = await createPsLiteSyncManager({
|
|
129324
130578
|
config: config2,
|
|
129325
130579
|
stateStore,
|
|
129326
130580
|
storage,
|
|
@@ -129328,10 +130582,14 @@ async function createIndexedDbPsLiteRuntime(options) {
|
|
|
129328
130582
|
ownerAddress: options.ownerAddress,
|
|
129329
130583
|
serverAccount: identity.account,
|
|
129330
130584
|
gateway,
|
|
130585
|
+
dataPointFeed: options.dataPointFeed,
|
|
130586
|
+
scopeDeletions,
|
|
129331
130587
|
diagnostics,
|
|
129332
130588
|
logger: options.logger,
|
|
129333
130589
|
lineageGateway
|
|
129334
|
-
})
|
|
130590
|
+
});
|
|
130591
|
+
syncManager = sync.syncManager;
|
|
130592
|
+
scopeDeletions = sync.scopeDeletions;
|
|
129335
130593
|
}
|
|
129336
130594
|
let runtimeRef = null;
|
|
129337
130595
|
const auth = options.auth ?? createWeb3SignedPsLiteAuth({
|
|
@@ -129360,6 +130618,7 @@ async function createIndexedDbPsLiteRuntime(options) {
|
|
|
129360
130618
|
serverOwner,
|
|
129361
130619
|
serverSigner,
|
|
129362
130620
|
syncManager,
|
|
130621
|
+
scopeDeletions,
|
|
129363
130622
|
diagnostics,
|
|
129364
130623
|
lineageGateway,
|
|
129365
130624
|
saveConfig: async (nextConfig) => {
|