applesauce-core 2.0.0 → 2.1.1
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/event-store/event-set.d.ts +1 -1
- package/dist/event-store/event-set.js +8 -8
- package/dist/event-store/event-store.js +2 -2
- package/dist/helpers/article.d.ts +1 -1
- package/dist/helpers/article.js +1 -1
- package/dist/helpers/event.d.ts +1 -7
- package/dist/helpers/event.js +12 -8
- package/dist/helpers/lists.d.ts +2 -0
- package/dist/helpers/lists.js +8 -2
- package/dist/helpers/url.d.ts +3 -1
- package/dist/helpers/url.js +15 -2
- package/package.json +1 -1
|
@@ -15,7 +15,7 @@ export declare class EventSet implements IEventSet {
|
|
|
15
15
|
protected created_at: NostrEvent[];
|
|
16
16
|
/** LRU cache of last events touched */
|
|
17
17
|
events: LRU<import("nostr-tools").Event>;
|
|
18
|
-
/** A sorted array of replaceable events by
|
|
18
|
+
/** A sorted array of replaceable events by address */
|
|
19
19
|
protected replaceable: Map<string, import("nostr-tools").Event[]>;
|
|
20
20
|
/** A stream of events inserted into the database */
|
|
21
21
|
insert$: Subject<import("nostr-tools").Event>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { binarySearch, insertEventIntoDescendingList } from "nostr-tools/utils";
|
|
2
2
|
import { Subject } from "rxjs";
|
|
3
|
-
import { createReplaceableAddress,
|
|
3
|
+
import { createReplaceableAddress, getIndexableTags, getReplaceableAddress, isReplaceable } from "../helpers/event.js";
|
|
4
4
|
import { LRU } from "../helpers/lru.js";
|
|
5
5
|
import { logger } from "../logger.js";
|
|
6
6
|
import { INDEXABLE_TAGS } from "./common.js";
|
|
@@ -17,7 +17,7 @@ export class EventSet {
|
|
|
17
17
|
created_at = [];
|
|
18
18
|
/** LRU cache of last events touched */
|
|
19
19
|
events = new LRU();
|
|
20
|
-
/** A sorted array of replaceable events by
|
|
20
|
+
/** A sorted array of replaceable events by address */
|
|
21
21
|
replaceable = new Map();
|
|
22
22
|
/** A stream of events inserted into the database */
|
|
23
23
|
insert$ = new Subject();
|
|
@@ -92,12 +92,12 @@ export class EventSet {
|
|
|
92
92
|
insertEventIntoDescendingList(this.created_at, event);
|
|
93
93
|
// Insert into replaceable index
|
|
94
94
|
if (isReplaceable(event.kind)) {
|
|
95
|
-
const
|
|
96
|
-
let array = this.replaceable.get(
|
|
97
|
-
if (!this.replaceable.has(
|
|
95
|
+
const address = getReplaceableAddress(event);
|
|
96
|
+
let array = this.replaceable.get(address);
|
|
97
|
+
if (!this.replaceable.has(address)) {
|
|
98
98
|
// add an empty array if there is no array
|
|
99
99
|
array = [];
|
|
100
|
-
this.replaceable.set(
|
|
100
|
+
this.replaceable.set(address, array);
|
|
101
101
|
}
|
|
102
102
|
// insert the event into the sorted array
|
|
103
103
|
insertEventIntoDescendingList(array, event);
|
|
@@ -135,8 +135,8 @@ export class EventSet {
|
|
|
135
135
|
this.events.delete(id);
|
|
136
136
|
// remove from replaceable index
|
|
137
137
|
if (isReplaceable(event.kind)) {
|
|
138
|
-
const
|
|
139
|
-
const array = this.replaceable.get(
|
|
138
|
+
const address = getReplaceableAddress(event);
|
|
139
|
+
const array = this.replaceable.get(address);
|
|
140
140
|
if (array && array.includes(event)) {
|
|
141
141
|
const idx = array.indexOf(event);
|
|
142
142
|
array.splice(idx, 1);
|
|
@@ -3,7 +3,7 @@ import { isAddressableKind } from "nostr-tools/kinds";
|
|
|
3
3
|
import { EMPTY, filter, finalize, from, merge, mergeMap, ReplaySubject, share, take, timer } from "rxjs";
|
|
4
4
|
import hash_sum from "hash-sum";
|
|
5
5
|
import { getDeleteCoordinates, getDeleteIds } from "../helpers/delete.js";
|
|
6
|
-
import { FromCacheSymbol,
|
|
6
|
+
import { FromCacheSymbol, getReplaceableAddress, getTagValue, isReplaceable } from "../helpers/event.js";
|
|
7
7
|
import { matchFilters } from "../helpers/filter.js";
|
|
8
8
|
import { parseCoordinate } from "../helpers/pointers.js";
|
|
9
9
|
import { addSeenRelay, getSeenRelays } from "../helpers/relays.js";
|
|
@@ -65,7 +65,7 @@ export class EventStore {
|
|
|
65
65
|
if (this.deletedIds.has(event.id))
|
|
66
66
|
return true;
|
|
67
67
|
if (isAddressableKind(event.kind)) {
|
|
68
|
-
const deleted = this.deletedCoords.get(
|
|
68
|
+
const deleted = this.deletedCoords.get(getReplaceableAddress(event));
|
|
69
69
|
if (deleted)
|
|
70
70
|
return deleted > event.created_at;
|
|
71
71
|
}
|
|
@@ -6,4 +6,4 @@ export declare function getArticleImage(article: NostrEvent): string | undefined
|
|
|
6
6
|
/** Returns an articles summary, if it exists */
|
|
7
7
|
export declare function getArticleSummary(article: NostrEvent): string | undefined;
|
|
8
8
|
/** Returns an articles published date, if it exists */
|
|
9
|
-
export declare function
|
|
9
|
+
export declare function getArticlePublished(article: NostrEvent): number;
|
package/dist/helpers/article.js
CHANGED
|
@@ -12,7 +12,7 @@ export function getArticleSummary(article) {
|
|
|
12
12
|
return getTagValue(article, "summary");
|
|
13
13
|
}
|
|
14
14
|
/** Returns an articles published date, if it exists */
|
|
15
|
-
export function
|
|
15
|
+
export function getArticlePublished(article) {
|
|
16
16
|
const ts = getTagValue(article, "published_at");
|
|
17
17
|
if (ts && !Number.isNaN(parseInt(ts)))
|
|
18
18
|
return parseInt(ts);
|
package/dist/helpers/event.d.ts
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
import { NostrEvent, VerifiedEvent } from "nostr-tools";
|
|
2
2
|
import { IEventStore } from "../event-store/interface.js";
|
|
3
3
|
export declare const EventUIDSymbol: unique symbol;
|
|
4
|
+
export declare const ReplaceableAddressSymbol: unique symbol;
|
|
4
5
|
export declare const EventIndexableTagsSymbol: unique symbol;
|
|
5
6
|
export declare const FromCacheSymbol: unique symbol;
|
|
6
7
|
export declare const ReplaceableIdentifierSymbol: unique symbol;
|
|
7
|
-
declare module "nostr-tools" {
|
|
8
|
-
interface Event {
|
|
9
|
-
[EventUIDSymbol]?: string;
|
|
10
|
-
[EventIndexableTagsSymbol]?: Set<string>;
|
|
11
|
-
[FromCacheSymbol]?: boolean;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
8
|
/**
|
|
15
9
|
* Checks if an object is a nostr event
|
|
16
10
|
* NOTE: does not validation the signature on the event
|
package/dist/helpers/event.js
CHANGED
|
@@ -5,6 +5,7 @@ import { EventStoreSymbol } from "../event-store/event-store.js";
|
|
|
5
5
|
import { getOrComputeCachedValue } from "./cache.js";
|
|
6
6
|
import { getHiddenTags } from "./hidden-tags.js";
|
|
7
7
|
export const EventUIDSymbol = Symbol.for("event-uid");
|
|
8
|
+
export const ReplaceableAddressSymbol = Symbol.for("replaceable-address");
|
|
8
9
|
export const EventIndexableTagsSymbol = Symbol.for("indexable-tags");
|
|
9
10
|
export const FromCacheSymbol = Symbol.for("from-cache");
|
|
10
11
|
export const ReplaceableIdentifierSymbol = Symbol.for("replaceable-identifier");
|
|
@@ -38,13 +39,13 @@ export function isReplaceable(kind) {
|
|
|
38
39
|
* For parametrized replaceable events this is ( event.kind + ":" + event.pubkey + ":" + event.tags.d )
|
|
39
40
|
*/
|
|
40
41
|
export function getEventUID(event) {
|
|
41
|
-
let uid = event
|
|
42
|
+
let uid = Reflect.get(event, EventUIDSymbol);
|
|
42
43
|
if (!uid) {
|
|
43
44
|
if (isReplaceable(event.kind))
|
|
44
45
|
uid = getReplaceableAddress(event);
|
|
45
46
|
else
|
|
46
47
|
uid = event.id;
|
|
47
|
-
event
|
|
48
|
+
Reflect.set(event, EventUIDSymbol, uid);
|
|
48
49
|
}
|
|
49
50
|
return uid;
|
|
50
51
|
}
|
|
@@ -52,8 +53,10 @@ export function getEventUID(event) {
|
|
|
52
53
|
export function getReplaceableAddress(event) {
|
|
53
54
|
if (!isReplaceable(event.kind))
|
|
54
55
|
throw new Error("Event is not replaceable or addressable");
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
return getOrComputeCachedValue(event, ReplaceableAddressSymbol, () => {
|
|
57
|
+
const identifier = isAddressableKind(event.kind) ? getReplaceableIdentifier(event) : undefined;
|
|
58
|
+
return createReplaceableAddress(event.kind, event.pubkey, identifier);
|
|
59
|
+
});
|
|
57
60
|
}
|
|
58
61
|
/** Creates a replaceable event address from a kind, pubkey, and identifier */
|
|
59
62
|
export function createReplaceableAddress(kind, pubkey, identifier) {
|
|
@@ -63,7 +66,7 @@ export function createReplaceableAddress(kind, pubkey, identifier) {
|
|
|
63
66
|
export const getReplaceableUID = createReplaceableAddress;
|
|
64
67
|
/** Returns a Set of tag names and values that are indexable */
|
|
65
68
|
export function getIndexableTags(event) {
|
|
66
|
-
let indexable = event
|
|
69
|
+
let indexable = Reflect.get(event, EventIndexableTagsSymbol);
|
|
67
70
|
if (!indexable) {
|
|
68
71
|
const tags = new Set();
|
|
69
72
|
for (const tag of event.tags) {
|
|
@@ -71,7 +74,8 @@ export function getIndexableTags(event) {
|
|
|
71
74
|
tags.add(tag[0] + ":" + tag[1]);
|
|
72
75
|
}
|
|
73
76
|
}
|
|
74
|
-
indexable =
|
|
77
|
+
indexable = tags;
|
|
78
|
+
Reflect.set(event, EventIndexableTagsSymbol, tags);
|
|
75
79
|
}
|
|
76
80
|
return indexable;
|
|
77
81
|
}
|
|
@@ -93,11 +97,11 @@ export function fakeVerifyEvent(event) {
|
|
|
93
97
|
}
|
|
94
98
|
/** Marks an event as being from a cache */
|
|
95
99
|
export function markFromCache(event) {
|
|
96
|
-
event
|
|
100
|
+
Reflect.set(event, FromCacheSymbol, true);
|
|
97
101
|
}
|
|
98
102
|
/** Returns if an event was from a cache */
|
|
99
103
|
export function isFromCache(event) {
|
|
100
|
-
return
|
|
104
|
+
return Reflect.get(event, FromCacheSymbol) === true;
|
|
101
105
|
}
|
|
102
106
|
/** Returns the EventStore of an event if its been added to one */
|
|
103
107
|
export function getParentEventStore(event) {
|
package/dist/helpers/lists.d.ts
CHANGED
|
@@ -28,6 +28,8 @@ export declare function isAddressPointerInList(list: NostrEvent, pointer: string
|
|
|
28
28
|
* @param type - Which types of tags to check
|
|
29
29
|
*/
|
|
30
30
|
export declare function isProfilePointerInList(list: NostrEvent, pointer: string | ProfilePointer, type?: ReadListTags): boolean;
|
|
31
|
+
/** Returns if an event is in a list */
|
|
32
|
+
export declare function isEventInList(list: NostrEvent, event: NostrEvent): boolean;
|
|
31
33
|
/**
|
|
32
34
|
* Returns all the EventPointer in a list or set
|
|
33
35
|
* @param list - The list or set to get the event pointers from
|
package/dist/helpers/lists.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isAddressableKind, isReplaceableKind } from "nostr-tools/kinds";
|
|
2
|
-
import { getReplaceableIdentifier } from "./event.js";
|
|
2
|
+
import { getReplaceableIdentifier, isReplaceable } from "./event.js";
|
|
3
3
|
import { getHiddenTags } from "./hidden-tags.js";
|
|
4
|
-
import { getAddressPointerFromATag, getCoordinateFromAddressPointer, getEventPointerFromETag, getProfilePointerFromPTag, } from "./pointers.js";
|
|
4
|
+
import { getAddressPointerForEvent, getAddressPointerFromATag, getCoordinateFromAddressPointer, getEventPointerFromETag, getProfilePointerFromPTag, } from "./pointers.js";
|
|
5
5
|
import { mergeRelaySets } from "./relays.js";
|
|
6
6
|
import { isATag, isETag, isPTag, processTags } from "./tags.js";
|
|
7
7
|
export const FAVORITE_RELAYS_KIND = 10012;
|
|
@@ -53,6 +53,12 @@ export function isProfilePointerInList(list, pointer, type) {
|
|
|
53
53
|
const tags = getListTags(list, type);
|
|
54
54
|
return tags.some((t) => t[0] === "p" && t[1] === pubkey);
|
|
55
55
|
}
|
|
56
|
+
/** Returns if an event is in a list */
|
|
57
|
+
export function isEventInList(list, event) {
|
|
58
|
+
return isReplaceable(event.kind)
|
|
59
|
+
? isAddressPointerInList(list, getAddressPointerForEvent(event))
|
|
60
|
+
: isEventPointerInList(list, event);
|
|
61
|
+
}
|
|
56
62
|
/**
|
|
57
63
|
* Returns all the EventPointer in a list or set
|
|
58
64
|
* @param list - The list or set to get the event pointers from
|
package/dist/helpers/url.d.ts
CHANGED
|
@@ -16,8 +16,10 @@ export declare function isAudioURL(url: string | URL): boolean;
|
|
|
16
16
|
export declare function isSameURL(a: string | URL, b: string | URL): boolean;
|
|
17
17
|
/** Adds a protocol to a URL string if its missing one */
|
|
18
18
|
export declare function ensureProtocol(url: string, protocol?: string): string;
|
|
19
|
-
/** Converts a URL to a WebSocket URL */
|
|
19
|
+
/** Converts a domain or HTTP URL to a WebSocket URL */
|
|
20
20
|
export declare function ensureWebSocketURL<T extends string | URL>(url: T): T;
|
|
21
|
+
/** Converts a domain or WS URL to a HTTP URL */
|
|
22
|
+
export declare function ensureHttpURL<T extends string | URL>(url: T): T;
|
|
21
23
|
/**
|
|
22
24
|
* Normalizes a string into a relay URL
|
|
23
25
|
* Does not remove the trailing slash
|
package/dist/helpers/url.js
CHANGED
|
@@ -3,7 +3,7 @@ export const getURLFilename = (url) => url.pathname.split("/").pop()?.toLocaleLo
|
|
|
3
3
|
export const IMAGE_EXT = [".svg", ".gif", ".png", ".jpg", ".jpeg", ".webp", ".avif"];
|
|
4
4
|
export const VIDEO_EXT = [".mp4", ".mkv", ".webm", ".mov"];
|
|
5
5
|
export const STREAM_EXT = [".m3u8"];
|
|
6
|
-
export const AUDIO_EXT = [".mp3", ".wav", ".ogg", ".aac"];
|
|
6
|
+
export const AUDIO_EXT = [".mp3", ".wav", ".ogg", ".aac", ".m4a"];
|
|
7
7
|
/** Checks if a url is a image URL */
|
|
8
8
|
export function isImageURL(url) {
|
|
9
9
|
url = convertToUrl(url);
|
|
@@ -46,7 +46,7 @@ export function ensureProtocol(url, protocol = "https:") {
|
|
|
46
46
|
return url;
|
|
47
47
|
return protocol + "//" + url;
|
|
48
48
|
}
|
|
49
|
-
/** Converts a URL to a WebSocket URL */
|
|
49
|
+
/** Converts a domain or HTTP URL to a WebSocket URL */
|
|
50
50
|
export function ensureWebSocketURL(url) {
|
|
51
51
|
const p = typeof url === "string" ? new URL(ensureProtocol(url, "wss:")) : new URL(url);
|
|
52
52
|
if (p.protocol === "http:")
|
|
@@ -59,6 +59,19 @@ export function ensureWebSocketURL(url) {
|
|
|
59
59
|
// @ts-expect-error
|
|
60
60
|
return typeof url === "string" ? p.toString() : p;
|
|
61
61
|
}
|
|
62
|
+
/** Converts a domain or WS URL to a HTTP URL */
|
|
63
|
+
export function ensureHttpURL(url) {
|
|
64
|
+
const p = typeof url === "string" ? new URL(ensureProtocol(url, "http:")) : new URL(url);
|
|
65
|
+
if (p.protocol === "ws:")
|
|
66
|
+
p.protocol = "http:";
|
|
67
|
+
else if (p.protocol === "wss:")
|
|
68
|
+
p.protocol = "https:";
|
|
69
|
+
else
|
|
70
|
+
p.protocol = "https:";
|
|
71
|
+
// return a string if a string was passed in
|
|
72
|
+
// @ts-expect-error
|
|
73
|
+
return typeof url === "string" ? p.toString() : p;
|
|
74
|
+
}
|
|
62
75
|
/**
|
|
63
76
|
* Normalizes a string into a relay URL
|
|
64
77
|
* Does not remove the trailing slash
|