From 74f73c0ecbfe630b77df77be456f584744047c9c Mon Sep 17 00:00:00 2001 From: Tobias Baunbaek Date: Tue, 13 Feb 2024 15:02:21 +0100 Subject: [PATCH 1/5] Add Making A Terminal App guide --- guide/making-a-pear-desktop-app.md | 2 +- guide/making-a-pear-terminal-app.md | 111 ++++++++++++++++++++-- guide/starting-a-pear-terminal-project.md | 27 ++++-- 3 files changed, 126 insertions(+), 14 deletions(-) diff --git a/guide/making-a-pear-desktop-app.md b/guide/making-a-pear-desktop-app.md index 2bf432e..b7302c4 100644 --- a/guide/making-a-pear-desktop-app.md +++ b/guide/making-a-pear-desktop-app.md @@ -166,7 +166,7 @@ Running `pear dev` should show ## Step 2. Module dependencies -**Note**: Close the app before installing dependencies. If dependencies are installed while the app is running, an error is thrown. +**Note**: Close the app before installing dependencies. If dependencies are installed while the app is running, an error is thrown. The app uses these modules: diff --git a/guide/making-a-pear-terminal-app.md b/guide/making-a-pear-terminal-app.md index d940659..2a5668b 100644 --- a/guide/making-a-pear-terminal-app.md +++ b/guide/making-a-pear-terminal-app.md @@ -1,19 +1,116 @@ # Making a Pear Terminal Application +This guide demonstrates how to build a peer-to-peer chat application. + +It continues where [Starting a Pear Terminal Project](./starting-a-pear-terminal-project.md) left off. + > [Build with Pear - Episode 04: Pear Terminal Applications]https://www.youtube.com/watch?v=73KVE0wocTE ## Step 1. Install modules -This app uses these modules: `hyperswarm`, `hypercore-crypto`, and `b4a`. +For the chat part of the app, the same modules are needed as in [Making a Pear Desktop Application](./making-a-pear-desktop-app.md), `hyperswarm`, `b4a`, `hypercore-crypto`. + +To read input we will want to use `readline`, but it's important that Pear does not run on Node.js. Instead it runs on `Bare`. Bare is a lightweight javascript runtime which means it does not include a lot of the standard library modules as Node.js does. To use the `bare` equivalent the modules `bare-readline` and `bare-tty` are needed + ``` -npm i hyperswarm hypercore-crypto b4a +npm i bare-readline bare-tty hyperswarm b4a hypercore-crypto ``` -**Note**: If the modules are installed while the app is running an error is thrown similar to `Cannot find package 'hyperswarm' imported from /app.js`. When installing modules, close down the app, before they can be installed. +## Step 2. JavaScript -- [hyperswarm](https://www.npmjs.com/package/hyperswarm). One of the main building blocks. Find peers that share a "topic". -- [hypercore-crypto](https://www.npmjs.com/package/hypercore-crypto). A set of crypto function used in Pear. -- [b4a](https://www.npmjs.com/package/b4a). A set of functions for bridging the gap between the Node.js `Buffer` class and the `Uint8Array` class. +Replace `index.js` with -## Step 2. +``` js +import Hyperswarm from 'hyperswarm' +import b4a from 'b4a' +import crypto from 'hypercore-crypto' +import readline from 'bare-readline' +import tty from 'bare-tty' + +const { teardown, config } = Pear +const key = config.args.pop() +const shouldCreateSwarm = !key +const swarm = new Hyperswarm() +const log = console.log +const rl = readline.createInterface({ + input: new tty.ReadStream(0), + output: new tty.WriteStream(1) +}) + +swarm.on('connection', peer => { + const name = b4a.toString(peer.remotePublicKey, 'hex').substr(0, 6) + console.log(`[info] New peer joined, ${name}`) + peer.on('data', message => appendMessage({ name, message })) +}) +swarm.on('update', () => { + console.log(`[info] Number of connections is now ${swarm.connections.size}`) +}) + +if (shouldCreateSwarm) { + await createChatRoom() +} else { + await joinChatRoom(key) +} + +rl.input.setMode(tty.constants.MODE_RAW) +rl.on('data', line => { + sendMessage(line) + rl.prompt() +}) +rl.prompt() + +async function createChatRoom () { + const topicBuffer = crypto.randomBytes(32) + await joinSwarm(topicBuffer) + const topic = b4a.toString(topicBuffer, 'hex') + console.log(`[info] Created new chat room: ${topic}`) +} + +async function joinChatRoom (topicStr) { + const topicBuffer = b4a.from(topicStr, 'hex') + await joinSwarm(topicBuffer) + console.log(`[info] Joined chat room`) +} + +async function joinSwarm (topicBuffer) { + const discovery = swarm.join(topicBuffer, { client: true, server: true }) + await discovery.flushed() +} + +function sendMessage (message) { + const peers = [...swarm.connections] + for (const peer of peers) peer.write(message) +} + +function appendMessage ({ name, message }) { + console.log(`[${name}] ${message}`) +} +``` + +## Step 3. Run in dev mode + +To test this chat app, in one terminal run `pear dev .`. + +The app will output something similar to: + +``` +[info] Created new chat room: a1b2c35fbeb452bc900c5a1c00306e52319a3159317312f54fe5a246d634f51a +``` + +In another terminal use this key as input, `pear dev . a1b2c35fbeb452bc900c5a1c00306e52319a3159317312f54fe5a246d634f51a`. + +The app will output: + +``` +[info] Number of connections is now 0 +[info] New peer joined, 6193ec +[info] Number of connections is now 1 +[info] Joined chat room +``` + +Type something in one app, and see that the two apps are now connected and can talk! + +## Next + +* [Sharing a Pear Application](./sharing-a-pear-app.md) diff --git a/guide/starting-a-pear-terminal-project.md b/guide/starting-a-pear-terminal-project.md index 2634351..0a2fa6f 100644 --- a/guide/starting-a-pear-terminal-project.md +++ b/guide/starting-a-pear-terminal-project.md @@ -4,17 +4,32 @@ ## Step 1. Init -First create a new project using `pear init`. +First create a new project using `pear init --type terminal`. ``` -mkdir chat-bot -cd chat-bot -pear init --yes +mkdir chat-app +cd chat-app +pear init --yes --type terminal ``` This creates the base project structure. - `package.json`. App configuration. Notice the `pear` property. - `index.js`. App entrypoint. -- `app.js`. Main code. -- `test/index.test.js`. Test skeleton. + +## Step 2. Verify Everything Works + +Use `pear dev` to see that it works. + +``` +pear dev +``` + +The app will now run. Note that it will keep running until you exit with `ctrl + c`. + +That's all there is to it! + + +## Next + +* [Making a Pear Terminal Application](./making-a-pear-terminal-app.md) From ddbf4c9dd71bedc734ecdbfc19e0847bb824a2a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Baunb=C3=A6k=20Christensen?= Date: Tue, 13 Feb 2024 15:08:00 +0100 Subject: [PATCH 2/5] Update guide/starting-a-pear-terminal-project.md Co-authored-by: David Mark Clements --- guide/starting-a-pear-terminal-project.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guide/starting-a-pear-terminal-project.md b/guide/starting-a-pear-terminal-project.md index 0a2fa6f..ce6623f 100644 --- a/guide/starting-a-pear-terminal-project.md +++ b/guide/starting-a-pear-terminal-project.md @@ -27,7 +27,7 @@ pear dev The app will now run. Note that it will keep running until you exit with `ctrl + c`. -That's all there is to it! +That's all there is to getting a Pear Terminal project started. ## Next From 407ea87f4089a7e0e9be68ff000dba77f9c352b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Baunb=C3=A6k=20Christensen?= Date: Tue, 13 Feb 2024 15:08:34 +0100 Subject: [PATCH 3/5] Update guide/making-a-pear-terminal-app.md Co-authored-by: David Mark Clements --- guide/making-a-pear-terminal-app.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guide/making-a-pear-terminal-app.md b/guide/making-a-pear-terminal-app.md index 2a5668b..4259cda 100644 --- a/guide/making-a-pear-terminal-app.md +++ b/guide/making-a-pear-terminal-app.md @@ -109,7 +109,7 @@ The app will output: [info] Joined chat room ``` -Type something in one app, and see that the two apps are now connected and can talk! +Type something in one of the applications. Two Terminal Applications are now connected peer-to-peer. ## Next From 377828459b31fa5d150d443c518e9d2b7c55fac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Baunb=C3=A6k=20Christensen?= Date: Tue, 13 Feb 2024 15:16:42 +0100 Subject: [PATCH 4/5] Update guide/making-a-pear-terminal-app.md Co-authored-by: David Mark Clements --- guide/making-a-pear-terminal-app.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guide/making-a-pear-terminal-app.md b/guide/making-a-pear-terminal-app.md index 4259cda..9fb5838 100644 --- a/guide/making-a-pear-terminal-app.md +++ b/guide/making-a-pear-terminal-app.md @@ -10,7 +10,7 @@ It continues where [Starting a Pear Terminal Project](./starting-a-pear-terminal For the chat part of the app, the same modules are needed as in [Making a Pear Desktop Application](./making-a-pear-desktop-app.md), `hyperswarm`, `b4a`, `hypercore-crypto`. -To read input we will want to use `readline`, but it's important that Pear does not run on Node.js. Instead it runs on `Bare`. Bare is a lightweight javascript runtime which means it does not include a lot of the standard library modules as Node.js does. To use the `bare` equivalent the modules `bare-readline` and `bare-tty` are needed +Pear runs on [`Bare`](https://github.com/holepunchto/bare), a lightweight JavaScript runtime which is similar to Node.js but comes with very few internal modules. Almost all Bare functionality comes from dependencies. Pear Terminal Applications are Bare applications so we will need `bare-readline` and `bare-tty` to read user input. ``` From 2a83cb57e61caa42470299ff6df76c687f1cd557 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Baunb=C3=A6k=20Christensen?= Date: Tue, 13 Feb 2024 15:16:54 +0100 Subject: [PATCH 5/5] Update guide/making-a-pear-terminal-app.md Co-authored-by: David Mark Clements --- guide/making-a-pear-terminal-app.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guide/making-a-pear-terminal-app.md b/guide/making-a-pear-terminal-app.md index 9fb5838..c04a6cb 100644 --- a/guide/making-a-pear-terminal-app.md +++ b/guide/making-a-pear-terminal-app.md @@ -8,7 +8,7 @@ It continues where [Starting a Pear Terminal Project](./starting-a-pear-terminal ## Step 1. Install modules -For the chat part of the app, the same modules are needed as in [Making a Pear Desktop Application](./making-a-pear-desktop-app.md), `hyperswarm`, `b4a`, `hypercore-crypto`. +For the chat part of the app, the same modules are needed as in [Making a Pear Desktop Application](./making-a-pear-desktop-app.md), `hyperswarm`, `b4a` and `hypercore-crypto`. Pear runs on [`Bare`](https://github.com/holepunchto/bare), a lightweight JavaScript runtime which is similar to Node.js but comes with very few internal modules. Almost all Bare functionality comes from dependencies. Pear Terminal Applications are Bare applications so we will need `bare-readline` and `bare-tty` to read user input.