From c402472b38c9545ae927da6530497a24717eb99c Mon Sep 17 00:00:00 2001 From: Jacob Karlsson Date: Mon, 20 May 2024 17:11:46 +0200 Subject: [PATCH 1/2] Start using the sdk for creating the peer --- main.js | 435 +++++++++++++++++++++---------------------------- package.json | 5 +- pnpm-lock.yaml | 59 ++++++- 3 files changed, 239 insertions(+), 260 deletions(-) diff --git a/main.js b/main.js index 2de1620..e4d4150 100644 --- a/main.js +++ b/main.js @@ -2,8 +2,8 @@ const { app, BrowserWindow, ipcMain, shell, clipboard } = require('electron') const Path = require('node:path') const URL = require('node:url') const p = require('node:util').promisify -const Keypair = require('pzp-keypair') const awaitable = require('pull-awaitable') +const { createPeer } = require('pzp-sdk') // WARNING monkey patch! ------------------------------------------------------- const na = require('sodium-native') @@ -23,283 +23,218 @@ app.setPath('userData', process.env.ZOOBOARD_DATA) const path = Path.resolve(app.getPath('userData'), 'pzp') console.log("Appdata path:", process.env.ZOOBOARD_DATA) -const keypairPath = Path.join(path, 'keypair.json') -const keypair = Keypair.loadOrCreateSync(keypairPath) let mainWindow -let globalAccountID = null let globalAccountName = null -const peer = require('secret-stack/bare')() - .use(require('secret-stack/plugins/net')) - .use(require('secret-handshake-ext/secret-stack')) - .use(require('pzp-net')) - .use(require('pzp-db')) - .use(require('pzp-set')) - .use(require('pzp-dict')) - .use(require('pzp-goals')) - .use(require('pzp-sync')) - .use(require('pzp-gc')) - .use(require('pzp-conductor')) - .use(require('pzp-hub-client')) - .use(require('pzp-promise')) - .use(require('pzp-invite')) - .call(null, { - shse: { - caps: require('pzp-caps'), - }, - global: { - keypair, - path, - timers: { - inactivity: 10 * 60e3, +createPeer({ path }).then(({ peer, account: globalAccountID }) => { + function createWindow() { + mainWindow = new BrowserWindow({ + width: 1200, + height: 1200, + title: 'Zooboard', + webPreferences: { + preload: Path.join(__dirname, 'preload.js'), }, - connections: { - incoming: { - tunnel: [{ transform: 'shse', scope: 'public' }], - }, - outgoing: { - net: [{ transform: 'shse' }], - tunnel: [{ transform: 'shse' }], - }, - }, - }, - net: { - autostart: false, - }, - }) - -function createWindow() { - mainWindow = new BrowserWindow({ - width: 1200, - height: 1200, - title: 'Zooboard', - webPreferences: { - preload: Path.join(__dirname, 'preload.js'), - }, - }) - - const startUrl = - process.env.ELECTRON_START_URL ?? - URL.format({ - pathname: Path.join(__dirname, '/../build/index.html'), - protocol: 'file:', - slashes: true, }) - mainWindow.loadURL(startUrl) - mainWindow.webContents.openDevTools({ mode: 'bottom', activate: true }) + const startUrl = + process.env.ELECTRON_START_URL ?? + URL.format({ + pathname: Path.join(__dirname, '/../build/index.html'), + protocol: 'file:', + slashes: true, + }) + mainWindow.loadURL(startUrl) - // open Web URLs in the default system browser - mainWindow.webContents.on('new-window', (ev, url) => { - ev.preventDefault() - shell.openExternal(url) - }) -} + mainWindow.webContents.openDevTools({ mode: 'bottom', activate: true }) -async function loadAccount() { - if (globalAccountID !== null) { - return { id: globalAccountID, name: globalAccountName } - } - - // Kickstart - await peer.db.loaded() - const id = await p(peer.db.account.findOrCreate)({ subdomain: 'person' }) - globalAccountID = id - await p(peer.set.load)(id) - await p(peer.dict.load)(id) - - // Read profile - const profile = await p(peer.dict.read)(id, 'profile') - const name = profile?.name ?? '' - globalAccountName = name - - await peer.net.start() - - return { id, name } -} - -async function setProfileName(ev, name) { - await p(peer.dict.update)('profile', { name }) - return name -} - -async function writeElements(ev, elements) { - if (globalAccountID === null) throw new Error('account not loaded') - for (const element of elements) { - await p(peer.db.feed.publish)({ - account: globalAccountID, - domain: 'zooboardElements', - data: element, + // open Web URLs in the default system browser + mainWindow.webContents.on('new-window', (ev, url) => { + ev.preventDefault() + shell.openExternal(url) }) } -} -async function createInvite() { - if (globalAccountID === null) throw new Error('account not loaded') - let { url } = await p(peer.invite.createForFriend)({ - hubs: 1, - id: globalAccountID, - }) - // if the hub is on localhost, it's probably on the default port of 3000, so let's make things a bit easier for the user - if (url.indexOf('0.0.0.0') !== -1) url = url.replace("0.0.0.0", "0.0.0.0:3000") - return url -} + async function loadAccount() { + if (globalAccountName !== null) { + return { id: globalAccountID, name: globalAccountName } + } -function copyToClipboard(ev, text) { - clipboard.writeText(text) -} + // Read profile + const profile = await p(peer.dict.read)(globalAccountID, 'profile') + const name = profile?.name ?? '' + globalAccountName = name -let hasSubscribedToReadElements = false -async function subscribeToReadElements() { - if (hasSubscribedToReadElements) return - hasSubscribedToReadElements = true + return { id: globalAccountID, name } + } - // Load initial elements and inform renderer - const elementsByID = new Map() - const msgIDToElemID = new Map() - for await (const { id: msgID, msg } of peer.db.records()) { - if (msg.data && msg.metadata.domain === 'zooboardElements') { - const { id: elemID, isDeleted } = msg.data - if (isDeleted) { - elementsByID.delete(elemID) - } else { - msgIDToElemID.set(msgID, elemID) - elementsByID.set(elemID, msg.data) - } + async function setProfileName(ev, name) { + await p(peer.dict.update)('profile', { name }) + return name + } + + async function writeElements(ev, elements) { + if (globalAccountID === null) throw new Error('account not loaded') + for (const element of elements) { + await p(peer.db.feed.publish)({ + account: globalAccountID, + domain: 'zooboardElements', + data: element, + }) } } - const initialElements = [...elementsByID.values()] - mainWindow.webContents.send('readElements', initialElements) - // Subscribe to new elements and inform renderer - peer.db.onRecordAdded(({ id: msgID, msg }) => { - if (msg.data && msg.metadata.domain === 'zooboardElements') { - const { id: elemID, isDeleted } = msg.data - if (isDeleted) { - elementsByID.delete(elemID) - } else { - msgIDToElemID.set(msgID, elemID) - elementsByID.set(elemID, msg.data) - } - mainWindow.webContents.send('readElements', [msg.data]) - } - }) - - // Subscribe to deleted elements and inform renderer - peer.db.onRecordDeletedOrErased((msgID) => { - const elemID = msgIDToElemID.get(msgID) - if (!elemID) return - msgIDToElemID.delete(msgID) - // Is there some other msgID that supports this elemID? If so, bail out - for (const [, remainingElemID] of msgIDToElemID) { - if (remainingElemID === elemID) { - return - } - } - // If not, delete the element - elementsByID.delete(elemID) - mainWindow.webContents.send('readElements', [ - { id: elemID, isDeleted: true }, - ]) - }) - - // Finally safe to kickstart replication and garbage collection - setTimeout(() => { - peer.conductor.start( - globalAccountID, - [ - ['profile@dict', 'zooboardElements@newest-100', 'hubs@set'], - ['profile@dict', 'zooboardElements@newest-100'], - ], - 64_000, - (err) => { - if (err) console.error('Starting conductor failed:', err) - } - ) - }, 32) -} - -let hasSubscribedToConnections = false -async function subscribeToConnections() { - if (hasSubscribedToConnections) return - hasSubscribedToConnections = true - - for await (const connections of awaitable(peer.net.peers())) { - mainWindow.webContents.send('connections', connections) + async function createInvite() { + if (globalAccountID === null) throw new Error('account not loaded') + let { url } = await p(peer.invite.createForFriend)({ + hubs: 1, + id: globalAccountID, + }) + // if the hub is on localhost, it's probably on the default port of 3000, so let's make things a bit easier for the user + if (url.indexOf('0.0.0.0') !== -1) url = url.replace("0.0.0.0", "0.0.0.0:3000") + return url } -} -async function handlePZPUri(ev, uri) { - if (!globalAccountID) { - setTimeout(handlePZPUri, 100, null, uri) - return + function copyToClipboard(ev, text) { + clipboard.writeText(text) } - if (uri.startsWith("http:") || uri.startsWith("https://")) { - uri = decodeURIComponent(uri.split('/invite#')[1]) - } - if (!uri.startsWith('pzp://')) return console.log('Not a pzp invite URI', uri) - const commands = peer.invite.parse(uri) - for (const command of commands) { - console.log('Executing command', JSON.stringify(command)) - switch (command.type) { - case 'join': { - try { - await p(peer.hubClient.addHub)(command.multiaddr) - } catch (err) { - console.error('Failed to properly join hub', err) + + let hasSubscribedToReadElements = false + async function subscribeToReadElements() { + if (hasSubscribedToReadElements) return + hasSubscribedToReadElements = true + + // Load initial elements and inform renderer + const elementsByID = new Map() + const msgIDToElemID = new Map() + for await (const { id: msgID, msg } of peer.db.records()) { + if (msg.data && msg.metadata.domain === 'zooboardElements') { + const { id: elemID, isDeleted } = msg.data + if (isDeleted) { + elementsByID.delete(elemID) + } else { + msgIDToElemID.set(msgID, elemID) + elementsByID.set(elemID, msg.data) } - break } - case 'follow': { - await p(peer.set.add)('follows', command.id) - break - } - case 'promise.follow': { - const [issuerType, issuerPubkey] = command.issuer - if (issuerType !== 'pubkey') { - throw new Error(`Dont know how to claim a ${issuerType} promise`) + } + const initialElements = [...elementsByID.values()] + mainWindow.webContents.send('readElements', initialElements) + + // Subscribe to new elements and inform renderer + peer.db.onRecordAdded(({ id: msgID, msg }) => { + if (msg.data && msg.metadata.domain === 'zooboardElements') { + const { id: elemID, isDeleted } = msg.data + if (isDeleted) { + elementsByID.delete(elemID) + } else { + msgIDToElemID.set(msgID, elemID) + elementsByID.set(elemID, msg.data) } - // eslint-disable-next-line no-loop-func - peer.addListener('rpc:connect', function onConnect(rpc) { - if (rpc.shse.pubkey === issuerPubkey) { - peer.removeListener('rpc:connect', onConnect) - rpc.promise.follow(command.token, globalAccountID, (err) => { - if (err) return console.error('Failed to use follow promise', err) - }) + mainWindow.webContents.send('readElements', [msg.data]) + } + }) + + // Subscribe to deleted elements and inform renderer + peer.db.onRecordDeletedOrErased((msgID) => { + const elemID = msgIDToElemID.get(msgID) + if (!elemID) return + msgIDToElemID.delete(msgID) + // Is there some other msgID that supports this elemID? If so, bail out + for (const [, remainingElemID] of msgIDToElemID) { + if (remainingElemID === elemID) { + return + } + } + // If not, delete the element + elementsByID.delete(elemID) + mainWindow.webContents.send('readElements', [ + { id: elemID, isDeleted: true }, + ]) + }) + + // Finally safe to kickstart replication and garbage collection + setTimeout(() => { + peer.conductor.start( + globalAccountID, + [ + ['profile@dict', 'zooboardElements@newest-100', 'hubs@set'], + ['profile@dict', 'zooboardElements@newest-100'], + ], + 64_000, + (err) => { + if (err) console.error('Starting conductor failed:', err) + } + ) + }, 32) + } + + let hasSubscribedToConnections = false + async function subscribeToConnections() { + if (hasSubscribedToConnections) return + hasSubscribedToConnections = true + + for await (const connections of awaitable(peer.net.peers())) { + mainWindow.webContents.send('connections', connections) + } + } + + async function handlePZPUri(ev, uri) { + if (!globalAccountID) { + setTimeout(handlePZPUri, 100, null, uri) + return + } + if (uri.startsWith("http:") || uri.startsWith("https://")) { + uri = decodeURIComponent(uri.split('/invite#')[1]) + } + if (!uri.startsWith('pzp://')) return console.log('Not a pzp invite URI', uri) + const commands = peer.invite.parse(uri) + for (const command of commands) { + console.log('Executing command', JSON.stringify(command)) + switch (command.type) { + case 'join': { + try { + await p(peer.hubClient.addHub)(command.multiaddr) + } catch (err) { + console.error('Failed to properly join hub', err) } - }) - break + break + } + case 'follow': { + await p(peer.set.add)('follows', command.id) + break + } + case 'promise.follow': { + const [issuerType, issuerPubkey] = command.issuer + if (issuerType !== 'pubkey') { + throw new Error(`Dont know how to claim a ${issuerType} promise`) + } + // eslint-disable-next-line no-loop-func + peer.addListener('rpc:connect', function onConnect(rpc) { + if (rpc.shse.pubkey === issuerPubkey) { + peer.removeListener('rpc:connect', onConnect) + rpc.promise.follow(command.token, globalAccountID, (err) => { + if (err) return console.error('Failed to use follow promise', err) + }) + } + }) + break + } + default: + console.log('Unknown command type', command.type) } - default: - console.log('Unknown command type', command.type) } } -} -if (process.defaultApp) { - if (process.argv.length >= 2) { - app.setAsDefaultProtocolClient('pzp', process.execPath, [ - Path.resolve(process.argv[1]), - ]) + if (process.defaultApp) { + if (process.argv.length >= 2) { + app.setAsDefaultProtocolClient('pzp', process.execPath, [ + Path.resolve(process.argv[1]), + ]) + } + } else { + app.setAsDefaultProtocolClient('pzp') } -} else { - app.setAsDefaultProtocolClient('pzp') -} - -//const hasLock = app.requestSingleInstanceLock() - -//if (!hasLock) { -// app.quit() -//} else { -// app.on('second-instance', (ev, argv, cwd, extraData) => { -// if (mainWindow) { -// if (mainWindow.isMinimized()) mainWindow.restore() -// mainWindow.focus() -// if (argv.length > 1) { -// handlePZPUri(null, argv[argv.length - 1]) -// } -// } -// }) app.whenReady().then(() => { ipcMain.handle('loadAccount', loadAccount) @@ -322,4 +257,4 @@ if (process.defaultApp) { if (process.platform !== 'darwin') app.quit() }) }) -//} +}).catch(err => console.error("Couldn't create peer:", err)) diff --git a/package.json b/package.json index 627cc5e..2da7bd9 100644 --- a/package.json +++ b/package.json @@ -22,14 +22,15 @@ "concurrently": "^8.2.2", "debounce": "2.0", "pzp-caps": "^1.0.0", - "pzp-db": "^1.0.1", + "pzp-db": "^1.0.2", "pzp-dict": "^1.0.0", "pzp-gc": "^1.0.0", "pzp-goals": "^1.0.0", "pzp-keypair": "^1.0.0", + "pzp-sdk": "git+https://codeberg.org/pzp/pzp-sdk.git", "pzp-set": "^1.0.0", "pzp-sync": "^1.0.0", - "pzp-conductor": "^1.0.0", + "pzp-conductor": "^1.0.2", "pzp-hub-client": "^1.0.0", "pzp-invite": "^1.0.0", "pzp-net": "^1.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ae47989..bd2d649 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,11 +26,11 @@ dependencies: specifier: ^1.0.0 version: 1.0.0 pzp-conductor: - specifier: ^1.0.0 - version: 1.0.0 + specifier: ^1.0.2 + version: 1.0.2 pzp-db: - specifier: ^1.0.1 - version: 1.0.1 + specifier: ^1.0.2 + version: 1.0.2 pzp-dict: specifier: ^1.0.0 version: 1.0.0 @@ -55,6 +55,9 @@ dependencies: pzp-promise: specifier: ^1.0.0 version: 1.0.0 + pzp-sdk: + specifier: git+https://codeberg.org/pzp/pzp-sdk.git + version: codeberg.org/pzp/pzp-sdk/45ae585bf5d2f114814274f188c4eea2c40ac1e7(pzp-caps@1.0.0)(pzp-conductor@1.0.2)(pzp-db@1.0.2)(pzp-dict@1.0.0)(pzp-gc@1.0.0)(pzp-goals@1.0.0)(pzp-hub-client@1.0.0)(pzp-invite@1.0.0)(pzp-keypair@1.0.0)(pzp-net@1.0.1)(pzp-promise@1.0.0)(pzp-set@1.0.0)(pzp-sync@1.0.0)(secret-handshake-ext@0.0.11)(secret-stack@8.1.0) pzp-set: specifier: ^1.0.0 version: 1.0.0 @@ -9611,8 +9614,8 @@ packages: resolution: {integrity: sha512-X/0lJFky3ztsypwwegrhjLODxe+ZFcQPWibBWD7SOuiG6+k01EhBFf7Tb9XvrYTncz9mbNXlaF4Iw0ihI55t0g==} dev: false - /pzp-conductor@1.0.0: - resolution: {integrity: sha512-FyZz446so7x5fRPhJZ70q1Icb4lVR7C/ovt/0fIPQf2UtxnqXaJtI1ptb/xmto6lg8ETc9OpPQMft/Ns6V8Rgw==} + /pzp-conductor@1.0.2: + resolution: {integrity: sha512-jNIxodNp/XjQQtJpz7kXV4r7rLYvd0pB/PP3CDvSgxO8i3p53yWmv5tRfpdIExmVwkTdjFbxsFEFWy8j0JYvQA==} engines: {node: '>=16'} dependencies: debug: 4.3.4 @@ -9620,8 +9623,8 @@ packages: - supports-color dev: false - /pzp-db@1.0.1: - resolution: {integrity: sha512-Bi3i4j9A49ElQ3yTGOl4a5eQ0p3vciaKUMZK+p2Rq42FrFI95BTZGYPFjgUDGgAstcnPsROEF3kCseaM46eoQg==} + /pzp-db@1.0.2: + resolution: {integrity: sha512-BBFw/VdFtw3toEgHHTUhnXItwOVsTgeAZuVyHqPUGw79MjI9sngY0PTLZRo51TFFxQQpFCNds4ljqXqiz2y6Pg==} engines: {node: '>=16'} dependencies: '@alloc/quick-lru': 5.2.0 @@ -12334,3 +12337,43 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} dev: false + + codeberg.org/pzp/pzp-sdk/45ae585bf5d2f114814274f188c4eea2c40ac1e7(pzp-caps@1.0.0)(pzp-conductor@1.0.2)(pzp-db@1.0.2)(pzp-dict@1.0.0)(pzp-gc@1.0.0)(pzp-goals@1.0.0)(pzp-hub-client@1.0.0)(pzp-invite@1.0.0)(pzp-keypair@1.0.0)(pzp-net@1.0.1)(pzp-promise@1.0.0)(pzp-set@1.0.0)(pzp-sync@1.0.0)(secret-handshake-ext@0.0.11)(secret-stack@8.1.0): + resolution: {commit: 45ae585bf5d2f114814274f188c4eea2c40ac1e7, repo: https://codeberg.org/pzp/pzp-sdk.git, type: git} + id: codeberg.org/pzp/pzp-sdk/45ae585bf5d2f114814274f188c4eea2c40ac1e7 + name: pzp-sdk + version: 0.0.1 + engines: {node: '>=18'} + peerDependencies: + pzp-caps: ^1.0.0 + pzp-conductor: ^1.0.2 + pzp-db: ^1.0.2 + pzp-dict: ^1.0.0 + pzp-gc: ^1.0.0 + pzp-goals: ^1.0.0 + pzp-hub-client: ^1.0.0 + pzp-invite: ^1.0.0 + pzp-keypair: ^1.0.0 + pzp-net: ^1.0.1 + pzp-promise: ^1.0.0 + pzp-set: ^1.0.0 + pzp-sync: ^1.0.0 + secret-handshake-ext: 0.0.11 + secret-stack: ~8.1.0 + dependencies: + pzp-caps: 1.0.0 + pzp-conductor: 1.0.2 + pzp-db: 1.0.2 + pzp-dict: 1.0.0 + pzp-gc: 1.0.0 + pzp-goals: 1.0.0 + pzp-hub-client: 1.0.0 + pzp-invite: 1.0.0 + pzp-keypair: 1.0.0 + pzp-net: 1.0.1 + pzp-promise: 1.0.0 + pzp-set: 1.0.0 + pzp-sync: 1.0.0 + secret-handshake-ext: 0.0.11 + secret-stack: 8.1.0 + dev: false From 558d86bff9374b383bb6d73c5f22510795001e36 Mon Sep 17 00:00:00 2001 From: Jacob Karlsson Date: Mon, 20 May 2024 17:44:54 +0200 Subject: [PATCH 2/2] Use sdk release --- package.json | 2 +- pnpm-lock.yaml | 81 ++++++++++++++++++++++++-------------------------- 2 files changed, 40 insertions(+), 43 deletions(-) diff --git a/package.json b/package.json index 2da7bd9..9e26fd0 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "pzp-gc": "^1.0.0", "pzp-goals": "^1.0.0", "pzp-keypair": "^1.0.0", - "pzp-sdk": "git+https://codeberg.org/pzp/pzp-sdk.git", + "pzp-sdk": "^1.0.0", "pzp-set": "^1.0.0", "pzp-sync": "^1.0.0", "pzp-conductor": "^1.0.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bd2d649..fd02dbe 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -56,8 +56,8 @@ dependencies: specifier: ^1.0.0 version: 1.0.0 pzp-sdk: - specifier: git+https://codeberg.org/pzp/pzp-sdk.git - version: codeberg.org/pzp/pzp-sdk/45ae585bf5d2f114814274f188c4eea2c40ac1e7(pzp-caps@1.0.0)(pzp-conductor@1.0.2)(pzp-db@1.0.2)(pzp-dict@1.0.0)(pzp-gc@1.0.0)(pzp-goals@1.0.0)(pzp-hub-client@1.0.0)(pzp-invite@1.0.0)(pzp-keypair@1.0.0)(pzp-net@1.0.1)(pzp-promise@1.0.0)(pzp-set@1.0.0)(pzp-sync@1.0.0)(secret-handshake-ext@0.0.11)(secret-stack@8.1.0) + specifier: ^1.0.0 + version: 1.0.0(pzp-caps@1.0.0)(pzp-conductor@1.0.2)(pzp-db@1.0.2)(pzp-dict@1.0.0)(pzp-gc@1.0.0)(pzp-goals@1.0.0)(pzp-hub-client@1.0.0)(pzp-invite@1.0.0)(pzp-keypair@1.0.0)(pzp-net@1.0.1)(pzp-promise@1.0.0)(pzp-set@1.0.0)(pzp-sync@1.0.0)(secret-handshake-ext@0.0.11)(secret-stack@8.1.0) pzp-set: specifier: ^1.0.0 version: 1.0.0 @@ -9746,6 +9746,43 @@ packages: bs58: 5.0.0 dev: false + /pzp-sdk@1.0.0(pzp-caps@1.0.0)(pzp-conductor@1.0.2)(pzp-db@1.0.2)(pzp-dict@1.0.0)(pzp-gc@1.0.0)(pzp-goals@1.0.0)(pzp-hub-client@1.0.0)(pzp-invite@1.0.0)(pzp-keypair@1.0.0)(pzp-net@1.0.1)(pzp-promise@1.0.0)(pzp-set@1.0.0)(pzp-sync@1.0.0)(secret-handshake-ext@0.0.11)(secret-stack@8.1.0): + resolution: {integrity: sha512-kpga5eN47PEsignEgY7cMCUl5dEnnCurvCj0c3dAH4T08MPsVRXzkC5yrBEnZbdXYjUAdZEEiUlMBsconmlxiQ==} + engines: {node: '>=18'} + peerDependencies: + pzp-caps: ^1.0.0 + pzp-conductor: ^1.0.2 + pzp-db: ^1.0.2 + pzp-dict: ^1.0.0 + pzp-gc: ^1.0.0 + pzp-goals: ^1.0.0 + pzp-hub-client: ^1.0.0 + pzp-invite: ^1.0.0 + pzp-keypair: ^1.0.0 + pzp-net: ^1.0.1 + pzp-promise: ^1.0.0 + pzp-set: ^1.0.0 + pzp-sync: ^1.0.0 + secret-handshake-ext: 0.0.11 + secret-stack: ~8.1.0 + dependencies: + pzp-caps: 1.0.0 + pzp-conductor: 1.0.2 + pzp-db: 1.0.2 + pzp-dict: 1.0.0 + pzp-gc: 1.0.0 + pzp-goals: 1.0.0 + pzp-hub-client: 1.0.0 + pzp-invite: 1.0.0 + pzp-keypair: 1.0.0 + pzp-net: 1.0.1 + pzp-promise: 1.0.0 + pzp-set: 1.0.0 + pzp-sync: 1.0.0 + secret-handshake-ext: 0.0.11 + secret-stack: 8.1.0 + dev: false + /pzp-set@1.0.0: resolution: {integrity: sha512-+BLssohjri/FgNSPSPffkcgBAXAxiycoS9W0kPZJtLeqSCwkhkyhPG3CHhOFhktUJ24wbTDFn0PnhOu0f9ZhbA==} engines: {node: '>=16'} @@ -12337,43 +12374,3 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} dev: false - - codeberg.org/pzp/pzp-sdk/45ae585bf5d2f114814274f188c4eea2c40ac1e7(pzp-caps@1.0.0)(pzp-conductor@1.0.2)(pzp-db@1.0.2)(pzp-dict@1.0.0)(pzp-gc@1.0.0)(pzp-goals@1.0.0)(pzp-hub-client@1.0.0)(pzp-invite@1.0.0)(pzp-keypair@1.0.0)(pzp-net@1.0.1)(pzp-promise@1.0.0)(pzp-set@1.0.0)(pzp-sync@1.0.0)(secret-handshake-ext@0.0.11)(secret-stack@8.1.0): - resolution: {commit: 45ae585bf5d2f114814274f188c4eea2c40ac1e7, repo: https://codeberg.org/pzp/pzp-sdk.git, type: git} - id: codeberg.org/pzp/pzp-sdk/45ae585bf5d2f114814274f188c4eea2c40ac1e7 - name: pzp-sdk - version: 0.0.1 - engines: {node: '>=18'} - peerDependencies: - pzp-caps: ^1.0.0 - pzp-conductor: ^1.0.2 - pzp-db: ^1.0.2 - pzp-dict: ^1.0.0 - pzp-gc: ^1.0.0 - pzp-goals: ^1.0.0 - pzp-hub-client: ^1.0.0 - pzp-invite: ^1.0.0 - pzp-keypair: ^1.0.0 - pzp-net: ^1.0.1 - pzp-promise: ^1.0.0 - pzp-set: ^1.0.0 - pzp-sync: ^1.0.0 - secret-handshake-ext: 0.0.11 - secret-stack: ~8.1.0 - dependencies: - pzp-caps: 1.0.0 - pzp-conductor: 1.0.2 - pzp-db: 1.0.2 - pzp-dict: 1.0.0 - pzp-gc: 1.0.0 - pzp-goals: 1.0.0 - pzp-hub-client: 1.0.0 - pzp-invite: 1.0.0 - pzp-keypair: 1.0.0 - pzp-net: 1.0.1 - pzp-promise: 1.0.0 - pzp-set: 1.0.0 - pzp-sync: 1.0.0 - secret-handshake-ext: 0.0.11 - secret-stack: 8.1.0 - dev: false