applesauce-core 6.0.2 → 6.0.3
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.
|
@@ -137,14 +137,24 @@ export class AsyncEventStore extends EventModels {
|
|
|
137
137
|
addSeenRelay(event, fromRelay);
|
|
138
138
|
// Get the replaceable identifier
|
|
139
139
|
const identifier = isReplaceable(event.kind) ? getReplaceableIdentifier(event) : undefined;
|
|
140
|
-
// Don't insert the event if there is already a
|
|
140
|
+
// Don't insert the event if there is already a winning version
|
|
141
|
+
// (NIP-01: newer created_at wins; on tie, lexicographically lower id wins).
|
|
141
142
|
if (this.keepOldVersions === false && isReplaceable(event.kind)) {
|
|
142
143
|
const existing = await this.database.getReplaceableHistory(event.kind, event.pubkey, identifier);
|
|
143
|
-
// If
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
144
|
+
// If the existing set has any event that beats the incoming one per
|
|
145
|
+
// NIP-01, the incoming event is rejected.
|
|
146
|
+
if (existing && existing.length > 0) {
|
|
147
|
+
let winner = existing[0];
|
|
148
|
+
for (const e of existing) {
|
|
149
|
+
if (e.created_at > winner.created_at || (e.created_at === winner.created_at && e.id < winner.id))
|
|
150
|
+
winner = e;
|
|
151
|
+
}
|
|
152
|
+
const incomingBeatsWinner = event.created_at > winner.created_at || (event.created_at === winner.created_at && event.id < winner.id);
|
|
153
|
+
if (!incomingBeatsWinner) {
|
|
154
|
+
if (EventStore.copySymbolsToDuplicateEvent(event, winner))
|
|
155
|
+
await this.update(winner);
|
|
156
|
+
return winner;
|
|
157
|
+
}
|
|
148
158
|
}
|
|
149
159
|
}
|
|
150
160
|
// Verify event before inserting into the database
|
|
@@ -173,17 +183,24 @@ export class AsyncEventStore extends EventModels {
|
|
|
173
183
|
if (EventStore.copySymbolsToDuplicateEvent(event, inserted))
|
|
174
184
|
await this.update(inserted);
|
|
175
185
|
}
|
|
176
|
-
// remove all
|
|
186
|
+
// remove all losing versions of the replaceable event
|
|
187
|
+
// (NIP-01: keep newest created_at; on tie, keep lowest id).
|
|
177
188
|
if (this.keepOldVersions === false && isReplaceable(event.kind)) {
|
|
178
189
|
const existing = await this.database.getReplaceableHistory(event.kind, event.pubkey, identifier);
|
|
179
190
|
if (existing && existing.length > 0) {
|
|
180
|
-
|
|
181
|
-
|
|
191
|
+
// Find the NIP-01 winner across all stored versions.
|
|
192
|
+
let winner = existing[0];
|
|
193
|
+
for (const e of existing) {
|
|
194
|
+
if (e.created_at > winner.created_at || (e.created_at === winner.created_at && e.id < winner.id))
|
|
195
|
+
winner = e;
|
|
196
|
+
}
|
|
197
|
+
const losers = existing.filter((e) => e !== winner);
|
|
198
|
+
for (const old of losers)
|
|
182
199
|
await this.remove(old);
|
|
183
|
-
// return the
|
|
200
|
+
// return the winning version of the replaceable event
|
|
184
201
|
// most of the time this will be === event, but not always
|
|
185
|
-
if (
|
|
186
|
-
return
|
|
202
|
+
if (losers.length > 0)
|
|
203
|
+
return winner;
|
|
187
204
|
}
|
|
188
205
|
}
|
|
189
206
|
// Add event to expiration manager if it has an expiration tag
|
|
@@ -161,14 +161,24 @@ export class EventStore extends EventModels {
|
|
|
161
161
|
addSeenRelay(event, fromRelay);
|
|
162
162
|
// Get the replaceable identifier
|
|
163
163
|
const identifier = isReplaceable(event.kind) ? getReplaceableIdentifier(event) : undefined;
|
|
164
|
-
// Don't insert the event if there is already a
|
|
164
|
+
// Don't insert the event if there is already a winning version
|
|
165
|
+
// (NIP-01: newer created_at wins; on tie, lexicographically lower id wins).
|
|
165
166
|
if (this.keepOldVersions === false && isReplaceable(event.kind)) {
|
|
166
167
|
const existing = this.database.getReplaceableHistory(event.kind, event.pubkey, identifier);
|
|
167
|
-
// If
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
168
|
+
// If the existing set has any event that beats the incoming one per
|
|
169
|
+
// NIP-01, the incoming event is rejected.
|
|
170
|
+
if (existing && existing.length > 0) {
|
|
171
|
+
let winner = existing[0];
|
|
172
|
+
for (const e of existing) {
|
|
173
|
+
if (e.created_at > winner.created_at || (e.created_at === winner.created_at && e.id < winner.id))
|
|
174
|
+
winner = e;
|
|
175
|
+
}
|
|
176
|
+
const incomingBeatsWinner = event.created_at > winner.created_at || (event.created_at === winner.created_at && event.id < winner.id);
|
|
177
|
+
if (!incomingBeatsWinner) {
|
|
178
|
+
if (EventStore.copySymbolsToDuplicateEvent(event, winner))
|
|
179
|
+
this.update(winner);
|
|
180
|
+
return winner;
|
|
181
|
+
}
|
|
172
182
|
}
|
|
173
183
|
}
|
|
174
184
|
// Verify event before inserting into the database
|
|
@@ -197,17 +207,24 @@ export class EventStore extends EventModels {
|
|
|
197
207
|
if (EventStore.copySymbolsToDuplicateEvent(event, inserted))
|
|
198
208
|
this.update(inserted);
|
|
199
209
|
}
|
|
200
|
-
// remove all
|
|
210
|
+
// remove all losing versions of the replaceable event
|
|
211
|
+
// (NIP-01: keep newest created_at; on tie, keep lowest id).
|
|
201
212
|
if (this.keepOldVersions === false && isReplaceable(event.kind)) {
|
|
202
213
|
const existing = this.database.getReplaceableHistory(event.kind, event.pubkey, identifier);
|
|
203
214
|
if (existing && existing.length > 0) {
|
|
204
|
-
|
|
205
|
-
|
|
215
|
+
// Find the NIP-01 winner across all stored versions.
|
|
216
|
+
let winner = existing[0];
|
|
217
|
+
for (const e of existing) {
|
|
218
|
+
if (e.created_at > winner.created_at || (e.created_at === winner.created_at && e.id < winner.id))
|
|
219
|
+
winner = e;
|
|
220
|
+
}
|
|
221
|
+
const losers = existing.filter((e) => e !== winner);
|
|
222
|
+
for (const old of losers)
|
|
206
223
|
this.remove(old);
|
|
207
|
-
// return the
|
|
224
|
+
// return the winning version of the replaceable event
|
|
208
225
|
// most of the time this will be === event, but not always
|
|
209
|
-
if (
|
|
210
|
-
return
|
|
226
|
+
if (losers.length > 0)
|
|
227
|
+
return winner;
|
|
211
228
|
}
|
|
212
229
|
}
|
|
213
230
|
// Add event to expiration manager if it has an expiration tag
|
package/dist/helpers/regexp.js
CHANGED
|
@@ -34,10 +34,10 @@ export const Tokens = {
|
|
|
34
34
|
return Expressions.link;
|
|
35
35
|
},
|
|
36
36
|
get cashu() {
|
|
37
|
-
return new RegExp(`(?<=^|\\s)${Expressions.cashu.source}`, "gi");
|
|
37
|
+
return new RegExp(`(?<=^|\\s|\\s\\()${Expressions.cashu.source}`, "gi");
|
|
38
38
|
},
|
|
39
39
|
get nostrLink() {
|
|
40
|
-
return new RegExp(`(?<=^|\\s)${Expressions.nostrLink.source}`, "gi");
|
|
40
|
+
return new RegExp(`(?<=^|\\s|\\s\\()${Expressions.nostrLink.source}`, "gi");
|
|
41
41
|
},
|
|
42
42
|
get emoji() {
|
|
43
43
|
return Expressions.emoji;
|
|
@@ -46,9 +46,9 @@ export const Tokens = {
|
|
|
46
46
|
return Expressions.hashtag;
|
|
47
47
|
},
|
|
48
48
|
get lightning() {
|
|
49
|
-
return new RegExp(`(?<=^|\\s)${Expressions.lightning.source}`, "gim");
|
|
49
|
+
return new RegExp(`(?<=^|\\s|\\s\\()${Expressions.lightning.source}`, "gim");
|
|
50
50
|
},
|
|
51
51
|
get blossom() {
|
|
52
|
-
return new RegExp(`(?<=^|\\s)${Expressions.blossom.source}`, "g");
|
|
52
|
+
return new RegExp(`(?<=^|\\s|\\s\\()${Expressions.blossom.source}`, "g");
|
|
53
53
|
},
|
|
54
54
|
};
|