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.
@@ -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 uid */
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, getEventUID, getIndexableTags, isReplaceable } from "../helpers/event.js";
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 uid */
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 uid = getEventUID(event);
96
- let array = this.replaceable.get(uid);
97
- if (!this.replaceable.has(uid)) {
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(uid, array);
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 uid = getEventUID(event);
139
- const array = this.replaceable.get(uid);
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, getEventUID, getTagValue, isReplaceable } from "../helpers/event.js";
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(getEventUID(event));
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 getArticlePublishd(article: NostrEvent): number;
9
+ export declare function getArticlePublished(article: NostrEvent): number;
@@ -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 getArticlePublishd(article) {
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);
@@ -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
@@ -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[EventUIDSymbol];
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[EventUIDSymbol] = uid;
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
- const identifier = isAddressableKind(event.kind) ? getReplaceableIdentifier(event) : undefined;
56
- return createReplaceableAddress(event.kind, event.pubkey, identifier);
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[EventIndexableTagsSymbol];
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 = event[EventIndexableTagsSymbol] = tags;
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[FromCacheSymbol] = true;
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 !!event[FromCacheSymbol];
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) {
@@ -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
@@ -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
@@ -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
@@ -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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "applesauce-core",
3
- "version": "2.0.0",
3
+ "version": "2.1.1",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",