@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.
- package/.turbo/turbo-build.log +28 -5
- package/.turbo/turbo-setup.log +13 -0
- package/.turbo/turbo-test.log +123 -0
- package/BunkerURI.test.ts +19 -14
- package/CHANGELOG.md +8 -0
- package/NBrowserSigner.test.ts +49 -34
- package/NCache.test.ts +14 -7
- package/NCache.ts +2 -2
- package/NConnectSigner.test.ts +48 -31
- package/NConnectSigner.ts +3 -3
- package/NIP05.test.ts +36 -44
- package/NIP05.ts +2 -2
- package/NIP50.test.ts +35 -34
- package/NIP98.test.ts +89 -76
- package/NIP98.ts +2 -2
- package/NKinds.test.ts +37 -36
- package/NPool.test.ts +35 -24
- package/NPool.ts +42 -23
- package/NRelay1.test.ts +100 -68
- package/NRelay1.ts +13 -6
- package/NSchema.test.ts +98 -56
- package/NSchema.ts +10 -14
- package/NSecSigner.test.ts +19 -10
- package/NSecSigner.ts +4 -3
- package/NSet.test.ts +123 -50
- package/NSet.ts +13 -6
- package/RelayError.test.ts +11 -10
- package/RelayError.ts +1 -1
- package/dist/BunkerURI.js +44 -44
- package/dist/NBrowserSigner.js +73 -83
- package/dist/NCache.d.ts +2 -2
- package/dist/NCache.d.ts.map +1 -1
- package/dist/NCache.js +35 -56
- package/dist/NConnectSigner.d.ts +1 -1
- package/dist/NConnectSigner.d.ts.map +1 -1
- package/dist/NConnectSigner.js +124 -117
- package/dist/NIP05.d.ts +1 -1
- package/dist/NIP05.d.ts.map +1 -1
- package/dist/NIP05.js +33 -33
- package/dist/NIP50.js +19 -20
- package/dist/NIP98.d.ts +1 -1
- package/dist/NIP98.d.ts.map +1 -1
- package/dist/NIP98.js +71 -64
- package/dist/NKinds.js +24 -22
- package/dist/NPool.d.ts +2 -2
- package/dist/NPool.d.ts.map +1 -1
- package/dist/NPool.js +143 -170
- package/dist/NRelay1.d.ts +5 -4
- package/dist/NRelay1.d.ts.map +1 -1
- package/dist/NRelay1.js +301 -315
- package/dist/NSchema.d.ts +1 -1
- package/dist/NSchema.d.ts.map +1 -1
- package/dist/NSchema.js +185 -208
- package/dist/NSecSigner.d.ts +1 -2
- package/dist/NSecSigner.d.ts.map +1 -1
- package/dist/NSecSigner.js +35 -46
- package/dist/NSet.d.ts +1 -1
- package/dist/NSet.d.ts.map +1 -1
- package/dist/NSet.js +138 -166
- package/dist/RelayError.d.ts +1 -1
- package/dist/RelayError.d.ts.map +1 -1
- package/dist/RelayError.js +18 -17
- package/dist/ln/LNURL.d.ts +4 -4
- package/dist/ln/LNURL.d.ts.map +1 -1
- package/dist/ln/LNURL.js +93 -93
- package/dist/ln/mod.d.ts +3 -3
- package/dist/ln/mod.js +4 -2
- package/dist/ln/mod.js.map +7 -1
- package/dist/ln/types/LNURLCallback.js +0 -2
- package/dist/ln/types/LNURLDetails.js +0 -2
- package/dist/mod.d.ts +14 -14
- package/dist/mod.js +30 -15
- package/dist/mod.js.map +7 -1
- package/dist/test/ErrorRelay.d.ts +1 -1
- package/dist/test/ErrorRelay.d.ts.map +1 -1
- package/dist/test/ErrorRelay.js +22 -21
- package/dist/test/MockRelay.d.ts +3 -3
- package/dist/test/MockRelay.d.ts.map +1 -1
- package/dist/test/MockRelay.js +56 -57
- package/dist/test/TestRelayServer.d.ts +6 -3
- package/dist/test/TestRelayServer.d.ts.map +1 -1
- package/dist/test/TestRelayServer.js +141 -122
- package/dist/test/mod.d.ts +3 -3
- package/dist/test/mod.d.ts.map +1 -1
- package/dist/test/mod.js +22 -19
- package/dist/test/mod.js.map +7 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/uploaders/BlossomUploader.d.ts +1 -1
- package/dist/uploaders/BlossomUploader.d.ts.map +1 -1
- package/dist/uploaders/BlossomUploader.js +69 -66
- package/dist/uploaders/NostrBuildUploader.d.ts +1 -2
- package/dist/uploaders/NostrBuildUploader.d.ts.map +1 -1
- package/dist/uploaders/NostrBuildUploader.js +61 -59
- package/dist/uploaders/mod.d.ts +2 -2
- package/dist/uploaders/mod.js +6 -3
- package/dist/uploaders/mod.js.map +7 -1
- package/dist/utils/CircularSet.d.ts +1 -1
- package/dist/utils/CircularSet.d.ts.map +1 -1
- package/dist/utils/CircularSet.js +26 -28
- package/dist/utils/Machina.js +35 -59
- package/dist/utils/N64.d.ts +1 -1
- package/dist/utils/N64.d.ts.map +1 -1
- package/dist/utils/N64.js +16 -18
- package/dist/utils/mod.d.ts +2 -2
- package/dist/utils/mod.js +6 -3
- package/dist/utils/mod.js.map +7 -1
- package/ln/LNURL.test.ts +70 -52
- package/ln/LNURL.ts +15 -15
- package/ln/mod.ts +3 -3
- package/mod.ts +14 -14
- package/package.json +5 -3
- package/test/ErrorRelay.test.ts +11 -10
- package/test/ErrorRelay.ts +17 -5
- package/test/MockRelay.test.ts +15 -8
- package/test/MockRelay.ts +3 -3
- package/test/TestRelayServer.ts +46 -17
- package/test/mod.ts +4 -4
- package/tsconfig.json +5 -2
- package/uploaders/BlossomUploader.test.ts +39 -22
- package/uploaders/BlossomUploader.ts +2 -2
- package/uploaders/NostrBuildUploader.test.ts +36 -18
- package/uploaders/NostrBuildUploader.ts +4 -4
- package/uploaders/mod.ts +2 -2
- package/utils/CircularSet.test.ts +5 -4
- package/utils/CircularSet.ts +3 -1
- package/utils/Machina.test.ts +30 -19
- package/utils/N64.test.ts +12 -11
- package/utils/N64.ts +2 -2
- package/utils/mod.ts +2 -2
- package/dist/BunkerURI.js.map +0 -1
- package/dist/NBrowserSigner.js.map +0 -1
- package/dist/NCache.js.map +0 -1
- package/dist/NConnectSigner.js.map +0 -1
- package/dist/NIP05.js.map +0 -1
- package/dist/NIP50.js.map +0 -1
- package/dist/NIP98.js.map +0 -1
- package/dist/NKinds.js.map +0 -1
- package/dist/NPool.js.map +0 -1
- package/dist/NRelay1.js.map +0 -1
- package/dist/NSchema.js.map +0 -1
- package/dist/NSecSigner.js.map +0 -1
- package/dist/NSet.js.map +0 -1
- package/dist/RelayError.js.map +0 -1
- package/dist/ln/LNURL.js.map +0 -1
- package/dist/ln/types/LNURLCallback.js.map +0 -1
- package/dist/ln/types/LNURLDetails.js.map +0 -1
- package/dist/test/ErrorRelay.js.map +0 -1
- package/dist/test/MockRelay.js.map +0 -1
- package/dist/test/TestRelayServer.js.map +0 -1
- package/dist/uploaders/BlossomUploader.js.map +0 -1
- package/dist/uploaders/NostrBuildUploader.js.map +0 -1
- package/dist/utils/CircularSet.js.map +0 -1
- package/dist/utils/Machina.js.map +0 -1
- package/dist/utils/N64.js.map +0 -1
package/ln/LNURL.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { NostrEvent } from
|
|
2
|
-
import { bech32 } from
|
|
1
|
+
import type { NostrEvent } from '@nostrify/types';
|
|
2
|
+
import { bech32 } from '@scure/base';
|
|
3
3
|
|
|
4
|
-
import { LNURLCallback } from
|
|
5
|
-
import { LNURLDetails } from
|
|
4
|
+
import { LNURLCallback } from './types/LNURLCallback.ts';
|
|
5
|
+
import { LNURLDetails } from './types/LNURLDetails.ts';
|
|
6
6
|
|
|
7
|
-
import { NSchema as n, z } from
|
|
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 !==
|
|
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(
|
|
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(
|
|
105
|
-
callback.searchParams.set(
|
|
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(
|
|
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(
|
|
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:
|
|
133
|
-
path: [
|
|
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(
|
|
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.
|
|
1
|
+
export { LNURL } from './LNURL.ts';
|
|
2
2
|
|
|
3
|
-
export type { LNURLCallback } from './types/LNURLCallback.
|
|
4
|
-
export type { LNURLDetails } from './types/LNURLDetails.
|
|
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.
|
|
2
|
-
export { NBrowserSigner } from './NBrowserSigner.
|
|
3
|
-
export { NCache } from './NCache.
|
|
4
|
-
export { NConnectSigner, type NConnectSignerOpts } from './NConnectSigner.
|
|
5
|
-
export { NIP05 } from './NIP05.
|
|
6
|
-
export { NIP50 } from './NIP50.
|
|
7
|
-
export { NIP98 } from './NIP98.
|
|
8
|
-
export { NKinds } from './NKinds.
|
|
9
|
-
export { NPool, type NPoolOpts } from './NPool.
|
|
10
|
-
export { NRelay1, type NRelay1Opts } from './NRelay1.
|
|
11
|
-
export { NSchema } from './NSchema.
|
|
12
|
-
export { NSecSigner } from './NSecSigner.
|
|
13
|
-
export { NSet } from './NSet.
|
|
14
|
-
export { RelayError } from './RelayError.
|
|
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.
|
|
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.
|
|
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
|
}
|
package/test/ErrorRelay.test.ts
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
import { genEvent } from "./mod.ts";
|
|
3
|
+
import { rejects } from "node:assert";
|
|
3
4
|
|
|
4
|
-
import { ErrorRelay } from
|
|
5
|
+
import { ErrorRelay } from "./ErrorRelay.ts";
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
await test("ErrorRelay", async () => {
|
|
7
8
|
const store = new ErrorRelay();
|
|
8
|
-
await
|
|
9
|
-
await
|
|
10
|
-
await
|
|
11
|
-
await
|
|
12
|
-
await
|
|
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
|
|
15
|
+
await rejects(async () => {
|
|
15
16
|
for await (const _ of store.req([])) {
|
|
16
17
|
// Do nothing.
|
|
17
18
|
}
|
package/test/ErrorRelay.ts
CHANGED
|
@@ -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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
package/test/MockRelay.test.ts
CHANGED
|
@@ -1,20 +1,27 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
import { deepStrictEqual } from "node:assert";
|
|
2
3
|
|
|
3
|
-
import { MockRelay } from
|
|
4
|
+
import { MockRelay } from "./MockRelay.ts";
|
|
4
5
|
|
|
5
|
-
import event1 from
|
|
6
|
+
import event1 from "../../../fixtures/event-1.json" with { type: "json" };
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
await test("MockRelay", async () => {
|
|
8
9
|
const relay = new MockRelay();
|
|
9
10
|
|
|
10
|
-
|
|
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
|
-
|
|
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
|
-
|
|
24
|
+
deepStrictEqual(result[0], event1);
|
|
18
25
|
|
|
19
|
-
|
|
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.
|
|
15
|
-
import { NSet } from '../NSet.
|
|
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 {
|
package/test/TestRelayServer.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { MockRelay } from './mod.
|
|
2
|
-
import { NostrClientMsg, NostrEvent, NostrRelayMsg } from '@nostrify/types';
|
|
3
|
-
import { NSchema as n } from '../NSchema.
|
|
4
|
-
import {
|
|
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(
|
|
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
|
|
51
|
-
//
|
|
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
|
-
|
|
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.
|
|
6
|
-
export { MockRelay } from './MockRelay.
|
|
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 {
|
|
2
|
-
import {
|
|
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
|
-
|
|
5
|
-
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
22
|
+
const uploader = new BlossomUploader({
|
|
23
|
+
servers: ["https://blossom.primal.net/"],
|
|
24
|
+
signer: new NSecSigner(generateSecretKey()),
|
|
25
|
+
});
|
|
11
26
|
|
|
12
|
-
|
|
13
|
-
servers: ['https://blossom.primal.net/'],
|
|
14
|
-
signer: new NSecSigner(generateSecretKey()),
|
|
15
|
-
});
|
|
27
|
+
const tags = await uploader.upload(file);
|
|
16
28
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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.
|
|
5
|
+
import { N64 } from '../utils/N64.ts';
|
|
6
6
|
|
|
7
7
|
/** BlossomUploader options. */
|
|
8
8
|
export interface BlossomUploaderOpts {
|
|
@@ -1,22 +1,40 @@
|
|
|
1
|
-
import {
|
|
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
|
|
7
|
+
import { NostrBuildUploader } from "./NostrBuildUploader.ts";
|
|
8
|
+
import { Readable } from "node:stream";
|
|
4
9
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
|
|
11
|
-
|
|
21
|
+
const uploader = new NostrBuildUploader();
|
|
22
|
+
const tags = await uploader.upload(file);
|
|
12
23
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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.
|
|
4
|
-
import { NIP98 } from '../NIP98.
|
|
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.
|
|
2
|
-
export { NostrBuildUploader } from './NostrBuildUploader.
|
|
1
|
+
export { BlossomUploader } from './BlossomUploader.ts';
|
|
2
|
+
export { NostrBuildUploader } from './NostrBuildUploader.ts';
|