applesauce-core 0.10.0 → 0.12.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.
Files changed (139) hide show
  1. package/dist/__tests__/fixtures.d.ts +8 -0
  2. package/dist/__tests__/fixtures.js +20 -0
  3. package/dist/event-store/__tests__/event-store.test.js +272 -0
  4. package/dist/event-store/database.d.ts +7 -5
  5. package/dist/event-store/database.js +14 -8
  6. package/dist/event-store/event-store.d.ts +40 -20
  7. package/dist/event-store/event-store.js +269 -314
  8. package/dist/event-store/index.d.ts +1 -0
  9. package/dist/event-store/index.js +1 -0
  10. package/dist/event-store/interface.d.ts +27 -0
  11. package/dist/helpers/__tests__/blossom.test.js +13 -0
  12. package/dist/helpers/__tests__/comment.test.d.ts +1 -0
  13. package/dist/helpers/__tests__/comment.test.js +235 -0
  14. package/dist/helpers/__tests__/emoji.test.d.ts +1 -0
  15. package/dist/helpers/__tests__/emoji.test.js +15 -0
  16. package/dist/helpers/__tests__/event.test.d.ts +1 -0
  17. package/dist/helpers/__tests__/event.test.js +36 -0
  18. package/dist/helpers/__tests__/file-metadata.test.d.ts +1 -0
  19. package/dist/helpers/__tests__/file-metadata.test.js +103 -0
  20. package/dist/helpers/__tests__/hidden-tags.test.d.ts +1 -0
  21. package/dist/helpers/{hidden-tags.test.js → __tests__/hidden-tags.test.js} +2 -1
  22. package/dist/helpers/__tests__/mailboxes.test.d.ts +1 -0
  23. package/dist/helpers/{mailboxes.test.js → __tests__/mailboxes.test.js} +1 -1
  24. package/dist/helpers/__tests__/nip-19.test.d.ts +1 -0
  25. package/dist/helpers/__tests__/nip-19.test.js +42 -0
  26. package/dist/helpers/__tests__/relays.test.d.ts +1 -0
  27. package/dist/helpers/__tests__/relays.test.js +21 -0
  28. package/dist/helpers/__tests__/tags.test.d.ts +1 -0
  29. package/dist/helpers/__tests__/tags.test.js +24 -0
  30. package/dist/helpers/__tests__/threading.test.d.ts +1 -0
  31. package/dist/helpers/{threading.test.js → __tests__/threading.test.js} +1 -1
  32. package/dist/helpers/blossom.d.ts +9 -0
  33. package/dist/helpers/blossom.js +22 -0
  34. package/dist/helpers/bookmarks.d.ts +15 -0
  35. package/dist/helpers/bookmarks.js +27 -0
  36. package/dist/helpers/cache.d.ts +3 -4
  37. package/dist/helpers/cache.js +1 -1
  38. package/dist/helpers/channels.d.ts +10 -0
  39. package/dist/helpers/channels.js +27 -0
  40. package/dist/helpers/comment.d.ts +3 -4
  41. package/dist/helpers/comment.js +20 -16
  42. package/dist/helpers/contacts.d.ts +3 -0
  43. package/dist/helpers/contacts.js +25 -0
  44. package/dist/helpers/direct-messages.d.ts +4 -0
  45. package/dist/helpers/direct-messages.js +5 -0
  46. package/dist/helpers/dns-identity.d.ts +7 -0
  47. package/dist/helpers/dns-identity.js +10 -0
  48. package/dist/helpers/emoji.d.ts +3 -1
  49. package/dist/helpers/emoji.js +2 -2
  50. package/dist/helpers/event.d.ts +15 -1
  51. package/dist/helpers/event.js +34 -11
  52. package/dist/helpers/file-metadata.d.ts +55 -0
  53. package/dist/helpers/file-metadata.js +99 -0
  54. package/dist/helpers/filter.d.ts +4 -0
  55. package/dist/helpers/filter.js +34 -1
  56. package/dist/helpers/gift-wraps.d.ts +12 -0
  57. package/dist/helpers/gift-wraps.js +49 -0
  58. package/dist/helpers/groups.d.ts +24 -0
  59. package/dist/helpers/groups.js +39 -0
  60. package/dist/helpers/hidden-content.d.ts +48 -0
  61. package/dist/helpers/hidden-content.js +88 -0
  62. package/dist/helpers/hidden-tags.d.ts +17 -35
  63. package/dist/helpers/hidden-tags.js +26 -83
  64. package/dist/helpers/index.d.ts +16 -1
  65. package/dist/helpers/index.js +16 -1
  66. package/dist/helpers/lists.d.ts +28 -0
  67. package/dist/helpers/lists.js +65 -0
  68. package/dist/helpers/mailboxes.js +16 -9
  69. package/dist/helpers/mutes.d.ts +15 -0
  70. package/dist/helpers/mutes.js +24 -0
  71. package/dist/helpers/nip-19.d.ts +4 -0
  72. package/dist/helpers/nip-19.js +27 -0
  73. package/dist/helpers/picture-post.d.ts +4 -0
  74. package/dist/helpers/picture-post.js +6 -0
  75. package/dist/helpers/pointers.js +13 -17
  76. package/dist/helpers/profile.d.ts +6 -1
  77. package/dist/helpers/profile.js +4 -0
  78. package/dist/helpers/relays.d.ts +6 -3
  79. package/dist/helpers/relays.js +25 -18
  80. package/dist/helpers/share.d.ts +4 -0
  81. package/dist/helpers/share.js +12 -0
  82. package/dist/helpers/tags.d.ts +17 -0
  83. package/dist/helpers/tags.js +28 -6
  84. package/dist/helpers/threading.js +3 -3
  85. package/dist/helpers/url.d.ts +7 -0
  86. package/dist/helpers/url.js +27 -0
  87. package/dist/helpers/user-status.d.ts +18 -0
  88. package/dist/helpers/user-status.js +21 -0
  89. package/dist/observable/__tests__/claim-events.test.d.ts +1 -0
  90. package/dist/observable/__tests__/claim-events.test.js +23 -0
  91. package/dist/observable/__tests__/claim-latest.test.d.ts +1 -0
  92. package/dist/observable/__tests__/claim-latest.test.js +37 -0
  93. package/dist/observable/__tests__/simple-timeout.test.d.ts +1 -0
  94. package/dist/observable/__tests__/simple-timeout.test.js +34 -0
  95. package/dist/observable/claim-events.d.ts +5 -0
  96. package/dist/observable/claim-events.js +28 -0
  97. package/dist/observable/claim-latest.d.ts +5 -0
  98. package/dist/observable/claim-latest.js +21 -0
  99. package/dist/observable/{get-value.d.ts → get-observable-value.d.ts} +1 -1
  100. package/dist/observable/{get-value.js → get-observable-value.js} +3 -8
  101. package/dist/observable/index.d.ts +2 -1
  102. package/dist/observable/index.js +2 -1
  103. package/dist/observable/share-latest-value.d.ts +2 -4
  104. package/dist/observable/share-latest-value.js +19 -16
  105. package/dist/observable/simple-timeout.d.ts +4 -0
  106. package/dist/observable/simple-timeout.js +6 -0
  107. package/dist/observable/with-immediate-value.d.ts +3 -0
  108. package/dist/observable/with-immediate-value.js +19 -0
  109. package/dist/queries/blossom.d.ts +2 -0
  110. package/dist/queries/blossom.js +10 -0
  111. package/dist/queries/bookmarks.d.ts +8 -0
  112. package/dist/queries/bookmarks.js +23 -0
  113. package/dist/queries/channels.d.ts +11 -0
  114. package/dist/queries/channels.js +73 -0
  115. package/dist/queries/contacts.d.ts +3 -0
  116. package/dist/queries/contacts.js +12 -0
  117. package/dist/queries/index.d.ts +6 -0
  118. package/dist/queries/index.js +6 -0
  119. package/dist/queries/mutes.d.ts +8 -0
  120. package/dist/queries/mutes.js +23 -0
  121. package/dist/queries/pins.d.ts +3 -0
  122. package/dist/queries/pins.js +12 -0
  123. package/dist/queries/simple.d.ts +3 -3
  124. package/dist/queries/simple.js +3 -3
  125. package/dist/queries/thread.js +1 -1
  126. package/dist/queries/user-status.d.ts +11 -0
  127. package/dist/queries/user-status.js +39 -0
  128. package/dist/query-store/__tests__/query-store.test.d.ts +1 -0
  129. package/dist/query-store/__tests__/query-store.test.js +63 -0
  130. package/dist/query-store/index.d.ts +1 -57
  131. package/dist/query-store/index.js +1 -66
  132. package/dist/query-store/query-store.d.ts +53 -0
  133. package/dist/query-store/query-store.js +97 -0
  134. package/package.json +20 -8
  135. package/dist/helpers/media-attachment.d.ts +0 -33
  136. package/dist/helpers/media-attachment.js +0 -60
  137. /package/dist/{helpers/hidden-tags.test.d.ts → event-store/__tests__/event-store.test.d.ts} +0 -0
  138. /package/dist/{helpers/mailboxes.test.d.ts → event-store/interface.js} +0 -0
  139. /package/dist/helpers/{threading.test.d.ts → __tests__/blossom.test.d.ts} +0 -0
@@ -1,57 +1 @@
1
- import { BehaviorSubject, Observable } from "rxjs";
2
- import { Filter, NostrEvent } from "nostr-tools";
3
- import { EventStore } from "../event-store/event-store.js";
4
- import { LRU } from "../helpers/lru.js";
5
- import * as Queries from "../queries/index.js";
6
- import { AddressPointer, EventPointer } from "nostr-tools/nip19";
7
- export type Query<T extends unknown> = {
8
- /**
9
- * A unique key for this query. this is used to detect duplicate queries
10
- */
11
- key: string;
12
- /** The args array this query was created with. This is mostly for debugging */
13
- args?: Array<any>;
14
- /**
15
- * The meat of the query, this should return an Observables that subscribes to the eventStore in some way
16
- */
17
- run: (events: EventStore, store: QueryStore) => Observable<T>;
18
- };
19
- export type QueryConstructor<T extends unknown, Args extends Array<any>> = (...args: Args) => Query<T>;
20
- export declare class QueryStore {
21
- static Queries: typeof Queries;
22
- store: EventStore;
23
- constructor(store: EventStore);
24
- queries: LRU<Query<any>>;
25
- observables: WeakMap<Query<any>, Observable<any> | BehaviorSubject<any>>;
26
- /** Creates a cached query */
27
- createQuery<T extends unknown, Args extends Array<any>>(queryConstructor: (...args: Args) => {
28
- key: string;
29
- run: (events: EventStore, store: QueryStore) => Observable<T>;
30
- }, ...args: Args): Observable<T>;
31
- /** Creates a SingleEventQuery */
32
- event(id: string): Observable<import("nostr-tools").Event | undefined>;
33
- /** Creates a MultipleEventsQuery */
34
- events(ids: string[]): Observable<Map<string, import("nostr-tools").Event>>;
35
- /** Creates a ReplaceableQuery */
36
- replaceable(kind: number, pubkey: string, d?: string): Observable<import("nostr-tools").Event | undefined>;
37
- /** Creates a ReplaceableSetQuery */
38
- replaceableSet(pointers: {
39
- kind: number;
40
- pubkey: string;
41
- identifier?: string;
42
- }[]): Observable<Map<string, import("nostr-tools").Event>>;
43
- /** Creates a TimelineQuery */
44
- timeline(filters: Filter | Filter[], keepOldVersions?: boolean): Observable<import("nostr-tools").Event[]>;
45
- /** Creates a ProfileQuery */
46
- profile(pubkey: string): Observable<import("../helpers/profile.js").ProfileContent | undefined>;
47
- /** Creates a ReactionsQuery */
48
- reactions(event: NostrEvent): Observable<import("nostr-tools").Event[]>;
49
- /** Creates a MailboxesQuery */
50
- mailboxes(pubkey: string): Observable<{
51
- inboxes: string[];
52
- outboxes: string[];
53
- } | undefined>;
54
- /** Creates a ThreadQuery */
55
- thread(root: string | EventPointer | AddressPointer): Observable<Queries.Thread>;
56
- }
57
- export { Queries };
1
+ export * from "./query-store.js";
@@ -1,66 +1 @@
1
- import { LRU } from "../helpers/lru.js";
2
- import * as Queries from "../queries/index.js";
3
- import { shareLatestValue } from "../observable/share-latest-value.js";
4
- export class QueryStore {
5
- static Queries = Queries;
6
- store;
7
- constructor(store) {
8
- this.store = store;
9
- }
10
- queries = new LRU();
11
- observables = new WeakMap();
12
- /** Creates a cached query */
13
- createQuery(queryConstructor, ...args) {
14
- const tempQuery = queryConstructor(...args);
15
- const key = `${queryConstructor.name}|${tempQuery.key}`;
16
- let query = this.queries.get(key);
17
- if (!query) {
18
- query = tempQuery;
19
- this.queries.set(key, tempQuery);
20
- }
21
- if (!this.observables.has(query)) {
22
- query.args = args;
23
- const observable = query.run(this.store, this).pipe(shareLatestValue());
24
- this.observables.set(query, observable);
25
- return observable;
26
- }
27
- return this.observables.get(query);
28
- }
29
- /** Creates a SingleEventQuery */
30
- event(id) {
31
- return this.createQuery(Queries.SingleEventQuery, id);
32
- }
33
- /** Creates a MultipleEventsQuery */
34
- events(ids) {
35
- return this.createQuery(Queries.MultipleEventsQuery, ids);
36
- }
37
- /** Creates a ReplaceableQuery */
38
- replaceable(kind, pubkey, d) {
39
- return this.createQuery(Queries.ReplaceableQuery, kind, pubkey, d);
40
- }
41
- /** Creates a ReplaceableSetQuery */
42
- replaceableSet(pointers) {
43
- return this.createQuery(Queries.ReplaceableSetQuery, pointers);
44
- }
45
- /** Creates a TimelineQuery */
46
- timeline(filters, keepOldVersions) {
47
- return this.createQuery(Queries.TimelineQuery, filters, keepOldVersions);
48
- }
49
- /** Creates a ProfileQuery */
50
- profile(pubkey) {
51
- return this.createQuery(Queries.ProfileQuery, pubkey);
52
- }
53
- /** Creates a ReactionsQuery */
54
- reactions(event) {
55
- return this.createQuery(Queries.ReactionsQuery, event);
56
- }
57
- /** Creates a MailboxesQuery */
58
- mailboxes(pubkey) {
59
- return this.createQuery(Queries.MailboxesQuery, pubkey);
60
- }
61
- /** Creates a ThreadQuery */
62
- thread(root) {
63
- return this.createQuery(Queries.ThreadQuery, root);
64
- }
65
- }
66
- export { Queries };
1
+ export * from "./query-store.js";
@@ -0,0 +1,53 @@
1
+ import { Observable } from "rxjs";
2
+ import { Filter, NostrEvent } from "nostr-tools";
3
+ import type { AddressPointer, EventPointer } from "nostr-tools/nip19";
4
+ import { IEventStore } from "../event-store/interface.js";
5
+ import * as Queries from "../queries/index.js";
6
+ export type Query<T extends unknown> = {
7
+ /** A unique key for this query. this is used to detect duplicate queries */
8
+ key: string;
9
+ /** The meat of the query, this should return an Observables that subscribes to the eventStore in some way */
10
+ run: (events: IEventStore, store: QueryStore) => Observable<T>;
11
+ };
12
+ export type QueryConstructor<T extends unknown, Args extends Array<any>> = (...args: Args) => Query<T>;
13
+ export declare class QueryStore {
14
+ static Queries: typeof Queries;
15
+ store: IEventStore;
16
+ constructor(store: IEventStore);
17
+ /** A directory of all active queries */
18
+ queries: Map<QueryConstructor<any, any[]>, Map<string, Observable<any>>>;
19
+ /** How long a query should be kept "warm" while nothing is subscribed to it */
20
+ queryKeepWarmTimeout: number;
21
+ /** Creates a cached query */
22
+ createQuery<T extends unknown, Args extends Array<any>>(queryConstructor: QueryConstructor<T, Args>, ...args: Args): Observable<T | undefined>;
23
+ /** Creates a query and waits for the next value */
24
+ executeQuery<T extends unknown, Args extends Array<any>>(queryConstructor: QueryConstructor<T, Args>, ...args: Args): Promise<T>;
25
+ /** Creates a SingleEventQuery */
26
+ event(id: string): Observable<import("nostr-tools").Event | undefined>;
27
+ /** Creates a MultipleEventsQuery */
28
+ events(ids: string[]): Observable<Record<string, import("nostr-tools").Event> | undefined>;
29
+ /** Creates a ReplaceableQuery */
30
+ replaceable(kind: number, pubkey: string, d?: string): Observable<import("nostr-tools").Event | undefined>;
31
+ /** Creates a ReplaceableSetQuery */
32
+ replaceableSet(pointers: {
33
+ kind: number;
34
+ pubkey: string;
35
+ identifier?: string;
36
+ }[]): Observable<Record<string, import("nostr-tools").Event> | undefined>;
37
+ /** Creates a TimelineQuery */
38
+ timeline(filters: Filter | Filter[], keepOldVersions?: boolean): Observable<import("nostr-tools").Event[] | undefined>;
39
+ /** Creates a ProfileQuery */
40
+ profile(pubkey: string): Observable<import("../helpers/profile.js").ProfileContent | undefined>;
41
+ /** Creates a ReactionsQuery */
42
+ reactions(event: NostrEvent): Observable<import("nostr-tools").Event[] | undefined>;
43
+ /** Creates a MailboxesQuery */
44
+ mailboxes(pubkey: string): Observable<{
45
+ inboxes: string[];
46
+ outboxes: string[];
47
+ } | undefined>;
48
+ /** Creates a query for a users blossom servers */
49
+ blossomServers(pubkey: string): Observable<URL[] | undefined>;
50
+ /** Creates a ThreadQuery */
51
+ thread(root: string | EventPointer | AddressPointer): Observable<Queries.Thread | undefined>;
52
+ }
53
+ export { Queries };
@@ -0,0 +1,97 @@
1
+ import { filter, finalize, ReplaySubject, share, timer } from "rxjs";
2
+ import hash_sum from "hash-sum";
3
+ import * as Queries from "../queries/index.js";
4
+ import { getObservableValue } from "../observable/get-observable-value.js";
5
+ import { withImmediateValueOrDefault } from "../observable/with-immediate-value.js";
6
+ export class QueryStore {
7
+ static Queries = Queries;
8
+ store;
9
+ constructor(store) {
10
+ if (!store)
11
+ throw new Error("EventStore required");
12
+ this.store = store;
13
+ }
14
+ /** A directory of all active queries */
15
+ queries = new Map();
16
+ /** How long a query should be kept "warm" while nothing is subscribed to it */
17
+ queryKeepWarmTimeout = 60_000;
18
+ /** Creates a cached query */
19
+ createQuery(queryConstructor, ...args) {
20
+ let observables = this.queries.get(queryConstructor);
21
+ if (!observables) {
22
+ observables = new Map();
23
+ this.queries.set(queryConstructor, observables);
24
+ }
25
+ const key = hash_sum(args);
26
+ let observable = observables.get(key);
27
+ if (!observable) {
28
+ const cleanup = () => {
29
+ if (observables.get(key) === observable)
30
+ observables.delete(key);
31
+ };
32
+ observable = queryConstructor(...args)
33
+ .run(this.store, this)
34
+ .pipe(
35
+ // always emit undefined so the observable is sync
36
+ withImmediateValueOrDefault(undefined),
37
+ // remove the observable when its subscribed
38
+ finalize(cleanup),
39
+ // only create a single observable for all components
40
+ share({
41
+ connector: () => new ReplaySubject(1),
42
+ resetOnComplete: () => timer(this.queryKeepWarmTimeout),
43
+ resetOnRefCountZero: () => timer(this.queryKeepWarmTimeout),
44
+ }));
45
+ // set debug fields
46
+ Reflect.set(observable, "queryArgs", args);
47
+ observables.set(key, observable);
48
+ }
49
+ return observable;
50
+ }
51
+ /** Creates a query and waits for the next value */
52
+ async executeQuery(queryConstructor, ...args) {
53
+ const query = this.createQuery(queryConstructor, ...args).pipe(filter((v) => v !== undefined));
54
+ return getObservableValue(query);
55
+ }
56
+ /** Creates a SingleEventQuery */
57
+ event(id) {
58
+ return this.createQuery(Queries.SingleEventQuery, id);
59
+ }
60
+ /** Creates a MultipleEventsQuery */
61
+ events(ids) {
62
+ return this.createQuery(Queries.MultipleEventsQuery, ids);
63
+ }
64
+ /** Creates a ReplaceableQuery */
65
+ replaceable(kind, pubkey, d) {
66
+ return this.createQuery(Queries.ReplaceableQuery, kind, pubkey, d);
67
+ }
68
+ /** Creates a ReplaceableSetQuery */
69
+ replaceableSet(pointers) {
70
+ return this.createQuery(Queries.ReplaceableSetQuery, pointers);
71
+ }
72
+ /** Creates a TimelineQuery */
73
+ timeline(filters, keepOldVersions) {
74
+ return this.createQuery(Queries.TimelineQuery, filters, keepOldVersions);
75
+ }
76
+ /** Creates a ProfileQuery */
77
+ profile(pubkey) {
78
+ return this.createQuery(Queries.ProfileQuery, pubkey);
79
+ }
80
+ /** Creates a ReactionsQuery */
81
+ reactions(event) {
82
+ return this.createQuery(Queries.ReactionsQuery, event);
83
+ }
84
+ /** Creates a MailboxesQuery */
85
+ mailboxes(pubkey) {
86
+ return this.createQuery(Queries.MailboxesQuery, pubkey);
87
+ }
88
+ /** Creates a query for a users blossom servers */
89
+ blossomServers(pubkey) {
90
+ return this.createQuery(Queries.UserBlossomServersQuery, pubkey);
91
+ }
92
+ /** Creates a ThreadQuery */
93
+ thread(root) {
94
+ return this.createQuery(Queries.ThreadQuery, root);
95
+ }
96
+ }
97
+ export { Queries };
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "applesauce-core",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
8
8
  "keywords": [
9
- "nostr"
9
+ "nostr",
10
+ "applesauce"
10
11
  ],
11
12
  "author": "hzrd149",
12
13
  "license": "MIT",
@@ -16,56 +17,67 @@
16
17
  "exports": {
17
18
  ".": {
18
19
  "import": "./dist/index.js",
20
+ "require": "./dist/index.js",
19
21
  "types": "./dist/index.d.ts"
20
22
  },
21
23
  "./helpers": {
22
24
  "import": "./dist/helpers/index.js",
25
+ "require": "./dist/helpers/index.js",
23
26
  "types": "./dist/helpers/index.d.ts"
24
27
  },
25
28
  "./helpers/*": {
26
29
  "import": "./dist/helpers/*.js",
30
+ "require": "./dist/helpers/*.js",
27
31
  "types": "./dist/helpers/*.d.ts"
28
32
  },
29
33
  "./queries": {
30
34
  "import": "./dist/queries/index.js",
35
+ "require": "./dist/queries/index.js",
31
36
  "types": "./dist/queries/index.d.ts"
32
37
  },
33
38
  "./queries/*": {
34
39
  "import": "./dist/queries/*.js",
40
+ "require": "./dist/queries/*.js",
35
41
  "types": "./dist/queries/*.d.ts"
36
42
  },
37
43
  "./observable": {
38
44
  "import": "./dist/observable/index.js",
45
+ "require": "./dist/observable/index.js",
39
46
  "types": "./dist/observable/index.d.ts"
40
47
  },
41
48
  "./promise": {
42
49
  "import": "./dist/promise/index.js",
50
+ "require": "./dist/promise/index.js",
43
51
  "types": "./dist/promise/index.d.ts"
44
52
  },
45
53
  "./query-store": {
46
54
  "import": "./dist/query-store/index.js",
55
+ "require": "./dist/query-store/index.js",
47
56
  "types": "./dist/query-store/index.d.ts"
48
57
  },
49
58
  "./event-store": {
50
59
  "import": "./dist/event-store/index.js",
60
+ "require": "./dist/event-store/index.js",
51
61
  "types": "./dist/event-store/index.d.ts"
52
62
  }
53
63
  },
54
64
  "dependencies": {
55
- "@scure/base": "^1.1.9",
56
- "debug": "^4.3.7",
65
+ "@noble/hashes": "^1.7.1",
66
+ "@scure/base": "^1.2.4",
67
+ "debug": "^4.4.0",
57
68
  "fast-deep-equal": "^3.1.3",
58
69
  "hash-sum": "^2.0.0",
59
70
  "light-bolt11-decoder": "^3.2.0",
60
- "nanoid": "^5.0.7",
61
- "nostr-tools": "^2.10.3",
71
+ "nanoid": "^5.0.9",
72
+ "nostr-tools": "^2.10.4",
62
73
  "rxjs": "^7.8.1"
63
74
  },
64
75
  "devDependencies": {
76
+ "@hirez_io/observer-spy": "^2.2.0",
65
77
  "@types/debug": "^4.1.12",
66
78
  "@types/hash-sum": "^1.0.2",
67
- "typescript": "^5.6.3",
68
- "vitest": "^2.1.8"
79
+ "typescript": "^5.7.3",
80
+ "vitest": "^3.0.5"
69
81
  },
70
82
  "funding": {
71
83
  "type": "lightning",
@@ -1,33 +0,0 @@
1
- import { NostrEvent } from "nostr-tools";
2
- export type MediaAttachment = {
3
- /** URL of the file */
4
- url: string;
5
- /** mime type */
6
- type?: string;
7
- /** sha256 hash of the file */
8
- sha256?: string;
9
- /** size of the file in bytes */
10
- size?: number;
11
- /** size of file in pixels in the form <width>x<height> */
12
- dimensions?: string;
13
- /** magnet */
14
- magnet?: string;
15
- /** torrent infohash */
16
- infohash?: string;
17
- /** URL to a thumbnail */
18
- thumb?: string;
19
- /** URL to a preview image with the same dimensions */
20
- image?: string;
21
- /** summary */
22
- summary?: string;
23
- /** description for accessability */
24
- alt?: string;
25
- };
26
- /**
27
- * Parses a imeta tag into a {@link MediaAttachment}
28
- * @throws
29
- */
30
- export declare function parseMediaAttachmentTag(tag: string[]): MediaAttachment;
31
- export declare const MediaAttachmentsSymbol: unique symbol;
32
- /** Gets all the media attachments on an event */
33
- export declare function getMediaAttachments(event: NostrEvent): MediaAttachment[];
@@ -1,60 +0,0 @@
1
- import { getOrComputeCachedValue } from "./cache.js";
2
- /**
3
- * Parses a imeta tag into a {@link MediaAttachment}
4
- * @throws
5
- */
6
- export function parseMediaAttachmentTag(tag) {
7
- const parts = tag.slice(1);
8
- const fields = {};
9
- for (const part of parts) {
10
- const match = part.match(/^(.+?)\s(.+)$/);
11
- if (match) {
12
- const [_, name, value] = match;
13
- fields[name] = value;
14
- }
15
- }
16
- if (!fields.url)
17
- throw new Error("Missing required url in attachment");
18
- const attachment = { url: fields.url };
19
- // parse size
20
- if (fields.size)
21
- attachment.size = parseInt(fields.size);
22
- // copy optional fields
23
- if (fields.m)
24
- attachment.type = fields.m;
25
- if (fields.x)
26
- attachment.sha256 = fields.x;
27
- if (fields.dim)
28
- attachment.dimensions = fields.dim;
29
- if (fields.magnet)
30
- attachment.magnet = fields.magnet;
31
- if (fields.i)
32
- attachment.infohash = fields.i;
33
- if (fields.thumb)
34
- attachment.thumb = fields.thumb;
35
- if (fields.image)
36
- attachment.image = fields.image;
37
- if (fields.summary)
38
- attachment.summary = fields.summary;
39
- if (fields.alt)
40
- attachment.alt = fields.alt;
41
- return attachment;
42
- }
43
- export const MediaAttachmentsSymbol = Symbol.for("media-attachments");
44
- /** Gets all the media attachments on an event */
45
- export function getMediaAttachments(event) {
46
- return getOrComputeCachedValue(event, MediaAttachmentsSymbol, () => {
47
- return event.tags
48
- .filter((t) => t[0] === "imeta")
49
- .map((tag) => {
50
- try {
51
- return parseMediaAttachmentTag(tag);
52
- }
53
- catch (error) {
54
- // ignore invalid attachments
55
- return undefined;
56
- }
57
- })
58
- .filter((a) => !!a);
59
- });
60
- }