applesauce-core 0.9.0 → 0.11.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/README.md +1 -1
- package/dist/__tests__/fixtures.d.ts +8 -0
- package/dist/__tests__/fixtures.js +20 -0
- package/dist/event-store/__tests__/event-store.test.js +259 -0
- package/dist/event-store/database.d.ts +22 -16
- package/dist/event-store/database.js +62 -39
- package/dist/event-store/event-store.d.ts +52 -15
- package/dist/event-store/event-store.js +283 -191
- package/dist/helpers/__tests__/blossom.test.d.ts +1 -0
- package/dist/helpers/__tests__/blossom.test.js +13 -0
- package/dist/helpers/__tests__/comment.test.d.ts +1 -0
- package/dist/helpers/__tests__/comment.test.js +235 -0
- package/dist/helpers/__tests__/emoji.test.d.ts +1 -0
- package/dist/helpers/__tests__/emoji.test.js +15 -0
- package/dist/helpers/__tests__/event.test.d.ts +1 -0
- package/dist/helpers/__tests__/event.test.js +36 -0
- package/dist/helpers/__tests__/file-metadata.test.d.ts +1 -0
- package/dist/helpers/__tests__/file-metadata.test.js +103 -0
- package/dist/helpers/__tests__/hidden-tags.test.d.ts +1 -0
- package/dist/helpers/__tests__/hidden-tags.test.js +29 -0
- package/dist/helpers/__tests__/mailboxes.test.d.ts +1 -0
- package/dist/helpers/{mailboxes.test.js → __tests__/mailboxes.test.js} +14 -13
- package/dist/helpers/__tests__/relays.test.d.ts +1 -0
- package/dist/helpers/__tests__/relays.test.js +21 -0
- package/dist/helpers/__tests__/tags.test.d.ts +1 -0
- package/dist/helpers/__tests__/tags.test.js +24 -0
- package/dist/helpers/__tests__/threading.test.d.ts +1 -0
- package/dist/helpers/__tests__/threading.test.js +41 -0
- package/dist/helpers/blossom.d.ts +9 -0
- package/dist/helpers/blossom.js +22 -0
- package/dist/helpers/bolt11.d.ts +1 -0
- package/dist/helpers/bolt11.js +1 -0
- package/dist/helpers/bookmarks.d.ts +15 -0
- package/dist/helpers/bookmarks.js +27 -0
- package/dist/helpers/channels.d.ts +10 -0
- package/dist/helpers/channels.js +27 -0
- package/dist/helpers/comment.d.ts +47 -0
- package/dist/helpers/comment.js +120 -0
- package/dist/helpers/contacts.d.ts +3 -0
- package/dist/helpers/contacts.js +25 -0
- package/dist/helpers/content.d.ts +3 -0
- package/dist/helpers/content.js +8 -0
- package/dist/helpers/delete.d.ts +3 -0
- package/dist/helpers/delete.js +7 -0
- package/dist/helpers/dns-identity.d.ts +7 -0
- package/dist/helpers/dns-identity.js +10 -0
- package/dist/helpers/emoji.d.ts +12 -1
- package/dist/helpers/emoji.js +13 -1
- package/dist/helpers/event.d.ts +17 -3
- package/dist/helpers/event.js +54 -12
- package/dist/helpers/external-id.d.ts +29 -0
- package/dist/helpers/external-id.js +20 -0
- package/dist/helpers/file-metadata.d.ts +55 -0
- package/dist/helpers/file-metadata.js +99 -0
- package/dist/helpers/filter.d.ts +4 -2
- package/dist/helpers/filter.js +36 -7
- package/dist/helpers/groups.d.ts +24 -0
- package/dist/helpers/groups.js +39 -0
- package/dist/helpers/hidden-tags.d.ts +48 -0
- package/dist/helpers/hidden-tags.js +86 -0
- package/dist/helpers/index.d.ts +28 -8
- package/dist/helpers/index.js +28 -8
- package/dist/helpers/json.d.ts +1 -0
- package/dist/helpers/json.js +1 -0
- package/dist/helpers/lists.d.ts +28 -0
- package/dist/helpers/lists.js +65 -0
- package/dist/helpers/lnurl.d.ts +4 -0
- package/dist/helpers/lnurl.js +40 -0
- package/dist/helpers/mailboxes.js +16 -9
- package/dist/helpers/mutes.d.ts +14 -0
- package/dist/helpers/mutes.js +23 -0
- package/dist/helpers/picture-post.d.ts +4 -0
- package/dist/helpers/picture-post.js +6 -0
- package/dist/helpers/pointers.d.ts +38 -5
- package/dist/helpers/pointers.js +105 -25
- package/dist/helpers/profile.d.ts +6 -1
- package/dist/helpers/profile.js +5 -1
- package/dist/helpers/relays.d.ts +6 -3
- package/dist/helpers/relays.js +25 -18
- package/dist/helpers/share.d.ts +4 -0
- package/dist/helpers/share.js +12 -0
- package/dist/helpers/string.d.ts +6 -0
- package/dist/helpers/string.js +2 -0
- package/dist/helpers/tags.d.ts +23 -0
- package/dist/helpers/tags.js +34 -6
- package/dist/helpers/threading.d.ts +6 -6
- package/dist/helpers/threading.js +30 -9
- package/dist/helpers/url.d.ts +11 -1
- package/dist/helpers/url.js +31 -3
- package/dist/helpers/user-status.d.ts +18 -0
- package/dist/helpers/user-status.js +21 -0
- package/dist/helpers/zap.d.ts +25 -0
- package/dist/helpers/zap.js +32 -3
- package/dist/observable/__tests__/claim-events.test.d.ts +1 -0
- package/dist/observable/__tests__/claim-events.test.js +23 -0
- package/dist/observable/__tests__/claim-latest.test.d.ts +1 -0
- package/dist/observable/__tests__/claim-latest.test.js +37 -0
- package/dist/observable/__tests__/simple-timeout.test.d.ts +1 -0
- package/dist/observable/__tests__/simple-timeout.test.js +34 -0
- package/dist/observable/claim-events.d.ts +5 -0
- package/dist/observable/claim-events.js +28 -0
- package/dist/observable/claim-latest.d.ts +4 -0
- package/dist/observable/claim-latest.js +20 -0
- package/dist/observable/get-observable-value.d.ts +3 -0
- package/dist/observable/get-observable-value.js +9 -0
- package/dist/observable/index.d.ts +2 -1
- package/dist/observable/index.js +2 -1
- package/dist/observable/share-latest-value.d.ts +2 -4
- package/dist/observable/share-latest-value.js +19 -16
- package/dist/observable/simple-timeout.d.ts +4 -0
- package/dist/observable/simple-timeout.js +6 -0
- package/dist/promise/deferred.d.ts +1 -0
- package/dist/promise/deferred.js +1 -0
- package/dist/queries/blossom.d.ts +2 -0
- package/dist/queries/blossom.js +10 -0
- package/dist/queries/bookmarks.d.ts +8 -0
- package/dist/queries/bookmarks.js +23 -0
- package/dist/queries/channels.d.ts +11 -0
- package/dist/queries/channels.js +73 -0
- package/dist/queries/comments.d.ts +4 -0
- package/dist/queries/comments.js +14 -0
- package/dist/queries/contacts.d.ts +3 -0
- package/dist/queries/contacts.js +12 -0
- package/dist/queries/index.d.ts +9 -2
- package/dist/queries/index.js +9 -2
- package/dist/queries/mailboxes.d.ts +1 -0
- package/dist/queries/mailboxes.js +1 -0
- package/dist/queries/mutes.d.ts +8 -0
- package/dist/queries/mutes.js +23 -0
- package/dist/queries/pins.d.ts +3 -0
- package/dist/queries/pins.js +12 -0
- package/dist/queries/profile.d.ts +1 -0
- package/dist/queries/profile.js +1 -0
- package/dist/queries/reactions.d.ts +1 -1
- package/dist/queries/reactions.js +1 -1
- package/dist/queries/simple.d.ts +4 -4
- package/dist/queries/simple.js +13 -13
- package/dist/queries/thread.d.ts +2 -0
- package/dist/queries/thread.js +30 -4
- package/dist/queries/user-status.d.ts +11 -0
- package/dist/queries/user-status.js +39 -0
- package/dist/queries/zaps.d.ts +1 -0
- package/dist/queries/zaps.js +1 -0
- package/dist/query-store/index.d.ts +1 -47
- package/dist/query-store/index.js +1 -60
- package/dist/query-store/query-store.d.ts +51 -0
- package/dist/query-store/query-store.js +88 -0
- package/dist/query-store/query-store.test.d.ts +1 -0
- package/dist/query-store/query-store.test.js +33 -0
- package/package.json +24 -21
- package/dist/observable/getValue.d.ts +0 -2
- package/dist/observable/getValue.js +0 -13
- /package/dist/{helpers/mailboxes.test.d.ts → event-store/__tests__/event-store.test.d.ts} +0 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { isNameValueTag, processTags } from "./tags.js";
|
|
2
|
+
export const BLOSSOM_SERVER_LIST_KIND = 10063;
|
|
3
|
+
/** Check if two servers are the same */
|
|
4
|
+
export function areBlossomServersEqual(a, b) {
|
|
5
|
+
const hostnameA = new URL("/", a).toString();
|
|
6
|
+
const hostnameB = new URL("/", b).toString();
|
|
7
|
+
return hostnameA === hostnameB;
|
|
8
|
+
}
|
|
9
|
+
/** Checks if a string is a sha256 hash */
|
|
10
|
+
export function isSha256(str) {
|
|
11
|
+
return !!str.match(/^[0-9a-f]{64}$/);
|
|
12
|
+
}
|
|
13
|
+
/** Returns an ordered array of servers found in a server list event (10063) */
|
|
14
|
+
export function getBlossomServersFromList(event) {
|
|
15
|
+
const tags = Array.isArray(event) ? event : event.tags;
|
|
16
|
+
return processTags(tags, (tag) => {
|
|
17
|
+
if (isNameValueTag(tag, "server") && URL.canParse(tag[1]))
|
|
18
|
+
return new URL("/", tag[1]);
|
|
19
|
+
else
|
|
20
|
+
return undefined;
|
|
21
|
+
});
|
|
22
|
+
}
|
package/dist/helpers/bolt11.d.ts
CHANGED
package/dist/helpers/bolt11.js
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { NostrEvent } from "nostr-tools";
|
|
2
|
+
import { AddressPointer, EventPointer } from "nostr-tools/nip19";
|
|
3
|
+
export declare const BookmarkPublicSymbol: unique symbol;
|
|
4
|
+
export declare const BookmarkHiddenSymbol: unique symbol;
|
|
5
|
+
export type Bookmarks = {
|
|
6
|
+
notes: EventPointer[];
|
|
7
|
+
articles: AddressPointer[];
|
|
8
|
+
hashtags: string[];
|
|
9
|
+
urls: string[];
|
|
10
|
+
};
|
|
11
|
+
export declare function parseBookmarkTags(tags: string[][]): Bookmarks;
|
|
12
|
+
/** Returns the public bookmarks of the event */
|
|
13
|
+
export declare function getBookmarks(bookmark: NostrEvent): Bookmarks;
|
|
14
|
+
/** Returns the bookmarks of the event if its unlocked */
|
|
15
|
+
export declare function getHiddenBookmarks(bookmark: NostrEvent): Bookmarks | undefined;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { kinds } from "nostr-tools";
|
|
2
|
+
import { getAddressPointerFromATag, getEventPointerFromETag } from "./pointers.js";
|
|
3
|
+
import { getOrComputeCachedValue } from "./cache.js";
|
|
4
|
+
import { getHiddenTags } from "./index.js";
|
|
5
|
+
export const BookmarkPublicSymbol = Symbol.for("bookmark-public");
|
|
6
|
+
export const BookmarkHiddenSymbol = Symbol.for("bookmark-hidden");
|
|
7
|
+
export function parseBookmarkTags(tags) {
|
|
8
|
+
const notes = tags.filter((t) => t[0] === "e" && t[1]).map(getEventPointerFromETag);
|
|
9
|
+
const articles = tags
|
|
10
|
+
.filter((t) => t[0] === "a" && t[1])
|
|
11
|
+
.map(getAddressPointerFromATag)
|
|
12
|
+
.filter((addr) => addr.kind === kinds.LongFormArticle);
|
|
13
|
+
const hashtags = tags.filter((t) => t[0] === "t" && t[1]).map((t) => t[1]);
|
|
14
|
+
const urls = tags.filter((t) => t[0] === "r" && t[1]).map((t) => t[1]);
|
|
15
|
+
return { notes, articles, hashtags, urls };
|
|
16
|
+
}
|
|
17
|
+
/** Returns the public bookmarks of the event */
|
|
18
|
+
export function getBookmarks(bookmark) {
|
|
19
|
+
return getOrComputeCachedValue(bookmark, BookmarkPublicSymbol, () => parseBookmarkTags(bookmark.tags));
|
|
20
|
+
}
|
|
21
|
+
/** Returns the bookmarks of the event if its unlocked */
|
|
22
|
+
export function getHiddenBookmarks(bookmark) {
|
|
23
|
+
return getOrComputeCachedValue(bookmark, BookmarkHiddenSymbol, () => {
|
|
24
|
+
const tags = getHiddenTags(bookmark);
|
|
25
|
+
return tags && parseBookmarkTags(tags);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { nip19, NostrEvent } from "nostr-tools";
|
|
2
|
+
import { ChannelMetadata } from "nostr-tools/nip28";
|
|
3
|
+
export declare const ChannelMetadataSymbol: unique symbol;
|
|
4
|
+
export type ChannelMetadataContent = ChannelMetadata & {
|
|
5
|
+
relays?: string[];
|
|
6
|
+
};
|
|
7
|
+
/** Gets the parsed metadata on a channel creation or channel metadata event */
|
|
8
|
+
export declare function getChannelMetadataContent(channel: NostrEvent): ChannelMetadataContent;
|
|
9
|
+
/** gets the EventPointer for a channel message or metadata event */
|
|
10
|
+
export declare function getChannelPointer(event: NostrEvent): nip19.EventPointer | undefined;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { getOrComputeCachedValue } from "./cache.js";
|
|
2
|
+
export const ChannelMetadataSymbol = Symbol.for("channel-metadata");
|
|
3
|
+
function parseChannelMetadataContent(channel) {
|
|
4
|
+
const metadata = JSON.parse(channel.content);
|
|
5
|
+
if (metadata.name === undefined)
|
|
6
|
+
throw new Error("Missing name");
|
|
7
|
+
if (metadata.about === undefined)
|
|
8
|
+
throw new Error("Missing about");
|
|
9
|
+
if (metadata.picture === undefined)
|
|
10
|
+
throw new Error("Missing picture");
|
|
11
|
+
if (metadata.relays && !Array.isArray(metadata.relays))
|
|
12
|
+
throw new Error("Invalid relays");
|
|
13
|
+
return metadata;
|
|
14
|
+
}
|
|
15
|
+
/** Gets the parsed metadata on a channel creation or channel metadata event */
|
|
16
|
+
export function getChannelMetadataContent(channel) {
|
|
17
|
+
return getOrComputeCachedValue(channel, ChannelMetadataSymbol, () => {
|
|
18
|
+
return parseChannelMetadataContent(channel);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
/** gets the EventPointer for a channel message or metadata event */
|
|
22
|
+
export function getChannelPointer(event) {
|
|
23
|
+
const tag = event.tags.find((t) => t[0] === "e" && t[1]);
|
|
24
|
+
if (!tag)
|
|
25
|
+
return undefined;
|
|
26
|
+
return tag[2] ? { id: tag[1], relays: [tag[2]] } : { id: tag[1] };
|
|
27
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { NostrEvent } from "nostr-tools";
|
|
2
|
+
import { ExternalPointer, ExternalIdentifiers } from "./external-id.js";
|
|
3
|
+
export declare const COMMENT_KIND = 1111;
|
|
4
|
+
export type CommentEventPointer = {
|
|
5
|
+
id: string;
|
|
6
|
+
kind: number;
|
|
7
|
+
pubkey?: string;
|
|
8
|
+
relay?: string;
|
|
9
|
+
};
|
|
10
|
+
export type CommentAddressPointer = {
|
|
11
|
+
id?: string;
|
|
12
|
+
kind: number;
|
|
13
|
+
pubkey: string;
|
|
14
|
+
identifier: string;
|
|
15
|
+
relay?: string;
|
|
16
|
+
};
|
|
17
|
+
export type CommentExternalPointer = ExternalPointer<keyof ExternalIdentifiers>;
|
|
18
|
+
export type CommentPointer = CommentEventPointer | CommentAddressPointer | CommentExternalPointer;
|
|
19
|
+
export declare const CommentRootPointerSymbol: unique symbol;
|
|
20
|
+
export declare const CommentReplyPointerSymbol: unique symbol;
|
|
21
|
+
/**
|
|
22
|
+
* Gets the EventPointer from an array of tags
|
|
23
|
+
* @throws
|
|
24
|
+
*/
|
|
25
|
+
export declare function getCommentEventPointer(tags: string[][], root?: boolean): CommentEventPointer | null;
|
|
26
|
+
/**
|
|
27
|
+
* Gets the AddressPointer from an array of tags
|
|
28
|
+
* @throws
|
|
29
|
+
*/
|
|
30
|
+
export declare function getCommentAddressPointer(tags: string[][], root?: boolean): CommentAddressPointer | null;
|
|
31
|
+
/**
|
|
32
|
+
* Gets the ExternalPointer from an array of tags
|
|
33
|
+
* @throws
|
|
34
|
+
*/
|
|
35
|
+
export declare function getCommentExternalPointer(tags: string[][], root?: boolean): CommentExternalPointer | null;
|
|
36
|
+
/**
|
|
37
|
+
* Returns the root pointer for a comment
|
|
38
|
+
* @throws
|
|
39
|
+
*/
|
|
40
|
+
export declare function getCommentRootPointer(comment: NostrEvent): CommentPointer | null;
|
|
41
|
+
/**
|
|
42
|
+
* Returns the reply pointer for a comment
|
|
43
|
+
* @throws
|
|
44
|
+
*/
|
|
45
|
+
export declare function getCommentReplyPointer(comment: NostrEvent): CommentPointer | null;
|
|
46
|
+
export declare function isCommentEventPointer(pointer: any): pointer is CommentEventPointer;
|
|
47
|
+
export declare function isCommentAddressPointer(pointer: any): pointer is CommentAddressPointer;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { getExternalPointerFromTag } from "./external-id.js";
|
|
2
|
+
import { getOrComputeCachedValue } from "./cache.js";
|
|
3
|
+
import { getAddressPointerFromATag } from "./pointers.js";
|
|
4
|
+
import { isSafeRelayURL } from "./relays.js";
|
|
5
|
+
export const COMMENT_KIND = 1111;
|
|
6
|
+
export const CommentRootPointerSymbol = Symbol.for("comment-root-pointer");
|
|
7
|
+
export const CommentReplyPointerSymbol = Symbol.for("comment-reply-pointer");
|
|
8
|
+
/**
|
|
9
|
+
* Gets the EventPointer from an array of tags
|
|
10
|
+
* @throws
|
|
11
|
+
*/
|
|
12
|
+
export function getCommentEventPointer(tags, root = false) {
|
|
13
|
+
const eTag = tags.find((t) => t[0] === (root ? "E" : "e"));
|
|
14
|
+
const kind = tags.find((t) => t[0] === (root ? "K" : "k"))?.[1];
|
|
15
|
+
if (eTag) {
|
|
16
|
+
if (!kind)
|
|
17
|
+
throw new Error("Missing kind tag");
|
|
18
|
+
// only the root pubkey can be gotten from the tags, since due to quotes and mentions there will be many "p" tags for replies
|
|
19
|
+
const rootPubkey = root ? tags.find((t) => t[0] === "P")?.[1] : undefined;
|
|
20
|
+
const pointer = {
|
|
21
|
+
id: eTag[1],
|
|
22
|
+
kind: parseInt(kind),
|
|
23
|
+
pubkey: eTag[3] || rootPubkey || undefined,
|
|
24
|
+
relay: eTag[2] && isSafeRelayURL(eTag[2]) ? eTag[2] : undefined,
|
|
25
|
+
};
|
|
26
|
+
return pointer;
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Gets the AddressPointer from an array of tags
|
|
32
|
+
* @throws
|
|
33
|
+
*/
|
|
34
|
+
export function getCommentAddressPointer(tags, root = false) {
|
|
35
|
+
const aTag = tags.find((t) => t[0] === (root ? "A" : "a"));
|
|
36
|
+
const eTag = tags.find((t) => t[0] === (root ? "E" : "e"));
|
|
37
|
+
const kind = tags.find((t) => t[0] === (root ? "K" : "k"))?.[1];
|
|
38
|
+
if (aTag) {
|
|
39
|
+
if (!kind)
|
|
40
|
+
throw new Error("Missing kind tag");
|
|
41
|
+
const addressPointer = getAddressPointerFromATag(aTag);
|
|
42
|
+
const pointer = {
|
|
43
|
+
id: eTag?.[1],
|
|
44
|
+
pubkey: addressPointer.pubkey,
|
|
45
|
+
identifier: addressPointer.identifier,
|
|
46
|
+
kind: addressPointer.kind || parseInt(kind),
|
|
47
|
+
relay: addressPointer.relays?.[0] || eTag?.[2],
|
|
48
|
+
};
|
|
49
|
+
return pointer;
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Gets the ExternalPointer from an array of tags
|
|
55
|
+
* @throws
|
|
56
|
+
*/
|
|
57
|
+
export function getCommentExternalPointer(tags, root = false) {
|
|
58
|
+
const iTag = tags.find((t) => t[0] === (root ? "I" : "i"));
|
|
59
|
+
const kind = tags.find((t) => t[0] === (root ? "K" : "k"))?.[1];
|
|
60
|
+
if (iTag) {
|
|
61
|
+
if (!kind)
|
|
62
|
+
throw new Error("Missing kind tag");
|
|
63
|
+
return getExternalPointerFromTag(iTag);
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Returns the root pointer for a comment
|
|
69
|
+
* @throws
|
|
70
|
+
*/
|
|
71
|
+
export function getCommentRootPointer(comment) {
|
|
72
|
+
if (comment.kind !== COMMENT_KIND)
|
|
73
|
+
throw new Error("Event is not a comment");
|
|
74
|
+
return getOrComputeCachedValue(comment, CommentRootPointerSymbol, () => {
|
|
75
|
+
// check for address pointer first since it can also have E tags
|
|
76
|
+
const A = getCommentAddressPointer(comment.tags, true);
|
|
77
|
+
if (A)
|
|
78
|
+
return A;
|
|
79
|
+
const E = getCommentEventPointer(comment.tags, true);
|
|
80
|
+
if (E)
|
|
81
|
+
return E;
|
|
82
|
+
const I = getCommentExternalPointer(comment.tags, true);
|
|
83
|
+
if (I)
|
|
84
|
+
return I;
|
|
85
|
+
return null;
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Returns the reply pointer for a comment
|
|
90
|
+
* @throws
|
|
91
|
+
*/
|
|
92
|
+
export function getCommentReplyPointer(comment) {
|
|
93
|
+
if (comment.kind !== COMMENT_KIND)
|
|
94
|
+
throw new Error("Event is not a comment");
|
|
95
|
+
return getOrComputeCachedValue(comment, CommentReplyPointerSymbol, () => {
|
|
96
|
+
// check for address pointer first since it can also have E tags
|
|
97
|
+
const A = getCommentAddressPointer(comment.tags, false);
|
|
98
|
+
if (A)
|
|
99
|
+
return A;
|
|
100
|
+
const E = getCommentEventPointer(comment.tags, false);
|
|
101
|
+
if (E)
|
|
102
|
+
return E;
|
|
103
|
+
const I = getCommentExternalPointer(comment.tags, false);
|
|
104
|
+
if (I)
|
|
105
|
+
return I;
|
|
106
|
+
return null;
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
export function isCommentEventPointer(pointer) {
|
|
110
|
+
return (Reflect.has(pointer, "id") &&
|
|
111
|
+
Reflect.has(pointer, "kind") &&
|
|
112
|
+
!Reflect.has(pointer, "identifier") &&
|
|
113
|
+
typeof pointer.kind === "number");
|
|
114
|
+
}
|
|
115
|
+
export function isCommentAddressPointer(pointer) {
|
|
116
|
+
return (Reflect.has(pointer, "identifier") &&
|
|
117
|
+
Reflect.has(pointer, "pubkey") &&
|
|
118
|
+
Reflect.has(pointer, "kind") &&
|
|
119
|
+
typeof pointer.kind === "number");
|
|
120
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { getOrComputeCachedValue } from "./cache.js";
|
|
2
|
+
import { isSafeRelayURL } from "./relays.js";
|
|
3
|
+
export const ContactsRelaysSymbol = Symbol.for("contacts-relays");
|
|
4
|
+
export function getRelaysFromContactsEvent(event) {
|
|
5
|
+
return getOrComputeCachedValue(event, ContactsRelaysSymbol, () => {
|
|
6
|
+
try {
|
|
7
|
+
const relayJson = JSON.parse(event.content);
|
|
8
|
+
const relays = new Map();
|
|
9
|
+
for (const [url, opts] of Object.entries(relayJson)) {
|
|
10
|
+
if (!isSafeRelayURL(url))
|
|
11
|
+
continue;
|
|
12
|
+
if (opts.write && opts.read)
|
|
13
|
+
relays.set(url, "all");
|
|
14
|
+
else if (opts.read)
|
|
15
|
+
relays.set(url, "inbox");
|
|
16
|
+
else if (opts.write)
|
|
17
|
+
relays.set(url, "outbox");
|
|
18
|
+
}
|
|
19
|
+
return relays;
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Returns the NIP-36 content-warning for an event. returns boolean if there is no "reason" */
|
|
2
|
+
export function getContentWarning(event) {
|
|
3
|
+
const tag = event.tags.find((t) => t[0] === "content-warning");
|
|
4
|
+
if (tag)
|
|
5
|
+
return tag[1] || true;
|
|
6
|
+
else
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { isATag, isETag } from "./tags.js";
|
|
2
|
+
export function getDeleteIds(deleteEvent) {
|
|
3
|
+
return deleteEvent.tags.filter(isETag).map((t) => t[1]);
|
|
4
|
+
}
|
|
5
|
+
export function getDeleteCoordinates(deleteEvent) {
|
|
6
|
+
return deleteEvent.tags.filter(isATag).map((t) => t[1]);
|
|
7
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { isNip05, NIP05_REGEX } from "nostr-tools/nip05";
|
|
2
|
+
/** Returns the name and domain for a NIP-05 address */
|
|
3
|
+
export function parseNIP05Address(address) {
|
|
4
|
+
const match = address.toLowerCase().match(NIP05_REGEX);
|
|
5
|
+
if (!match)
|
|
6
|
+
return null;
|
|
7
|
+
const [, name = "_", domain] = match;
|
|
8
|
+
return { name, domain };
|
|
9
|
+
}
|
|
10
|
+
export { isNip05, NIP05_REGEX };
|
package/dist/helpers/emoji.d.ts
CHANGED
|
@@ -1,2 +1,13 @@
|
|
|
1
1
|
import { EventTemplate, NostrEvent } from "nostr-tools";
|
|
2
|
-
|
|
2
|
+
/** Gets an "emoji" tag that matches an emoji code */
|
|
3
|
+
export declare function getEmojiTag(event: NostrEvent | EventTemplate, code: string): ["emoji", string, string] | undefined;
|
|
4
|
+
/** Returns the name of a NIP-30 emoji pack */
|
|
5
|
+
export declare function getPackName(pack: NostrEvent): string | undefined;
|
|
6
|
+
export type Emoji = {
|
|
7
|
+
/** The emoji shortcode (without the ::) */
|
|
8
|
+
shortcode: string;
|
|
9
|
+
/** The URL to the emoji image */
|
|
10
|
+
url: string;
|
|
11
|
+
};
|
|
12
|
+
/** Returns an array of emojis from a NIP-30 emoji pack */
|
|
13
|
+
export declare function getEmojis(pack: NostrEvent): Emoji[];
|
package/dist/helpers/emoji.js
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
|
+
import { getTagValue } from "./event.js";
|
|
2
|
+
/** Gets an "emoji" tag that matches an emoji code */
|
|
1
3
|
export function getEmojiTag(event, code) {
|
|
2
4
|
code = code.replace(/^:|:$/g, "").toLocaleLowerCase();
|
|
3
|
-
return event.tags.
|
|
5
|
+
return event.tags.find((t) => t[0] === "emoji" && t.length >= 3 && t[1].toLowerCase() === code);
|
|
6
|
+
}
|
|
7
|
+
/** Returns the name of a NIP-30 emoji pack */
|
|
8
|
+
export function getPackName(pack) {
|
|
9
|
+
return getTagValue(pack, "title") || getTagValue(pack, "d");
|
|
10
|
+
}
|
|
11
|
+
/** Returns an array of emojis from a NIP-30 emoji pack */
|
|
12
|
+
export function getEmojis(pack) {
|
|
13
|
+
return pack.tags
|
|
14
|
+
.filter((t) => t[0] === "emoji" && t[1] && t[2])
|
|
15
|
+
.map((t) => ({ shortcode: t[1], url: t[2] }));
|
|
4
16
|
}
|
package/dist/helpers/event.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { NostrEvent, VerifiedEvent } from "nostr-tools";
|
|
1
|
+
import { EventTemplate, NostrEvent, VerifiedEvent } from "nostr-tools";
|
|
2
2
|
export declare const EventUIDSymbol: unique symbol;
|
|
3
3
|
export declare const EventIndexableTagsSymbol: unique symbol;
|
|
4
4
|
export declare const FromCacheSymbol: unique symbol;
|
|
5
|
+
export declare const ReplaceableIdentifierSymbol: unique symbol;
|
|
5
6
|
declare module "nostr-tools" {
|
|
6
7
|
interface Event {
|
|
7
8
|
[EventUIDSymbol]?: string;
|
|
@@ -9,6 +10,11 @@ declare module "nostr-tools" {
|
|
|
9
10
|
[FromCacheSymbol]?: boolean;
|
|
10
11
|
}
|
|
11
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Checks if an object is a nostr event
|
|
15
|
+
* NOTE: does not validation the signature on the event
|
|
16
|
+
*/
|
|
17
|
+
export declare function isEvent(event: any): event is NostrEvent;
|
|
12
18
|
/**
|
|
13
19
|
* Returns if a kind is replaceable ( 10000 <= n < 20000 || n == 0 || n == 3 )
|
|
14
20
|
* or parameterized replaceable ( 30000 <= n < 40000 )
|
|
@@ -24,11 +30,19 @@ export declare function getEventUID(event: NostrEvent): string;
|
|
|
24
30
|
export declare function getReplaceableUID(kind: number, pubkey: string, d?: string): string;
|
|
25
31
|
/** Returns a Set of tag names and values that are indexable */
|
|
26
32
|
export declare function getIndexableTags(event: NostrEvent): Set<string>;
|
|
27
|
-
/**
|
|
28
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Returns the second index ( tag[1] ) of the first tag that matches the name
|
|
35
|
+
* If the event has any hidden tags they will be searched first
|
|
36
|
+
*/
|
|
37
|
+
export declare function getTagValue(event: NostrEvent | EventTemplate, name: string): string | undefined;
|
|
29
38
|
/** Sets events verified flag without checking anything */
|
|
30
39
|
export declare function fakeVerifyEvent(event: NostrEvent): event is VerifiedEvent;
|
|
31
40
|
/** Marks an event as being from a cache */
|
|
32
41
|
export declare function markFromCache(event: NostrEvent): void;
|
|
33
42
|
/** Returns if an event was from a cache */
|
|
34
43
|
export declare function isFromCache(event: NostrEvent): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Returns the replaceable identifier for a replaceable event
|
|
46
|
+
* @throws
|
|
47
|
+
*/
|
|
48
|
+
export declare function getReplaceableIdentifier(event: NostrEvent): string;
|
package/dist/helpers/event.js
CHANGED
|
@@ -1,8 +1,28 @@
|
|
|
1
1
|
import { kinds, verifiedSymbol } from "nostr-tools";
|
|
2
2
|
import { INDEXABLE_TAGS } from "../event-store/common.js";
|
|
3
|
+
import { getHiddenTags } from "./hidden-tags.js";
|
|
4
|
+
import { getOrComputeCachedValue } from "./cache.js";
|
|
5
|
+
import { isParameterizedReplaceableKind } from "nostr-tools/kinds";
|
|
3
6
|
export const EventUIDSymbol = Symbol.for("event-uid");
|
|
4
7
|
export const EventIndexableTagsSymbol = Symbol.for("indexable-tags");
|
|
5
8
|
export const FromCacheSymbol = Symbol.for("from-cache");
|
|
9
|
+
export const ReplaceableIdentifierSymbol = Symbol.for("replaceable-identifier");
|
|
10
|
+
/**
|
|
11
|
+
* Checks if an object is a nostr event
|
|
12
|
+
* NOTE: does not validation the signature on the event
|
|
13
|
+
*/
|
|
14
|
+
export function isEvent(event) {
|
|
15
|
+
if (event === undefined || event === null)
|
|
16
|
+
return false;
|
|
17
|
+
return (event.id?.length === 64 &&
|
|
18
|
+
typeof event.sig === "string" &&
|
|
19
|
+
typeof event.pubkey === "string" &&
|
|
20
|
+
event.pubkey.length === 64 &&
|
|
21
|
+
typeof event.content === "string" &&
|
|
22
|
+
Array.isArray(event.tags) &&
|
|
23
|
+
typeof event.created_at === "number" &&
|
|
24
|
+
event.created_at > 0);
|
|
25
|
+
}
|
|
6
26
|
/**
|
|
7
27
|
* Returns if a kind is replaceable ( 10000 <= n < 20000 || n == 0 || n == 3 )
|
|
8
28
|
* or parameterized replaceable ( 30000 <= n < 40000 )
|
|
@@ -17,20 +37,20 @@ export function isReplaceable(kind) {
|
|
|
17
37
|
* For parametrized replaceable events this is ( event.kind + ":" + event.pubkey + ":" + event.tags.d.1 )
|
|
18
38
|
*/
|
|
19
39
|
export function getEventUID(event) {
|
|
20
|
-
let
|
|
21
|
-
if (!
|
|
40
|
+
let uid = event[EventUIDSymbol];
|
|
41
|
+
if (!uid) {
|
|
22
42
|
if (isReplaceable(event.kind)) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
id = event.id;
|
|
43
|
+
let d = event.tags.find((t) => t[0] === "d")?.[1];
|
|
44
|
+
uid = getReplaceableUID(event.kind, event.pubkey, d);
|
|
28
45
|
}
|
|
46
|
+
else
|
|
47
|
+
uid = event.id;
|
|
48
|
+
event[EventUIDSymbol] = uid;
|
|
29
49
|
}
|
|
30
|
-
return
|
|
50
|
+
return uid;
|
|
31
51
|
}
|
|
32
52
|
export function getReplaceableUID(kind, pubkey, d) {
|
|
33
|
-
return d ?
|
|
53
|
+
return d ? kind + ":" + pubkey + ":" + d : kind + ":" + pubkey;
|
|
34
54
|
}
|
|
35
55
|
/** Returns a Set of tag names and values that are indexable */
|
|
36
56
|
export function getIndexableTags(event) {
|
|
@@ -38,7 +58,7 @@ export function getIndexableTags(event) {
|
|
|
38
58
|
if (!indexable) {
|
|
39
59
|
const tags = new Set();
|
|
40
60
|
for (const tag of event.tags) {
|
|
41
|
-
if (tag[0] && INDEXABLE_TAGS.has(tag[0])
|
|
61
|
+
if (tag.length >= 2 && tag[0].length === 1 && INDEXABLE_TAGS.has(tag[0])) {
|
|
42
62
|
tags.add(tag[0] + ":" + tag[1]);
|
|
43
63
|
}
|
|
44
64
|
}
|
|
@@ -46,13 +66,21 @@ export function getIndexableTags(event) {
|
|
|
46
66
|
}
|
|
47
67
|
return indexable;
|
|
48
68
|
}
|
|
49
|
-
/**
|
|
69
|
+
/**
|
|
70
|
+
* Returns the second index ( tag[1] ) of the first tag that matches the name
|
|
71
|
+
* If the event has any hidden tags they will be searched first
|
|
72
|
+
*/
|
|
50
73
|
export function getTagValue(event, name) {
|
|
74
|
+
const hidden = getHiddenTags(event);
|
|
75
|
+
const hiddenValue = hidden?.find((t) => t[0] === name)?.[1];
|
|
76
|
+
if (hiddenValue)
|
|
77
|
+
return hiddenValue;
|
|
51
78
|
return event.tags.find((t) => t[0] === name)?.[1];
|
|
52
79
|
}
|
|
53
80
|
/** Sets events verified flag without checking anything */
|
|
54
81
|
export function fakeVerifyEvent(event) {
|
|
55
|
-
|
|
82
|
+
event[verifiedSymbol] = true;
|
|
83
|
+
return true;
|
|
56
84
|
}
|
|
57
85
|
/** Marks an event as being from a cache */
|
|
58
86
|
export function markFromCache(event) {
|
|
@@ -62,3 +90,17 @@ export function markFromCache(event) {
|
|
|
62
90
|
export function isFromCache(event) {
|
|
63
91
|
return !!event[FromCacheSymbol];
|
|
64
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Returns the replaceable identifier for a replaceable event
|
|
95
|
+
* @throws
|
|
96
|
+
*/
|
|
97
|
+
export function getReplaceableIdentifier(event) {
|
|
98
|
+
if (!isParameterizedReplaceableKind(event.kind))
|
|
99
|
+
throw new Error("Event is not replaceable");
|
|
100
|
+
return getOrComputeCachedValue(event, ReplaceableIdentifierSymbol, () => {
|
|
101
|
+
const d = getTagValue(event, "d");
|
|
102
|
+
if (d === undefined)
|
|
103
|
+
throw new Error("Event missing identifier");
|
|
104
|
+
return d;
|
|
105
|
+
});
|
|
106
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export type ExternalIdentifiers = {
|
|
2
|
+
"#": `#${string}`;
|
|
3
|
+
geo: `geo:${string}`;
|
|
4
|
+
isbn: `isbn:${string}`;
|
|
5
|
+
"podcast:guid": `podcast:guid:${string}`;
|
|
6
|
+
"podcast:item:guid": `podcast:item:guid:${string}`;
|
|
7
|
+
"podcast:publisher:guid": `podcast:publisher:guid:${string}`;
|
|
8
|
+
isan: `isan:${string}`;
|
|
9
|
+
doi: `doi:${string}`;
|
|
10
|
+
};
|
|
11
|
+
export type ExternalPointer<Prefix extends keyof ExternalIdentifiers> = {
|
|
12
|
+
kind: Prefix;
|
|
13
|
+
identifier: ExternalIdentifiers[Prefix];
|
|
14
|
+
};
|
|
15
|
+
export type ParseResult = {
|
|
16
|
+
[P in keyof ExternalIdentifiers]: ExternalPointer<P>;
|
|
17
|
+
}[keyof ExternalIdentifiers];
|
|
18
|
+
/**
|
|
19
|
+
* Parses a NIP-73 external identifier
|
|
20
|
+
* @throws
|
|
21
|
+
*/
|
|
22
|
+
export declare function parseExternalPointer<Prefix extends keyof ExternalIdentifiers>(identifier: `${Prefix}1${string}`): ExternalPointer<Prefix>;
|
|
23
|
+
export declare function parseExternalPointer(identifier: string): ParseResult;
|
|
24
|
+
/**
|
|
25
|
+
* Gets an ExternalPointer for a "i" tag
|
|
26
|
+
* @throws
|
|
27
|
+
*/
|
|
28
|
+
export declare function getExternalPointerFromTag<Prefix extends keyof ExternalIdentifiers>(tag: string[]): ExternalPointer<Prefix>;
|
|
29
|
+
export declare function getExternalPointerFromTag(tag: string[]): ParseResult;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function parseExternalPointer(identifier) {
|
|
2
|
+
if (identifier.startsWith("#"))
|
|
3
|
+
return { kind: "#", identifier: identifier };
|
|
4
|
+
if (identifier.startsWith("geo:"))
|
|
5
|
+
return { kind: "geo", identifier: identifier };
|
|
6
|
+
if (identifier.startsWith("podcast:guid:"))
|
|
7
|
+
return { kind: "podcast:guid", identifier: identifier };
|
|
8
|
+
if (identifier.startsWith("podcast:item:guid:"))
|
|
9
|
+
return { kind: "podcast:item:guid", identifier: identifier };
|
|
10
|
+
if (identifier.startsWith("podcast:publisher:guid:"))
|
|
11
|
+
return { kind: "podcast:publisher:guid", identifier: identifier };
|
|
12
|
+
if (identifier.startsWith("isan:"))
|
|
13
|
+
return { kind: "isan", identifier: identifier };
|
|
14
|
+
if (identifier.startsWith("doi:"))
|
|
15
|
+
return { kind: "doi", identifier: identifier };
|
|
16
|
+
throw new Error("Failed to parse external identifier");
|
|
17
|
+
}
|
|
18
|
+
export function getExternalPointerFromTag(tag) {
|
|
19
|
+
return parseExternalPointer(tag[1]);
|
|
20
|
+
}
|