diff --git a/guide/creating-a-pear-init-template.md b/guide/creating-a-pear-init-template.md index cbfa321..792ed3e 100644 --- a/guide/creating-a-pear-init-template.md +++ b/guide/creating-a-pear-init-template.md @@ -78,37 +78,37 @@ Replace the contents of `_template.json` with ```json { - "params": [ - { - "name": "name", - "prompt": "name" - }, - { - "name": "main", - "default": "index.html", - "prompt": "main", - "validation": "(value) => value.endsWith('.html')", - "msg": "must have an .html file extension" - }, - { - "name": "height", - "validation": "(value) => Number.isInteger(+value)", - "prompt": "height", - "msg": "must be an integer" - }, - { - "name": "width", - "validation": "(value) => Number.isInteger(+value)", - "prompt": "width", - "msg": "must be an integer" - }, - { - "name": "license", - "default": "Apache-2.0", - "prompt": "license" - } - ] - } + "params": [ + { + "name": "name", + "prompt": "name" + }, + { + "name": "main", + "default": "index.html", + "prompt": "main", + "validation": "(value) => value.endsWith('.html')", + "msg": "must have an .html file extension" + }, + { + "name": "height", + "validation": "(value) => Number.isInteger(+value)", + "prompt": "height", + "msg": "must be an integer" + }, + { + "name": "width", + "validation": "(value) => Number.isInteger(+value)", + "prompt": "width", + "msg": "must be an integer" + }, + { + "name": "license", + "default": "Apache-2.0", + "prompt": "license" + } + ] +} ``` ## App Content @@ -166,6 +166,21 @@ Replace the contents of `index.html` file with : ``` +Temporarily set the contents of `package.json` to: + +```json +{ + "pear": { + "name": "pear-init-template-tutorial", + "type": "desktop" + } +} +``` + +This is the minimal requirements for a Pear Application `package.json` to run. +This will allow us to test the template's `index.html` as a pear desktop +app. + Run the application using: ```bash @@ -216,4 +231,4 @@ pear init [dir] Here replace `[dir]` with the local template directory path. This can also be a `pear://` link. -This should now initialize a new Pear project from the created template. \ No newline at end of file +This should now initialize a new Pear project from the created template. diff --git a/guide/releasing-a-pear-app.md b/guide/releasing-a-pear-app.md index 4ff5f5e..7be9894 100644 --- a/guide/releasing-a-pear-app.md +++ b/guide/releasing-a-pear-app.md @@ -39,7 +39,7 @@ pear release production ``` -Run `pear release help` for more info on the command. +Run `pear help release` for more info on the command. Keep in mind that changes to an application can only propagate to peers when the application is being seeded: @@ -61,7 +61,7 @@ Opening the application with `pear run ` will **not** output the log, beca The latest staged changes of a released application can be previewed with the `--checkout` flag: ``` -pear run --checkout=staged +pear run --checkout=staged ``` The value of the `--checkout` flag may be `staged`, `released` (the default) or a number referring to a specific version length. diff --git a/guide/sharing-a-pear-app.md b/guide/sharing-a-pear-app.md index e03280f..c298e1e 100644 --- a/guide/sharing-a-pear-app.md +++ b/guide/sharing-a-pear-app.md @@ -85,7 +85,7 @@ As long as the process is running the application is being seeded. If other peer ## Step 4. Run the app on another machine -It's important that the application seeding process from the former step is up and running otherwise peers will not be able to reach connect and replicate state. +It's important that the application seeding process from the former step is up and running otherwise peers will not be able to connect and replicate state. With another machine or friend that has `pear` installed execute the `pear run ` command to load the application directly peer-to-peer. So with the same example application link it would be: @@ -111,7 +111,7 @@ The trust dialog is a security mechanism in Pear that appears when the user trie ![Trust dialog](../assets/trust-dialog.png) -> During development with `pear run --dev`, applications are automatically trusted, as they are assumed to be safe for testing purposes. Trust dialog can be suppressed using the `--no-ask-trust` flag with `pear run` in which case the application will automatically decline unknown keys. +> During development with `pear run --dev`, applications are automatically trusted, as they are assumed to be safe for testing purposes. Trust dialog can be suppressed using the `--no-ask` flag with `pear run` in which case the application will automatically decline unknown keys. The application has no state when it's opened for the first time, so the application may show a loader until it's ready to reveal. diff --git a/guide/starting-a-pear-desktop-project.md b/guide/starting-a-pear-desktop-project.md index 6ce7edc..925cf10 100644 --- a/guide/starting-a-pear-desktop-project.md +++ b/guide/starting-a-pear-desktop-project.md @@ -53,7 +53,7 @@ Now Pear watches project files. When they change, the app is automatically reloa While keeping the `pear run --dev .` command running, open `index.html` in an editor. -Change `

chat

` to `

Hello world

`. +Change `

desktop

` to `

Hello world

`. The app should now show: diff --git a/guide/starting-a-pear-terminal-project.md b/guide/starting-a-pear-terminal-project.md index 87074ad..a0de6bb 100644 --- a/guide/starting-a-pear-terminal-project.md +++ b/guide/starting-a-pear-terminal-project.md @@ -16,6 +16,7 @@ This creates the base project structure. - `package.json`. App configuration. Notice the `pear` property. - `index.js`. App entrypoint. +- `test/index.test.js`. Test skeleton. ## Step 2. Verify Everything Works @@ -27,9 +28,7 @@ pear run --dev . > A directory or link needs to be specified with `pear run`, here `.` denotes the current Project directory. -The app will now run. Note that it will keep running until you exit with `ctrl + c`. - -That's all there is to getting a Pear Terminal project started. +The app will now run. That's all there is to getting a Pear Terminal project started. ## Next diff --git a/howto/connect-to-many-peers-by-topic-with-hyperswarm.md b/howto/connect-to-many-peers-by-topic-with-hyperswarm.md index 039d9ab..07faeb9 100644 --- a/howto/connect-to-many-peers-by-topic-with-hyperswarm.md +++ b/howto/connect-to-many-peers-by-topic-with-hyperswarm.md @@ -4,8 +4,6 @@ In the former example, two peers connected directly using the first peer's publi The [Hyperswarm](../building-blocks/hyperswarm.md) module provides a higher-level interface over the underlying DHT, abstracting away the mechanics of establishing and maintaining connections. Instead, 'join' topics, and the swarm discovers peers automatically. It also handles reconnections in the event of failures. -{% embed url="https://www.youtube.com/watch?v=y2G97xz78gU" %} Build with Pear - Episode 01: Developing with Pear {% embeded %} - In the [How to connect two Peers by key with Hyperdht](./connect-two-peers-by-key-with-hyperdht.md), we needed to explicitly indicate which peer was the server and which was the client. By using Hyperswarm, we create two peers, have them join a common topic, and let the swarm deal with connections. This How-to consists of a single application, `peer-app`. @@ -49,7 +47,7 @@ process.stdin.on('data', d => { }) // Join a common topic -const topic = process.argv[3] ? b4a.from(process.argv[3], 'hex') : crypto.randomBytes(32) +const topic = Pear.config.args[0] ? b4a.from(Pear.config.args[0], 'hex') : crypto.randomBytes(32) const discovery = swarm.join(topic, { client: true, server: true }) // The flushed promise will resolve when the topic has been fully announced to the DHT diff --git a/howto/connect-two-peers-by-key-with-hyperdht.md b/howto/connect-two-peers-by-key-with-hyperdht.md index 0132723..6bcc03d 100644 --- a/howto/connect-two-peers-by-key-with-hyperdht.md +++ b/howto/connect-two-peers-by-key-with-hyperdht.md @@ -67,8 +67,11 @@ import DHT from 'hyperdht' import b4a from 'b4a' import process from 'bare-process' -console.log('Connecting to:', process.argv[3]) -const publicKey = b4a.from(process.argv[3], 'hex') +const key = Pear.config.args[0] +if (!key) throw new Error('provide a key') + +console.log('Connecting to:', key) +const publicKey = b4a.from(key, 'hex') const dht = new DHT() const conn = dht.connect(publicKey) @@ -81,7 +84,7 @@ Pass the key to the client: ``` cd client-app -pear run --dev . -- +pear run --dev . ``` The `client-app` will spin up a client, and the public key copied earlier must be supplied as a command line argument for connecting to the server. The client process will log `got connection` into the console when it connects to the server. diff --git a/howto/create-a-full-peer-to-peer-filesystem-with-hyperdrive.md b/howto/create-a-full-peer-to-peer-filesystem-with-hyperdrive.md index b7f8def..bda28a9 100644 --- a/howto/create-a-full-peer-to-peer-filesystem-with-hyperdrive.md +++ b/howto/create-a-full-peer-to-peer-filesystem-with-hyperdrive.md @@ -2,7 +2,7 @@ [`Hyperdrive`](../building-blocks/hyperdrive.md) is a secure, real-time distributed file system designed for easy peer-to-peer file sharing. In the same way that a Hyperbee is just a wrapper around a Hypercore, a Hyperdrive is a wrapper around two Hypercores: one is a Hyperbee index for storing file metadata, and the other is used to store file contents. -This How-to consists of three applications: `drive-writer-app`, `drive-reader-app` and `bee-reader-app`. +This How-to consists of three applications: `drive-writer-app`, `drive-reader-app` and `drive-bee-reader-app`. Now let's mirror a local directory into a Hyperdrive, replicate it with a reader peer, who then mirrors it into their own local copy. When the writer modifies its drive, by adding, removing, or changing files, the reader's local copy will be updated to reflect that. To do this, we'll use two additional tools: [`MirrorDrive`](../helpers/mirrordrive.md) and [`LocalDrive`](../helpers/localdrive.md), which handle all interactions between Hyperdrives and the local filesystem. @@ -152,30 +152,32 @@ In a new terminal, execute the `drive-reader-app` with `pear run --dev .`, passi ``` cd drive-reader-app -pear run --dev . -- +pear run --dev . ``` `LocalDrive` does not create the directory passed to it until something has been written, so create the `drive-writer-app/writer-dir` (`mkdir writer-dir`) and then add/remove/modify files inside `drive-writer-app/writer-dir` then press `Enter` in the writer's terminal (to import the local changes into the writer's drive). Observe that all new changes mirror into `reader-app/reader-dir`. Just as a Hyperbee is **just** a Hypercore, a Hyperdrive is **just** a Hyperbee - which is **just** a Hypercore. -In a new terminal, create the `bee-reader-app` project with these commands: +In a new terminal, create the `drive-bee-reader-app` project with these commands: ``` -mkdir bee-reader-app -cd bee-reader-app +mkdir drive-bee-reader-app +cd drive-bee-reader-app pear init -y -t terminal -npm install corestore hyperswarm hyperdrive hyperbee b4a bare-process +npm install corestore hyperswarm hyperdrive hyperbee b4a ``` -Adjust the `bee-reader-app/index.js` file to: +Adjust the `drive-bee-reader-app/index.js` file to: ```javascript import Hyperswarm from 'hyperswarm' import Corestore from 'corestore' import Hyperbee from 'hyperbee' import b4a from 'b4a' -import process from 'bare-process' + +const key = Pear.config.args[0] +if (!key) throw new Error('provide a key') // create a Corestore instance const store = new Corestore(Pear.config.storage) @@ -187,7 +189,7 @@ Pear.teardown(() => swarm.destroy()) swarm.on('connection', conn => store.replicate(conn)) // create/get the hypercore instance using the public key supplied as command-line arg -const core = store.get({ key: b4a.from(process.argv[3], 'hex') }) +const core = store.get({ key: b4a.from(key, 'hex') }) // create a hyperbee instance using the hypercore instance const bee = new Hyperbee(core, { @@ -219,13 +221,13 @@ async function listBee () { Now the Hyperdrive can be inspected as though it were a Hyperbee, and log out some file metadata. -Execute the `bee-reader-app` with `pear run --dev .`, passing it the key output by the `driver-writer-app`: +Execute the `drive-bee-reader-app` with `pear run --dev .`, passing it the key output by the `driver-writer-app`: ``` -cd bee-reader-app +cd drive-bee-reader-app pear run --dev . ``` -The `bee-reader-app` creates a Hyperbee instance using the Hypercore instance created with the copied public key. Every time the Hyperbee is updated (an `append` event is emitted on the underlying Hypercore), all file metadata nodes will be logged out. +The `drive-bee-reader-app` creates a Hyperbee instance using the Hypercore instance created with the copied public key. Every time the Hyperbee is updated (an `append` event is emitted on the underlying Hypercore), all file metadata nodes will be logged out. Try adding or removing a few files from the writer's data directory, then pressing `Enter` in the writer's terminal to mirror the changes. diff --git a/howto/replicate-and-persist-with-hypercore.md b/howto/replicate-and-persist-with-hypercore.md index 92d1dee..78d0543 100644 --- a/howto/replicate-and-persist-with-hypercore.md +++ b/howto/replicate-and-persist-with-hypercore.md @@ -28,28 +28,28 @@ npm install bare-path bare-process hypercore hyperswarm b4a Alter the generated `writer-app/index.js` file to the following: ```javascript - import path from 'bare-path' - import process from 'bare-process' - import Hyperswarm from 'hyperswarm' - import Hypercore from 'hypercore' - import b4a from 'b4a' +import path from 'bare-path' +import process from 'bare-process' +import Hyperswarm from 'hyperswarm' +import Hypercore from 'hypercore' +import b4a from 'b4a' - const swarm = new Hyperswarm() - Pear.teardown(() => swarm.destroy()) +const swarm = new Hyperswarm() +Pear.teardown(() => swarm.destroy()) - const core = new Hypercore(path.join(Pear.config.storage, 'writer-storage')) +const core = new Hypercore(path.join(Pear.config.storage, 'writer-storage')) - // core.key and core.discoveryKey will only be set after core.ready resolves - await core.ready() - console.log('hypercore key:', b4a.toString(core.key, 'hex')) +// core.key and core.discoveryKey will only be set after core.ready resolves +await core.ready() +console.log('hypercore key:', b4a.toString(core.key, 'hex')) - // Append all stdin data as separate blocks to the core - process.stdin.on('data', (data) => core.append(data)) +// Append all stdin data as separate blocks to the core +process.stdin.on('data', (data) => core.append(data)) - // core.discoveryKey is *not* a read capability for the core - // It's only used to discover other peers who *might* have the core - swarm.join(core.discoveryKey) - swarm.on('connection', conn => core.replicate(conn)) +// core.discoveryKey is *not* a read capability for the core +// It's only used to discover other peers who *might* have the core +swarm.join(core.discoveryKey) +swarm.on('connection', conn => core.replicate(conn)) ``` @@ -112,7 +112,7 @@ In another terminal, open the `reader-app` and pass it the key: ``` cd reader-app -pear run --dev . -- +pear run --dev . ``` As inputs are made to the terminal running the writer application, outputs should be shown in the terminal running the reader application. diff --git a/howto/share-append-only-databases-with-hyperbee.md b/howto/share-append-only-databases-with-hyperbee.md index 359af41..979910e 100644 --- a/howto/share-append-only-databases-with-hyperbee.md +++ b/howto/share-append-only-databases-with-hyperbee.md @@ -149,12 +149,12 @@ Open the `bee-reader-app` and pass it the core key: ``` cd bee-reader-app -pear run --dev . -- +pear run --dev . ``` Query the database by entering a key to lookup into the `bee-reader-app` terminal and hitting return. -Each application has dedicated storage at `Pear.config.storage`. Try logging out `Pear.config.storage` for the `bee-reader-app` and then look at the disk space for that storage path after each query. Notice that it's significantly smaller than `writer-storage`! This is because Hyperbee only downloads the Hypercore blocks it needs to satisfy each query, a feature we call **sparse downloading.** +Each application has dedicated storage at `Pear.config.storage`. Try logging out `Pear.config.storage` for the `bee-reader-app` and then look at the disk space for that storage path after each query. Notice that it's significantly smaller than `bee-writer-app`! This is because Hyperbee only downloads the Hypercore blocks it needs to satisfy each query, a feature we call **sparse downloading.** Importantly, a Hyperbee is **just** a Hypercore, where the tree nodes are stored as Hypercore blocks. @@ -164,7 +164,7 @@ Finally create a `core-reader-app` project: mkdir core-reader-app cd core-reader-app pear init -y -t terminal -npm install corestore hyperswarm hyperbee b4a bare-process +npm install corestore hyperswarm hyperbee b4a ``` @@ -174,10 +174,12 @@ Alter the generated `core-reader-app/index.js` file to the following import Hyperswarm from 'hyperswarm' import Corestore from 'corestore' import b4a from 'b4a' -import process from 'bare-process' import { Node } from 'hyperbee/lib/messages.js' +const key = Pear.config.args[0] +if (!key) throw new Error('provide a key') + // creation of a corestore instance const store = new Corestore('./reader-storage') @@ -188,7 +190,7 @@ Pear.teardown(() => swarm.destroy()) swarm.on('connection', conn => store.replicate(conn)) // create or get the hypercore using the public key supplied as command-line argument -const core = store.get({ key: b4a.from(process.argv[3], 'hex') }) +const core = store.get({ key: b4a.from(key, 'hex') }) // wait till the properties of the hypercore instance are initialized await core.ready() @@ -212,7 +214,7 @@ Open the `core-reader-app` with `pear run --dev .`, passing the core key to it: ``` cd core-reader-app -pear run --dev . -- +pear run --dev . ``` Now we can examine the Hyperbee as if it were just a Hypercore. diff --git a/reference/pear/cli.md b/reference/pear/cli.md index 5d66570..8d677ae 100644 --- a/reference/pear/cli.md +++ b/reference/pear/cli.md @@ -96,7 +96,6 @@ Run an application from a link or dir. --checkout=n Run a checkout, n is version length --checkout=release Run checkout from marked released length --checkout=staged Run checkout from latest version length - --no-ask-trust Exit instead of asking to trust unknown keys --detached Wakeup existing app or run detached --no-ask Suppress permissions dialogs --help|-h Show help