@nostrify/nostrify 0.47.0 → 0.48.1

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.
@@ -1,15 +1,15 @@
1
- import { z } from 'zod';
1
+ import { z } from "zod";
2
2
 
3
- import { N64 } from '../utils/N64.ts';
4
- import { NIP98 } from '../NIP98.ts';
5
- import type { NostrSigner, 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";
6
6
 
7
7
  /** NostrBuildUploader options. */
8
8
  export interface NostrBuildUploaderOpts {
9
9
  /** nostr.build endpoint to use. Default: `https://nostr.build/api/v2/upload/files` */
10
10
  endpoint?: string;
11
11
  /** Signer to authenticate with NIP-98 requests. */
12
- signer?: NostrSigner;
12
+ signer: NostrSigner;
13
13
  /** Custom fetch implementation. */
14
14
  fetch?: typeof fetch;
15
15
  }
@@ -17,11 +17,11 @@ export interface NostrBuildUploaderOpts {
17
17
  /** Upload files to nostr.build or another compatible server. */
18
18
  export class NostrBuildUploader implements NUploader {
19
19
  private endpoint: string;
20
- private signer?: NostrSigner;
20
+ private signer: NostrSigner;
21
21
  private fetch: typeof fetch;
22
22
 
23
23
  constructor(opts?: NostrBuildUploaderOpts) {
24
- this.endpoint = opts?.endpoint ?? 'https://nostr.build/api/v2/upload/files';
24
+ this.endpoint = opts?.endpoint ?? "https://nostr.build/api/v2/upload/files";
25
25
  this.signer = opts?.signer;
26
26
  this.fetch = opts?.fetch ?? globalThis.fetch.bind(globalThis);
27
27
  }
@@ -29,12 +29,12 @@ export class NostrBuildUploader implements NUploader {
29
29
  async upload(
30
30
  file: File,
31
31
  opts?: { signal?: AbortSignal },
32
- ): Promise<[['url', string], ...string[][]]> {
32
+ ): Promise<[["url", string], ...string[][]]> {
33
33
  const formData = new FormData();
34
- formData.append('fileToUpload', file);
34
+ formData.append("fileToUpload", file);
35
35
 
36
36
  const request = new Request(this.endpoint, {
37
- method: 'POST',
37
+ method: "POST",
38
38
  body: formData,
39
39
  signal: opts?.signal,
40
40
  });
@@ -42,7 +42,7 @@ export class NostrBuildUploader implements NUploader {
42
42
  if (this.signer) {
43
43
  const t = await NIP98.template(request);
44
44
  const event = await this.signer.signEvent(t);
45
- request.headers.set('authorization', `Nostr ${N64.encodeEvent(event)}`);
45
+ request.headers.set("authorization", `Nostr ${N64.encodeEvent(event)}`);
46
46
  }
47
47
 
48
48
  const response = await this.fetch(request);
@@ -50,20 +50,20 @@ export class NostrBuildUploader implements NUploader {
50
50
  console.log(json);
51
51
  const [data] = NostrBuildUploader.schema().parse(json).data;
52
52
 
53
- const tags: [['url', string], ...string[][]] = [
54
- ['url', data.url],
55
- ['m', data.mime],
56
- ['x', data.sha256],
57
- ['ox', data.original_sha256],
58
- ['size', data.size.toString()],
53
+ const tags: [["url", string], ...string[][]] = [
54
+ ["url", data.url],
55
+ ["m", data.mime],
56
+ ["x", data.sha256],
57
+ ["ox", data.original_sha256],
58
+ ["size", data.size.toString()],
59
59
  ];
60
60
 
61
61
  if (data.dimensions) {
62
- tags.push(['dim', `${data.dimensions.width}x${data.dimensions.height}`]);
62
+ tags.push(["dim", `${data.dimensions.width}x${data.dimensions.height}`]);
63
63
  }
64
64
 
65
65
  if (data.blurhash) {
66
- tags.push(['blurhash', data.blurhash]);
66
+ tags.push(["blurhash", data.blurhash]);
67
67
  }
68
68
 
69
69
  return tags;
@@ -1,4 +1,4 @@
1
- import type { NostrEvent } from '@nostrify/types';
1
+ import type { NostrEvent } from "@nostrify/types";
2
2
  /** Nostr base64 helper utilities. */
3
3
  export declare class N64 {
4
4
  /** Encode an event as a base64 string. */
package/dist/utils/N64.js CHANGED
@@ -1,13 +1,13 @@
1
- import { decodeBase64, encodeBase64 } from "@std/encoding/base64";
1
+ import { fromBase64, toBase64 } from "@smithy/util-base64";
2
2
  import { NSchema as n } from "../NSchema.js";
3
3
  class N64 {
4
4
  /** Encode an event as a base64 string. */
5
5
  static encodeEvent(event) {
6
- return encodeBase64(JSON.stringify(event));
6
+ return toBase64(JSON.stringify(event));
7
7
  }
8
8
  /** Decode an event from a base64 string. Validates the event's structure but does not verify its signature. */
9
9
  static decodeEvent(base64) {
10
- const bytes = decodeBase64(base64);
10
+ const bytes = fromBase64(base64);
11
11
  const text = new TextDecoder().decode(bytes);
12
12
  return n.json().pipe(n.event()).parse(text);
13
13
  }
package/dist/utils/N64.ts CHANGED
@@ -1,18 +1,18 @@
1
- import type { NostrEvent } from '@nostrify/types';
2
- import { decodeBase64, encodeBase64 } from '@std/encoding/base64';
1
+ import type { NostrEvent } from "@nostrify/types";
2
+ import { fromBase64, toBase64 } from "@smithy/util-base64";
3
3
 
4
- import { NSchema as n } from '../NSchema.ts';
4
+ import { NSchema as n } from "../NSchema.ts";
5
5
 
6
6
  /** Nostr base64 helper utilities. */
7
7
  export class N64 {
8
8
  /** Encode an event as a base64 string. */
9
9
  static encodeEvent(event: NostrEvent): string {
10
- return encodeBase64(JSON.stringify(event));
10
+ return toBase64(JSON.stringify(event));
11
11
  }
12
12
 
13
13
  /** Decode an event from a base64 string. Validates the event's structure but does not verify its signature. */
14
14
  static decodeEvent(base64: string): NostrEvent {
15
- const bytes = decodeBase64(base64);
15
+ const bytes = fromBase64(base64);
16
16
  const text = new TextDecoder().decode(bytes);
17
17
 
18
18
  return n
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nostrify/nostrify",
3
- "version": "0.47.0",
3
+ "version": "0.48.1",
4
4
  "exports": {
5
5
  ".": "./dist/mod.js",
6
6
  "./ln": "./dist/ln/mod.js",
@@ -12,14 +12,15 @@
12
12
  "types": "dist/mod.d.ts",
13
13
  "type": "module",
14
14
  "dependencies": {
15
- "ws": "^8.18.3",
15
+ "@scure/base": "^2.0.0",
16
+ "@smithy/util-base64": "^4.3.0",
17
+ "@smithy/util-hex-encoding": "^4.2.0",
18
+ "@types/node": "^24.1.0",
16
19
  "lru-cache": "^10.2.0",
17
20
  "nostr-tools": "^2.13.0",
18
21
  "websocket-ts": "^2.2.1",
22
+ "ws": "^8.18.3",
19
23
  "zod": "^3.23.8",
20
- "@types/node": "^24.1.0",
21
- "@scure/base": "^1.2.6",
22
- "@std/encoding": "npm:@jsr/std__encoding@^0.224.1",
23
24
  "@nostrify/types": "0.36.7"
24
25
  },
25
26
  "publishConfig": {
@@ -1,13 +1,13 @@
1
- import type { NostrSigner, NUploader } from '@nostrify/types';
2
- import { encodeHex } from '@std/encoding/hex';
3
- import { z } from 'zod';
1
+ import type { NostrSigner, NUploader } from "@nostrify/types";
2
+ import { toHex } from "@smithy/util-hex-encoding";
3
+ import { z } from "zod";
4
4
 
5
- import { N64 } from '../utils/N64.ts';
5
+ import { N64 } from "../utils/N64.ts";
6
6
 
7
7
  /** BlossomUploader options. */
8
8
  export interface BlossomUploaderOpts {
9
9
  /** Blossom servers to use. */
10
- servers: Request['url'][];
10
+ servers: Request["url"][];
11
11
  /** Signer for Blossom authorizations. */
12
12
  signer: NostrSigner;
13
13
  /** Custom fetch implementation. */
@@ -18,7 +18,7 @@ export interface BlossomUploaderOpts {
18
18
 
19
19
  /** Upload files to Blossom servers. */
20
20
  export class BlossomUploader implements NUploader {
21
- private servers: Request['url'][];
21
+ private servers: Request["url"][];
22
22
  private signer: NostrSigner;
23
23
  private fetch: typeof fetch;
24
24
  private expiresIn: number;
@@ -33,10 +33,12 @@ export class BlossomUploader implements NUploader {
33
33
  async upload(
34
34
  file: File,
35
35
  opts?: { signal?: AbortSignal },
36
- ): Promise<[['url', string], ...string[][]]> {
37
- const x = encodeHex(
38
- await crypto.subtle.digest('SHA-256', await file.arrayBuffer()),
36
+ ): Promise<[["url", string], ...string[][]]> {
37
+ const digest = await crypto.subtle.digest(
38
+ "SHA-256",
39
+ await file.arrayBuffer(),
39
40
  );
41
+ const x = toHex(new Uint8Array(digest));
40
42
 
41
43
  const now = Date.now();
42
44
  const expiration = now + this.expiresIn;
@@ -46,24 +48,24 @@ export class BlossomUploader implements NUploader {
46
48
  content: `Upload ${file.name}`,
47
49
  created_at: Math.floor(now / 1000),
48
50
  tags: [
49
- ['t', 'upload'],
50
- ['x', x],
51
- ['size', file.size.toString()],
52
- ['expiration', Math.floor(expiration / 1000).toString()],
51
+ ["t", "upload"],
52
+ ["x", x],
53
+ ["size", file.size.toString()],
54
+ ["expiration", Math.floor(expiration / 1000).toString()],
53
55
  ],
54
56
  });
55
57
 
56
58
  const authorization = `Nostr ${N64.encodeEvent(event)}`;
57
59
 
58
60
  return Promise.any(this.servers.map(async (server) => {
59
- const url = new URL('/upload', server);
61
+ const url = new URL("/upload", server);
60
62
 
61
63
  const response = await this.fetch(url, {
62
- method: 'PUT',
64
+ method: "PUT",
63
65
  body: file,
64
66
  headers: {
65
67
  authorization,
66
- 'content-type': file.type,
68
+ "content-type": file.type,
67
69
  },
68
70
  signal: opts?.signal,
69
71
  });
@@ -71,15 +73,15 @@ export class BlossomUploader implements NUploader {
71
73
  const json = await response.json();
72
74
  const data = BlossomUploader.schema().parse(json);
73
75
 
74
- const tags: [['url', string], ...string[][]] = [
75
- ['url', data.url],
76
- ['x', data.sha256],
77
- ['ox', data.sha256],
78
- ['size', data.size.toString()],
76
+ const tags: [["url", string], ...string[][]] = [
77
+ ["url", data.url],
78
+ ["x", data.sha256],
79
+ ["ox", data.sha256],
80
+ ["size", data.size.toString()],
79
81
  ];
80
82
 
81
83
  if (data.type) {
82
- tags.push(['m', data.type]);
84
+ tags.push(["m", data.type]);
83
85
  }
84
86
 
85
87
  return tags;
@@ -6,6 +6,8 @@ import fs from "node:fs/promises";
6
6
 
7
7
  import { NostrBuildUploader } from "./NostrBuildUploader.ts";
8
8
  import { Readable } from "node:stream";
9
+ import { NSecSigner } from "../NSecSigner.ts";
10
+ import { hexToBytes } from "nostr-tools/utils";
9
11
 
10
12
  await test(
11
13
  "NostrBuildUploader.upload",
@@ -18,7 +20,20 @@ await test(
18
20
  .blob();
19
21
  const file = new File([blob], "voadi.png", { type: "image/png" });
20
22
 
21
- const uploader = new NostrBuildUploader();
23
+ const seckey = process.env.NOSTRIFY_NBU_SECRET_KEY;
24
+ if (!seckey) {
25
+ throw new Error(
26
+ "nostr.build with default uploader requires a secret key to be configured",
27
+ );
28
+ }
29
+
30
+ const uploader = new NostrBuildUploader({
31
+ signer: new NSecSigner(
32
+ hexToBytes(
33
+ seckey,
34
+ ),
35
+ ),
36
+ });
22
37
  const tags = await uploader.upload(file);
23
38
 
24
39
  deepStrictEqual(tags, [
@@ -1,15 +1,15 @@
1
- import { z } from 'zod';
1
+ import { z } from "zod";
2
2
 
3
- import { N64 } from '../utils/N64.ts';
4
- import { NIP98 } from '../NIP98.ts';
5
- import type { NostrSigner, 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";
6
6
 
7
7
  /** NostrBuildUploader options. */
8
8
  export interface NostrBuildUploaderOpts {
9
9
  /** nostr.build endpoint to use. Default: `https://nostr.build/api/v2/upload/files` */
10
10
  endpoint?: string;
11
11
  /** Signer to authenticate with NIP-98 requests. */
12
- signer?: NostrSigner;
12
+ signer: NostrSigner;
13
13
  /** Custom fetch implementation. */
14
14
  fetch?: typeof fetch;
15
15
  }
@@ -17,11 +17,11 @@ export interface NostrBuildUploaderOpts {
17
17
  /** Upload files to nostr.build or another compatible server. */
18
18
  export class NostrBuildUploader implements NUploader {
19
19
  private endpoint: string;
20
- private signer?: NostrSigner;
20
+ private signer: NostrSigner;
21
21
  private fetch: typeof fetch;
22
22
 
23
23
  constructor(opts?: NostrBuildUploaderOpts) {
24
- this.endpoint = opts?.endpoint ?? 'https://nostr.build/api/v2/upload/files';
24
+ this.endpoint = opts?.endpoint ?? "https://nostr.build/api/v2/upload/files";
25
25
  this.signer = opts?.signer;
26
26
  this.fetch = opts?.fetch ?? globalThis.fetch.bind(globalThis);
27
27
  }
@@ -29,12 +29,12 @@ export class NostrBuildUploader implements NUploader {
29
29
  async upload(
30
30
  file: File,
31
31
  opts?: { signal?: AbortSignal },
32
- ): Promise<[['url', string], ...string[][]]> {
32
+ ): Promise<[["url", string], ...string[][]]> {
33
33
  const formData = new FormData();
34
- formData.append('fileToUpload', file);
34
+ formData.append("fileToUpload", file);
35
35
 
36
36
  const request = new Request(this.endpoint, {
37
- method: 'POST',
37
+ method: "POST",
38
38
  body: formData,
39
39
  signal: opts?.signal,
40
40
  });
@@ -42,7 +42,7 @@ export class NostrBuildUploader implements NUploader {
42
42
  if (this.signer) {
43
43
  const t = await NIP98.template(request);
44
44
  const event = await this.signer.signEvent(t);
45
- request.headers.set('authorization', `Nostr ${N64.encodeEvent(event)}`);
45
+ request.headers.set("authorization", `Nostr ${N64.encodeEvent(event)}`);
46
46
  }
47
47
 
48
48
  const response = await this.fetch(request);
@@ -50,20 +50,20 @@ export class NostrBuildUploader implements NUploader {
50
50
  console.log(json);
51
51
  const [data] = NostrBuildUploader.schema().parse(json).data;
52
52
 
53
- const tags: [['url', string], ...string[][]] = [
54
- ['url', data.url],
55
- ['m', data.mime],
56
- ['x', data.sha256],
57
- ['ox', data.original_sha256],
58
- ['size', data.size.toString()],
53
+ const tags: [["url", string], ...string[][]] = [
54
+ ["url", data.url],
55
+ ["m", data.mime],
56
+ ["x", data.sha256],
57
+ ["ox", data.original_sha256],
58
+ ["size", data.size.toString()],
59
59
  ];
60
60
 
61
61
  if (data.dimensions) {
62
- tags.push(['dim', `${data.dimensions.width}x${data.dimensions.height}`]);
62
+ tags.push(["dim", `${data.dimensions.width}x${data.dimensions.height}`]);
63
63
  }
64
64
 
65
65
  if (data.blurhash) {
66
- tags.push(['blurhash', data.blurhash]);
66
+ tags.push(["blurhash", data.blurhash]);
67
67
  }
68
68
 
69
69
  return tags;
package/utils/N64.ts CHANGED
@@ -1,18 +1,18 @@
1
- import type { NostrEvent } from '@nostrify/types';
2
- import { decodeBase64, encodeBase64 } from '@std/encoding/base64';
1
+ import type { NostrEvent } from "@nostrify/types";
2
+ import { fromBase64, toBase64 } from "@smithy/util-base64";
3
3
 
4
- import { NSchema as n } from '../NSchema.ts';
4
+ import { NSchema as n } from "../NSchema.ts";
5
5
 
6
6
  /** Nostr base64 helper utilities. */
7
7
  export class N64 {
8
8
  /** Encode an event as a base64 string. */
9
9
  static encodeEvent(event: NostrEvent): string {
10
- return encodeBase64(JSON.stringify(event));
10
+ return toBase64(JSON.stringify(event));
11
11
  }
12
12
 
13
13
  /** Decode an event from a base64 string. Validates the event's structure but does not verify its signature. */
14
14
  static decodeEvent(base64: string): NostrEvent {
15
- const bytes = decodeBase64(base64);
15
+ const bytes = fromBase64(base64);
16
16
  const text = new TextDecoder().decode(bytes);
17
17
 
18
18
  return n