What is Nostr?
Kind 1617
git patch: feat: integrate nostr-login for user authentication
Author Public Key
npub1pt0kw36ue3w2g4haxq3wgm6a2fhtptmzsjlc2j2vphtcgle72qesgpjyc6
Published at
2024-10-01 22:34:39
Kind type
1617
Event JSON
{ "id": "cc3dc085935b92de706fbf51e175d21b897d4f6507bd3155206d8c1ef77051bb", "pubkey": "0adf67475ccc5ca456fd3022e46f5d526eb0af6284bf85494c0dd7847f3e5033", "created_at": 1727822079, "kind": 1617, "tags": [ [ "a", "30617:a008def15796fba9a0d6fab04e8fd57089285d9fd505da5a83fe8aad57a3564d:gitworkshop" ], [ "r", "f9cbcfb08098bf664cd5fd304f31dc0f2bdc31da" ], [ "r", "9b84454f53ff248a1390e9ec7a676093f7669697" ], [ "alt", "git patch: feat: integrate nostr-login for user authentication" ], [ "t", "root" ], [ "branch-name", "nostr-login" ], [ "p", "a008def15796fba9a0d6fab04e8fd57089285d9fd505da5a83fe8aad57a3564d" ], [ "commit", "9b84454f53ff248a1390e9ec7a676093f7669697" ], [ "parent-commit", "6e6654810f9e0befd5cb1be89360bd5d23bce2ac" ], [ "commit-pgp-sig", "" ], [ "description", "feat: integrate nostr-login for user authentication\n\nThis commit integrates nostr-login for user authentication and removes the previous method. It includes changes in the package.json, Navbar.svelte, users.ts and the creation of a new file nostr-login/index.ts. This new method provides a more streamlined and efficient user authentication process.\n" ], [ "author", "fsociety", "fsociety.mp3@pm.me", "1727822016", "120" ], [ "committer", "fsociety", "fsociety.mp3@pm.me", "1727822016", "120" ] ], "content": "From 9b84454f53ff248a1390e9ec7a676093f7669697 Mon Sep 17 00:00:00 2001\nFrom: fsociety \u003cfsociety.mp3@pm.me\u003e\nDate: Wed, 2 Oct 2024 00:33:36 +0200\nSubject: [PATCH] feat: integrate nostr-login for user authentication\n\nThis commit integrates nostr-login for user authentication and removes the previous method. It includes changes in the package.json, Navbar.svelte, users.ts and the creation of a new file nostr-login/index.ts. This new method provides a more streamlined and efficient user authentication process.\n---\n package.json | 1 +\n src/lib/components/Navbar.svelte | 45 +++++++++++++++++----------------------------\n src/lib/signers/nostr-login/index.ts | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n src/lib/stores/users.ts | 72 +++++++++++++++++++++++-------------------------------------------------\n src/lib/wrappers/Navbar.svelte | 21 ++-------------------\n yarn.lock | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------\n 6 files changed, 240 insertions(+), 109 deletions(-)\n create mode 100644 src/lib/signers/nostr-login/index.ts\n\ndiff --git a/package.json b/package.json\nindex 8db6542..2539883 100644\n--- a/package.json\n+++ b/package.json\n@@ -34,6 +34,7 @@\n \"eslint-config-prettier\": \"^9.1.0\",\n \"eslint-plugin-prettier\": \"^5.2.1\",\n \"eslint-plugin-svelte\": \"^2.44.0\",\n+ \"nostr-login\": \"^1.6.6\",\n \"postcss\": \"^8.4.47\",\n \"prettier\": \"^3.3.3\",\n \"prettier-plugin-svelte\": \"^3.2.6\",\ndiff --git a/src/lib/components/Navbar.svelte b/src/lib/components/Navbar.svelte\nindex e66e96d..d5d3d3c 100644\n--- a/src/lib/components/Navbar.svelte\n+++ b/src/lib/components/Navbar.svelte\n@@ -1,13 +1,28 @@\n \u003cscript lang=\"ts\"\u003e\n+ import { onMount } from 'svelte'\n import { logout } from '$lib/stores/users'\n import Container from './Container.svelte'\n import UserHeader from './users/UserHeader.svelte'\n import type { User } from './users/type'\n \n export let logged_in_user: User | undefined = undefined\n- export let nip07_plugin: boolean | undefined = undefined\n export let login_function = () =\u003e {}\n- export let singup_function = () =\u003e {}\n+\n+ interface NlAuthEvent extends Event {\n+ detail: {\n+ type: string\n+ }\n+ }\n+\n+ onMount(() =\u003e {\n+ login_function()\n+ document.addEventListener('nlAuth', (e: Event) =\u003e {\n+ const event = e as NlAuthEvent\n+ if (event.detail.type === 'logout') {\n+ logout()\n+ }\n+ })\n+ })\n \u003c/script\u003e\n \n \u003cdiv class=\"bg-base-400\"\u003e\n@@ -35,34 +50,8 @@\n class=\"menu dropdown-content z-[1] -mr-4 rounded-box bg-base-400 p-2 shadow\"\n \u003e\n \u003cli\u003e\u003cUserHeader user={logged_in_user} /\u003e\u003c/li\u003e\n- \u003c!-- svelte-ignore a11y-click-events-have-key-events --\u003e\n- \u003c!-- svelte-ignore a11y-missing-attribute --\u003e\n- \u003cli\u003e\n- \u003c!-- svelte-ignore a11y-no-static-element-interactions --\u003e\n- \u003ca\n- on:click={() =\u003e {\n- logout()\n- }}\u003eLogout\u003c/a\n- \u003e\n- \u003c/li\u003e\n \u003c/ul\u003e\n \u003c/div\u003e\n- {:else if nip07_plugin === undefined}\n- \u003cdiv class=\"skeleton h-8 w-20\"\u003e\u003c/div\u003e\n- {:else if nip07_plugin}\n- \u003cbutton\n- on:click={() =\u003e {\n- login_function()\n- }}\n- class=\"btn btn-ghost btn-sm normal-case\"\u003eLogin\u003c/button\n- \u003e\n- {:else}\n- \u003cbutton\n- on:click={() =\u003e {\n- singup_function()\n- }}\n- class=\"btn btn-ghost btn-sm normal-case\"\u003eSign up\u003c/button\n- \u003e\n {/if}\n \u003c/div\u003e\n \u003c/div\u003e\ndiff --git a/src/lib/signers/nostr-login/index.ts b/src/lib/signers/nostr-login/index.ts\nnew file mode 100644\nindex 0000000..563a8db\n--- /dev/null\n+++ b/src/lib/signers/nostr-login/index.ts\n@@ -0,0 +1,111 @@\n+import NDK, { NDKUser, NDKRelay } from '@nostr-dev-kit/ndk'\n+import type { NDKSigner, NostrEvent } from '@nostr-dev-kit/ndk'\n+\n+export class NDKNostrLoginSigner implements NDKSigner {\n+ private _userPromise: Promise\u003cNDKUser\u003e | undefined\n+\n+ blockUntilReady(): Promise\u003cNDKUser\u003e {\n+ return new Promise((resolve) =\u003e {\n+ const eventHandler = (event: Event) =\u003e {\n+ document.removeEventListener('nlAuth', eventHandler)\n+ const customEvent = event as CustomEvent\u003c{ pubkey: string }\u003e\n+ resolve(new NDKUser({ pubkey: customEvent.detail.pubkey }))\n+ }\n+\n+ document.addEventListener('nlAuth', eventHandler)\n+ })\n+ }\n+\n+ user(): Promise\u003cNDKUser\u003e {\n+ if (!this._userPromise) {\n+ this._userPromise = this.blockUntilReady()\n+ }\n+\n+ return this._userPromise\n+ }\n+\n+ async sign(event: NostrEvent): Promise\u003cstring\u003e {\n+ if (!window.nostr) {\n+ throw new Error('window.nostr is undefined')\n+ }\n+ const signedEvent = await window.nostr.signEvent(event)\n+ return signedEvent.sig\n+ }\n+\n+ async relays?(ndk?: NDK): Promise\u003cNDKRelay[]\u003e {\n+ const relays = (await window.nostr?.getRelays?.()) || {}\n+\n+ const activeRelays: string[] = []\n+ for (const url of Object.keys(relays)) {\n+ // Currently only respects relays that are both readable and writable.\n+ if (relays[url].read \u0026\u0026 relays[url].write) {\n+ activeRelays.push(url)\n+ }\n+ }\n+ return activeRelays.map(\n+ (url) =\u003e new NDKRelay(url, ndk?.relayAuthDefaultPolicy, ndk)\n+ )\n+ }\n+\n+ async encrypt(\n+ recipient: NDKUser,\n+ value: string,\n+ type: string = 'nip04'\n+ ): Promise\u003cstring\u003e {\n+ if (type === 'nip44') {\n+ return this.nip44Encrypt(recipient, value)\n+ } else {\n+ return this.nip04Encrypt(recipient, value)\n+ }\n+ }\n+\n+ async decrypt(\n+ sender: NDKUser,\n+ value: string,\n+ type: string = 'nip04'\n+ ): Promise\u003cstring\u003e {\n+ if (type === 'nip44') {\n+ return this.nip44Decrypt(sender, value)\n+ } else {\n+ return this.nip04Decrypt(sender, value)\n+ }\n+ }\n+\n+ private async nip44Encrypt(\n+ recipient: NDKUser,\n+ value: string\n+ ): Promise\u003cstring\u003e {\n+ // @ts-expect-error window.nostr.nip44 is not defined in the type definitions\n+ if (!window.nostr || !window.nostr.nip44) {\n+ throw new Error('window.nostr or window.nostr.nip44 is undefined')\n+ }\n+ // @ts-expect-error window.nostr.nip44 is not defined in the type definitions\n+ return await window.nostr.nip44.encrypt(recipient.pubkey, value)\n+ }\n+\n+ private async nip04Encrypt(\n+ recipient: NDKUser,\n+ value: string\n+ ): Promise\u003cstring\u003e {\n+ if (!window.nostr || !window.nostr.nip04) {\n+ throw new Error('window.nostr or window.nostr.nip04 is undefined')\n+ }\n+ return await window.nostr.nip04.encrypt(recipient.pubkey, value)\n+ }\n+\n+ private async nip44Decrypt(sender: NDKUser, value: string): Promise\u003cstring\u003e {\n+ // @ts-expect-error window.nostr.nip44 is not defined in the type definitions\n+ if (!window.nostr || !window.nostr.nip44) {\n+ throw new Error('window.nostr or window.nostr.nip44 is undefined')\n+ }\n+ // @ts-expect-error window.nostr.nip44 is not defined in the type definitions\n+ return await window.nostr.nip44.decrypt(sender.pubkey, value)\n+ }\n+\n+ private async nip04Decrypt(sender: NDKUser, value: string): Promise\u003cstring\u003e {\n+ if (!window.nostr || !window.nostr.nip04) {\n+ throw new Error('window.nostr or window.nostr.nip04 is undefined')\n+ }\n+ return await window.nostr.nip04.decrypt(sender.pubkey, value)\n+ }\n+}\ndiff --git a/src/lib/stores/users.ts b/src/lib/stores/users.ts\nindex 608ffed..40ed744 100644\n--- a/src/lib/stores/users.ts\n+++ b/src/lib/stores/users.ts\n@@ -2,13 +2,12 @@ import {\n defaults as user_defaults,\n type UserObject,\n } from '$lib/components/users/type'\n-import {\n- getRelayListForUser,\n- NDKNip07Signer,\n- NDKRelayList,\n-} from '@nostr-dev-kit/ndk'\n+import { getRelayListForUser, NDKRelayList } from '@nostr-dev-kit/ndk'\n import { get, writable, type Unsubscriber, type Writable } from 'svelte/store'\n import { ndk } from './ndk'\n+import { init as initNostrLogin } from 'nostr-login'\n+import { NDKNostrLoginSigner } from '$lib/signers/nostr-login'\n+import type { NostrLoginAuthOptions } from 'nostr-login/dist/types'\n \n export const users: { [hexpubkey: string]: Writable\u003cUserObject\u003e } = {}\n \n@@ -85,31 +84,7 @@ export const returnUser = async (hexpubkey: string): Promise\u003cUserObject\u003e =\u003e {\n })\n }\n \n-// nip07_plugin is set in Navbar component\n-export const nip07_plugin: Writable\u003cundefined | boolean\u003e = writable(undefined)\n-\n-export const checkForNip07Plugin = () =\u003e {\n- if (window.nostr) {\n- nip07_plugin.set(true)\n- if (localStorage.getItem('nip07pubkey')) login()\n- } else {\n- let timerId: NodeJS.Timeout | undefined = undefined\n- const intervalId = setInterval(() =\u003e {\n- if (window.nostr) {\n- clearTimeout(timerId)\n- clearInterval(intervalId)\n- nip07_plugin.set(true)\n- if (localStorage.getItem('nip07pubkey')) login()\n- }\n- }, 100)\n- timerId = setTimeout(() =\u003e {\n- clearInterval(intervalId)\n- nip07_plugin.set(false)\n- }, 5000)\n- }\n-}\n-\n-const signer = new NDKNip07Signer(2000)\n+const signer = new NDKNostrLoginSigner()\n \n export const logged_in_user: Writable\u003cundefined | UserObject\u003e =\n writable(undefined)\n@@ -118,24 +93,24 @@ export const login = async (): Promise\u003cvoid\u003e =\u003e {\n return new Promise(async (res, rej) =\u003e {\n const user = get(logged_in_user)\n if (user) return res()\n- if (get(nip07_plugin)) {\n- try {\n- const ndk_user = await signer.blockUntilReady()\n- localStorage.setItem('nip07pubkey', ndk_user.pubkey)\n- logged_in_user.set({\n- ...user_defaults,\n- hexpubkey: ndk_user.pubkey,\n- })\n- ndk.signer = signer\n- ensureUser(ndk_user.pubkey).subscribe((user) =\u003e {\n- logged_in_user.set({ ...user })\n- })\n- return res()\n- } catch (e) {\n- alert(e)\n- rej()\n- }\n- } else {\n+ try {\n+ ndk.signer = signer\n+ initNostrLogin({\n+ onAuth: async (_npub: string, options: NostrLoginAuthOptions) =\u003e {\n+ const pubkey =\n+ typeof options.pubkey === 'string' ? options.pubkey : ''\n+ logged_in_user.set({\n+ ...user_defaults,\n+ hexpubkey: pubkey,\n+ })\n+ ensureUser(pubkey).subscribe((user) =\u003e {\n+ logged_in_user.set({ ...user })\n+ })\n+ return res()\n+ },\n+ })\n+ } catch (e) {\n+ alert(e)\n rej()\n }\n })\n@@ -143,7 +118,6 @@ export const login = async (): Promise\u003cvoid\u003e =\u003e {\n \n export const logout = async (): Promise\u003cvoid\u003e =\u003e {\n logged_in_user.set(undefined)\n- localStorage.removeItem('nip07pubkey')\n ndk.signer = undefined\n }\n \ndiff --git a/src/lib/wrappers/Navbar.svelte b/src/lib/wrappers/Navbar.svelte\nindex 4b63bc7..1f7146f 100644\n--- a/src/lib/wrappers/Navbar.svelte\n+++ b/src/lib/wrappers/Navbar.svelte\n@@ -1,23 +1,6 @@\n \u003cscript lang=\"ts\"\u003e\n- import {\n- checkForNip07Plugin,\n- logged_in_user,\n- login,\n- nip07_plugin,\n- } from '$lib/stores/users'\n- import { onMount } from 'svelte'\n+ import { logged_in_user, login } from '$lib/stores/users'\n import Navbar from '$lib/components/Navbar.svelte'\n-\n- let singup_function = () =\u003e {\n- alert('a NIP-07 browser extension is required. currently no signup page')\n- }\n-\n- onMount(checkForNip07Plugin)\n \u003c/script\u003e\n \n-\u003cNavbar\n- logged_in_user={$logged_in_user}\n- nip07_plugin={$nip07_plugin}\n- login_function={login}\n- {singup_function}\n-/\u003e\n+\u003cNavbar logged_in_user={$logged_in_user} login_function={login} /\u003e\ndiff --git a/yarn.lock b/yarn.lock\nindex f75be09..f976ab4 100644\n--- a/yarn.lock\n+++ b/yarn.lock\n@@ -566,6 +566,13 @@ __metadata:\n languageName: node\n linkType: hard\n \n+\"@noble/ciphers@npm:0.2.0\":\n+ version: 0.2.0\n+ resolution: \"@noble/ciphers@npm:0.2.0\"\n+ checksum: 10c0/57dea65c32741df20a1ac24f365d616a558527109d778c1bec877f20b28875a26b80097bce51ae19529f3792ccf8285fe73839ff404733e32a27a6ebf60edd2c\n+ languageName: node\n+ linkType: hard\n+\n \"@noble/ciphers@npm:^0.5.1\":\n version: 0.5.3\n resolution: \"@noble/ciphers@npm:0.5.3\"\n@@ -573,6 +580,15 @@ __metadata:\n languageName: node\n linkType: hard\n \n+\"@noble/curves@npm:1.1.0, @noble/curves@npm:~1.1.0\":\n+ version: 1.1.0\n+ resolution: \"@noble/curves@npm:1.1.0\"\n+ dependencies:\n+ \"@noble/hashes\": \"npm:1.3.1\"\n+ checksum: 10c0/81115c3ebfa7e7da2d7e18d44d686f98dc6d35dbde3964412c05707c92d0994a01545bc265d5c0bc05c8c49333f75b99c9acef6750f5a79b3abcc8e0546acf88\n+ languageName: node\n+ linkType: hard\n+\n \"@noble/curves@npm:1.2.0\":\n version: 1.2.0\n resolution: \"@noble/curves@npm:1.2.0\"\n@@ -582,7 +598,7 @@ __metadata:\n languageName: node\n linkType: hard\n \n-\"@noble/curves@npm:^1.4.0\":\n+\"@noble/curves@npm:^1.4.0, @noble/curves@npm:^1.6.0\":\n version: 1.6.0\n resolution: \"@noble/curves@npm:1.6.0\"\n dependencies:\n@@ -591,15 +607,6 @@ __metadata:\n languageName: node\n linkType: hard\n \n-\"@noble/curves@npm:~1.1.0\":\n- version: 1.1.0\n- resolution: \"@noble/curves@npm:1.1.0\"\n- dependencies:\n- \"@noble/hashes\": \"npm:1.3.1\"\n- checksum: 10c0/81115c3ebfa7e7da2d7e18d44d686f98dc6d35dbde3964412c05707c92d0994a01545bc265d5c0bc05c8c49333f75b99c9acef6750f5a79b3abcc8e0546acf88\n- languageName: node\n- linkType: hard\n-\n \"@noble/hashes@npm:1.3.1\":\n version: 1.3.1\n resolution: \"@noble/hashes@npm:1.3.1\"\n@@ -614,7 +621,7 @@ __metadata:\n languageName: node\n linkType: hard\n \n-\"@noble/hashes@npm:1.5.0, @noble/hashes@npm:^1.3.1\":\n+\"@noble/hashes@npm:1.5.0, @noble/hashes@npm:^1.3.1, @noble/hashes@npm:^1.5.0\":\n version: 1.5.0\n resolution: \"@noble/hashes@npm:1.5.0\"\n checksum: 10c0/1b46539695fbfe4477c0822d90c881a04d4fa2921c08c552375b444a48cac9930cb1ee68de0a3c7859e676554d0f3771999716606dc4d8f826e414c11692cdd9\n@@ -628,7 +635,7 @@ __metadata:\n languageName: node\n linkType: hard\n \n-\"@noble/secp256k1@npm:^2.0.0\":\n+\"@noble/secp256k1@npm:^2.0.0, @noble/secp256k1@npm:^2.1.0\":\n version: 2.1.0\n resolution: \"@noble/secp256k1@npm:2.1.0\"\n checksum: 10c0/b4c7edd2a5ec5acf294546cd06d08dc2a2a2b2ebe34a6da1f2f5104f56983f81dd31c261ad365c6b9757d1c54017fc3363331ee33bba8715ff94c2bc954313cc\n@@ -692,6 +699,25 @@ __metadata:\n languageName: node\n linkType: hard\n \n+\"@nostr-dev-kit/ndk@npm:^2.3.1\":\n+ version: 2.10.1\n+ resolution: \"@nostr-dev-kit/ndk@npm:2.10.1\"\n+ dependencies:\n+ \"@noble/curves\": \"npm:^1.6.0\"\n+ \"@noble/hashes\": \"npm:^1.5.0\"\n+ \"@noble/secp256k1\": \"npm:^2.1.0\"\n+ \"@scure/base\": \"npm:^1.1.9\"\n+ debug: \"npm:^4.3.6\"\n+ light-bolt11-decoder: \"npm:^3.2.0\"\n+ nostr-tools: \"npm:^2.7.1\"\n+ tseep: \"npm:^1.2.2\"\n+ typescript-lru-cache: \"npm:^2.0.0\"\n+ utf8-buffer: \"npm:^1.0.0\"\n+ websocket-polyfill: \"npm:^0.0.3\"\n+ checksum: 10c0/b73cd0e9f036e60893d0470d778c5e672795f93308edca389d42c9487267e95df208b2b2353b20eb766ae606cfd1c328d03a1e43d69351e27159843cdb619cc9\n+ languageName: node\n+ linkType: hard\n+\n \"@npmcli/agent@npm:^2.0.0\":\n version: 2.2.2\n resolution: \"@npmcli/agent@npm:2.2.2\"\n@@ -854,7 +880,7 @@ __metadata:\n languageName: node\n linkType: hard\n \n-\"@scure/base@npm:^1.1.1, @scure/base@npm:~1.1.0\":\n+\"@scure/base@npm:^1.1.1, @scure/base@npm:^1.1.9, @scure/base@npm:~1.1.0\":\n version: 1.1.9\n resolution: \"@scure/base@npm:1.1.9\"\n checksum: 10c0/77a06b9a2db8144d22d9bf198338893d77367c51b58c72b99df990c0a11f7cadd066d4102abb15e3ca6798d1529e3765f55c4355742465e49aed7a0c01fe76e8\n@@ -3857,6 +3883,7 @@ __metadata:\n eslint-plugin-prettier: \"npm:^5.2.1\"\n eslint-plugin-svelte: \"npm:^2.44.0\"\n highlight.js: \"npm:^11.10.0\"\n+ nostr-login: \"npm:^1.6.6\"\n nostr-tools: \"npm:^2.7.2\"\n parse-diff: \"npm:^0.11.1\"\n postcss: \"npm:^8.4.47\"\n@@ -4492,6 +4519,15 @@ __metadata:\n languageName: node\n linkType: hard\n \n+\"light-bolt11-decoder@npm:^3.2.0\":\n+ version: 3.2.0\n+ resolution: \"light-bolt11-decoder@npm:3.2.0\"\n+ dependencies:\n+ \"@scure/base\": \"npm:1.1.1\"\n+ checksum: 10c0/65c1514b40b3b7fd5f4f0b40412bab35b0135f20f6b4929f5616bc5693f759fa8636d2393ba71fa782b2d9204315015e044628736ee7aea72f71939b0eb486f1\n+ languageName: node\n+ linkType: hard\n+\n \"lilconfig@npm:^2.0.5, lilconfig@npm:^2.1.0\":\n version: 2.1.0\n resolution: \"lilconfig@npm:2.1.0\"\n@@ -5030,6 +5066,36 @@ __metadata:\n languageName: node\n linkType: hard\n \n+\"nostr-login@npm:^1.6.6\":\n+ version: 1.6.6\n+ resolution: \"nostr-login@npm:1.6.6\"\n+ dependencies:\n+ \"@nostr-dev-kit/ndk\": \"npm:^2.3.1\"\n+ nostr-tools: \"npm:^1.17.0\"\n+ tseep: \"npm:^1.2.1\"\n+ checksum: 10c0/f521f906eef377321406838d2ab3be314c9755cbbad90328f32cd65fc5b035bb85729116bc5da313445c399aafb9f1bc12833a789f440e58f12619e84d9ff15f\n+ languageName: node\n+ linkType: hard\n+\n+\"nostr-tools@npm:^1.17.0\":\n+ version: 1.17.0\n+ resolution: \"nostr-tools@npm:1.17.0\"\n+ dependencies:\n+ \"@noble/ciphers\": \"npm:0.2.0\"\n+ \"@noble/curves\": \"npm:1.1.0\"\n+ \"@noble/hashes\": \"npm:1.3.1\"\n+ \"@scure/base\": \"npm:1.1.1\"\n+ \"@scure/bip32\": \"npm:1.3.1\"\n+ \"@scure/bip39\": \"npm:1.2.1\"\n+ peerDependencies:\n+ typescript: \"\u003e=5.0.0\"\n+ peerDependenciesMeta:\n+ typescript:\n+ optional: true\n+ checksum: 10c0/b52732df3e403ef3c73a41fe1dea89accbff91597b231d811d577c35a9bd9307651de65ec7fbcc9989aef4c35e9c6b1005200fbbfec45544dcd64f928bbfc476\n+ languageName: node\n+ linkType: hard\n+\n \"nostr-tools@npm:^2.7.1, nostr-tools@npm:^2.7.2\":\n version: 2.7.2\n resolution: \"nostr-tools@npm:2.7.2\"\n@@ -6638,6 +6704,13 @@ __metadata:\n languageName: node\n linkType: hard\n \n+\"tseep@npm:^1.2.1, tseep@npm:^1.2.2\":\n+ version: 1.3.1\n+ resolution: \"tseep@npm:1.3.1\"\n+ checksum: 10c0/01b68f1f0e1084ff78bed9f28d83a595b4b6256caecd8c245af62716037dc4e87c9916c90d5d5cd4a2935f7d438a1117b2703dbf8abc79f087bc176a6f247ed6\n+ languageName: node\n+ linkType: hard\n+\n \"tslib@npm:^2.0.1, tslib@npm:^2.6.2, tslib@npm:^2.7.0\":\n version: 2.7.0\n resolution: \"tslib@npm:2.7.0\"\n--\nlibgit2 1.8.1\n\n", "sig": "b2a0eb5ac92b4687774c1ef0a8eb96d585147d15ca9658f3100d1661852c28fb27481ec2ac07c51fcaa7bed9d3dc915720edbe6d9c18277546d858230cc23827" }