applesauce-core 0.0.0-next-20250423145737 → 0.0.0-next-20250423181842
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/helpers/__tests__/bookmarks.test.d.ts +1 -0
- package/dist/helpers/__tests__/bookmarks.test.js +88 -0
- package/dist/helpers/__tests__/contacts.test.d.ts +1 -0
- package/dist/helpers/__tests__/contacts.test.js +34 -0
- package/dist/helpers/bookmarks.d.ts +6 -1
- package/dist/helpers/bookmarks.js +52 -7
- package/dist/helpers/contacts.d.ts +11 -0
- package/dist/helpers/contacts.js +34 -0
- package/dist/helpers/mutes.d.ts +4 -0
- package/dist/helpers/mutes.js +27 -5
- package/dist/helpers/nip-19.d.ts +14 -0
- package/dist/helpers/nip-19.js +29 -0
- package/dist/observable/defined.d.ts +3 -0
- package/dist/observable/defined.js +5 -0
- package/dist/observable/get-observable-value.d.ts +4 -1
- package/dist/observable/get-observable-value.js +4 -1
- package/dist/observable/index.d.ts +3 -1
- package/dist/observable/index.js +3 -1
- package/dist/observable/listen-latest-updates.d.ts +5 -0
- package/dist/observable/listen-latest-updates.js +12 -0
- package/dist/queries/blossom.js +1 -6
- package/dist/queries/bookmarks.d.ts +5 -5
- package/dist/queries/bookmarks.js +18 -17
- package/dist/queries/channels.js +41 -53
- package/dist/queries/comments.js +6 -9
- package/dist/queries/contacts.d.ts +6 -1
- package/dist/queries/contacts.js +21 -9
- package/dist/queries/mailboxes.js +4 -7
- package/dist/queries/mutes.d.ts +6 -6
- package/dist/queries/mutes.js +20 -19
- package/dist/queries/pins.d.ts +1 -0
- package/dist/queries/pins.js +4 -6
- package/dist/queries/profile.js +1 -6
- package/dist/queries/reactions.js +11 -14
- package/dist/queries/simple.js +5 -22
- package/dist/queries/thread.js +44 -50
- package/dist/queries/user-status.js +23 -29
- package/dist/queries/zaps.js +10 -13
- package/dist/query-store/query-store.d.ts +7 -6
- package/dist/query-store/query-store.js +13 -8
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { kinds } from "nostr-tools";
|
|
3
|
+
import { mergeBookmarks } from "../bookmarks.js";
|
|
4
|
+
describe("mergeBookmarks", () => {
|
|
5
|
+
it("should merge bookmarks and handle duplicates", () => {
|
|
6
|
+
// Create test data with some duplicates
|
|
7
|
+
const eventPointer1 = {
|
|
8
|
+
id: "event1",
|
|
9
|
+
relays: ["wss://relay1.com/", "wss://relay2.com/"],
|
|
10
|
+
author: "author1",
|
|
11
|
+
};
|
|
12
|
+
const eventPointer2 = {
|
|
13
|
+
id: "event1", // Same ID as eventPointer1
|
|
14
|
+
relays: ["wss://relay2.com/", "wss://relay3.com/"],
|
|
15
|
+
author: "author1",
|
|
16
|
+
};
|
|
17
|
+
const eventPointer3 = {
|
|
18
|
+
id: "event2",
|
|
19
|
+
relays: ["wss://relay1.com/"],
|
|
20
|
+
author: "author2",
|
|
21
|
+
};
|
|
22
|
+
const addressPointer1 = {
|
|
23
|
+
kind: kinds.LongFormArticle,
|
|
24
|
+
pubkey: "pubkey1",
|
|
25
|
+
identifier: "article1",
|
|
26
|
+
relays: ["wss://relay1.com/", "wss://relay2.com/"],
|
|
27
|
+
};
|
|
28
|
+
const addressPointer2 = {
|
|
29
|
+
kind: kinds.LongFormArticle,
|
|
30
|
+
pubkey: "pubkey1",
|
|
31
|
+
identifier: "article1", // Same as addressPointer1
|
|
32
|
+
relays: ["wss://relay3.com/"],
|
|
33
|
+
};
|
|
34
|
+
const bookmark1 = {
|
|
35
|
+
notes: [eventPointer1],
|
|
36
|
+
articles: [addressPointer1],
|
|
37
|
+
hashtags: ["tag1", "tag2"],
|
|
38
|
+
urls: ["https://example1.com/"],
|
|
39
|
+
};
|
|
40
|
+
const bookmark2 = {
|
|
41
|
+
notes: [eventPointer2, eventPointer3],
|
|
42
|
+
articles: [addressPointer2],
|
|
43
|
+
hashtags: ["tag2", "tag3"],
|
|
44
|
+
urls: ["https://example1.com/", "https://example2.com/"],
|
|
45
|
+
};
|
|
46
|
+
const result = mergeBookmarks(bookmark1, bookmark2);
|
|
47
|
+
// Check that duplicates are properly merged
|
|
48
|
+
expect(result.notes).toHaveLength(2); // event1 should be merged, plus event2
|
|
49
|
+
expect(result.articles).toHaveLength(1); // article1 should be merged
|
|
50
|
+
expect(result.hashtags).toHaveLength(3); // unique tags
|
|
51
|
+
expect(result.urls).toHaveLength(2); // unique urls
|
|
52
|
+
// Check that relays are merged for duplicate event
|
|
53
|
+
const mergedEvent = result.notes.find((note) => note.id === "event1");
|
|
54
|
+
expect(mergedEvent?.relays).toHaveLength(3);
|
|
55
|
+
expect(mergedEvent?.relays).toContain("wss://relay1.com/");
|
|
56
|
+
expect(mergedEvent?.relays).toContain("wss://relay2.com/");
|
|
57
|
+
expect(mergedEvent?.relays).toContain("wss://relay3.com/");
|
|
58
|
+
// Check that relays are merged for duplicate article
|
|
59
|
+
const mergedArticle = result.articles[0];
|
|
60
|
+
expect(mergedArticle.relays).toHaveLength(3);
|
|
61
|
+
expect(mergedArticle.relays).toContain("wss://relay1.com/");
|
|
62
|
+
expect(mergedArticle.relays).toContain("wss://relay2.com/");
|
|
63
|
+
expect(mergedArticle.relays).toContain("wss://relay3.com/");
|
|
64
|
+
// Check that hashtags are unique
|
|
65
|
+
expect(result.hashtags).toContain("tag1");
|
|
66
|
+
expect(result.hashtags).toContain("tag2");
|
|
67
|
+
expect(result.hashtags).toContain("tag3");
|
|
68
|
+
// Check that urls are unique
|
|
69
|
+
expect(result.urls).toContain("https://example1.com/");
|
|
70
|
+
expect(result.urls).toContain("https://example2.com/");
|
|
71
|
+
});
|
|
72
|
+
it("should handle undefined bookmarks", () => {
|
|
73
|
+
const bookmark = {
|
|
74
|
+
notes: [{ id: "event1", relays: ["wss://relay1.com/"] }],
|
|
75
|
+
articles: [],
|
|
76
|
+
hashtags: ["tag1"],
|
|
77
|
+
urls: ["https://example.com/"],
|
|
78
|
+
};
|
|
79
|
+
const result = mergeBookmarks(bookmark, undefined);
|
|
80
|
+
expect(result).toEqual(bookmark);
|
|
81
|
+
expect(mergeBookmarks(undefined, undefined)).toEqual({
|
|
82
|
+
notes: [],
|
|
83
|
+
articles: [],
|
|
84
|
+
hashtags: [],
|
|
85
|
+
urls: [],
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { mergeContacts } from "../contacts.js";
|
|
3
|
+
describe("mergeContacts", () => {
|
|
4
|
+
it("should merge contacts and remove duplicates", () => {
|
|
5
|
+
// Create some test profile pointers
|
|
6
|
+
const pointer1 = { pubkey: "pubkey1", relays: ["relay1"] };
|
|
7
|
+
const pointer2 = { pubkey: "pubkey2" }; // No relays
|
|
8
|
+
const pointer3 = { pubkey: "pubkey3", relays: ["relay3"] };
|
|
9
|
+
const pointer4 = { pubkey: "pubkey1" }; // Duplicate pubkey without relays
|
|
10
|
+
// Test merging arrays of pointers
|
|
11
|
+
const result1 = mergeContacts([pointer1, pointer2], [pointer3, pointer4]);
|
|
12
|
+
// Should have 3 unique pubkeys
|
|
13
|
+
expect(result1.length).toBe(3);
|
|
14
|
+
// Check that the duplicate was handled correctly (last one should win)
|
|
15
|
+
const pubkey1Entry = result1.find((p) => p.pubkey === "pubkey1");
|
|
16
|
+
expect(pubkey1Entry).toBeDefined();
|
|
17
|
+
expect(pubkey1Entry?.relays).toBeUndefined();
|
|
18
|
+
// Test with undefined values
|
|
19
|
+
const result2 = mergeContacts([pointer1], undefined, [pointer2, undefined]);
|
|
20
|
+
expect(result2.length).toBe(2);
|
|
21
|
+
// Test with single pointers
|
|
22
|
+
const result3 = mergeContacts(pointer1, pointer2, pointer1);
|
|
23
|
+
expect(result3.length).toBe(2);
|
|
24
|
+
// Test with empty arrays
|
|
25
|
+
const result4 = mergeContacts([], [pointer1], []);
|
|
26
|
+
expect(result4.length).toBe(1);
|
|
27
|
+
// Test with pointers that have and don't have relays
|
|
28
|
+
const pointer5 = { pubkey: "pubkey5", relays: ["relay5"] };
|
|
29
|
+
const pointer6 = { pubkey: "pubkey5" }; // Same pubkey without relays
|
|
30
|
+
const result5 = mergeContacts([pointer5], [pointer6]);
|
|
31
|
+
expect(result5.length).toBe(1);
|
|
32
|
+
expect(result5[0].relays).toBeUndefined();
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -8,8 +8,13 @@ export type Bookmarks = {
|
|
|
8
8
|
hashtags: string[];
|
|
9
9
|
urls: string[];
|
|
10
10
|
};
|
|
11
|
+
/** Parses an array of tags into a {@link Bookmarks} object */
|
|
11
12
|
export declare function parseBookmarkTags(tags: string[][]): Bookmarks;
|
|
12
|
-
/**
|
|
13
|
+
/** Merges any number of {@link Bookmarks} objects */
|
|
14
|
+
export declare function mergeBookmarks(...bookmarks: (Bookmarks | undefined)[]): Bookmarks;
|
|
15
|
+
/** Returns all the bookmarks of the event */
|
|
13
16
|
export declare function getBookmarks(bookmark: NostrEvent): Bookmarks;
|
|
17
|
+
/** Returns the public bookmarks of the event */
|
|
18
|
+
export declare function getPublicBookmarks(bookmark: NostrEvent): Bookmarks;
|
|
14
19
|
/** Returns the bookmarks of the event if its unlocked */
|
|
15
20
|
export declare function getHiddenBookmarks(bookmark: NostrEvent): Bookmarks | undefined;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { kinds } from "nostr-tools";
|
|
2
|
-
import { getAddressPointerFromATag, getEventPointerFromETag } from "./pointers.js";
|
|
3
2
|
import { getOrComputeCachedValue } from "./cache.js";
|
|
4
|
-
import { getHiddenTags } from "./index.js";
|
|
3
|
+
import { getHiddenTags, isHiddenTagsLocked } from "./index.js";
|
|
4
|
+
import { mergeAddressPointers, mergeEventPointers } from "./nip-19.js";
|
|
5
|
+
import { getAddressPointerFromATag, getCoordinateFromAddressPointer, getEventPointerFromETag } from "./pointers.js";
|
|
5
6
|
export const BookmarkPublicSymbol = Symbol.for("bookmark-public");
|
|
6
7
|
export const BookmarkHiddenSymbol = Symbol.for("bookmark-hidden");
|
|
8
|
+
/** Parses an array of tags into a {@link Bookmarks} object */
|
|
7
9
|
export function parseBookmarkTags(tags) {
|
|
8
10
|
const notes = tags.filter((t) => t[0] === "e" && t[1]).map(getEventPointerFromETag);
|
|
9
11
|
const articles = tags
|
|
@@ -14,14 +16,57 @@ export function parseBookmarkTags(tags) {
|
|
|
14
16
|
const urls = tags.filter((t) => t[0] === "r" && t[1]).map((t) => t[1]);
|
|
15
17
|
return { notes, articles, hashtags, urls };
|
|
16
18
|
}
|
|
17
|
-
/**
|
|
19
|
+
/** Merges any number of {@link Bookmarks} objects */
|
|
20
|
+
export function mergeBookmarks(...bookmarks) {
|
|
21
|
+
const notes = new Map();
|
|
22
|
+
const articles = new Map();
|
|
23
|
+
const hashtags = new Set();
|
|
24
|
+
const urls = new Set();
|
|
25
|
+
for (const bookmark of bookmarks) {
|
|
26
|
+
if (!bookmark)
|
|
27
|
+
continue;
|
|
28
|
+
for (const note of bookmark.notes) {
|
|
29
|
+
const existing = notes.get(note.id);
|
|
30
|
+
if (existing)
|
|
31
|
+
notes.set(note.id, mergeEventPointers(existing, note));
|
|
32
|
+
else
|
|
33
|
+
notes.set(note.id, note);
|
|
34
|
+
}
|
|
35
|
+
for (const article of bookmark.articles) {
|
|
36
|
+
const coord = getCoordinateFromAddressPointer(article);
|
|
37
|
+
const existing = articles.get(coord);
|
|
38
|
+
if (existing)
|
|
39
|
+
articles.set(coord, mergeAddressPointers(existing, article));
|
|
40
|
+
else
|
|
41
|
+
articles.set(coord, article);
|
|
42
|
+
}
|
|
43
|
+
for (const hashtag of bookmark.hashtags)
|
|
44
|
+
hashtags.add(hashtag);
|
|
45
|
+
for (const url of bookmark.urls)
|
|
46
|
+
urls.add(url);
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
notes: Array.from(notes.values()),
|
|
50
|
+
articles: Array.from(articles.values()),
|
|
51
|
+
hashtags: Array.from(hashtags),
|
|
52
|
+
urls: Array.from(urls),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/** Returns all the bookmarks of the event */
|
|
18
56
|
export function getBookmarks(bookmark) {
|
|
57
|
+
const hidden = getHiddenBookmarks(bookmark);
|
|
58
|
+
if (hidden)
|
|
59
|
+
return mergeBookmarks(hidden, getPublicBookmarks(bookmark));
|
|
60
|
+
else
|
|
61
|
+
return getPublicBookmarks(bookmark);
|
|
62
|
+
}
|
|
63
|
+
/** Returns the public bookmarks of the event */
|
|
64
|
+
export function getPublicBookmarks(bookmark) {
|
|
19
65
|
return getOrComputeCachedValue(bookmark, BookmarkPublicSymbol, () => parseBookmarkTags(bookmark.tags));
|
|
20
66
|
}
|
|
21
67
|
/** Returns the bookmarks of the event if its unlocked */
|
|
22
68
|
export function getHiddenBookmarks(bookmark) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
});
|
|
69
|
+
if (isHiddenTagsLocked(bookmark))
|
|
70
|
+
return undefined;
|
|
71
|
+
return getOrComputeCachedValue(bookmark, BookmarkHiddenSymbol, () => parseBookmarkTags(getHiddenTags(bookmark)));
|
|
27
72
|
}
|
|
@@ -1,3 +1,14 @@
|
|
|
1
1
|
import { NostrEvent } from "nostr-tools";
|
|
2
|
+
import { ProfilePointer } from "nostr-tools/nip19";
|
|
2
3
|
export declare const ContactsRelaysSymbol: unique symbol;
|
|
4
|
+
export declare const PublicContactsSymbol: unique symbol;
|
|
5
|
+
export declare const HiddenContactsSymbol: unique symbol;
|
|
3
6
|
export declare function getRelaysFromContactsEvent(event: NostrEvent): Map<string, "all" | "inbox" | "outbox"> | null;
|
|
7
|
+
/** Merges any number of contact lists into a single list */
|
|
8
|
+
export declare function mergeContacts(...pointers: (ProfilePointer | undefined | (ProfilePointer | undefined)[])[]): ProfilePointer[];
|
|
9
|
+
/** Returns all public and hidden contacts from a contacts list event */
|
|
10
|
+
export declare function getContacts(event: NostrEvent): ProfilePointer[];
|
|
11
|
+
/** Returns only the public contacts from a contacts list event */
|
|
12
|
+
export declare function getPublicContacts(event: NostrEvent): ProfilePointer[];
|
|
13
|
+
/** Returns only the hidden contacts from a contacts list event */
|
|
14
|
+
export declare function getHiddenContacts(event: NostrEvent): ProfilePointer[] | undefined;
|
package/dist/helpers/contacts.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { getOrComputeCachedValue } from "./cache.js";
|
|
2
2
|
import { isSafeRelayURL } from "./relays.js";
|
|
3
|
+
import { isPTag, processTags } from "./tags.js";
|
|
4
|
+
import { getProfilePointerFromPTag } from "./pointers.js";
|
|
5
|
+
import { getHiddenTags, isHiddenTagsLocked } from "./hidden-tags.js";
|
|
3
6
|
export const ContactsRelaysSymbol = Symbol.for("contacts-relays");
|
|
7
|
+
export const PublicContactsSymbol = Symbol.for("public-contacts");
|
|
8
|
+
export const HiddenContactsSymbol = Symbol.for("hidden-contacts");
|
|
4
9
|
export function getRelaysFromContactsEvent(event) {
|
|
5
10
|
return getOrComputeCachedValue(event, ContactsRelaysSymbol, () => {
|
|
6
11
|
try {
|
|
@@ -23,3 +28,32 @@ export function getRelaysFromContactsEvent(event) {
|
|
|
23
28
|
}
|
|
24
29
|
});
|
|
25
30
|
}
|
|
31
|
+
/** Merges any number of contact lists into a single list */
|
|
32
|
+
export function mergeContacts(...pointers) {
|
|
33
|
+
const merged = new Map();
|
|
34
|
+
for (const arr of pointers) {
|
|
35
|
+
if (Array.isArray(arr)) {
|
|
36
|
+
for (const pointer of arr)
|
|
37
|
+
if (pointer)
|
|
38
|
+
merged.set(pointer.pubkey, pointer);
|
|
39
|
+
}
|
|
40
|
+
else if (arr) {
|
|
41
|
+
merged.set(arr.pubkey, arr);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return Array.from(merged.values());
|
|
45
|
+
}
|
|
46
|
+
/** Returns all public and hidden contacts from a contacts list event */
|
|
47
|
+
export function getContacts(event) {
|
|
48
|
+
return mergeContacts(getPublicContacts(event), getHiddenContacts(event));
|
|
49
|
+
}
|
|
50
|
+
/** Returns only the public contacts from a contacts list event */
|
|
51
|
+
export function getPublicContacts(event) {
|
|
52
|
+
return getOrComputeCachedValue(event, PublicContactsSymbol, () => processTags(event.tags, (t) => (isPTag(t) ? t : undefined), getProfilePointerFromPTag));
|
|
53
|
+
}
|
|
54
|
+
/** Returns only the hidden contacts from a contacts list event */
|
|
55
|
+
export function getHiddenContacts(event) {
|
|
56
|
+
if (isHiddenTagsLocked(event))
|
|
57
|
+
return undefined;
|
|
58
|
+
return getOrComputeCachedValue(event, HiddenContactsSymbol, () => processTags(getHiddenTags(event), (t) => (isPTag(t) ? t : undefined), getProfilePointerFromPTag));
|
|
59
|
+
}
|
package/dist/helpers/mutes.d.ts
CHANGED
|
@@ -7,9 +7,13 @@ export type Mutes = {
|
|
|
7
7
|
hashtags: Set<string>;
|
|
8
8
|
words: Set<string>;
|
|
9
9
|
};
|
|
10
|
+
/** Merges any number of mute sets */
|
|
11
|
+
export declare function mergeMutes(...mutes: Mutes[]): Mutes;
|
|
10
12
|
/** Parses mute tags */
|
|
11
13
|
export declare function parseMutedTags(tags: string[][]): Mutes;
|
|
12
14
|
/** Returns muted things */
|
|
13
15
|
export declare function getMutedThings(mute: NostrEvent): Mutes;
|
|
16
|
+
/** Returns only the public muted things from a mute event */
|
|
17
|
+
export declare function getPublicMutedThings(mute: NostrEvent): Mutes;
|
|
14
18
|
/** Returns the hidden muted content if the event is unlocked */
|
|
15
19
|
export declare function getHiddenMutedThings(mute: NostrEvent): Mutes | undefined;
|
package/dist/helpers/mutes.js
CHANGED
|
@@ -1,8 +1,23 @@
|
|
|
1
1
|
import { isETag, isPTag, isTTag } from "./tags.js";
|
|
2
2
|
import { getOrComputeCachedValue } from "./cache.js";
|
|
3
|
-
import { getHiddenTags } from "./hidden-tags.js";
|
|
3
|
+
import { getHiddenTags, isHiddenTagsLocked } from "./hidden-tags.js";
|
|
4
4
|
export const MutePublicSymbol = Symbol.for("mute-public");
|
|
5
5
|
export const MuteHiddenSymbol = Symbol.for("mute-hidden");
|
|
6
|
+
/** Merges any number of mute sets */
|
|
7
|
+
export function mergeMutes(...mutes) {
|
|
8
|
+
const mute = { pubkeys: new Set(), threads: new Set(), hashtags: new Set(), words: new Set() };
|
|
9
|
+
for (const m of mutes) {
|
|
10
|
+
for (const pubkey of m.pubkeys)
|
|
11
|
+
mute.pubkeys.add(pubkey);
|
|
12
|
+
for (const thread of m.threads)
|
|
13
|
+
mute.threads.add(thread);
|
|
14
|
+
for (const hashtag of m.hashtags)
|
|
15
|
+
mute.hashtags.add(hashtag);
|
|
16
|
+
for (const word of m.words)
|
|
17
|
+
mute.words.add(word);
|
|
18
|
+
}
|
|
19
|
+
return mute;
|
|
20
|
+
}
|
|
6
21
|
/** Parses mute tags */
|
|
7
22
|
export function parseMutedTags(tags) {
|
|
8
23
|
const pubkeys = new Set(tags.filter(isPTag).map((t) => t[1]));
|
|
@@ -13,12 +28,19 @@ export function parseMutedTags(tags) {
|
|
|
13
28
|
}
|
|
14
29
|
/** Returns muted things */
|
|
15
30
|
export function getMutedThings(mute) {
|
|
31
|
+
const hidden = getHiddenMutedThings(mute);
|
|
32
|
+
const mutes = getPublicMutedThings(mute);
|
|
33
|
+
if (hidden)
|
|
34
|
+
return mergeMutes(hidden, mutes);
|
|
35
|
+
return mutes;
|
|
36
|
+
}
|
|
37
|
+
/** Returns only the public muted things from a mute event */
|
|
38
|
+
export function getPublicMutedThings(mute) {
|
|
16
39
|
return getOrComputeCachedValue(mute, MutePublicSymbol, () => parseMutedTags(mute.tags));
|
|
17
40
|
}
|
|
18
41
|
/** Returns the hidden muted content if the event is unlocked */
|
|
19
42
|
export function getHiddenMutedThings(mute) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
});
|
|
43
|
+
if (isHiddenTagsLocked(mute))
|
|
44
|
+
return undefined;
|
|
45
|
+
return getOrComputeCachedValue(mute, MuteHiddenSymbol, () => parseMutedTags(getHiddenTags(mute)));
|
|
24
46
|
}
|
package/dist/helpers/nip-19.d.ts
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
|
+
import { AddressPointer, EventPointer, ProfilePointer } from "nostr-tools/nip19";
|
|
1
2
|
/** Gets the hex pubkey from any nip-19 encoded string */
|
|
2
3
|
export declare function normalizeToPubkey(str: string): string;
|
|
3
4
|
/** Converts hex to nsec strings into Uint8 secret keys */
|
|
4
5
|
export declare function normalizeToSecretKey(str: string): Uint8Array;
|
|
6
|
+
/**
|
|
7
|
+
* Merges two event points and keeps all relays
|
|
8
|
+
* @throws if the ids are different
|
|
9
|
+
*/
|
|
10
|
+
export declare function mergeEventPointers(a: EventPointer, b: EventPointer): EventPointer;
|
|
11
|
+
/** Merges two address pointers and keeps all relays
|
|
12
|
+
* @throws if the kinds, pubkeys, or identifiers are different
|
|
13
|
+
*/
|
|
14
|
+
export declare function mergeAddressPointers(a: AddressPointer, b: AddressPointer): AddressPointer;
|
|
15
|
+
/** Merges two profile pointers and keeps all relays
|
|
16
|
+
* @throws if the pubkeys are different
|
|
17
|
+
*/
|
|
18
|
+
export declare function mergeProfilePointers(a: ProfilePointer, b: ProfilePointer): ProfilePointer;
|
package/dist/helpers/nip-19.js
CHANGED
|
@@ -2,6 +2,7 @@ import { nip19 } from "nostr-tools";
|
|
|
2
2
|
import { hexToBytes } from "@noble/hashes/utils";
|
|
3
3
|
import { isHexKey } from "./string.js";
|
|
4
4
|
import { getPubkeyFromDecodeResult } from "./pointers.js";
|
|
5
|
+
import { mergeRelaySets } from "./relays.js";
|
|
5
6
|
/** Gets the hex pubkey from any nip-19 encoded string */
|
|
6
7
|
export function normalizeToPubkey(str) {
|
|
7
8
|
if (isHexKey(str))
|
|
@@ -25,3 +26,31 @@ export function normalizeToSecretKey(str) {
|
|
|
25
26
|
return decode.data;
|
|
26
27
|
}
|
|
27
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Merges two event points and keeps all relays
|
|
31
|
+
* @throws if the ids are different
|
|
32
|
+
*/
|
|
33
|
+
export function mergeEventPointers(a, b) {
|
|
34
|
+
if (a.id !== b.id)
|
|
35
|
+
throw new Error("Cant merge event pointers with different ids");
|
|
36
|
+
const relays = mergeRelaySets(a.relays, b.relays);
|
|
37
|
+
return { id: a.id, kind: a.kind ?? b.kind, author: a.author ?? b.author, relays };
|
|
38
|
+
}
|
|
39
|
+
/** Merges two address pointers and keeps all relays
|
|
40
|
+
* @throws if the kinds, pubkeys, or identifiers are different
|
|
41
|
+
*/
|
|
42
|
+
export function mergeAddressPointers(a, b) {
|
|
43
|
+
if (a.kind !== b.kind || a.pubkey !== b.pubkey || a.identifier !== b.identifier)
|
|
44
|
+
throw new Error("Cant merge address pointers with different kinds, pubkeys, or identifiers");
|
|
45
|
+
const relays = mergeRelaySets(a.relays, b.relays);
|
|
46
|
+
return { ...a, relays };
|
|
47
|
+
}
|
|
48
|
+
/** Merges two profile pointers and keeps all relays
|
|
49
|
+
* @throws if the pubkeys are different
|
|
50
|
+
*/
|
|
51
|
+
export function mergeProfilePointers(a, b) {
|
|
52
|
+
if (a.pubkey !== b.pubkey)
|
|
53
|
+
throw new Error("Cant merge profile pointers with different pubkeys");
|
|
54
|
+
const relays = mergeRelaySets(a.relays, b.relays);
|
|
55
|
+
return { ...a, relays };
|
|
56
|
+
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
import { Observable } from "rxjs";
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Subscribes and returns the observables current or next value
|
|
4
|
+
* @deprecated use `firstValueFrom` instead
|
|
5
|
+
*/
|
|
3
6
|
export declare function getObservableValue<T>(observable: Observable<T>): T | Promise<T>;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { BehaviorSubject, firstValueFrom } from "rxjs";
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Subscribes and returns the observables current or next value
|
|
4
|
+
* @deprecated use `firstValueFrom` instead
|
|
5
|
+
*/
|
|
3
6
|
export function getObservableValue(observable) {
|
|
4
7
|
if (observable instanceof BehaviorSubject)
|
|
5
8
|
return observable.value;
|
package/dist/observable/index.js
CHANGED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { NostrEvent } from "nostr-tools";
|
|
2
|
+
import { MonoTypeOperatorFunction } from "rxjs";
|
|
3
|
+
import { IStreamEventStore } from "../event-store/interface.js";
|
|
4
|
+
/** Lists for any updates to the latest event and remits it */
|
|
5
|
+
export declare function listenLatestUpdates(eventStore: IStreamEventStore): MonoTypeOperatorFunction<NostrEvent | undefined>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { filter, merge, tap } from "rxjs";
|
|
2
|
+
/** Lists for any updates to the latest event and remits it */
|
|
3
|
+
export function listenLatestUpdates(eventStore) {
|
|
4
|
+
return (source) => {
|
|
5
|
+
let latest;
|
|
6
|
+
return merge(
|
|
7
|
+
// Get the latest event
|
|
8
|
+
source.pipe(tap((value) => (latest = value))),
|
|
9
|
+
// listen for updates
|
|
10
|
+
eventStore.updates.pipe(filter((e) => e.id === latest?.id)));
|
|
11
|
+
};
|
|
12
|
+
}
|
package/dist/queries/blossom.js
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
import { map } from "rxjs/operators";
|
|
2
2
|
import { BLOSSOM_SERVER_LIST_KIND, getBlossomServersFromList } from "../helpers/blossom.js";
|
|
3
3
|
export function UserBlossomServersQuery(pubkey) {
|
|
4
|
-
return
|
|
5
|
-
key: pubkey,
|
|
6
|
-
run: (store) => store
|
|
7
|
-
.replaceable(BLOSSOM_SERVER_LIST_KIND, pubkey)
|
|
8
|
-
.pipe(map((event) => event && getBlossomServersFromList(event))),
|
|
9
|
-
};
|
|
4
|
+
return (store) => store.replaceable(BLOSSOM_SERVER_LIST_KIND, pubkey).pipe(map((event) => event && getBlossomServersFromList(event)));
|
|
10
5
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Bookmarks } from "../helpers/bookmarks.js";
|
|
2
2
|
import { Query } from "../query-store/index.js";
|
|
3
|
+
/** A query that returns all the bookmarks of a user */
|
|
3
4
|
export declare function UserBookmarkQuery(pubkey: string): Query<Bookmarks | undefined>;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} | undefined>;
|
|
5
|
+
/** A query that returns all the public bookmarks of a user */
|
|
6
|
+
export declare function UserPublicBookmarkQuery(pubkey: string): Query<Bookmarks | undefined>;
|
|
7
|
+
/** A query that returns all the hidden bookmarks of a user */
|
|
8
|
+
export declare function UserHiddenBookmarkQuery(pubkey: string): Query<Bookmarks | null | undefined>;
|
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
import { kinds } from "nostr-tools";
|
|
2
2
|
import { map } from "rxjs/operators";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { getBookmarks, getHiddenBookmarks, getPublicBookmarks } from "../helpers/bookmarks.js";
|
|
4
|
+
import { listenLatestUpdates } from "../observable/index.js";
|
|
5
|
+
/** A query that returns all the bookmarks of a user */
|
|
5
6
|
export function UserBookmarkQuery(pubkey) {
|
|
6
|
-
return
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
return (events) => events.replaceable(kinds.Mutelist, pubkey).pipe(
|
|
8
|
+
// listen for event updates (hidden tags unlocked)
|
|
9
|
+
listenLatestUpdates(events),
|
|
10
|
+
// Get all bookmarks
|
|
11
|
+
map((event) => event && getBookmarks(event)));
|
|
10
12
|
}
|
|
13
|
+
/** A query that returns all the public bookmarks of a user */
|
|
14
|
+
export function UserPublicBookmarkQuery(pubkey) {
|
|
15
|
+
return (events) => events.replaceable(kinds.Mutelist, pubkey).pipe(map((event) => event && getPublicBookmarks(event)));
|
|
16
|
+
}
|
|
17
|
+
/** A query that returns all the hidden bookmarks of a user */
|
|
11
18
|
export function UserHiddenBookmarkQuery(pubkey) {
|
|
12
|
-
return
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const bookmarks = getHiddenBookmarks(event);
|
|
18
|
-
if (isHiddenTagsLocked(event) || !bookmarks)
|
|
19
|
-
return { locked: true };
|
|
20
|
-
return { locked: false, ...bookmarks };
|
|
21
|
-
})),
|
|
22
|
-
};
|
|
19
|
+
return (events) => events.replaceable(kinds.Mutelist, pubkey).pipe(
|
|
20
|
+
// listen for event updates (hidden tags unlocked)
|
|
21
|
+
listenLatestUpdates(events),
|
|
22
|
+
// Get hidden bookmarks
|
|
23
|
+
map((event) => event && (getHiddenBookmarks(event) ?? null)));
|
|
23
24
|
}
|