applesauce-core 0.1.0 → 0.3.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 (50) hide show
  1. package/README.md +39 -0
  2. package/dist/event-store/database.d.ts +57 -13
  3. package/dist/event-store/database.js +52 -15
  4. package/dist/event-store/event-store.d.ts +4 -1
  5. package/dist/event-store/event-store.js +122 -31
  6. package/dist/event-store/index.d.ts +2 -1
  7. package/dist/event-store/index.js +2 -1
  8. package/dist/helpers/channel.d.ts +15 -0
  9. package/dist/helpers/channel.js +27 -0
  10. package/dist/helpers/event.d.ts +12 -0
  11. package/dist/helpers/event.js +13 -8
  12. package/dist/helpers/filter.d.ts +5 -0
  13. package/dist/helpers/filter.js +5 -2
  14. package/dist/helpers/index.d.ts +1 -1
  15. package/dist/helpers/index.js +1 -1
  16. package/dist/helpers/json.d.ts +1 -0
  17. package/dist/helpers/json.js +8 -0
  18. package/dist/helpers/mailboxes.d.ts +14 -0
  19. package/dist/helpers/mailboxes.js +14 -7
  20. package/dist/helpers/mailboxes.test.d.ts +1 -0
  21. package/dist/helpers/mailboxes.test.js +80 -0
  22. package/dist/helpers/mute.d.ts +21 -0
  23. package/dist/helpers/mute.js +52 -0
  24. package/dist/helpers/profile.d.ts +6 -0
  25. package/dist/helpers/profile.js +4 -4
  26. package/dist/helpers/relays.d.ts +6 -0
  27. package/dist/helpers/relays.js +7 -6
  28. package/dist/promise/index.d.ts +1 -1
  29. package/dist/promise/index.js +1 -1
  30. package/dist/query-store/index.d.ts +35 -17
  31. package/dist/query-store/index.js +40 -58
  32. package/dist/query-store/queries/channel.d.ts +11 -0
  33. package/dist/query-store/queries/channel.js +72 -0
  34. package/dist/query-store/queries/index.d.ts +6 -0
  35. package/dist/query-store/queries/index.js +6 -0
  36. package/dist/query-store/queries/mailboxes.d.ts +5 -0
  37. package/dist/query-store/queries/mailboxes.js +11 -0
  38. package/dist/query-store/queries/mute.d.ts +7 -0
  39. package/dist/query-store/queries/mute.js +16 -0
  40. package/dist/query-store/queries/profile.d.ts +3 -0
  41. package/dist/query-store/queries/profile.js +10 -0
  42. package/dist/query-store/queries/reactions.d.ts +4 -0
  43. package/dist/query-store/queries/reactions.js +19 -0
  44. package/dist/query-store/queries/simple.d.ts +5 -0
  45. package/dist/query-store/queries/simple.js +20 -0
  46. package/dist/utils/lru.d.ts +32 -0
  47. package/dist/utils/lru.js +148 -0
  48. package/package.json +19 -3
  49. package/dist/helpers/symbols.d.ts +0 -17
  50. package/dist/helpers/symbols.js +0 -10
@@ -0,0 +1,19 @@
1
+ import { kinds } from "nostr-tools";
2
+ import { getEventUID, isReplaceable } from "../../helpers/event.js";
3
+ /** Creates a query that returns all reactions to an event (supports replaceable events) */
4
+ export function ReactionsQuery(event) {
5
+ return {
6
+ key: getEventUID(event),
7
+ run: (events) => events.timeline(isReplaceable(event.kind)
8
+ ? [
9
+ { kinds: [kinds.Reaction], "#e": [event.id] },
10
+ { kinds: [kinds.Reaction], "#a": [getEventUID(event)] },
11
+ ]
12
+ : [
13
+ {
14
+ kinds: [kinds.Reaction],
15
+ "#e": [event.id],
16
+ },
17
+ ]),
18
+ };
19
+ }
@@ -0,0 +1,5 @@
1
+ import { Filter, NostrEvent } from "nostr-tools";
2
+ import { Query } from "../index.js";
3
+ export declare function SingleEventQuery(uid: string): Query<NostrEvent | undefined>;
4
+ export declare function ReplaceableQuery(kind: number, pubkey: string, d?: string): Query<NostrEvent | undefined>;
5
+ export declare function TimelineQuery(filters: Filter | Filter[]): Query<NostrEvent[]>;
@@ -0,0 +1,20 @@
1
+ import stringify from "json-stringify-deterministic";
2
+ import { getReplaceableUID } from "../../helpers/event.js";
3
+ export function SingleEventQuery(uid) {
4
+ return {
5
+ key: uid,
6
+ run: (events) => events.event(uid),
7
+ };
8
+ }
9
+ export function ReplaceableQuery(kind, pubkey, d) {
10
+ return {
11
+ key: getReplaceableUID(kind, pubkey, d),
12
+ run: (events) => events.replaceable(kind, pubkey, d),
13
+ };
14
+ }
15
+ export function TimelineQuery(filters) {
16
+ return {
17
+ key: stringify(filters),
18
+ run: (events) => events.timeline(Array.isArray(filters) ? filters : [filters]),
19
+ };
20
+ }
@@ -0,0 +1,32 @@
1
+ type Item<T> = {
2
+ key: string;
3
+ prev: Item<T> | null;
4
+ value: T;
5
+ next: Item<T> | null;
6
+ expiry: number;
7
+ };
8
+ /**
9
+ * Copied from tiny-lru and modified to support typescript
10
+ * @see https://github.com/avoidwork/tiny-lru/blob/master/src/lru.js
11
+ */
12
+ export declare class LRU<T extends unknown> {
13
+ first: Item<T> | null;
14
+ items: Record<string, Item<T>>;
15
+ last: Item<T> | null;
16
+ max: number;
17
+ resetTtl: boolean;
18
+ size: number;
19
+ ttl: number;
20
+ constructor(max?: number, ttl?: number, resetTtl?: boolean);
21
+ clear(): this;
22
+ delete(key: string): this;
23
+ entries(keys?: string[]): (string | T | undefined)[][];
24
+ evict(bypass?: boolean): this;
25
+ expiresAt(key: string): number | undefined;
26
+ get(key: string): T | undefined;
27
+ has(key: string): boolean;
28
+ keys(): string[];
29
+ set(key: string, value: T, bypass?: boolean, resetTtl?: boolean): this;
30
+ values(keys?: string[]): NonNullable<T>[];
31
+ }
32
+ export {};
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Copied from tiny-lru and modified to support typescript
3
+ * @see https://github.com/avoidwork/tiny-lru/blob/master/src/lru.js
4
+ */
5
+ export class LRU {
6
+ first = null;
7
+ items = Object.create(null);
8
+ last = null;
9
+ max;
10
+ resetTtl;
11
+ size;
12
+ ttl;
13
+ constructor(max = 0, ttl = 0, resetTtl = false) {
14
+ this.first = null;
15
+ this.items = Object.create(null);
16
+ this.last = null;
17
+ this.max = max;
18
+ this.resetTtl = resetTtl;
19
+ this.size = 0;
20
+ this.ttl = ttl;
21
+ }
22
+ clear() {
23
+ this.first = null;
24
+ this.items = Object.create(null);
25
+ this.last = null;
26
+ this.size = 0;
27
+ return this;
28
+ }
29
+ delete(key) {
30
+ if (this.has(key)) {
31
+ const item = this.items[key];
32
+ delete this.items[key];
33
+ this.size--;
34
+ if (item.prev !== null) {
35
+ item.prev.next = item.next;
36
+ }
37
+ if (item.next !== null) {
38
+ item.next.prev = item.prev;
39
+ }
40
+ if (this.first === item) {
41
+ this.first = item.next;
42
+ }
43
+ if (this.last === item) {
44
+ this.last = item.prev;
45
+ }
46
+ }
47
+ return this;
48
+ }
49
+ entries(keys = this.keys()) {
50
+ return keys.map((key) => [key, this.get(key)]);
51
+ }
52
+ evict(bypass = false) {
53
+ if (bypass || this.size > 0) {
54
+ const item = this.first;
55
+ delete this.items[item.key];
56
+ if (--this.size === 0) {
57
+ this.first = null;
58
+ this.last = null;
59
+ }
60
+ else {
61
+ this.first = item.next;
62
+ this.first.prev = null;
63
+ }
64
+ }
65
+ return this;
66
+ }
67
+ expiresAt(key) {
68
+ let result;
69
+ if (this.has(key)) {
70
+ result = this.items[key].expiry;
71
+ }
72
+ return result;
73
+ }
74
+ get(key) {
75
+ let result;
76
+ if (this.has(key)) {
77
+ const item = this.items[key];
78
+ if (this.ttl > 0 && item.expiry <= Date.now()) {
79
+ this.delete(key);
80
+ }
81
+ else {
82
+ result = item.value;
83
+ this.set(key, result, true);
84
+ }
85
+ }
86
+ return result;
87
+ }
88
+ has(key) {
89
+ return key in this.items;
90
+ }
91
+ keys() {
92
+ const result = [];
93
+ let x = this.first;
94
+ while (x !== null) {
95
+ result.push(x.key);
96
+ x = x.next;
97
+ }
98
+ return result;
99
+ }
100
+ set(key, value, bypass = false, resetTtl = this.resetTtl) {
101
+ let item;
102
+ if (bypass || this.has(key)) {
103
+ item = this.items[key];
104
+ item.value = value;
105
+ if (bypass === false && resetTtl) {
106
+ item.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;
107
+ }
108
+ if (this.last !== item) {
109
+ const last = this.last, next = item.next, prev = item.prev;
110
+ if (this.first === item) {
111
+ this.first = item.next;
112
+ }
113
+ item.next = null;
114
+ item.prev = this.last;
115
+ last.next = item;
116
+ if (prev !== null) {
117
+ prev.next = next;
118
+ }
119
+ if (next !== null) {
120
+ next.prev = prev;
121
+ }
122
+ }
123
+ }
124
+ else {
125
+ if (this.max > 0 && this.size === this.max) {
126
+ this.evict(true);
127
+ }
128
+ item = this.items[key] = {
129
+ expiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,
130
+ key: key,
131
+ prev: this.last,
132
+ next: null,
133
+ value,
134
+ };
135
+ if (++this.size === 1) {
136
+ this.first = item;
137
+ }
138
+ else {
139
+ this.last.next = item;
140
+ }
141
+ }
142
+ this.last = item;
143
+ return this;
144
+ }
145
+ values(keys = this.keys()) {
146
+ return keys.map((key) => this.get(key));
147
+ }
148
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "applesauce-core",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -36,18 +36,34 @@
36
36
  }
37
37
  },
38
38
  "dependencies": {
39
+ "@types/zen-push": "^0.1.4",
39
40
  "debug": "^4.3.7",
40
41
  "json-stringify-deterministic": "^1.0.12",
41
42
  "nanoid": "^5.0.7",
42
43
  "nostr-tools": "^2.7.2",
43
- "tiny-lru": "^11.2.11"
44
+ "zen-push": "^0.3.1"
44
45
  },
45
46
  "devDependencies": {
47
+ "@jest/globals": "^29.7.0",
46
48
  "@types/debug": "^4.1.12",
49
+ "@types/jest": "^29.5.13",
47
50
  "@types/zen-observable": "^0.8.7",
51
+ "jest": "^29.7.0",
52
+ "jest-extended": "^4.0.2",
48
53
  "zen-observable": "^0.10.0"
49
54
  },
55
+ "jest": {
56
+ "roots": [
57
+ "dist"
58
+ ],
59
+ "setupFilesAfterEnv": [
60
+ "jest-extended/all"
61
+ ]
62
+ },
50
63
  "scripts": {
51
- "build": "tsc"
64
+ "build": "tsc",
65
+ "watch:build": "tsc --watch > /dev/null",
66
+ "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
67
+ "watch:test": "(trap 'kill 0' SIGINT; pnpm run build -w > /dev/null & pnpm run test --watch)"
52
68
  }
53
69
  }
@@ -1,17 +0,0 @@
1
- import { ProfileContent as TProfileContent } from "./profile.js";
2
- export declare const EventUID: unique symbol;
3
- export declare const EventIndexableTags: unique symbol;
4
- export declare const MailboxesInboxes: unique symbol;
5
- export declare const MailboxesOutboxes: unique symbol;
6
- export declare const ProfileContent: unique symbol;
7
- export declare const FromRelays: unique symbol;
8
- declare module "nostr-tools" {
9
- interface Event {
10
- [EventUID]?: string;
11
- [MailboxesInboxes]?: Set<string>;
12
- [MailboxesOutboxes]?: Set<string>;
13
- [ProfileContent]?: TProfileContent | Error;
14
- [EventIndexableTags]?: Set<string>;
15
- [FromRelays]?: Set<string>;
16
- }
17
- }
@@ -1,10 +0,0 @@
1
- // event
2
- export const EventUID = Symbol.for("event-uid");
3
- export const EventIndexableTags = Symbol.for("indexable-tags");
4
- // mailboxes
5
- export const MailboxesInboxes = Symbol.for("mailboxes-inboxes");
6
- export const MailboxesOutboxes = Symbol.for("mailboxes-outboxes");
7
- // profile
8
- export const ProfileContent = Symbol.for("profile-content");
9
- // event relays
10
- export const FromRelays = Symbol.for("from-relays");