applesauce-core 0.0.0-next-20250220230505 → 0.0.0-next-20250221171454

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.
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,235 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { getCommentAddressPointer, getCommentEventPointer, getCommentExternalPointer, getCommentReplyPointer, getCommentRootPointer, } from "../comment.js";
3
+ import { FakeUser } from "../../__tests__/fixtures.js";
4
+ const user = new FakeUser();
5
+ describe("getCommentRootPointer", () => {
6
+ it("should throw if event is not a comment", () => {
7
+ expect(() => {
8
+ getCommentRootPointer(user.note("testing"));
9
+ }).toThrow("Event is not a comment");
10
+ });
11
+ });
12
+ describe("getCommentReplyPointer", () => {
13
+ it("should throw if event is not a comment", () => {
14
+ expect(() => {
15
+ getCommentReplyPointer(user.note("testing"));
16
+ }).toThrow("Event is not a comment");
17
+ });
18
+ });
19
+ describe("getCommentEventPointer", () => {
20
+ it("should get pubkey from P tag when root=true", () => {
21
+ const tags = [
22
+ ["E", "86c0b95589b016ffb703bfc080d49e54106e74e2d683295119c3453e494dbe6f"],
23
+ ["K", "1621"],
24
+ ["P", "e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10"],
25
+ ["k", "1621"],
26
+ ["p", "e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10"],
27
+ ["e", "86c0b95589b016ffb703bfc080d49e54106e74e2d683295119c3453e494dbe6f"],
28
+ ];
29
+ expect(getCommentEventPointer(tags, true)).toEqual({
30
+ id: "86c0b95589b016ffb703bfc080d49e54106e74e2d683295119c3453e494dbe6f",
31
+ kind: 1621,
32
+ pubkey: "e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10",
33
+ relay: undefined,
34
+ });
35
+ });
36
+ it("should default to pubkey in E tag when root pubkey do not match", () => {
37
+ const tags = [
38
+ [
39
+ "E",
40
+ "86c0b95589b016ffb703bfc080d49e54106e74e2d683295119c3453e494dbe6f",
41
+ "",
42
+ "e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10",
43
+ ],
44
+ ["K", "1621"],
45
+ ["P", "bad-pubkey"],
46
+ ];
47
+ expect(getCommentEventPointer(tags, true)).toEqual({
48
+ id: "86c0b95589b016ffb703bfc080d49e54106e74e2d683295119c3453e494dbe6f",
49
+ kind: 1621,
50
+ pubkey: "e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10",
51
+ relay: undefined,
52
+ });
53
+ });
54
+ it("should get pubkey from E tag", () => {
55
+ const tags = [
56
+ [
57
+ "E",
58
+ "86c0b95589b016ffb703bfc080d49e54106e74e2d683295119c3453e494dbe6f",
59
+ "",
60
+ "e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10",
61
+ ],
62
+ ["K", "1621"],
63
+ ];
64
+ expect(getCommentEventPointer(tags, true)).toEqual({
65
+ id: "86c0b95589b016ffb703bfc080d49e54106e74e2d683295119c3453e494dbe6f",
66
+ kind: 1621,
67
+ pubkey: "e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10",
68
+ relay: undefined,
69
+ });
70
+ });
71
+ it("should get relay from E tag", () => {
72
+ const tags = [
73
+ ["E", "86c0b95589b016ffb703bfc080d49e54106e74e2d683295119c3453e494dbe6f", "wss://relay.io/"],
74
+ ["K", "1621"],
75
+ ["P", "e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10"],
76
+ ];
77
+ expect(getCommentEventPointer(tags, true)).toEqual({
78
+ id: "86c0b95589b016ffb703bfc080d49e54106e74e2d683295119c3453e494dbe6f",
79
+ kind: 1621,
80
+ pubkey: "e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10",
81
+ relay: "wss://relay.io/",
82
+ });
83
+ });
84
+ it("should throw if K tag is missing", () => {
85
+ const tags = [
86
+ ["E", "86c0b95589b016ffb703bfc080d49e54106e74e2d683295119c3453e494dbe6f", "wss://relay.io/"],
87
+ ["P", "e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10"],
88
+ ];
89
+ expect(() => {
90
+ getCommentEventPointer(tags, true);
91
+ }).toThrow("Missing kind tag");
92
+ });
93
+ it("should return null if missing E tag", () => {
94
+ const tags = [
95
+ ["K", "1621"],
96
+ ["P", "e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10"],
97
+ ];
98
+ expect(getCommentEventPointer(tags, true)).toBe(null);
99
+ expect(getCommentEventPointer(tags)).toBe(null);
100
+ });
101
+ });
102
+ describe("getCommentAddressPointer", () => {
103
+ it("should get event id from E tag", () => {
104
+ // root
105
+ expect(getCommentAddressPointer([
106
+ ["A", "30000:e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10:list"],
107
+ ["E", "86c0b95589b016ffb703bfc080d49e54106e74e2d683295119c3453e494dbe6f"],
108
+ ["K", "30000"],
109
+ ], true)).toEqual({
110
+ id: "86c0b95589b016ffb703bfc080d49e54106e74e2d683295119c3453e494dbe6f",
111
+ kind: 30000,
112
+ pubkey: "e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10",
113
+ identifier: "list",
114
+ });
115
+ // reply
116
+ expect(getCommentAddressPointer([
117
+ ["a", "30000:e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10:list"],
118
+ ["e", "86c0b95589b016ffb703bfc080d49e54106e74e2d683295119c3453e494dbe6f"],
119
+ ["k", "30000"],
120
+ ])).toEqual({
121
+ id: "86c0b95589b016ffb703bfc080d49e54106e74e2d683295119c3453e494dbe6f",
122
+ kind: 30000,
123
+ pubkey: "e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10",
124
+ identifier: "list",
125
+ });
126
+ });
127
+ it("should get relay from A tag", () => {
128
+ // root
129
+ expect(getCommentAddressPointer([
130
+ ["A", "30000:e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10:list", "wss://relay.io/"],
131
+ ["K", "30000"],
132
+ ], true)).toEqual({
133
+ kind: 30000,
134
+ pubkey: "e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10",
135
+ identifier: "list",
136
+ relay: "wss://relay.io/",
137
+ });
138
+ // reply
139
+ expect(getCommentAddressPointer([
140
+ ["a", "30000:e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10:list", "wss://relay.io/"],
141
+ ["k", "30000"],
142
+ ])).toEqual({
143
+ kind: 30000,
144
+ pubkey: "e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10",
145
+ identifier: "list",
146
+ relay: "wss://relay.io/",
147
+ });
148
+ });
149
+ it("should get relay from E tag", () => {
150
+ // root
151
+ expect(getCommentAddressPointer([
152
+ ["A", "30000:e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10:list"],
153
+ ["E", "86c0b95589b016ffb703bfc080d49e54106e74e2d683295119c3453e494dbe6f", "wss://relay.io/"],
154
+ ["K", "30000"],
155
+ ], true)).toEqual({
156
+ id: "86c0b95589b016ffb703bfc080d49e54106e74e2d683295119c3453e494dbe6f",
157
+ kind: 30000,
158
+ pubkey: "e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10",
159
+ identifier: "list",
160
+ relay: "wss://relay.io/",
161
+ });
162
+ // reply
163
+ expect(getCommentAddressPointer([
164
+ ["a", "30000:e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10:list"],
165
+ ["e", "86c0b95589b016ffb703bfc080d49e54106e74e2d683295119c3453e494dbe6f", "wss://relay.io/"],
166
+ ["k", "30000"],
167
+ ])).toEqual({
168
+ id: "86c0b95589b016ffb703bfc080d49e54106e74e2d683295119c3453e494dbe6f",
169
+ kind: 30000,
170
+ pubkey: "e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10",
171
+ identifier: "list",
172
+ relay: "wss://relay.io/",
173
+ });
174
+ });
175
+ it("should return A tag kind over K tag", () => {
176
+ // root
177
+ expect(getCommentAddressPointer([
178
+ ["A", "30010:e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10:list"],
179
+ ["K", "30000"],
180
+ ], true)).toEqual({
181
+ kind: 30010,
182
+ pubkey: "e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10",
183
+ identifier: "list",
184
+ });
185
+ // reply
186
+ expect(getCommentAddressPointer([
187
+ ["a", "30010:e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10:list"],
188
+ ["k", "30000"],
189
+ ])).toEqual({
190
+ kind: 30010,
191
+ pubkey: "e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10",
192
+ identifier: "list",
193
+ });
194
+ });
195
+ it("should throw if missing K tag", () => {
196
+ // root
197
+ expect(() => getCommentAddressPointer([["A", "30010:e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10:list"]], true)).toThrow("Missing kind tag");
198
+ // reply
199
+ expect(() => getCommentAddressPointer([["a", "30010:e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10:list"]])).toThrow("Missing kind tag");
200
+ });
201
+ it("should return null if missing A tag", () => {
202
+ const tags = [
203
+ ["K", "1621"],
204
+ ["P", "e4336cd525df79fa4d3af364fd9600d4b10dce4215aa4c33ed77ea0842344b10"],
205
+ ];
206
+ expect(getCommentEventPointer(tags, true)).toBe(null);
207
+ expect(getCommentEventPointer(tags)).toBe(null);
208
+ });
209
+ });
210
+ describe("getCommentExternalPointer", () => {
211
+ it("should get kind prefix from I tag", () => {
212
+ // root
213
+ expect(getCommentExternalPointer([
214
+ ["I", "podcast:item:guid:d98d189b-dc7b-45b1-8720-d4b98690f31f"],
215
+ ["K", "podcast:item:guid"],
216
+ ], true)).toEqual({
217
+ identifier: "podcast:item:guid:d98d189b-dc7b-45b1-8720-d4b98690f31f",
218
+ kind: "podcast:item:guid",
219
+ });
220
+ // reply
221
+ expect(getCommentExternalPointer([
222
+ ["i", "podcast:item:guid:d98d189b-dc7b-45b1-8720-d4b98690f31f"],
223
+ ["k", "podcast:item:guid"],
224
+ ])).toEqual({
225
+ identifier: "podcast:item:guid:d98d189b-dc7b-45b1-8720-d4b98690f31f",
226
+ kind: "podcast:item:guid",
227
+ });
228
+ });
229
+ it("should throw if missing K tag", () => {
230
+ // root
231
+ expect(() => getCommentExternalPointer([["I", "podcast:item:guid:d98d189b-dc7b-45b1-8720-d4b98690f31f"]], true)).toThrow("Missing kind tag");
232
+ // reply
233
+ expect(() => getCommentExternalPointer([["i", "podcast:item:guid:d98d189b-dc7b-45b1-8720-d4b98690f31f"]])).toThrow("Missing kind tag");
234
+ });
235
+ });
@@ -10,16 +10,18 @@ export const CommentReplyPointerSymbol = Symbol.for("comment-reply-pointer");
10
10
  * @throws
11
11
  */
12
12
  export function getCommentEventPointer(tags, root = false) {
13
- const tag = tags.find((t) => t[0] === (root ? "E" : "e"));
13
+ const eTag = tags.find((t) => t[0] === (root ? "E" : "e"));
14
14
  const kind = tags.find((t) => t[0] === (root ? "K" : "k"))?.[1];
15
- if (tag) {
15
+ if (eTag) {
16
16
  if (!kind)
17
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;
18
20
  const pointer = {
19
- id: tag[1],
21
+ id: eTag[1],
20
22
  kind: parseInt(kind),
21
- pubkey: tag[3] || undefined,
22
- relay: tag[2] && isSafeRelayURL(tag[2]) ? tag[2] : undefined,
23
+ pubkey: eTag[3] || rootPubkey || undefined,
24
+ relay: eTag[2] && isSafeRelayURL(eTag[2]) ? eTag[2] : undefined,
23
25
  };
24
26
  return pointer;
25
27
  }
@@ -30,16 +32,19 @@ export function getCommentEventPointer(tags, root = false) {
30
32
  * @throws
31
33
  */
32
34
  export function getCommentAddressPointer(tags, root = false) {
33
- const tag = tags.find((t) => t[0] === (root ? "A" : "a"));
34
- const id = tags.find((t) => t[0] === (root ? "E" : "e"))?.[1];
35
+ const aTag = tags.find((t) => t[0] === (root ? "A" : "a"));
36
+ const eTag = tags.find((t) => t[0] === (root ? "E" : "e"));
35
37
  const kind = tags.find((t) => t[0] === (root ? "K" : "k"))?.[1];
36
- if (tag) {
38
+ if (aTag) {
37
39
  if (!kind)
38
40
  throw new Error("Missing kind tag");
41
+ const addressPointer = getAddressPointerFromATag(aTag);
39
42
  const pointer = {
40
- id,
41
- ...getAddressPointerFromATag(tag),
42
- kind: parseInt(kind),
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],
43
48
  };
44
49
  return pointer;
45
50
  }
@@ -50,13 +55,12 @@ export function getCommentAddressPointer(tags, root = false) {
50
55
  * @throws
51
56
  */
52
57
  export function getCommentExternalPointer(tags, root = false) {
53
- const tag = tags.find((t) => t[0] === (root ? "I" : "i"));
58
+ const iTag = tags.find((t) => t[0] === (root ? "I" : "i"));
54
59
  const kind = tags.find((t) => t[0] === (root ? "K" : "k"))?.[1];
55
- if (tag) {
60
+ if (iTag) {
56
61
  if (!kind)
57
62
  throw new Error("Missing kind tag");
58
- const pointer = getExternalPointerFromTag(tag);
59
- return pointer;
63
+ return getExternalPointerFromTag(iTag);
60
64
  }
61
65
  return null;
62
66
  }
@@ -36,7 +36,11 @@ export declare function getListEncryptionMethods(kind: number, signer: HiddenTag
36
36
  * @param store An optional EventStore to notify about the update
37
37
  * @throws
38
38
  */
39
- export declare function unlockHiddenTags(event: NostrEvent, signer: HiddenTagsSigner, store?: EventStore): Promise<NostrEvent>;
39
+ export declare function unlockHiddenTags<T extends {
40
+ kind: number;
41
+ pubkey: string;
42
+ content: string;
43
+ }>(event: T, signer: HiddenTagsSigner, store?: EventStore): Promise<T>;
40
44
  /**
41
45
  * Override the hidden tags in an event
42
46
  * @throws
@@ -1,6 +1,7 @@
1
1
  import { kinds } from "nostr-tools";
2
2
  import { GROUPS_LIST_KIND } from "./groups.js";
3
3
  import { unixNow } from "./time.js";
4
+ import { isEvent } from "./event.js";
4
5
  export const HiddenTagsSymbol = Symbol.for("hidden-tags");
5
6
  /** Various event kinds that can have encrypted tags in their content and which encryption method they use */
6
7
  export const EventEncryptionMethod = {
@@ -63,7 +64,7 @@ export async function unlockHiddenTags(event, signer, store) {
63
64
  // Convert array to tags array string[][]
64
65
  const tags = parsed.filter((t) => Array.isArray(t)).map((t) => t.map((v) => String(v)));
65
66
  Reflect.set(event, HiddenTagsSymbol, tags);
66
- if (store)
67
+ if (store && isEvent(event))
67
68
  store.update(event);
68
69
  return event;
69
70
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "applesauce-core",
3
- "version": "0.0.0-next-20250220230505",
3
+ "version": "0.0.0-next-20250221171454",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",