@nostrify/nostrify 0.46.7 → 0.46.8

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 (154) hide show
  1. package/.turbo/turbo-build.log +28 -5
  2. package/.turbo/turbo-setup.log +13 -0
  3. package/.turbo/turbo-test.log +123 -0
  4. package/BunkerURI.test.ts +19 -14
  5. package/CHANGELOG.md +8 -0
  6. package/NBrowserSigner.test.ts +49 -34
  7. package/NCache.test.ts +14 -7
  8. package/NCache.ts +2 -2
  9. package/NConnectSigner.test.ts +48 -31
  10. package/NConnectSigner.ts +3 -3
  11. package/NIP05.test.ts +36 -44
  12. package/NIP05.ts +2 -2
  13. package/NIP50.test.ts +35 -34
  14. package/NIP98.test.ts +89 -76
  15. package/NIP98.ts +2 -2
  16. package/NKinds.test.ts +37 -36
  17. package/NPool.test.ts +35 -24
  18. package/NPool.ts +42 -23
  19. package/NRelay1.test.ts +100 -68
  20. package/NRelay1.ts +13 -6
  21. package/NSchema.test.ts +98 -56
  22. package/NSchema.ts +10 -14
  23. package/NSecSigner.test.ts +19 -10
  24. package/NSecSigner.ts +4 -3
  25. package/NSet.test.ts +123 -50
  26. package/NSet.ts +13 -6
  27. package/RelayError.test.ts +11 -10
  28. package/RelayError.ts +1 -1
  29. package/dist/BunkerURI.js +44 -44
  30. package/dist/NBrowserSigner.js +73 -83
  31. package/dist/NCache.d.ts +2 -2
  32. package/dist/NCache.d.ts.map +1 -1
  33. package/dist/NCache.js +35 -56
  34. package/dist/NConnectSigner.d.ts +1 -1
  35. package/dist/NConnectSigner.d.ts.map +1 -1
  36. package/dist/NConnectSigner.js +124 -117
  37. package/dist/NIP05.d.ts +1 -1
  38. package/dist/NIP05.d.ts.map +1 -1
  39. package/dist/NIP05.js +33 -33
  40. package/dist/NIP50.js +19 -20
  41. package/dist/NIP98.d.ts +1 -1
  42. package/dist/NIP98.d.ts.map +1 -1
  43. package/dist/NIP98.js +71 -64
  44. package/dist/NKinds.js +24 -22
  45. package/dist/NPool.d.ts +2 -2
  46. package/dist/NPool.d.ts.map +1 -1
  47. package/dist/NPool.js +143 -170
  48. package/dist/NRelay1.d.ts +5 -4
  49. package/dist/NRelay1.d.ts.map +1 -1
  50. package/dist/NRelay1.js +301 -315
  51. package/dist/NSchema.d.ts +1 -1
  52. package/dist/NSchema.d.ts.map +1 -1
  53. package/dist/NSchema.js +185 -208
  54. package/dist/NSecSigner.d.ts +1 -2
  55. package/dist/NSecSigner.d.ts.map +1 -1
  56. package/dist/NSecSigner.js +35 -46
  57. package/dist/NSet.d.ts +1 -1
  58. package/dist/NSet.d.ts.map +1 -1
  59. package/dist/NSet.js +138 -166
  60. package/dist/RelayError.d.ts +1 -1
  61. package/dist/RelayError.d.ts.map +1 -1
  62. package/dist/RelayError.js +18 -17
  63. package/dist/ln/LNURL.d.ts +4 -4
  64. package/dist/ln/LNURL.d.ts.map +1 -1
  65. package/dist/ln/LNURL.js +93 -93
  66. package/dist/ln/mod.d.ts +3 -3
  67. package/dist/ln/mod.js +4 -2
  68. package/dist/ln/mod.js.map +7 -1
  69. package/dist/ln/types/LNURLCallback.js +0 -2
  70. package/dist/ln/types/LNURLDetails.js +0 -2
  71. package/dist/mod.d.ts +14 -14
  72. package/dist/mod.js +30 -15
  73. package/dist/mod.js.map +7 -1
  74. package/dist/test/ErrorRelay.d.ts +1 -1
  75. package/dist/test/ErrorRelay.d.ts.map +1 -1
  76. package/dist/test/ErrorRelay.js +22 -21
  77. package/dist/test/MockRelay.d.ts +3 -3
  78. package/dist/test/MockRelay.d.ts.map +1 -1
  79. package/dist/test/MockRelay.js +56 -57
  80. package/dist/test/TestRelayServer.d.ts +6 -3
  81. package/dist/test/TestRelayServer.d.ts.map +1 -1
  82. package/dist/test/TestRelayServer.js +141 -122
  83. package/dist/test/mod.d.ts +3 -3
  84. package/dist/test/mod.d.ts.map +1 -1
  85. package/dist/test/mod.js +22 -19
  86. package/dist/test/mod.js.map +7 -1
  87. package/dist/tsconfig.tsbuildinfo +1 -1
  88. package/dist/uploaders/BlossomUploader.d.ts +1 -1
  89. package/dist/uploaders/BlossomUploader.d.ts.map +1 -1
  90. package/dist/uploaders/BlossomUploader.js +69 -66
  91. package/dist/uploaders/NostrBuildUploader.d.ts +1 -2
  92. package/dist/uploaders/NostrBuildUploader.d.ts.map +1 -1
  93. package/dist/uploaders/NostrBuildUploader.js +61 -59
  94. package/dist/uploaders/mod.d.ts +2 -2
  95. package/dist/uploaders/mod.js +6 -3
  96. package/dist/uploaders/mod.js.map +7 -1
  97. package/dist/utils/CircularSet.d.ts +1 -1
  98. package/dist/utils/CircularSet.d.ts.map +1 -1
  99. package/dist/utils/CircularSet.js +26 -28
  100. package/dist/utils/Machina.js +35 -59
  101. package/dist/utils/N64.d.ts +1 -1
  102. package/dist/utils/N64.d.ts.map +1 -1
  103. package/dist/utils/N64.js +16 -18
  104. package/dist/utils/mod.d.ts +2 -2
  105. package/dist/utils/mod.js +6 -3
  106. package/dist/utils/mod.js.map +7 -1
  107. package/ln/LNURL.test.ts +70 -52
  108. package/ln/LNURL.ts +15 -15
  109. package/ln/mod.ts +3 -3
  110. package/mod.ts +14 -14
  111. package/package.json +5 -3
  112. package/test/ErrorRelay.test.ts +11 -10
  113. package/test/ErrorRelay.ts +17 -5
  114. package/test/MockRelay.test.ts +15 -8
  115. package/test/MockRelay.ts +3 -3
  116. package/test/TestRelayServer.ts +46 -17
  117. package/test/mod.ts +4 -4
  118. package/tsconfig.json +5 -2
  119. package/uploaders/BlossomUploader.test.ts +39 -22
  120. package/uploaders/BlossomUploader.ts +2 -2
  121. package/uploaders/NostrBuildUploader.test.ts +36 -18
  122. package/uploaders/NostrBuildUploader.ts +4 -4
  123. package/uploaders/mod.ts +2 -2
  124. package/utils/CircularSet.test.ts +5 -4
  125. package/utils/CircularSet.ts +3 -1
  126. package/utils/Machina.test.ts +30 -19
  127. package/utils/N64.test.ts +12 -11
  128. package/utils/N64.ts +2 -2
  129. package/utils/mod.ts +2 -2
  130. package/dist/BunkerURI.js.map +0 -1
  131. package/dist/NBrowserSigner.js.map +0 -1
  132. package/dist/NCache.js.map +0 -1
  133. package/dist/NConnectSigner.js.map +0 -1
  134. package/dist/NIP05.js.map +0 -1
  135. package/dist/NIP50.js.map +0 -1
  136. package/dist/NIP98.js.map +0 -1
  137. package/dist/NKinds.js.map +0 -1
  138. package/dist/NPool.js.map +0 -1
  139. package/dist/NRelay1.js.map +0 -1
  140. package/dist/NSchema.js.map +0 -1
  141. package/dist/NSecSigner.js.map +0 -1
  142. package/dist/NSet.js.map +0 -1
  143. package/dist/RelayError.js.map +0 -1
  144. package/dist/ln/LNURL.js.map +0 -1
  145. package/dist/ln/types/LNURLCallback.js.map +0 -1
  146. package/dist/ln/types/LNURLDetails.js.map +0 -1
  147. package/dist/test/ErrorRelay.js.map +0 -1
  148. package/dist/test/MockRelay.js.map +0 -1
  149. package/dist/test/TestRelayServer.js.map +0 -1
  150. package/dist/uploaders/BlossomUploader.js.map +0 -1
  151. package/dist/uploaders/NostrBuildUploader.js.map +0 -1
  152. package/dist/utils/CircularSet.js.map +0 -1
  153. package/dist/utils/Machina.js.map +0 -1
  154. package/dist/utils/N64.js.map +0 -1
package/ln/LNURL.ts CHANGED
@@ -1,10 +1,10 @@
1
- import { NostrEvent } from "@nostrify/types";
2
- import { bech32 } from "@scure/base";
1
+ import type { NostrEvent } from '@nostrify/types';
2
+ import { bech32 } from '@scure/base';
3
3
 
4
- import { LNURLCallback } from "./types/LNURLCallback.js";
5
- import { LNURLDetails } from "./types/LNURLDetails.js";
4
+ import { LNURLCallback } from './types/LNURLCallback.ts';
5
+ import { LNURLDetails } from './types/LNURLDetails.ts';
6
6
 
7
- import { NSchema as n, z } from "../NSchema.js";
7
+ import { NSchema as n, z } from '../NSchema.ts';
8
8
 
9
9
  /**
10
10
  * Represents an LNURL, with methods to fetch details and generate invoices.
@@ -45,7 +45,7 @@ export class LNURL {
45
45
  20000,
46
46
  );
47
47
 
48
- if (prefix !== "lnurl") {
48
+ if (prefix !== 'lnurl') {
49
49
  throw new Error('Expected a bech32 string starting with "lnurl1"');
50
50
  }
51
51
 
@@ -69,7 +69,7 @@ export class LNURL {
69
69
  );
70
70
  }
71
71
 
72
- const [name, host] = ln.split("@");
72
+ const [name, host] = ln.split('@');
73
73
  const url = new URL(`/.well-known/lnurlp/${name}`, `https://${host}`);
74
74
 
75
75
  return new LNURL(url, opts);
@@ -79,7 +79,7 @@ export class LNURL {
79
79
  toString(): `lnurl1${string}` {
80
80
  const data = new TextEncoder().encode(this.url.toString());
81
81
  const words = bech32.toWords(data);
82
- return bech32.encode("lnurl", words, 20000);
82
+ return bech32.encode('lnurl', words, 20000);
83
83
  }
84
84
 
85
85
  /** Resolve an LNURL to its details. */
@@ -101,11 +101,11 @@ export class LNURL {
101
101
  const details = await this.getDetails(opts);
102
102
  const callback = new URL(details.callback);
103
103
 
104
- callback.searchParams.set("amount", opts.amount.toString());
105
- callback.searchParams.set("lnurl", this.toString());
104
+ callback.searchParams.set('amount', opts.amount.toString());
105
+ callback.searchParams.set('lnurl', this.toString());
106
106
 
107
107
  if (opts.nostr) {
108
- callback.searchParams.set("nostr", JSON.stringify(opts.nostr));
108
+ callback.searchParams.set('nostr', JSON.stringify(opts.nostr));
109
109
  }
110
110
 
111
111
  const response = await this.fetch(callback, opts);
@@ -124,13 +124,13 @@ export class LNURL {
124
124
  minSendable: z.number().positive().int(),
125
125
  metadata: z.string(),
126
126
  nostrPubkey: n.id().optional(),
127
- tag: z.literal("payRequest"),
127
+ tag: z.literal('payRequest'),
128
128
  }).superRefine((details, ctx) => {
129
129
  if (details.minSendable > details.maxSendable) {
130
130
  ctx.addIssue({
131
131
  code: z.ZodIssueCode.custom,
132
- message: "minSendable must be less than or equal to maxSendable",
133
- path: ["minSendable"],
132
+ message: 'minSendable must be less than or equal to maxSendable',
133
+ path: ['minSendable'],
134
134
  });
135
135
  }
136
136
  }) as z.ZodType<LNURLDetails>;
@@ -139,7 +139,7 @@ export class LNURL {
139
139
  /** LNURL callback schema. */
140
140
  static lnurlCallbackSchema(): z.ZodType<LNURLCallback> {
141
141
  return z.object({
142
- pr: n.bech32("lnbc"),
142
+ pr: n.bech32('lnbc'),
143
143
  routes: z.tuple([]),
144
144
  }) as unknown as z.ZodType<LNURLCallback>;
145
145
  }
package/ln/mod.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { LNURL } from './LNURL.js';
1
+ export { LNURL } from './LNURL.ts';
2
2
 
3
- export type { LNURLCallback } from './types/LNURLCallback.js';
4
- export type { LNURLDetails } from './types/LNURLDetails.js';
3
+ export type { LNURLCallback } from './types/LNURLCallback.ts';
4
+ export type { LNURLDetails } from './types/LNURLDetails.ts';
package/mod.ts CHANGED
@@ -1,16 +1,16 @@
1
- export { BunkerURI } from './BunkerURI.js';
2
- export { NBrowserSigner } from './NBrowserSigner.js';
3
- export { NCache } from './NCache.js';
4
- export { NConnectSigner, type NConnectSignerOpts } from './NConnectSigner.js';
5
- export { NIP05 } from './NIP05.js';
6
- export { NIP50 } from './NIP50.js';
7
- export { NIP98 } from './NIP98.js';
8
- export { NKinds } from './NKinds.js';
9
- export { NPool, type NPoolOpts } from './NPool.js';
10
- export { NRelay1, type NRelay1Opts } from './NRelay1.js';
11
- export { NSchema } from './NSchema.js';
12
- export { NSecSigner } from './NSecSigner.js';
13
- export { NSet } from './NSet.js';
14
- export { RelayError } from './RelayError.js';
1
+ export { BunkerURI } from './BunkerURI.ts';
2
+ export { NBrowserSigner } from './NBrowserSigner.ts';
3
+ export { NCache } from './NCache.ts';
4
+ export { NConnectSigner, type NConnectSignerOpts } from './NConnectSigner.ts';
5
+ export { NIP05 } from './NIP05.ts';
6
+ export { NIP50 } from './NIP50.ts';
7
+ export { NIP98 } from './NIP98.ts';
8
+ export { NKinds } from './NKinds.ts';
9
+ export { NPool, type NPoolOpts } from './NPool.ts';
10
+ export { NRelay1, type NRelay1Opts } from './NRelay1.ts';
11
+ export { NSchema } from './NSchema.ts';
12
+ export { NSecSigner } from './NSecSigner.ts';
13
+ export { NSet } from './NSet.ts';
14
+ export { RelayError } from './RelayError.ts';
15
15
 
16
16
  export type * from '@nostrify/types';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nostrify/nostrify",
3
- "version": "0.46.7",
3
+ "version": "0.46.8",
4
4
  "exports": {
5
5
  ".": "./dist/mod.js",
6
6
  "./ln": "./dist/ln/mod.js",
@@ -20,12 +20,14 @@
20
20
  "@types/node": "^24.1.0",
21
21
  "@scure/base": "^1.2.6",
22
22
  "@std/encoding": "npm:@jsr/std__encoding@^0.224.1",
23
- "@nostrify/types": "0.36.3"
23
+ "@nostrify/types": "0.36.4"
24
24
  },
25
25
  "publishConfig": {
26
26
  "access": "public"
27
27
  },
28
28
  "scripts": {
29
- "build": "tsc -p tsconfig.json"
29
+ "build": "tsc -p tsconfig.json && node ../../esbuild.config.js --package ./",
30
+ "setup": "pnpm i",
31
+ "test": "node --test \"**/*.test.ts\""
30
32
  }
31
33
  }
@@ -1,17 +1,18 @@
1
- import { genEvent } from '@nostrify/nostrify/test';
2
- import { assertRejects } from '@std/assert';
1
+ import { test } from "node:test";
2
+ import { genEvent } from "./mod.ts";
3
+ import { rejects } from "node:assert";
3
4
 
4
- import { ErrorRelay } from './ErrorRelay.ts';
5
+ import { ErrorRelay } from "./ErrorRelay.ts";
5
6
 
6
- Deno.test('ErrorRelay', async () => {
7
+ await test("ErrorRelay", async () => {
7
8
  const store = new ErrorRelay();
8
- await assertRejects(() => store.event(genEvent()));
9
- await assertRejects(() => store.query([]));
10
- await assertRejects(() => store.count([]));
11
- await assertRejects(() => store.remove([]));
12
- await assertRejects(() => store.close());
9
+ await rejects(() => store.event(genEvent()));
10
+ await rejects(() => store.query([]));
11
+ await rejects(() => store.count([]));
12
+ await rejects(() => store.remove([]));
13
+ await rejects(() => store.close());
13
14
 
14
- await assertRejects(async () => {
15
+ await rejects(async () => {
15
16
  for await (const _ of store.req([])) {
16
17
  // Do nothing.
17
18
  }
@@ -1,5 +1,5 @@
1
1
  // deno-lint-ignore-file require-await require-yield
2
- import {
2
+ import type {
3
3
  NostrEvent,
4
4
  NostrFilter,
5
5
  NostrRelayCLOSED,
@@ -18,19 +18,31 @@ export class ErrorRelay implements NRelay {
18
18
  throw new Error('This error is intentional.');
19
19
  }
20
20
 
21
- async event(_event: NostrEvent, _opts?: { signal?: AbortSignal }): Promise<void> {
21
+ async event(
22
+ _event: NostrEvent,
23
+ _opts?: { signal?: AbortSignal },
24
+ ): Promise<void> {
22
25
  throw new Error('This error is intentional.');
23
26
  }
24
27
 
25
- async query(_filters: NostrFilter[], _opts?: { signal?: AbortSignal }): Promise<NostrEvent[]> {
28
+ async query(
29
+ _filters: NostrFilter[],
30
+ _opts?: { signal?: AbortSignal },
31
+ ): Promise<NostrEvent[]> {
26
32
  throw new Error('This error is intentional.');
27
33
  }
28
34
 
29
- async count(_filters: NostrFilter[], _opts?: { signal?: AbortSignal }): Promise<NostrRelayCOUNT[2]> {
35
+ async count(
36
+ _filters: NostrFilter[],
37
+ _opts?: { signal?: AbortSignal },
38
+ ): Promise<NostrRelayCOUNT[2]> {
30
39
  throw new Error('This error is intentional.');
31
40
  }
32
41
 
33
- async remove(_filters: NostrFilter[], _opts?: { signal?: AbortSignal }): Promise<void> {
42
+ async remove(
43
+ _filters: NostrFilter[],
44
+ _opts?: { signal?: AbortSignal },
45
+ ): Promise<void> {
34
46
  throw new Error('This error is intentional.');
35
47
  }
36
48
 
@@ -1,20 +1,27 @@
1
- import { assertEquals } from '@std/assert';
1
+ import { test } from "node:test";
2
+ import { deepStrictEqual } from "node:assert";
2
3
 
3
- import { MockRelay } from './MockRelay.ts';
4
+ import { MockRelay } from "./MockRelay.ts";
4
5
 
5
- import event1 from '../../../fixtures/event-1.json' with { type: 'json' };
6
+ import event1 from "../../../fixtures/event-1.json" with { type: "json" };
6
7
 
7
- Deno.test('MockRelay', async () => {
8
+ await test("MockRelay", async () => {
8
9
  const relay = new MockRelay();
9
10
 
10
- assertEquals(await relay.count([{ ids: [event1.id] }]), { count: 0, approximate: false });
11
+ deepStrictEqual(await relay.count([{ ids: [event1.id] }]), {
12
+ count: 0,
13
+ approximate: false,
14
+ });
11
15
 
12
16
  await relay.event(event1);
13
17
 
14
- assertEquals(await relay.count([{ ids: [event1.id] }]), { count: 1, approximate: false });
18
+ deepStrictEqual(await relay.count([{ ids: [event1.id] }]), {
19
+ count: 1,
20
+ approximate: false,
21
+ });
15
22
 
16
23
  const result = await relay.query([{ ids: [event1.id] }]);
17
- assertEquals(result[0], event1);
24
+ deepStrictEqual(result[0], event1);
18
25
 
19
- assertEquals(relay.subs.size, 0); // cleanup
26
+ deepStrictEqual(relay.subs.size, 0); // cleanup
20
27
  });
package/test/MockRelay.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  // deno-lint-ignore-file require-await
2
2
 
3
- import {
3
+ import type {
4
4
  NostrEvent,
5
5
  NostrFilter,
6
6
  NostrRelayCLOSED,
@@ -11,8 +11,8 @@ import {
11
11
  } from '@nostrify/types';
12
12
  import { matchFilters } from 'nostr-tools';
13
13
 
14
- import { Machina } from '../utils/Machina.js';
15
- import { NSet } from '../NSet.js';
14
+ import { Machina } from '../utils/Machina.ts';
15
+ import { NSet } from '../NSet.ts';
16
16
 
17
17
  /** Mock relay for testing. */
18
18
  export class MockRelay extends NSet implements NRelay {
@@ -1,9 +1,10 @@
1
- import { MockRelay } from './mod.js';
2
- import { NostrClientMsg, NostrEvent, NostrRelayMsg } from '@nostrify/types';
3
- import { NSchema as n } from '../NSchema.js';
4
- import { WebSocketServer, WebSocket } from 'ws';
1
+ import { MockRelay } from './mod.ts';
2
+ import type { NostrClientMsg, NostrEvent, NostrRelayMsg } from '@nostrify/types';
3
+ import { NSchema as n } from '../NSchema.ts';
4
+ import { WebSocket, WebSocketServer } from 'ws';
5
5
  import { createServer, Server } from 'node:http';
6
- import { AddressInfo } from 'node:net';
6
+ import type { AddressInfo } from 'node:net';
7
+ import { Buffer } from 'node:buffer';
7
8
 
8
9
  interface TestRelayServerOpts {
9
10
  handleMessage?(socket: WebSocket, msg: NostrClientMsg): Promise<void> | void;
@@ -11,19 +12,30 @@ interface TestRelayServerOpts {
11
12
 
12
13
  export class TestRelayServer {
13
14
  private port = 0;
15
+ private inited = false;
14
16
  private httpServer: Server;
15
17
  private wsServer: WebSocketServer;
18
+ private opts: TestRelayServerOpts;
16
19
  private connections = new Set<WebSocket>();
17
20
  private controllers = new Map<string, AbortController>();
18
21
  private store = new MockRelay();
19
22
 
20
- constructor(private opts?: TestRelayServerOpts) {
23
+ constructor(opts?: TestRelayServerOpts) {
24
+ this.opts = opts || {};
21
25
  this.httpServer = createServer();
22
26
  this.wsServer = new WebSocketServer({ server: this.httpServer });
23
27
  this.setupWebSocketServer();
28
+ }
29
+
30
+ init() {
31
+ const { resolve, promise } = Promise.withResolvers<void>();
24
32
  this.httpServer.listen(0, '127.0.0.1', () => {
25
33
  this.port = (this.httpServer.address() as AddressInfo).port;
34
+ this.inited = true;
35
+ resolve();
26
36
  });
37
+
38
+ return promise;
27
39
  }
28
40
 
29
41
  private setupWebSocketServer(): void {
@@ -32,7 +44,6 @@ export class TestRelayServer {
32
44
 
33
45
  socket.on('close', () => {
34
46
  this.connections.delete(socket);
35
- // Clean up any subscriptions for this socket
36
47
  for (const [subId, controller] of this.controllers.entries()) {
37
48
  controller.abort();
38
49
  this.controllers.delete(subId);
@@ -47,12 +58,12 @@ export class TestRelayServer {
47
58
  this.handleMessage.bind(this);
48
59
  handleMessage(socket, result.data);
49
60
  }
50
- } catch (error) {
51
- // Handle parsing errors silently
61
+ } catch {
62
+ // do nothing
52
63
  }
53
64
  });
54
65
 
55
- socket.on('error', (error) => {
66
+ socket.on('error', (error: any) => {
56
67
  console.error('WebSocket error:', error);
57
68
  this.connections.delete(socket);
58
69
  });
@@ -60,6 +71,7 @@ export class TestRelayServer {
60
71
  }
61
72
 
62
73
  send(socket: WebSocket, msg: NostrRelayMsg): void {
74
+ if (!this.inited) throw new Error('TestRelayServer not initialized');
63
75
  if (socket.readyState === WebSocket.OPEN) {
64
76
  socket.send(JSON.stringify(msg));
65
77
  }
@@ -69,6 +81,8 @@ export class TestRelayServer {
69
81
  socket: WebSocket,
70
82
  msg: NostrClientMsg,
71
83
  ): Promise<void> {
84
+ if (!this.inited) throw new Error('TestRelayServer not initialized');
85
+
72
86
  switch (msg[0]) {
73
87
  case 'REQ': {
74
88
  const [_, subId, ...filters] = msg;
@@ -107,13 +121,15 @@ export class TestRelayServer {
107
121
  }
108
122
 
109
123
  get url(): string {
124
+ if (!this.inited) throw new Error('TestRelayServer not initialized');
110
125
  const addr = this.httpServer.address() as AddressInfo;
111
126
  return `ws://${addr.address}:${addr.port}`;
112
127
  }
113
128
 
129
+ // deno-lint-ignore require-await
114
130
  async close(): Promise<void> {
131
+ if (!this.inited) throw new Error('TestRelayServer not initialized');
115
132
  return new Promise((resolve) => {
116
- // Close all WebSocket connections
117
133
  this.connections.forEach((conn) => {
118
134
  if (conn.readyState === WebSocket.OPEN) {
119
135
  conn.close();
@@ -121,36 +137,49 @@ export class TestRelayServer {
121
137
  });
122
138
  this.connections.clear();
123
139
 
124
- // Abort all controllers
125
140
  this.controllers.forEach((controller) => controller.abort());
126
141
  this.controllers.clear();
127
142
 
128
- // Close WebSocket server
129
143
  this.wsServer.close(() => {
130
- // Close HTTP server
131
144
  this.httpServer.close(() => {
145
+ this.inited = false;
132
146
  resolve();
133
147
  });
134
148
  });
135
149
  });
136
150
  }
137
151
 
138
- open(): void {
152
+ open(): Promise<void> {
153
+ if (this.inited) throw new Error('TestRelayServer already initialized');
139
154
  if (!this.httpServer.listening) {
155
+ const { resolve, promise } = Promise.withResolvers<void>();
140
156
  this.httpServer = createServer();
141
157
  this.wsServer = new WebSocketServer({ server: this.httpServer });
142
158
  this.setupWebSocketServer();
143
159
  this.httpServer.listen(0, '127.0.0.1', () => {
144
160
  this.port = (this.httpServer.address() as AddressInfo).port;
161
+ this.inited = true;
162
+ resolve();
145
163
  });
164
+ return promise;
146
165
  }
166
+ return Promise.resolve();
147
167
  }
148
168
 
149
169
  event(event: NostrEvent): Promise<void> {
170
+ if (!this.inited) throw new Error('TestRelayServer not initialized');
150
171
  return this.store.event(event);
151
172
  }
152
173
 
153
174
  async [Symbol.asyncDispose](): Promise<void> {
154
- await this.close();
175
+ if (this.inited) {
176
+ await this.close();
177
+ }
155
178
  }
156
- }
179
+
180
+ static async create(opts?: TestRelayServerOpts) {
181
+ const server = new TestRelayServer(opts);
182
+ await server.init();
183
+ return server;
184
+ }
185
+ }
package/test/mod.ts CHANGED
@@ -1,14 +1,14 @@
1
- import { NostrEvent } from '@nostrify/types';
1
+ import type { NostrEvent } from '@nostrify/types';
2
2
  import { finalizeEvent, generateSecretKey } from 'nostr-tools';
3
3
  import { readFile } from 'node:fs/promises';
4
4
 
5
- export { ErrorRelay } from './ErrorRelay.js';
6
- export { MockRelay } from './MockRelay.js';
5
+ export { ErrorRelay } from './ErrorRelay.ts';
6
+ export { MockRelay } from './MockRelay.ts';
7
7
 
8
8
  /** Import a JSONL fixture by name in tests. */
9
9
  export async function jsonlEvents(path: string): Promise<NostrEvent[]> {
10
10
  const data = await readFile(path, { encoding: 'utf8' });
11
- return data.split('\n').map((line) => JSON.parse(line));
11
+ return data.split('\n').map((line: string) => JSON.parse(line));
12
12
  }
13
13
 
14
14
  /** Generate an event for use in tests. */
package/tsconfig.json CHANGED
@@ -1,7 +1,9 @@
1
1
  {
2
2
  "extends": "../../tsconfig.base.json",
3
3
  "include": [
4
- "./**/*.ts"
4
+ "./**/*.ts",
5
+ "!./**/*.test.ts",
6
+ "!./**/*.bench.ts"
5
7
  ],
6
8
  "exclude": [
7
9
  "./dist",
@@ -9,6 +11,7 @@
9
11
  "./**/*.test.ts"
10
12
  ],
11
13
  "compilerOptions": {
12
- "outDir": "./dist"
14
+ "outDir": "./dist",
15
+ "target": "es2024"
13
16
  }
14
17
  }
@@ -1,26 +1,43 @@
1
- import { assertEquals } from '@std/assert';
2
- import { generateSecretKey } from 'nostr-tools';
1
+ import { test } from "node:test";
2
+ import { deepStrictEqual } from "node:assert";
3
+ import { generateSecretKey } from "nostr-tools";
4
+ import process from "node:process";
5
+ import { BlossomUploader } from "./BlossomUploader.ts";
6
+ import { NSecSigner } from "../NSecSigner.ts";
7
+ import fs from "node:fs/promises";
8
+ import { URL } from "node:url";
9
+ import { Readable } from "node:stream";
3
10
 
4
- import { BlossomUploader } from './BlossomUploader.ts';
5
- import { NSecSigner } from '../NSecSigner.ts';
11
+ await test(
12
+ "BlossomUploader.upload",
13
+ { skip: process.env.CI === "true" || process.env.CI === "1" },
14
+ async () => {
15
+ const fsFile = await fs.open(
16
+ new URL("../../../fixtures/voadi.png", import.meta.url),
17
+ );
18
+ const blob = await (new Response(Readable.toWeb(fsFile.createReadStream())))
19
+ .blob();
20
+ const file = new File([blob], "voadi.png", { type: "image/png" });
6
21
 
7
- Deno.test('BlossomUploader.upload', { ignore: Deno.env.get('CI') === 'true' }, async () => {
8
- const fsFile = await Deno.open(new URL('../../../fixtures/voadi.png', import.meta.url));
9
- const blob = await (new Response(fsFile.readable)).blob();
10
- const file = new File([blob], 'voadi.png', { type: 'image/png' });
22
+ const uploader = new BlossomUploader({
23
+ servers: ["https://blossom.primal.net/"],
24
+ signer: new NSecSigner(generateSecretKey()),
25
+ });
11
26
 
12
- const uploader = new BlossomUploader({
13
- servers: ['https://blossom.primal.net/'],
14
- signer: new NSecSigner(generateSecretKey()),
15
- });
27
+ const tags = await uploader.upload(file);
16
28
 
17
- const tags = await uploader.upload(file);
18
-
19
- assertEquals(tags, [
20
- ['url', 'https://blossom.primal.net/7508bd9d8b0ed6e0891a3b973adf6011b1e49f6174910d6a1eb722a4a2e30539.png'],
21
- ['x', '7508bd9d8b0ed6e0891a3b973adf6011b1e49f6174910d6a1eb722a4a2e30539'],
22
- ['ox', '7508bd9d8b0ed6e0891a3b973adf6011b1e49f6174910d6a1eb722a4a2e30539'],
23
- ['size', '172'],
24
- ['m', 'image/png'],
25
- ]);
26
- });
29
+ deepStrictEqual(tags, [
30
+ [
31
+ "url",
32
+ "https://blossom.primal.net/7508bd9d8b0ed6e0891a3b973adf6011b1e49f6174910d6a1eb722a4a2e30539.png",
33
+ ],
34
+ ["x", "7508bd9d8b0ed6e0891a3b973adf6011b1e49f6174910d6a1eb722a4a2e30539"],
35
+ [
36
+ "ox",
37
+ "7508bd9d8b0ed6e0891a3b973adf6011b1e49f6174910d6a1eb722a4a2e30539",
38
+ ],
39
+ ["size", "172"],
40
+ ["m", "image/png"],
41
+ ]);
42
+ },
43
+ );
@@ -1,8 +1,8 @@
1
- import { NostrSigner, NUploader } from '@nostrify/types';
1
+ import type { NostrSigner, NUploader } from '@nostrify/types';
2
2
  import { encodeHex } from '@std/encoding/hex';
3
3
  import { z } from 'zod';
4
4
 
5
- import { N64 } from '../utils/N64.js';
5
+ import { N64 } from '../utils/N64.ts';
6
6
 
7
7
  /** BlossomUploader options. */
8
8
  export interface BlossomUploaderOpts {
@@ -1,22 +1,40 @@
1
- import { assertEquals } from '@std/assert';
1
+ import { test } from "node:test";
2
+ import { deepStrictEqual } from "node:assert";
3
+ import process from "node:process";
4
+ import { URL } from "node:url";
5
+ import fs from "node:fs/promises";
2
6
 
3
- import { NostrBuildUploader } from './NostrBuildUploader.ts';
7
+ import { NostrBuildUploader } from "./NostrBuildUploader.ts";
8
+ import { Readable } from "node:stream";
4
9
 
5
- Deno.test('NostrBuildUploader.upload', { ignore: Deno.env.get('CI') === 'true' }, async () => {
6
- const fsFile = await Deno.open(new URL('../../../fixtures/voadi.png', import.meta.url));
7
- const blob = await (new Response(fsFile.readable)).blob();
8
- const file = new File([blob], 'voadi.png', { type: 'image/png' });
10
+ await test(
11
+ "NostrBuildUploader.upload",
12
+ { skip: process.env.CI === "true" || process.env.CI === "1" },
13
+ async () => {
14
+ const fsFile = await fs.open(
15
+ new URL("../../../fixtures/voadi.png", import.meta.url),
16
+ );
17
+ const blob = await (new Response(Readable.toWeb(fsFile.createReadStream())))
18
+ .blob();
19
+ const file = new File([blob], "voadi.png", { type: "image/png" });
9
20
 
10
- const uploader = new NostrBuildUploader();
11
- const tags = await uploader.upload(file);
21
+ const uploader = new NostrBuildUploader();
22
+ const tags = await uploader.upload(file);
12
23
 
13
- assertEquals(tags, [
14
- ['url', 'https://image.nostr.build/7508bd9d8b0ed6e0891a3b973adf6011b1e49f6174910d6a1eb722a4a2e30539.png'],
15
- ['m', 'image/png'],
16
- ['x', '21608eecb7df80ca3838deb428fd6568a0d0d3b1baac56491e2247a1c110649a'],
17
- ['ox', '7508bd9d8b0ed6e0891a3b973adf6011b1e49f6174910d6a1eb722a4a2e30539'],
18
- ['size', '171'],
19
- ['dim', '16x16'],
20
- ['blurhash', 'LCB20ssn0+NcbsfjRmaz12WW}osn'],
21
- ]);
22
- });
24
+ deepStrictEqual(tags, [
25
+ [
26
+ "url",
27
+ "https://image.nostr.build/7508bd9d8b0ed6e0891a3b973adf6011b1e49f6174910d6a1eb722a4a2e30539.png",
28
+ ],
29
+ ["m", "image/png"],
30
+ ["x", "21608eecb7df80ca3838deb428fd6568a0d0d3b1baac56491e2247a1c110649a"],
31
+ [
32
+ "ox",
33
+ "7508bd9d8b0ed6e0891a3b973adf6011b1e49f6174910d6a1eb722a4a2e30539",
34
+ ],
35
+ ["size", "171"],
36
+ ["dim", "16x16"],
37
+ ["blurhash", "LCB20ssn0+NcbsfjRmaz12WW}osn"],
38
+ ]);
39
+ },
40
+ );
@@ -1,9 +1,8 @@
1
1
  import { z } from 'zod';
2
2
 
3
- import { N64 } from '../utils/N64.js';
4
- import { NIP98 } from '../NIP98.js';
5
- import { NostrSigner } from '@nostrify/types';
6
- import { NUploader } from '@nostrify/types';
3
+ import { N64 } from '../utils/N64.ts';
4
+ import { NIP98 } from '../NIP98.ts';
5
+ import type { NostrSigner, NUploader } from '@nostrify/types';
7
6
 
8
7
  /** NostrBuildUploader options. */
9
8
  export interface NostrBuildUploaderOpts {
@@ -48,6 +47,7 @@ export class NostrBuildUploader implements NUploader {
48
47
 
49
48
  const response = await this.fetch(request);
50
49
  const json = await response.json();
50
+ console.log(json);
51
51
  const [data] = NostrBuildUploader.schema().parse(json).data;
52
52
 
53
53
  const tags: [['url', string], ...string[][]] = [
package/uploaders/mod.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { BlossomUploader } from './BlossomUploader.js';
2
- export { NostrBuildUploader } from './NostrBuildUploader.js';
1
+ export { BlossomUploader } from './BlossomUploader.ts';
2
+ export { NostrBuildUploader } from './NostrBuildUploader.ts';