tablinum 0.7.0 → 0.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/index.js +101 -27
- package/dist/svelte/index.svelte.js +101 -27
- package/dist/sync/deletion.d.ts +10 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -547,30 +547,6 @@ function resolveWinner(existing, incoming) {
|
|
|
547
547
|
function isPlainObject(value) {
|
|
548
548
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
549
549
|
}
|
|
550
|
-
function deepDiff(before, after) {
|
|
551
|
-
const result = {};
|
|
552
|
-
let hasChanges = false;
|
|
553
|
-
for (const key of Object.keys(after)) {
|
|
554
|
-
const a = before[key];
|
|
555
|
-
const b = after[key];
|
|
556
|
-
if (isPlainObject(a) && isPlainObject(b)) {
|
|
557
|
-
const nested = deepDiff(a, b);
|
|
558
|
-
if (nested !== null) {
|
|
559
|
-
result[key] = nested;
|
|
560
|
-
hasChanges = true;
|
|
561
|
-
}
|
|
562
|
-
} else if (Array.isArray(a) && Array.isArray(b)) {
|
|
563
|
-
if (JSON.stringify(a) !== JSON.stringify(b)) {
|
|
564
|
-
result[key] = b;
|
|
565
|
-
hasChanges = true;
|
|
566
|
-
}
|
|
567
|
-
} else if (a !== b) {
|
|
568
|
-
result[key] = b;
|
|
569
|
-
hasChanges = true;
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
return hasChanges ? result : null;
|
|
573
|
-
}
|
|
574
550
|
function deepMerge(target, source) {
|
|
575
551
|
const result = { ...target };
|
|
576
552
|
for (const key of Object.keys(source)) {
|
|
@@ -1056,13 +1032,12 @@ function createCollectionHandle(def, storage, watchCtx, validator, partialValida
|
|
|
1056
1032
|
const { _d, _u, _a, _e, ...existingFields } = existing;
|
|
1057
1033
|
const merged = { ...existingFields, ...data, id };
|
|
1058
1034
|
yield* validator(merged);
|
|
1059
|
-
const diff = deepDiff(existingFields, merged);
|
|
1060
1035
|
const event = {
|
|
1061
1036
|
id: makeEventId(),
|
|
1062
1037
|
collection: collectionName,
|
|
1063
1038
|
recordId: id,
|
|
1064
1039
|
kind: "u",
|
|
1065
|
-
data:
|
|
1040
|
+
data: merged,
|
|
1066
1041
|
createdAt: Date.now(),
|
|
1067
1042
|
author: localAuthor
|
|
1068
1043
|
};
|
|
@@ -1070,7 +1045,7 @@ function createCollectionHandle(def, storage, watchCtx, validator, partialValida
|
|
|
1070
1045
|
yield* Effect7.logDebug("Record updated", {
|
|
1071
1046
|
collection: collectionName,
|
|
1072
1047
|
recordId: id,
|
|
1073
|
-
data:
|
|
1048
|
+
data: merged
|
|
1074
1049
|
});
|
|
1075
1050
|
yield* pruneEvents(storage, collectionName, id, def.eventRetention);
|
|
1076
1051
|
})
|
|
@@ -2227,6 +2202,20 @@ function fetchAuthorProfile(relay, relayUrls, pubkey) {
|
|
|
2227
2202
|
});
|
|
2228
2203
|
}
|
|
2229
2204
|
|
|
2205
|
+
// src/sync/deletion.ts
|
|
2206
|
+
import { finalizeEvent } from "nostr-tools/pure";
|
|
2207
|
+
function createDeletionEvent(targetEventIds, signingKey) {
|
|
2208
|
+
return finalizeEvent(
|
|
2209
|
+
{
|
|
2210
|
+
kind: 5,
|
|
2211
|
+
content: "",
|
|
2212
|
+
tags: targetEventIds.map((id) => ["e", id]),
|
|
2213
|
+
created_at: Math.floor(Date.now() / 1e3)
|
|
2214
|
+
},
|
|
2215
|
+
signingKey
|
|
2216
|
+
);
|
|
2217
|
+
}
|
|
2218
|
+
|
|
2230
2219
|
// src/services/Identity.ts
|
|
2231
2220
|
import { ServiceMap as ServiceMap3 } from "effect";
|
|
2232
2221
|
var Identity = class extends ServiceMap3.Service()("tablinum/Identity") {
|
|
@@ -2916,6 +2905,12 @@ var TablinumLive = Layer9.effect(
|
|
|
2916
2905
|
}
|
|
2917
2906
|
const gw = wrapResult.success;
|
|
2918
2907
|
yield* storage.putGiftWrap({ id: gw.id, event: gw, createdAt: gw.created_at });
|
|
2908
|
+
const metaKey = `gw_record:${event.collection}:${event.recordId}`;
|
|
2909
|
+
const prevMapping = yield* storage.getMeta(metaKey).pipe(
|
|
2910
|
+
Effect21.orElseSucceed(() => void 0)
|
|
2911
|
+
);
|
|
2912
|
+
const epochPubKey = gw.tags.find((t) => t[0] === "p")?.[1];
|
|
2913
|
+
yield* storage.putMeta(metaKey, { gwId: gw.id, epochPubKey });
|
|
2919
2914
|
yield* Effect21.forkIn(
|
|
2920
2915
|
Effect21.gen(function* () {
|
|
2921
2916
|
const publishResult = yield* Effect21.result(
|
|
@@ -2928,10 +2923,80 @@ var TablinumLive = Layer9.effect(
|
|
|
2928
2923
|
if (publishResult._tag === "Failure") {
|
|
2929
2924
|
reportSyncError(config.onSyncError, publishResult.failure);
|
|
2930
2925
|
}
|
|
2926
|
+
if (prevMapping?.epochPubKey) {
|
|
2927
|
+
const signingKey = getDecryptionKey(epochStore, prevMapping.epochPubKey);
|
|
2928
|
+
if (signingKey) {
|
|
2929
|
+
const deletionEvent = createDeletionEvent(
|
|
2930
|
+
[prevMapping.gwId],
|
|
2931
|
+
signingKey
|
|
2932
|
+
);
|
|
2933
|
+
yield* relay.publish(deletionEvent, [...config.relays]).pipe(
|
|
2934
|
+
Effect21.tapError(
|
|
2935
|
+
(e) => Effect21.sync(() => reportSyncError(config.onSyncError, e))
|
|
2936
|
+
),
|
|
2937
|
+
Effect21.ignore
|
|
2938
|
+
);
|
|
2939
|
+
}
|
|
2940
|
+
yield* storage.deleteGiftWrap(prevMapping.gwId).pipe(Effect21.ignore);
|
|
2941
|
+
}
|
|
2931
2942
|
}),
|
|
2932
2943
|
scope
|
|
2933
2944
|
);
|
|
2934
2945
|
});
|
|
2946
|
+
const republishAllUnderCurrentEpoch = () => Effect21.gen(function* () {
|
|
2947
|
+
const oldGwDeletions = [];
|
|
2948
|
+
for (const [, def] of allSchemaEntries) {
|
|
2949
|
+
const collectionName = def.name;
|
|
2950
|
+
const allRecords = yield* storage.getAllRecords(collectionName);
|
|
2951
|
+
for (const record of allRecords) {
|
|
2952
|
+
const recordId = record.id;
|
|
2953
|
+
const { _d, _u, _a, _e, ...fields } = record;
|
|
2954
|
+
const content = _d ? JSON.stringify(null) : JSON.stringify(fields);
|
|
2955
|
+
const dTag = `${collectionName}:${recordId}`;
|
|
2956
|
+
const wrapResult = yield* Effect21.result(
|
|
2957
|
+
giftWrap.wrap({
|
|
2958
|
+
kind: 1,
|
|
2959
|
+
content,
|
|
2960
|
+
tags: [["d", dTag]],
|
|
2961
|
+
created_at: Math.floor(Date.now() / 1e3)
|
|
2962
|
+
})
|
|
2963
|
+
);
|
|
2964
|
+
if (wrapResult._tag === "Failure") continue;
|
|
2965
|
+
const gw = wrapResult.success;
|
|
2966
|
+
yield* storage.putGiftWrap({ id: gw.id, event: gw, createdAt: gw.created_at });
|
|
2967
|
+
const metaKey = `gw_record:${collectionName}:${recordId}`;
|
|
2968
|
+
const prevMapping = yield* storage.getMeta(metaKey).pipe(
|
|
2969
|
+
Effect21.orElseSucceed(() => void 0)
|
|
2970
|
+
);
|
|
2971
|
+
if (prevMapping) oldGwDeletions.push(prevMapping);
|
|
2972
|
+
const epochPubKey = gw.tags.find((t) => t[0] === "p")?.[1];
|
|
2973
|
+
yield* storage.putMeta(metaKey, { gwId: gw.id, epochPubKey });
|
|
2974
|
+
yield* relay.publish(gw, [...config.relays]).pipe(
|
|
2975
|
+
Effect21.tapError((e) => Effect21.sync(() => reportSyncError(config.onSyncError, e))),
|
|
2976
|
+
Effect21.ignore
|
|
2977
|
+
);
|
|
2978
|
+
}
|
|
2979
|
+
}
|
|
2980
|
+
const byEpoch = /* @__PURE__ */ new Map();
|
|
2981
|
+
for (const { gwId, epochPubKey } of oldGwDeletions) {
|
|
2982
|
+
const ids = byEpoch.get(epochPubKey) ?? [];
|
|
2983
|
+
ids.push(gwId);
|
|
2984
|
+
byEpoch.set(epochPubKey, ids);
|
|
2985
|
+
}
|
|
2986
|
+
for (const [epochPubKey, gwIds] of byEpoch) {
|
|
2987
|
+
const signingKey = getDecryptionKey(epochStore, epochPubKey);
|
|
2988
|
+
if (signingKey) {
|
|
2989
|
+
const deletionEvent = createDeletionEvent(gwIds, signingKey);
|
|
2990
|
+
yield* relay.publish(deletionEvent, [...config.relays]).pipe(
|
|
2991
|
+
Effect21.tapError((e) => Effect21.sync(() => reportSyncError(config.onSyncError, e))),
|
|
2992
|
+
Effect21.ignore
|
|
2993
|
+
);
|
|
2994
|
+
}
|
|
2995
|
+
for (const gwId of gwIds) {
|
|
2996
|
+
yield* storage.deleteGiftWrap(gwId).pipe(Effect21.ignore);
|
|
2997
|
+
}
|
|
2998
|
+
}
|
|
2999
|
+
});
|
|
2935
3000
|
const knownAuthors = /* @__PURE__ */ new Set();
|
|
2936
3001
|
const putMemberRecord = (record) => Effect21.gen(function* () {
|
|
2937
3002
|
const existing = yield* storage.getRecord("_members", record.id);
|
|
@@ -3019,6 +3084,13 @@ var TablinumLive = Layer9.effect(
|
|
|
3019
3084
|
addedInEpoch: getCurrentEpoch(epochStore).id
|
|
3020
3085
|
});
|
|
3021
3086
|
}
|
|
3087
|
+
const migrated = yield* storage.getMeta("migration_gw_republish").pipe(
|
|
3088
|
+
Effect21.orElseSucceed(() => void 0)
|
|
3089
|
+
);
|
|
3090
|
+
if (!migrated) {
|
|
3091
|
+
yield* republishAllUnderCurrentEpoch().pipe(Effect21.ignore);
|
|
3092
|
+
yield* storage.putMeta("migration_gw_republish", true);
|
|
3093
|
+
}
|
|
3022
3094
|
const withLog = (effect) => Effect21.provideService(effect, References3.MinimumLogLevel, config.logLevel);
|
|
3023
3095
|
const ensureOpen = (effect) => withLog(
|
|
3024
3096
|
Effect21.gen(function* () {
|
|
@@ -3098,6 +3170,7 @@ var TablinumLive = Layer9.effect(
|
|
|
3098
3170
|
removedAt: Date.now(),
|
|
3099
3171
|
removedInEpoch: result.epoch.id
|
|
3100
3172
|
});
|
|
3173
|
+
yield* republishAllUnderCurrentEpoch();
|
|
3101
3174
|
yield* Effect21.forEach(
|
|
3102
3175
|
result.wrappedEvents,
|
|
3103
3176
|
(wrappedEvent) => relay.publish(wrappedEvent, [...config.relays]).pipe(
|
|
@@ -3172,6 +3245,7 @@ var TablinumLive = Layer9.effect(
|
|
|
3172
3245
|
removedAt: Date.now(),
|
|
3173
3246
|
removedInEpoch: result.epoch.id
|
|
3174
3247
|
});
|
|
3248
|
+
yield* republishAllUnderCurrentEpoch();
|
|
3175
3249
|
yield* Effect21.forEach(
|
|
3176
3250
|
result.wrappedEvents,
|
|
3177
3251
|
(wrappedEvent) => relay.publish(wrappedEvent, [...config.relays]).pipe(
|
|
@@ -581,30 +581,6 @@ function resolveWinner(existing, incoming) {
|
|
|
581
581
|
function isPlainObject(value) {
|
|
582
582
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
583
583
|
}
|
|
584
|
-
function deepDiff(before, after) {
|
|
585
|
-
const result = {};
|
|
586
|
-
let hasChanges = false;
|
|
587
|
-
for (const key of Object.keys(after)) {
|
|
588
|
-
const a = before[key];
|
|
589
|
-
const b = after[key];
|
|
590
|
-
if (isPlainObject(a) && isPlainObject(b)) {
|
|
591
|
-
const nested = deepDiff(a, b);
|
|
592
|
-
if (nested !== null) {
|
|
593
|
-
result[key] = nested;
|
|
594
|
-
hasChanges = true;
|
|
595
|
-
}
|
|
596
|
-
} else if (Array.isArray(a) && Array.isArray(b)) {
|
|
597
|
-
if (JSON.stringify(a) !== JSON.stringify(b)) {
|
|
598
|
-
result[key] = b;
|
|
599
|
-
hasChanges = true;
|
|
600
|
-
}
|
|
601
|
-
} else if (a !== b) {
|
|
602
|
-
result[key] = b;
|
|
603
|
-
hasChanges = true;
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
return hasChanges ? result : null;
|
|
607
|
-
}
|
|
608
584
|
function deepMerge(target, source) {
|
|
609
585
|
const result = { ...target };
|
|
610
586
|
for (const key of Object.keys(source)) {
|
|
@@ -1090,13 +1066,12 @@ function createCollectionHandle(def, storage, watchCtx, validator, partialValida
|
|
|
1090
1066
|
const { _d, _u, _a, _e, ...existingFields } = existing;
|
|
1091
1067
|
const merged = { ...existingFields, ...data, id };
|
|
1092
1068
|
yield* validator(merged);
|
|
1093
|
-
const diff = deepDiff(existingFields, merged);
|
|
1094
1069
|
const event = {
|
|
1095
1070
|
id: makeEventId(),
|
|
1096
1071
|
collection: collectionName,
|
|
1097
1072
|
recordId: id,
|
|
1098
1073
|
kind: "u",
|
|
1099
|
-
data:
|
|
1074
|
+
data: merged,
|
|
1100
1075
|
createdAt: Date.now(),
|
|
1101
1076
|
author: localAuthor
|
|
1102
1077
|
};
|
|
@@ -1104,7 +1079,7 @@ function createCollectionHandle(def, storage, watchCtx, validator, partialValida
|
|
|
1104
1079
|
yield* Effect7.logDebug("Record updated", {
|
|
1105
1080
|
collection: collectionName,
|
|
1106
1081
|
recordId: id,
|
|
1107
|
-
data:
|
|
1082
|
+
data: merged
|
|
1108
1083
|
});
|
|
1109
1084
|
yield* pruneEvents(storage, collectionName, id, def.eventRetention);
|
|
1110
1085
|
})
|
|
@@ -2261,6 +2236,20 @@ function fetchAuthorProfile(relay, relayUrls, pubkey) {
|
|
|
2261
2236
|
});
|
|
2262
2237
|
}
|
|
2263
2238
|
|
|
2239
|
+
// src/sync/deletion.ts
|
|
2240
|
+
import { finalizeEvent } from "nostr-tools/pure";
|
|
2241
|
+
function createDeletionEvent(targetEventIds, signingKey) {
|
|
2242
|
+
return finalizeEvent(
|
|
2243
|
+
{
|
|
2244
|
+
kind: 5,
|
|
2245
|
+
content: "",
|
|
2246
|
+
tags: targetEventIds.map((id) => ["e", id]),
|
|
2247
|
+
created_at: Math.floor(Date.now() / 1e3)
|
|
2248
|
+
},
|
|
2249
|
+
signingKey
|
|
2250
|
+
);
|
|
2251
|
+
}
|
|
2252
|
+
|
|
2264
2253
|
// src/services/Identity.ts
|
|
2265
2254
|
import { ServiceMap as ServiceMap3 } from "effect";
|
|
2266
2255
|
var Identity = class extends ServiceMap3.Service()("tablinum/Identity") {
|
|
@@ -2950,6 +2939,12 @@ var TablinumLive = Layer9.effect(
|
|
|
2950
2939
|
}
|
|
2951
2940
|
const gw = wrapResult.success;
|
|
2952
2941
|
yield* storage.putGiftWrap({ id: gw.id, event: gw, createdAt: gw.created_at });
|
|
2942
|
+
const metaKey = `gw_record:${event.collection}:${event.recordId}`;
|
|
2943
|
+
const prevMapping = yield* storage.getMeta(metaKey).pipe(
|
|
2944
|
+
Effect21.orElseSucceed(() => void 0)
|
|
2945
|
+
);
|
|
2946
|
+
const epochPubKey = gw.tags.find((t) => t[0] === "p")?.[1];
|
|
2947
|
+
yield* storage.putMeta(metaKey, { gwId: gw.id, epochPubKey });
|
|
2953
2948
|
yield* Effect21.forkIn(
|
|
2954
2949
|
Effect21.gen(function* () {
|
|
2955
2950
|
const publishResult = yield* Effect21.result(
|
|
@@ -2962,10 +2957,80 @@ var TablinumLive = Layer9.effect(
|
|
|
2962
2957
|
if (publishResult._tag === "Failure") {
|
|
2963
2958
|
reportSyncError(config.onSyncError, publishResult.failure);
|
|
2964
2959
|
}
|
|
2960
|
+
if (prevMapping?.epochPubKey) {
|
|
2961
|
+
const signingKey = getDecryptionKey(epochStore, prevMapping.epochPubKey);
|
|
2962
|
+
if (signingKey) {
|
|
2963
|
+
const deletionEvent = createDeletionEvent(
|
|
2964
|
+
[prevMapping.gwId],
|
|
2965
|
+
signingKey
|
|
2966
|
+
);
|
|
2967
|
+
yield* relay.publish(deletionEvent, [...config.relays]).pipe(
|
|
2968
|
+
Effect21.tapError(
|
|
2969
|
+
(e) => Effect21.sync(() => reportSyncError(config.onSyncError, e))
|
|
2970
|
+
),
|
|
2971
|
+
Effect21.ignore
|
|
2972
|
+
);
|
|
2973
|
+
}
|
|
2974
|
+
yield* storage.deleteGiftWrap(prevMapping.gwId).pipe(Effect21.ignore);
|
|
2975
|
+
}
|
|
2965
2976
|
}),
|
|
2966
2977
|
scope
|
|
2967
2978
|
);
|
|
2968
2979
|
});
|
|
2980
|
+
const republishAllUnderCurrentEpoch = () => Effect21.gen(function* () {
|
|
2981
|
+
const oldGwDeletions = [];
|
|
2982
|
+
for (const [, def] of allSchemaEntries) {
|
|
2983
|
+
const collectionName = def.name;
|
|
2984
|
+
const allRecords = yield* storage.getAllRecords(collectionName);
|
|
2985
|
+
for (const record of allRecords) {
|
|
2986
|
+
const recordId = record.id;
|
|
2987
|
+
const { _d, _u, _a, _e, ...fields } = record;
|
|
2988
|
+
const content = _d ? JSON.stringify(null) : JSON.stringify(fields);
|
|
2989
|
+
const dTag = `${collectionName}:${recordId}`;
|
|
2990
|
+
const wrapResult = yield* Effect21.result(
|
|
2991
|
+
giftWrap.wrap({
|
|
2992
|
+
kind: 1,
|
|
2993
|
+
content,
|
|
2994
|
+
tags: [["d", dTag]],
|
|
2995
|
+
created_at: Math.floor(Date.now() / 1e3)
|
|
2996
|
+
})
|
|
2997
|
+
);
|
|
2998
|
+
if (wrapResult._tag === "Failure") continue;
|
|
2999
|
+
const gw = wrapResult.success;
|
|
3000
|
+
yield* storage.putGiftWrap({ id: gw.id, event: gw, createdAt: gw.created_at });
|
|
3001
|
+
const metaKey = `gw_record:${collectionName}:${recordId}`;
|
|
3002
|
+
const prevMapping = yield* storage.getMeta(metaKey).pipe(
|
|
3003
|
+
Effect21.orElseSucceed(() => void 0)
|
|
3004
|
+
);
|
|
3005
|
+
if (prevMapping) oldGwDeletions.push(prevMapping);
|
|
3006
|
+
const epochPubKey = gw.tags.find((t) => t[0] === "p")?.[1];
|
|
3007
|
+
yield* storage.putMeta(metaKey, { gwId: gw.id, epochPubKey });
|
|
3008
|
+
yield* relay.publish(gw, [...config.relays]).pipe(
|
|
3009
|
+
Effect21.tapError((e) => Effect21.sync(() => reportSyncError(config.onSyncError, e))),
|
|
3010
|
+
Effect21.ignore
|
|
3011
|
+
);
|
|
3012
|
+
}
|
|
3013
|
+
}
|
|
3014
|
+
const byEpoch = /* @__PURE__ */ new Map();
|
|
3015
|
+
for (const { gwId, epochPubKey } of oldGwDeletions) {
|
|
3016
|
+
const ids = byEpoch.get(epochPubKey) ?? [];
|
|
3017
|
+
ids.push(gwId);
|
|
3018
|
+
byEpoch.set(epochPubKey, ids);
|
|
3019
|
+
}
|
|
3020
|
+
for (const [epochPubKey, gwIds] of byEpoch) {
|
|
3021
|
+
const signingKey = getDecryptionKey(epochStore, epochPubKey);
|
|
3022
|
+
if (signingKey) {
|
|
3023
|
+
const deletionEvent = createDeletionEvent(gwIds, signingKey);
|
|
3024
|
+
yield* relay.publish(deletionEvent, [...config.relays]).pipe(
|
|
3025
|
+
Effect21.tapError((e) => Effect21.sync(() => reportSyncError(config.onSyncError, e))),
|
|
3026
|
+
Effect21.ignore
|
|
3027
|
+
);
|
|
3028
|
+
}
|
|
3029
|
+
for (const gwId of gwIds) {
|
|
3030
|
+
yield* storage.deleteGiftWrap(gwId).pipe(Effect21.ignore);
|
|
3031
|
+
}
|
|
3032
|
+
}
|
|
3033
|
+
});
|
|
2969
3034
|
const knownAuthors = /* @__PURE__ */ new Set();
|
|
2970
3035
|
const putMemberRecord = (record) => Effect21.gen(function* () {
|
|
2971
3036
|
const existing = yield* storage.getRecord("_members", record.id);
|
|
@@ -3053,6 +3118,13 @@ var TablinumLive = Layer9.effect(
|
|
|
3053
3118
|
addedInEpoch: getCurrentEpoch(epochStore).id
|
|
3054
3119
|
});
|
|
3055
3120
|
}
|
|
3121
|
+
const migrated = yield* storage.getMeta("migration_gw_republish").pipe(
|
|
3122
|
+
Effect21.orElseSucceed(() => void 0)
|
|
3123
|
+
);
|
|
3124
|
+
if (!migrated) {
|
|
3125
|
+
yield* republishAllUnderCurrentEpoch().pipe(Effect21.ignore);
|
|
3126
|
+
yield* storage.putMeta("migration_gw_republish", true);
|
|
3127
|
+
}
|
|
3056
3128
|
const withLog = (effect) => Effect21.provideService(effect, References3.MinimumLogLevel, config.logLevel);
|
|
3057
3129
|
const ensureOpen = (effect) => withLog(
|
|
3058
3130
|
Effect21.gen(function* () {
|
|
@@ -3132,6 +3204,7 @@ var TablinumLive = Layer9.effect(
|
|
|
3132
3204
|
removedAt: Date.now(),
|
|
3133
3205
|
removedInEpoch: result.epoch.id
|
|
3134
3206
|
});
|
|
3207
|
+
yield* republishAllUnderCurrentEpoch();
|
|
3135
3208
|
yield* Effect21.forEach(
|
|
3136
3209
|
result.wrappedEvents,
|
|
3137
3210
|
(wrappedEvent) => relay.publish(wrappedEvent, [...config.relays]).pipe(
|
|
@@ -3206,6 +3279,7 @@ var TablinumLive = Layer9.effect(
|
|
|
3206
3279
|
removedAt: Date.now(),
|
|
3207
3280
|
removedInEpoch: result.epoch.id
|
|
3208
3281
|
});
|
|
3282
|
+
yield* republishAllUnderCurrentEpoch();
|
|
3209
3283
|
yield* Effect21.forEach(
|
|
3210
3284
|
result.wrappedEvents,
|
|
3211
3285
|
(wrappedEvent) => relay.publish(wrappedEvent, [...config.relays]).pipe(
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { NostrEvent } from "nostr-tools/pure";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a NIP-09 deletion request (kind 5) for one or more events.
|
|
4
|
+
*
|
|
5
|
+
* For gift wraps (kind 1059), NIP-59 specifies that relays SHOULD honor
|
|
6
|
+
* deletions where the signer's pubkey matches the gift wrap's p-tag.
|
|
7
|
+
* This means the epoch key holder can delete any gift wrap addressed
|
|
8
|
+
* to that epoch — regardless of who originally created it.
|
|
9
|
+
*/
|
|
10
|
+
export declare function createDeletionEvent(targetEventIds: readonly string[], signingKey: Uint8Array): NostrEvent;
|