@kodelyth/nostr 2026.5.42 → 2026.6.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.
Files changed (47) hide show
  1. package/klaw.plugin.json +185 -2
  2. package/package.json +17 -4
  3. package/api.ts +0 -10
  4. package/channel-plugin-api.ts +0 -1
  5. package/index.ts +0 -95
  6. package/runtime-api.ts +0 -6
  7. package/setup-api.ts +0 -1
  8. package/setup-entry.ts +0 -9
  9. package/setup-plugin-api.ts +0 -3
  10. package/src/channel-api.ts +0 -11
  11. package/src/channel.inbound.test.ts +0 -187
  12. package/src/channel.outbound.test.ts +0 -163
  13. package/src/channel.setup.ts +0 -234
  14. package/src/channel.test.ts +0 -526
  15. package/src/channel.ts +0 -215
  16. package/src/config-schema.ts +0 -98
  17. package/src/default-relays.ts +0 -1
  18. package/src/gateway.ts +0 -321
  19. package/src/inbound-direct-dm-runtime.ts +0 -1
  20. package/src/metrics.ts +0 -458
  21. package/src/nostr-bus.fuzz.test.ts +0 -382
  22. package/src/nostr-bus.inbound.test.ts +0 -526
  23. package/src/nostr-bus.integration.test.ts +0 -477
  24. package/src/nostr-bus.test.ts +0 -231
  25. package/src/nostr-bus.ts +0 -789
  26. package/src/nostr-key-utils.ts +0 -94
  27. package/src/nostr-profile-core.ts +0 -134
  28. package/src/nostr-profile-http-runtime.ts +0 -6
  29. package/src/nostr-profile-http.test.ts +0 -632
  30. package/src/nostr-profile-http.ts +0 -583
  31. package/src/nostr-profile-import.test.ts +0 -119
  32. package/src/nostr-profile-import.ts +0 -262
  33. package/src/nostr-profile-url-safety.ts +0 -21
  34. package/src/nostr-profile.fuzz.test.ts +0 -430
  35. package/src/nostr-profile.test.ts +0 -415
  36. package/src/nostr-profile.ts +0 -144
  37. package/src/nostr-state-store.test.ts +0 -237
  38. package/src/nostr-state-store.ts +0 -206
  39. package/src/runtime.ts +0 -9
  40. package/src/seen-tracker.ts +0 -289
  41. package/src/session-route.ts +0 -25
  42. package/src/setup-surface.ts +0 -264
  43. package/src/test-fixtures.ts +0 -45
  44. package/src/types.ts +0 -117
  45. package/test/setup.ts +0 -5
  46. package/test-api.ts +0 -1
  47. package/tsconfig.json +0 -16
@@ -1,94 +0,0 @@
1
- import { getPublicKey, nip19 } from "nostr-tools";
2
-
3
- /**
4
- * Validate and normalize a private key (accepts hex or nsec format)
5
- */
6
- export function validatePrivateKey(key: string): Uint8Array {
7
- const trimmed = key.trim();
8
-
9
- // Handle nsec (bech32) format
10
- if (trimmed.startsWith("nsec1")) {
11
- const decoded = nip19.decode(trimmed);
12
- if (decoded.type !== "nsec") {
13
- throw new Error("Invalid nsec key: wrong type");
14
- }
15
- return decoded.data;
16
- }
17
-
18
- // Handle hex format
19
- if (!/^[0-9a-fA-F]{64}$/.test(trimmed)) {
20
- throw new Error("Private key must be 64 hex characters or nsec bech32 format");
21
- }
22
-
23
- // Convert hex string to Uint8Array
24
- const bytes = new Uint8Array(32);
25
- for (let i = 0; i < 32; i++) {
26
- bytes[i] = Number.parseInt(trimmed.slice(i * 2, i * 2 + 2), 16);
27
- }
28
- return bytes;
29
- }
30
-
31
- /**
32
- * Get public key from private key (hex or nsec format)
33
- */
34
- export function getPublicKeyFromPrivate(privateKey: string): string {
35
- const sk = validatePrivateKey(privateKey);
36
- return getPublicKey(sk);
37
- }
38
-
39
- /**
40
- * Check if a string looks like a valid Nostr pubkey (hex or npub)
41
- */
42
- export function isValidPubkey(input: string): boolean {
43
- if (typeof input !== "string") {
44
- return false;
45
- }
46
- const trimmed = input.trim();
47
-
48
- // npub format
49
- if (trimmed.startsWith("npub1")) {
50
- try {
51
- const decoded = nip19.decode(trimmed);
52
- return decoded.type === "npub";
53
- } catch {
54
- return false;
55
- }
56
- }
57
-
58
- // Hex format
59
- return /^[0-9a-fA-F]{64}$/.test(trimmed);
60
- }
61
-
62
- /**
63
- * Normalize a pubkey to hex format (accepts npub or hex)
64
- */
65
- export function normalizePubkey(input: string): string {
66
- const trimmed = input.trim();
67
-
68
- // npub format - decode to hex
69
- if (trimmed.startsWith("npub1")) {
70
- const decoded = nip19.decode(trimmed);
71
- if (decoded.type !== "npub") {
72
- throw new Error("Invalid npub key");
73
- }
74
- // Convert Uint8Array to hex string
75
- return Array.from(decoded.data as unknown as Uint8Array)
76
- .map((b) => b.toString(16).padStart(2, "0"))
77
- .join("");
78
- }
79
-
80
- // Already hex - validate and return lowercase
81
- if (!/^[0-9a-fA-F]{64}$/.test(trimmed)) {
82
- throw new Error("Pubkey must be 64 hex characters or npub format");
83
- }
84
- return trimmed.toLowerCase();
85
- }
86
-
87
- /**
88
- * Convert a hex pubkey to npub format
89
- */
90
- export function pubkeyToNpub(hexPubkey: string): string {
91
- const normalized = normalizePubkey(hexPubkey);
92
- // npubEncode expects a hex string, not Uint8Array
93
- return nip19.npubEncode(normalized);
94
- }
@@ -1,134 +0,0 @@
1
- import { type NostrProfile, NostrProfileSchema } from "./config-schema.js";
2
-
3
- /** NIP-01 profile content (JSON inside kind:0 event). */
4
- export interface ProfileContent {
5
- name?: string;
6
- display_name?: string;
7
- about?: string;
8
- picture?: string;
9
- banner?: string;
10
- website?: string;
11
- nip05?: string;
12
- lud16?: string;
13
- }
14
-
15
- /**
16
- * Convert our config profile schema to NIP-01 content format.
17
- * Strips undefined fields and validates URLs.
18
- */
19
- export function profileToContent(profile: NostrProfile): ProfileContent {
20
- const validated = NostrProfileSchema.parse(profile);
21
-
22
- const content: ProfileContent = {};
23
-
24
- if (validated.name !== undefined) {
25
- content.name = validated.name;
26
- }
27
- if (validated.displayName !== undefined) {
28
- content.display_name = validated.displayName;
29
- }
30
- if (validated.about !== undefined) {
31
- content.about = validated.about;
32
- }
33
- if (validated.picture !== undefined) {
34
- content.picture = validated.picture;
35
- }
36
- if (validated.banner !== undefined) {
37
- content.banner = validated.banner;
38
- }
39
- if (validated.website !== undefined) {
40
- content.website = validated.website;
41
- }
42
- if (validated.nip05 !== undefined) {
43
- content.nip05 = validated.nip05;
44
- }
45
- if (validated.lud16 !== undefined) {
46
- content.lud16 = validated.lud16;
47
- }
48
-
49
- return content;
50
- }
51
-
52
- /**
53
- * Convert NIP-01 content format back to our config profile schema.
54
- * Useful for importing existing profiles from relays.
55
- */
56
- export function contentToProfile(content: ProfileContent): NostrProfile {
57
- const profile: NostrProfile = {};
58
-
59
- if (content.name !== undefined) {
60
- profile.name = content.name;
61
- }
62
- if (content.display_name !== undefined) {
63
- profile.displayName = content.display_name;
64
- }
65
- if (content.about !== undefined) {
66
- profile.about = content.about;
67
- }
68
- if (content.picture !== undefined) {
69
- profile.picture = content.picture;
70
- }
71
- if (content.banner !== undefined) {
72
- profile.banner = content.banner;
73
- }
74
- if (content.website !== undefined) {
75
- profile.website = content.website;
76
- }
77
- if (content.nip05 !== undefined) {
78
- profile.nip05 = content.nip05;
79
- }
80
- if (content.lud16 !== undefined) {
81
- profile.lud16 = content.lud16;
82
- }
83
-
84
- return profile;
85
- }
86
-
87
- /**
88
- * Validate a profile without throwing (returns result object).
89
- */
90
- export function validateProfile(profile: unknown): {
91
- valid: boolean;
92
- profile?: NostrProfile;
93
- errors?: string[];
94
- } {
95
- const result = NostrProfileSchema.safeParse(profile);
96
-
97
- if (result.success) {
98
- return { valid: true, profile: result.data };
99
- }
100
-
101
- return {
102
- valid: false,
103
- errors: result.error.issues.map((e) => `${e.path.join(".")}: ${e.message}`),
104
- };
105
- }
106
-
107
- /**
108
- * Sanitize profile text fields to prevent XSS when displaying in UI.
109
- * Escapes HTML special characters.
110
- */
111
- export function sanitizeProfileForDisplay(profile: NostrProfile): NostrProfile {
112
- const escapeHtml = (str: string | undefined): string | undefined => {
113
- if (str === undefined) {
114
- return undefined;
115
- }
116
- return str
117
- .replace(/&/g, "&amp;")
118
- .replace(/</g, "&lt;")
119
- .replace(/>/g, "&gt;")
120
- .replace(/"/g, "&quot;")
121
- .replace(/'/g, "&#039;");
122
- };
123
-
124
- return {
125
- name: escapeHtml(profile.name),
126
- displayName: escapeHtml(profile.displayName),
127
- about: escapeHtml(profile.about),
128
- picture: profile.picture,
129
- banner: profile.banner,
130
- website: profile.website,
131
- nip05: escapeHtml(profile.nip05),
132
- lud16: escapeHtml(profile.lud16),
133
- };
134
- }
@@ -1,6 +0,0 @@
1
- export {
2
- readJsonBodyWithLimit,
3
- requestBodyErrorToText,
4
- } from "klaw/plugin-sdk/webhook-request-guards";
5
- export { createFixedWindowRateLimiter } from "klaw/plugin-sdk/webhook-ingress";
6
- export { getPluginRuntimeGatewayRequestScope } from "../runtime-api.js";