This commit is contained in:
Raven Scott
2026-02-19 16:12:47 -05:00
parent 4b42e14d98
commit d599843acc
14 changed files with 1784 additions and 22 deletions
+142
View File
@@ -0,0 +1,142 @@
# pear-aliases - Built-in Pear Link Aliases
## Overview
pear-aliases exports a curated set of well-known Pear link aliases and their corresponding Hypercore keys. It also exposes EOL (end-of-line) release lines for selected aliases.
### Key Features
- **Canonical aliases**: Standard names like `pear`, `keet`, `runtime`.
- **Alias resolution**: Maps alias strings to decoded Hypercore keys.
- **EOL tracking**: Lists release line keys for deprecated streams.
- **Simple surface**: Two exports: `ALIASES` and `EOLS`.
### Use Cases
- **Link parsing**: Resolve `pear://alias` to a concrete key.
- **UI labeling**: Display official app names for known keys.
- **Release management**: Identify EOL release lines.
- **Validation**: Restrict to recognized aliases in security-sensitive flows.
## Installation
```bash
npm install pear-aliases
```
## Quick Start
```js
const { ALIASES } = require('pear-aliases')
console.log(!!ALIASES.pear)
```
## Architecture
```mermaid
flowchart TD
A[pear-aliases] --> B[hypercore-id-encoding]
A --> C[ALIASES map]
A --> D[EOLS map]
```
## API Reference
### `const { ALIASES, EOLS } = require('pear-aliases')`
Exports two objects.
### `ALIASES`
Map of alias name -> decoded Hypercore key (Buffer). Known entries include:
- `pear`
- `keet`
- `runtime`
- `doctor`
- `templates`
- `electron`
- `pass`
### `EOLS`
Map of alias name -> array of decoded keys for end-of-line release streams. Current entries include `pear` and `keet`.
## Complete Examples
### Example 1: Resolve an Alias
```js
const { ALIASES } = require('pear-aliases')
const key = ALIASES.pear
console.log(key.toString('hex'))
```
### Example 2: Validate Alias Presence
```js
const { ALIASES } = require('pear-aliases')
function isKnownAlias(name) {
return Object.prototype.hasOwnProperty.call(ALIASES, name)
}
console.log(isKnownAlias('keet'))
```
### Example 3: Check for EOL Release Lines
```js
const { EOLS } = require('pear-aliases')
const eolKeys = EOLS.pear || []
console.log('EOL lines:', eolKeys.length)
```
### Example 4: Integrate with pear-link
```js
const plink = require('pear-link')
const parsed = plink.parse('pear://pear')
console.log(parsed.drive.key)
```
## Best Practices
- **Prefer aliases** for user-facing links when available.
- **Treat unknown aliases as errors** in security-sensitive code.
- **Cache lookups** locally if you access `ALIASES` often.
## Performance Notes
- Constant-time map lookup; negligible overhead.
## Security Considerations
- Alias mappings are authoritative; verify provenance of the package in production.
- Avoid trusting alias names from untrusted input without checking `ALIASES`.
## Integration with Other Modules
### With pear-link
`pear-link` resolves aliases using `pear-aliases`, so you typically do not need to interact with `ALIASES` directly.
### With hypercore-id-encoding
Keys are decoded using `hypercore-id-encoding` for consistency with core ecosystem formats.
## Error Handling
- `pear-aliases` itself does not throw.
- Consumers should handle missing aliases or empty `EOLS` arrays as normal cases.
## License
Apache-2.0
---
**Module Type**: Utility | **Ecosystem Role**: Link Aliases | **Dependencies**: hypercore-id-encoding
+147
View File
@@ -0,0 +1,147 @@
# pear-message - Send Pear App Messages
## Overview
pear-message sends object messages between a Pear application's processes/threads. It publishes messages onto Pear's internal message bus, where they can be received via `pear-messages` using object pattern matching.
### Key Features
- **IPC-based**: Uses Pear runtime IPC to deliver messages.
- **Object payloads**: Send arbitrary JSON-like objects.
- **Pattern routing**: Messages can include matching metadata for receivers.
- **Reference tracking**: Uses `pear-ref` to track IPC lifetime.
### Use Cases
- **App event bus**: Broadcast UI or background events.
- **Cross-process messaging**: Notify background services or workers.
- **Deep-link handling**: Emit events triggered by link actions.
- **Telemetry hooks**: Send structured event objects to listeners.
## Installation
```bash
npm install pear-message
```
## Quick Start
```js
const message = require('pear-message')
await message({ type: 'my-app/ready', data: { ok: true } })
```
## Architecture
```mermaid
flowchart LR
A[Sender] --> B[pear-message]
B --> C[global.Pear IPC]
C --> D[Message bus]
D --> E[pear-messages subscribers]
```
## API Reference
### `const message = require('pear-message')`
Exports a single function.
### `await message(msg) -> any`
Send a message over Pear IPC.
**Parameters:**
- `msg` (object): Arbitrary message payload. Can include a `to` pattern.
**Returns:**
- Value returned by the IPC call (runtime-dependent); usually a tracked ref.
**Throws:**
- Error if IPC is missing: `pear-message is designed for Pear - IPC missing`.
## Complete Examples
### Example 1: Basic Event Message
```js
const message = require('pear-message')
await message({ type: 'my-app/user-login', userId: '123' })
```
### Example 2: Pattern-Targeted Message
```js
const message = require('pear-message')
await message({
type: 'my-app/cta-click',
to: { pattern: ['match', 'against'] }
})
```
### Example 3: Guard for Non-Pear Environments
```js
const message = require('pear-message')
try {
await message({ type: 'my-app/ping' })
} catch (err) {
if (/IPC missing/.test(err.message)) {
console.error('pear-message requires Pear runtime')
} else {
throw err
}
}
```
### Example 4: Pair with pear-messages
```js
const message = require('pear-message')
const messages = require('pear-messages')
messages({ type: 'my-app/log' }, (msg) => console.log(msg))
await message({ type: 'my-app/log', data: { value: 1 } })
```
## Best Practices
- **Use a `type` field** to make pattern routing clear and stable.
- **Keep payloads small** to reduce IPC overhead.
- **Handle IPC absence** when running in non-Pear contexts.
## Performance Notes
- Messaging cost is dominated by IPC serialization; keep objects lightweight.
## Security Considerations
- Do not send secrets in messages unless the receiver is trusted.
- Validate incoming message data on the receiving side.
## Integration with Other Modules
### With pear-messages
`pear-messages` is the standard subscriber side for objects sent by `pear-message`.
### With pear-ref
`pear-message` uses `pear-ref` to track IPC resource lifetimes automatically.
## Error Handling
- Missing IPC throws immediately.
- Runtime-specific IPC errors will surface as rejected promises.
## License
Apache-2.0
---
**Module Type**: Runtime Helper | **Ecosystem Role**: App Messaging | **Dependencies**: pear-ref
+149
View File
@@ -0,0 +1,149 @@
# pear-messages - Receive Pear App Messages
## Overview
pear-messages subscribes to Pear's internal message bus and emits object messages matching a provided pattern. It pairs with `pear-message` to enable cross-process or cross-thread messaging inside a Pear app.
### Key Features
- **Pattern matching**: Match message objects by subset of properties.
- **Stream-based**: Returns an `Iambus` subscriber (Readable stream).
- **Pear lifecycle aware**: Auto-ends on `Pear.teardown`.
- **Listener shortcuts**: Optional listener callback for convenience.
### Use Cases
- **App event bus**: Subscribe to internal events.
- **UI orchestration**: React to background actions.
- **System signals**: Listen for Pear platform messages.
- **Telemetry**: Collect message-based analytics.
## Installation
```bash
npm install pear-messages
```
## Quick Start
```js
const messages = require('pear-messages')
const stream = messages({ type: 'my-app/ready' })
stream.once('data', console.log)
```
## Architecture
```mermaid
flowchart LR
A[pear-message] --> B[IPC bus]
B --> C[pear-messages]
C --> D[Readable stream]
D --> E[App listeners]
```
## API Reference
### `const messages = require('pear-messages')`
Exports a single function.
### `messages(pattern[, listener]) -> Readable`
Subscribe to messages that match `pattern`.
**Parameters:**
- `pattern` (object): Subset of properties to match. Use `{}` or omit for all messages.
- `listener` (function, optional): Called for each matching message.
**Returns:**
- `Readable` (Iambus subscriber) emitting matching message objects.
### `messages(listener)`
If the first argument is a function, it is treated as the listener and a catch-all pattern is used.
**Throws:**
- Error if IPC is missing: `pear-messages is designed for Pear - IPC missing`.
## Complete Examples
### Example 1: Listen with Pattern
```js
const messages = require('pear-messages')
messages({ type: 'pear/wakeup' }, (msg) => {
console.log('wakeup:', msg)
})
```
### Example 2: Catch-all Stream
```js
const messages = require('pear-messages')
for await (const msg of messages()) {
console.log('bus:', msg)
}
```
### Example 3: Pair with pear-message
```js
const message = require('pear-message')
const messages = require('pear-messages')
const clicks = messages({ type: 'my-app/cta' })
clicks.on('data', (msg) => console.log(msg))
await message({ type: 'my-app/cta', data: { id: 1 } })
```
### Example 4: Manual Cleanup
```js
const messages = require('pear-messages')
const stream = messages({ type: 'my-app/once' })
stream.once('data', () => stream.end())
```
## Best Practices
- **Use explicit `type` strings** to avoid collisions.
- **Keep patterns small** for faster matching.
- **Detach listeners** on shutdown if you manage stream lifetimes manually.
## Performance Notes
- Pattern matching is lightweight but scales with message volume.
- Catch-all patterns can be noisy; filter early for hot paths.
## Security Considerations
- Treat message data as untrusted; validate before using.
- Avoid leaking sensitive data into global message streams.
## Integration with Other Modules
### With pear-message
`pear-message` is the producer side; use it to publish messages that `pear-messages` consumes.
### With iambus / streamx
The returned subscriber is a readable stream; it can be piped or consumed via async iteration.
## Error Handling
- Missing IPC throws immediately.
- Stream errors propagate normally via `error` events.
## License
Apache-2.0
---
**Module Type**: Runtime Helper | **Ecosystem Role**: App Messaging | **Dependencies**: pear-ref, iambus
+171
View File
@@ -0,0 +1,171 @@
# pear-opstream - Operation Stream Base Class
## Overview
pear-opstream provides a readable stream wrapper around an async operation function. It standardizes progress status emission and always ends with a `final` status object. Logical operation errors are emitted as status objects rather than thrown as stream errors.
### Key Features
- **Structured status events**: Emits `{ tag, data }` objects.
- **Guaranteed final**: Always emits exactly one `final` status.
- **Logical error reporting**: Emits `tag: 'error'` without necessarily erroring the stream.
- **Link normalization**: Normalizes `params.link` via `pear-link`.
### Use Cases
- **CLI operations**: Stream progress to terminal or JSON output.
- **UI progress reporting**: Drive progress UIs with status events.
- **Composable pipelines**: Pair with `pear-opwait` for promise semantics.
- **Long-running tasks**: Standardize result reporting.
## Installation
```bash
npm install pear-opstream
```
## Quick Start
```js
const Opstream = require('pear-opstream')
const stream = new Opstream(async (params) => {
// do work
})
stream.on('data', console.log)
```
## Architecture
```mermaid
flowchart TD
A[Opstream] --> B[Async op(params)]
B --> C[Status events]
C --> D[{ tag: 'error' }]
C --> E[{ tag: 'final' }]
```
## API Reference
### `const Opstream = require('pear-opstream')`
Exports the `Opstream` class.
### `new Opstream(op, params, done?)`
Create a new operation stream.
**Parameters:**
- `op` (function): Async function `(params) => Promise<any>` executed once when the stream reads.
- `params` (object): Input passed to `op`. If `params.link` exists, it is normalized.
- `done` (function, optional): Called after the final chunk is emitted and the stream ends.
### `instance.final`
Optional object to merge into the final status payload.
**Default:** `{}`
### Emitted Status Objects
- **Error status** (logical failure):
```js
{
tag: 'error',
data: { stack, code, message, success: false, info }
}
```
- **Final status** (always emitted once):
```js
{
tag: 'final',
data: { success, ...final }
}
```
## Complete Examples
### Example 1: Basic Opstream
```js
const Opstream = require('pear-opstream')
const stream = new Opstream(async () => {
// perform work
})
stream.on('data', (status) => console.log(status))
```
### Example 2: Custom Final Payload
```js
const Opstream = require('pear-opstream')
const stream = new Opstream(async () => {
stream.final = { result: 42 }
})
stream.on('data', console.log)
```
### Example 3: Link Normalization
```js
const Opstream = require('pear-opstream')
const stream = new Opstream(async (params) => {
console.log(params.link) // normalized
}, { link: 'pear://app/path/' })
```
### Example 4: Pair with pear-opwait
```js
const Opstream = require('pear-opstream')
const opwait = require('pear-opwait')
const stream = new Opstream(async () => {})
const result = await opwait(stream, (status) => console.log(status.tag))
```
## Best Practices
- **Use `tag` values consistently** (`init`, `progress`, `final`, etc.).
- **Set `this.final`** in subclasses before finishing work.
- **Use `pear-opwait`** when you need promise-style completion.
## Performance Notes
- Overhead is small; statuses are simple objects pushed to the stream.
## Security Considerations
- Do not include sensitive data in status payloads if logs are untrusted.
- Normalize user-provided links to avoid path discrepancies.
## Integration with Other Modules
### With pear-opwait
`pear-opwait` consumes opstreams and resolves the final payload, surfacing errors as promise rejections.
### With pear-link
If `params.link` is provided, it is normalized via `pear-link`.
## Error Handling
- Operation rejections emit an `error` status and still end with `final`.
- Stream-level errors still propagate through `error` events.
## License
Apache-2.0
---
**Module Type**: Utility | **Ecosystem Role**: Operation Reporting | **Dependencies**: streamx, pear-link
+150
View File
@@ -0,0 +1,150 @@
# pear-opwait - Await Opstream Completion
## Overview
pear-opwait turns an opstream into a promise. It watches `{ tag, data }` status objects, resolves with the `final` payload, and converts logical `error` statuses into rejected promises.
### Key Features
- **Promise wrapper**: Resolve on `final`, reject on errors.
- **Status observer**: Optional async hook for each status event.
- **Error translation**: Converts `tag: 'error'` into `ERR_OPERATION_FAILED`.
- **Stream-safe**: Destroys the stream on observer errors.
### Use Cases
- **CLI commands**: Await operations while still logging progress.
- **Programmatic API**: Convert stream-based ops into async/await flows.
- **Testing**: Assert on final results without manual stream handling.
## Installation
```bash
npm install pear-opwait
```
## Quick Start
```js
const opwait = require('pear-opwait')
const Opstream = require('pear-opstream')
const stream = new Opstream(async () => {})
const final = await opwait(stream, (status) => console.log(status.tag))
```
## Architecture
```mermaid
flowchart TD
A[Opstream] --> B[pear-opwait]
B --> C[Observe status events]
C --> D[Resolve final]
C --> E[Reject on error]
```
## API Reference
### `const opwait = require('pear-opwait')`
Exports a single function.
### `opwait(stream[, onstatus]) -> Promise<any>`
Wait for a status-emitting stream to finish.
**Parameters:**
- `stream` (Readable): Emits `{ tag, data }` status objects.
- `onstatus` (function, optional): Called for each status. May be async.
**Behavior:**
- `tag === 'final'` stores the resolution value.
- `tag === 'error'` destroys the stream with `ERR_OPERATION_FAILED`.
- Promise resolves on `end` with last `final` (or `null` if none).
- Promise rejects on `error` events.
## Complete Examples
### Example 1: Await an Opstream
```js
const opwait = require('pear-opwait')
const Opstream = require('pear-opstream')
const stream = new Opstream(async () => {
stream.final = { ok: true }
})
const result = await opwait(stream)
console.log(result.ok)
```
### Example 2: Log Status Events
```js
const opwait = require('pear-opwait')
await opwait(stream, (status) => {
console.log(status.tag, status.data)
})
```
### Example 3: Async Status Observer
```js
const opwait = require('pear-opwait')
await opwait(stream, async (status) => {
if (status.tag === 'progress') {
await writeProgress(status.data)
}
})
```
### Example 4: Handling Operation Failure
```js
const opwait = require('pear-opwait')
try {
await opwait(stream)
} catch (err) {
console.error(err.code, err.message)
}
```
## Best Practices
- **Always attach `onstatus`** if you need progress logs.
- **Avoid heavy work** in `onstatus` to keep streams responsive.
- **Handle rejections** to report meaningful errors to users.
## Performance Notes
- The wrapper does minimal work; overhead is negligible.
## Security Considerations
- Status events may contain sensitive data; avoid logging in untrusted contexts.
## Integration with Other Modules
### With pear-opstream
`pear-opwait` is designed to consume `pear-opstream` status streams.
### With pear-errors
Logical operation failures are wrapped using `ERR_OPERATION_FAILED`.
## Error Handling
- `ERR_OPERATION_FAILED` includes the original status payload as metadata.
- Stream errors propagate directly to the promise rejection.
## License
Apache-2.0
---
**Module Type**: Utility | **Ecosystem Role**: Operation Awaiter | **Dependencies**: pear-errors
+135
View File
@@ -0,0 +1,135 @@
# pear-runtime-appling - Pear Runtime App Shell
## Overview
pear-runtime-appling defines the platform app shell (appling) for the Pear Runtime. It uses `cmake-pear` to generate macOS, Linux, and Windows app artifacts with consistent metadata, signing configuration, and branding assets.
### Key Features
- **Cross-platform app shell**: Generates native app bundles for macOS, Linux, Windows.
- **CMake integration**: Uses `add_pear_appling` to declaratively define metadata.
- **Signing metadata**: Embeds macOS and Windows signing identifiers.
- **Branding assets**: Includes platform-specific icons and splash assets.
### Use Cases
- **Runtime packaging**: Build the Pear Runtime shell for distribution.
- **OEM builds**: Customize metadata for white-label runtime shells.
- **CI release steps**: Produce consistent platform-native app shells.
## Installation
```bash
npm install
```
## Build
```bash
bare-make generate
bare-make build
```
## Architecture
```mermaid
flowchart TD
A[CMakeLists.txt] --> B[cmake-pear]
B --> C[add_pear_appling]
C --> D[Platform app shell]
D --> E[macOS .app]
D --> F[Windows .exe/app]
D --> G[Linux app bundle]
```
## Configuration Reference
The build is defined via `add_pear_appling` in `CMakeLists.txt` with fields:
- `KEY runtime`: Pear link alias for the runtime.
- `NAME "Pear Runtime"`: Human-friendly app name.
- `VERSION 1.0.0`: Shell version (metadata).
- `AUTHOR Holepunch`
- `DESCRIPTION "Pear Runtime"`
- `MACOS_IDENTIFIER com.pears.docs`
- `MACOS_CATEGORY public.app-category.developer-tools`
- `MACOS_SIGNING_IDENTITY ...`
- `WINDOWS_SIGNING_SUBJECT ...`
- `WINDOWS_SIGNING_THUMBPRINT ...`
- `LINUX_CATEGORY Development`
## Complete Examples
### Example 1: Build the Appling
```bash
bare-make generate
bare-make build
```
### Example 2: Customize Metadata (Fork)
```cmake
add_pear_appling(
pear_runtime_appling
KEY runtime
NAME "My Runtime"
VERSION 1.0.1
AUTHOR "Acme"
DESCRIPTION "Acme Runtime"
LINUX_CATEGORY Development
)
```
### Example 3: Replace Icons
Place custom icons in:
- `assets/darwin/icon.png`
- `assets/linux/icon.png`
- `assets/win32/icon.png`
### Example 4: Integrate with pear-runtime-bootstrap
```bash
# pear-runtime-bootstrap will consume build outputs
node build.js
```
## Best Practices
- **Keep metadata stable** for a predictable app identity across releases.
- **Provide platform icons** for consistent UX.
- **Align signing identity** with your distribution certificate.
- **Use CI** to build reproducible, signed shells.
## Performance Notes
- The app shell itself is lightweight; build time is dominated by platform tooling.
## Security Considerations
- Validate signing identity values in CI to avoid unsigned releases.
- Treat signing credentials as secrets and store securely.
## Integration with Other Modules
### With pear-runtime-bootstrap
`pear-runtime-bootstrap` bundles the appling artifacts into platform builds.
### With cmake-pear
The build uses `cmake-pear`'s `add_pear_appling` helper to standardize packaging.
## Error Handling
- Build failures typically come from missing signing tools or CMake setup.
- Check `bare-make` output for platform-specific errors.
## License
Apache-2.0
---
**Module Type**: Build Artifact | **Ecosystem Role**: Runtime Shell | **Dependencies**: cmake-pear
+123
View File
@@ -0,0 +1,123 @@
# pear-runtime-bare - Bare Runtime Host for Pear
## Overview
pear-runtime-bare is a native executable that hosts the Pear runtime on top of the Bare platform. It initializes a dedicated JS platform thread, loads the runtime bundle (preferring `.bundle` if present), and runs the Bare event loop with restart semantics.
### Key Features
- **Bare host executable**: Native binary that boots the Pear runtime.
- **JS platform thread**: Dedicated platform thread for JS engine creation.
- **Bundle resolution**: Loads `boot.bundle` if present, otherwise `boot.js`.
- **Restart loop**: Supports a restart exit code to relaunch the runtime.
- **Resource limits**: Increases open file limits where supported.
### Use Cases
- **Runtime packaging**: Core runtime binary for Pear distributions.
- **Platform boot**: Embedded runtime in appling packaging flows.
- **System integration**: Launchable binary for sidecar or CLI orchestration.
## Build
This module is built using CMake and `bare-dev` tooling:
```bash
bare-make generate
bare-make build
```
## Architecture
```mermaid
flowchart TD
A[pear-runtime-bare] --> B[Initialize platform thread]
B --> C[Create JS platform]
A --> D[Bare loop]
A --> E[Resolve boot.bundle/boot.js]
E --> F[bare_load + bare_run]
F --> G[bare_teardown]
G -->|RESTART_EXIT_CODE| F
```
## Runtime Flow
1. Set file descriptor limits and ignore SIGPIPE.
2. Start a dedicated JS platform thread (`js_create_platform`).
3. Resolve executable path and locate runtime root.
4. Load `boot.bundle` if present, otherwise fallback to `boot.js`.
5. Run the Bare event loop; on restart exit code, repeat.
6. Shutdown platform and exit with the final exit code.
## Build Configuration
Key CMake configuration elements:
- Fetches `bare`, `libpath`, and `librlimit`.
- Links `bare_static` into the executable.
- Applies platform-specific code signing on macOS and Windows.
## Complete Examples
### Example 1: Build the Runtime Binary
```bash
bare-make generate
bare-make build
```
### Example 2: Run the Binary
```bash
./build/pear-runtime
```
### Example 3: Bundle vs JS Boot
```text
runtime-root/
boot.bundle # preferred if present
boot.js # fallback
```
### Example 4: Restart Semantics
If the runtime exits with code `75`, the host restarts the runtime loop.
## Best Practices
- **Ship boot.bundle** for faster startup and fewer file reads.
- **Keep boot.js as fallback** for developer builds.
- **Use signing** for release builds to avoid OS trust warnings.
## Performance Notes
- Startup cost includes JS platform creation and bundle loading.
- Bundled boot can reduce IO and improve cold start.
## Security Considerations
- The runtime loads code from the runtime directory; ensure it is trusted.
- Ensure signing identities and entitlements are correct for distribution.
## Integration with Other Modules
### With pear-runtime-appling
`pear-runtime-bare` is packaged into the runtime app shell produced by `pear-runtime-appling` and bundled by `pear-runtime-bootstrap`.
### With bare
Uses Bare APIs (`bare_setup`, `bare_load`, `bare_run`, `bare_teardown`) to host the runtime.
## Error Handling
- Assertions guard critical failures; in production builds ensure logs capture failures.
- Missing boot files will cause load errors; validate runtime directory layout.
## License
Apache-2.0
---
**Module Type**: Runtime Binary | **Ecosystem Role**: Runtime Host | **Dependencies**: bare, libpath, librlimit
+144
View File
@@ -0,0 +1,144 @@
# pear-runtime-bootstrap - Build and Package Pear Runtime
## Overview
pear-runtime-bootstrap is a small script-based toolchain to build and package the Pear runtime across platforms. It orchestrates `bare-dev` builds for native components, builds the Electron-based runtime app, and assembles a `build/` output directory. It can then pack the build into a gzipped tarball with `by-arch` layout.
### Key Features
- **Multi-component build**: Builds libappling, pear-runtime-bare, wakeup, and electron-runtime.
- **Platform-aware**: Handles macOS, Linux, and Windows layout differences.
- **Packaging**: Produces `build.tar.gz` with `by-arch/<platform-arch>` layout.
- **Minimal entrypoints**: `build.js` and `pack.js` scripts.
### Use Cases
- **Runtime release pipeline**: Build runtime artifacts for distribution.
- **CI packaging**: Produce per-arch bundles for update systems.
- **Developer builds**: Quick local runtime build.
## Installation
```bash
npm install
```
## Build
```bash
node build.js
```
## Pack
```bash
node pack.js
```
## Architecture
```mermaid
flowchart TD
A[build.js] --> B[bare-dev vendor sync]
A --> C[libappling build]
A --> D[pear-runtime-bare build]
A --> E[wakeup build]
A --> F[electron-runtime build]
A --> G[build/ layout]
H[pack.js] --> I[tar.gz output]
```
## Build Output Layout
`build/` contains:
- `build/bin/` (runtime binaries and app bundle)
- `build/lib/` (libappling launch library)
`pack.js` produces `build.tar.gz` with entries under:
```
by-arch/<platform-arch>/...
```
## Script Details
### `build.js`
- Runs `bare-dev vendor sync`.
- Builds:
- `vendor/libappling` (via npm + bare-dev)
- `vendor/pear-runtime-bare` (via bare-dev + CMake install)
- `vendor/wakeup` (via bare-dev + CMake install)
- `vendor/electron-runtime` (via npm dist)
- Copies artifacts into `build/bin` and `build/lib` with platform-specific naming.
### `pack.js`
- Streams `build/` into a gzipped tarball.
- Prefixes all entries with `by-arch/<platform>-<arch>/`.
## Complete Examples
### Example 1: Build on macOS
```bash
npm install
node build.js
```
### Example 2: Package for Distribution
```bash
node pack.js
ls build.tar.gz
```
### Example 3: Inspect Build Output
```bash
ls build/bin
ls build/lib
```
### Example 4: Customizing Artifacts
Fork and adjust `build.js` to alter the output layout or include extra binaries.
## Best Practices
- **Run on target OS** for native artifacts.
- **Use clean build directories** to avoid stale files.
- **Keep vendor submodules in sync** with the runtime version.
## Performance Notes
- Electron runtime builds are the slowest stage.
- Using CI caching for `vendor/` and npm installs significantly reduces build time.
## Security Considerations
- Ensure the build environment is trusted and locked down.
- Verify signing identities for macOS/Windows builds.
## Integration with Other Modules
### With pear-runtime-appling
The appling shell is built in `vendor/` and moved into `build/bin`.
### With pear-updater
The `build.tar.gz` output can be served to the updater for runtime updates.
## Error Handling
- Missing build tools (`bare-dev`, `cmake`, `npm`) will cause failures early.
- Platform mismatches will break artifact path assumptions.
## License
Apache-2.0
---
**Module Type**: Build Tool | **Ecosystem Role**: Runtime Packaging | **Dependencies**: shellblazer, tar-fs, which-runtime
+124
View File
@@ -0,0 +1,124 @@
# pear-tryboot - Sidecar Auto-Start Helper
## Overview
pear-tryboot is a small helper used with `pear-ipc` to auto-start the Pear sidecar if it is not already running. It spawns the runtime binary with `--sidecar` and forwards optional DHT bootstrap arguments.
### Key Features
- **Sidecar spawn**: Launches Pear runtime with `--sidecar`.
- **Argument passthrough**: Forwards `--dht-bootstrap` when present.
- **Portable**: Uses `bare-daemon` to spawn detached processes.
### Use Cases
- **IPC auto-connect**: Ensure sidecar is running before IPC connection.
- **CLI tools**: Start Pear runtime on-demand.
- **Desktop integrations**: Launch sidecar in the background.
## Installation
```bash
npm install pear-tryboot
```
## Quick Start
```js
const IPC = require('pear-ipc')
const tryboot = require('pear-tryboot')
const client = new IPC.Client({
socketPath: '/tmp/pear.sock',
connect: tryboot
})
```
## Architecture
```mermaid
flowchart LR
A[IPC connect] --> B[pear-tryboot]
B --> C[bare-daemon.spawn]
C --> D[Pear runtime --sidecar]
```
## API Reference
### `const tryboot = require('pear-tryboot')`
Exports a single function.
### `tryboot()`
Spawns the Pear runtime sidecar using `bare-daemon`.
**Behavior:**
- Uses `pear-constants` for `RUNTIME` binary and `PLATFORM_DIR`.
- Adds `--sidecar` to args.
- If `--dht-bootstrap` is present in argv, forwards it to the runtime.
## Complete Examples
### Example 1: Basic Sidecar Spawn
```js
const tryboot = require('pear-tryboot')
tryboot()
```
### Example 2: With pear-ipc Client
```js
const IPC = require('pear-ipc')
const tryboot = require('pear-tryboot')
const client = new IPC.Client({
socketPath: '/tmp/pear.sock',
connect: tryboot
})
```
### Example 3: CLI Context with DHT Bootstrap
```bash
pear --dht-bootstrap 1.2.3.4:49737
```
In this case, `pear-tryboot` forwards the `--dht-bootstrap` arg.
## Best Practices
- **Use only for Pear runtime**; it assumes Pear sidecar semantics.
- **Pass socket path** via IPC settings, not via tryboot.
- **Avoid double-spawning** by using `pear-ipc` connection checks.
## Performance Notes
- Spawn cost is OS-dependent; it is intended for cold-start scenarios.
## Security Considerations
- Ensure the runtime binary path is trusted (`pear-constants`).
- Be careful passing bootstrap nodes from untrusted input.
## Integration with Other Modules
### With pear-ipc
`pear-tryboot` is designed to be passed as the `connect` handler for `pear-ipc` clients.
### With pear-constants
Uses `RUNTIME` and `PLATFORM_DIR` to locate the runtime binary and working directory.
## Error Handling
- Errors from `bare-daemon.spawn` may surface if the runtime is missing or permissions are insufficient.
## License
Apache-2.0
---
**Module Type**: Utility | **Ecosystem Role**: Sidecar Boot | **Dependencies**: bare-daemon, pear-constants
+139
View File
@@ -0,0 +1,139 @@
# pear-updater-bootstrap - Bootstrap Runtime Updates
## Overview
pear-updater-bootstrap bootstraps the Pear runtime updater from a known drive key. It sets up a Corestore + Hyperdrive, joins Hyperswarm to replicate updates, waits for the first valid checkout, and applies the update locally. It also provides a CLI and a device-file validation helper.
### Key Features
- **One-shot bootstrap**: Downloads enough data to apply the first update.
- **Swarm replication**: Uses Hyperswarm to replicate the runtime drive.
- **Lock and swap support**: Optional locking and swap handling.
- **CLI interface**: Simple `pear-updater-bootstrap <key> <dir>`.
- **Validation**: Checks the platform Corestore device file.
### Use Cases
- **First-time install**: Populate runtime files on a new system.
- **Recovery tooling**: Rebuild the runtime directory from a key.
- **CI images**: Prepopulate runtime on build machines.
## Installation
```bash
npm install pear-updater-bootstrap
```
## Quick Start
```js
const bootstrap = require('pear-updater-bootstrap')
await bootstrap(key, '/opt/pear')
```
## CLI
```bash
pear-updater-bootstrap <key> <platform-dir>
```
## Architecture
```mermaid
flowchart TD
A[bootstrap()] --> B[Corestore + Hyperdrive]
A --> C[PearUpdater]
A --> D[Hyperswarm join]
D --> E[Replicate data]
A --> F[u.wait(min length)]
A --> G[u.applyUpdate()]
```
## API Reference
### `await bootstrap(key, directory = 'pear', opts)`
**Parameters:**
- `key` (string|Buffer, required): Drive key for runtime updates.
- `directory` (string): Platform directory (default `pear`).
- `opts.lock` (boolean): Create lock file (default true).
- `opts.bootstrap` (array): Hyperswarm bootstrap nodes.
- `opts.onupdater` (function): Callback with updater instance.
- `opts.onapply` (function): Called before apply.
- `opts.length` (number): Initial checkout length.
- `opts.fork` (number): Initial checkout fork.
- `opts.force` (boolean): Force update even if current exists.
- `opts.host` (string): Override host triplet.
### `bootstrap.validate(directory) -> Promise<boolean>`
Validates the Corestore device file in the platform directory.
## Complete Examples
### Example 1: Basic Bootstrap
```js
await bootstrap('pzcjqm...')
```
### Example 2: Custom Platform Directory
```js
await bootstrap('pzcjqm...', '/opt/pear-runtime')
```
### Example 3: Custom Bootstrap Nodes
```js
await bootstrap('pzcjqm...', '/opt/pear', {
bootstrap: [{ host: '1.2.3.4', port: 49737 }]
})
```
### Example 4: Validate Platform Directory
```js
const ok = await bootstrap.validate('/opt/pear')
console.log('valid', ok)
```
## Best Practices
- **Provide a stable directory** to avoid conflicting installs.
- **Use lockfiles** when multiple processes may bootstrap.
- **Close resources** if you wrap `bootstrap` in higher-level flows.
## Performance Notes
- Initial bootstrap downloads only what is needed to reach the first checkout.
- Network latency dominates the first update on cold installs.
## Security Considerations
- Only use trusted keys; updates are not automatically signed here.
- Restrict bootstrap nodes if you operate on private networks.
## Integration with Other Modules
### With pear-updater
Internally constructs `pear-updater` and uses `wait` + `applyUpdate`.
### With hyperswarm
Uses Hyperswarm to replicate the runtime drive from peers.
## Error Handling
- Missing `key` throws immediately.
- Network issues can prevent reaching the first checkout.
- Filesystem errors surface during swap or lock creation.
## License
Apache-2.0
---
**Module Type**: Bootstrap Tool | **Ecosystem Role**: Runtime Install | **Dependencies**: hyperdrive, hyperswarm, pear-updater
+182
View File
@@ -0,0 +1,182 @@
# pear-updater - Runtime Update Engine
## Overview
pear-updater is the update engine used by the Pear runtime. It watches a Hyperdrive for new releases, downloads required assets, bundles the runtime entrypoint, manages per-arch swap directories, and applies updates atomically. It exposes progress metrics and a stream-based watch API for update events.
### Key Features
- **Drive-backed updates**: Watches a Hyperdrive for new checkouts.
- **Per-arch updates**: Supports `by-arch/<host>` layouts.
- **Atomic swaps**: Updates swap directories and symlinks safely.
- **Bundling**: Produces `.bundle` files via `drive-bundler` and `bare-bundle`.
- **Progress metrics**: Tracks downloaded/uploaded blocks and speed.
### Use Cases
- **Runtime self-update**: Apply updates in the Pear runtime.
- **Custom update services**: Embed into other updatable runtimes.
- **CI/CD deploy**: Automate runtime release channels.
## Installation
```bash
npm install pear-updater
```
## Quick Start
```js
const PearUpdater = require('pear-updater')
const updater = new PearUpdater(drive, {
directory: '/opt/pear',
swap: '/opt/pear/current/0',
checkout: { key, length: 0, fork: 0 }
})
updater.on('update', (checkout) => console.log('updated', checkout))
await updater.update()
await updater.applyUpdate()
```
## Architecture
```mermaid
flowchart TD
A[Hyperdrive] --> B[PearUpdater]
B --> C[watch() stream]
B --> D[update()]
D --> E[download by-arch assets]
D --> F[bundle entrypoint]
D --> G[swap directory]
B --> H[applyUpdate()]
H --> I[atomic symlink/rename]
```
## API Reference
### `new PearUpdater(drive, opts)`
**Parameters:**
- `drive` (Hyperdrive): Drive containing runtime bundles and assets.
- `opts.directory` (string, required): Base runtime directory.
- `opts.checkout` (object): Current checkout `{ key, length, fork }`.
- `opts.swap` (string): Swap directory path.
- `opts.lock` (string|null): Lockfile path for update synchronization.
- `opts.host` (string): Host triplet (default `platform-arch`).
- `opts.byArch` (boolean): Use `by-arch/<host>` layout (default true).
- `opts.force` (boolean): Force update even if checkout unchanged.
- Hooks: `onupdating`, `onupdate`, `onapply` (async callbacks).
### `await updater.update()`
Fetch and prepare the latest update. Emits `updating` and `update` events.
### `await updater.applyUpdate()`
Apply a prepared update atomically. Returns checkout or `null` if none.
### `updater.watch(opts) -> Readable`
Stream of checkout objects as updates land.
### `await updater.wait(minCheckout, opts)`
Wait until a checkout reaches a minimum `{ length, fork }`.
### Status and Metrics
- `updater.status`: `waiting`, `updating-assets`, `updating-bundle`, `updated`.
- `downloadedBlocks`, `downloadedBlocksEstimate`.
- `downloadedBytes`, `downloadSpeed()`.
- `uploadedBlocks`, `uploadedBytes`, `uploadSpeed()`.
- `downloadProgress` (0..1; capped at 0.9 while downloading).
## Events
- `updating(checkout, old)`
- `update(checkout, old)`
- `update-applied(checkout)`
## Complete Examples
### Example 1: Watch for Updates
```js
for await (const checkout of updater.watch()) {
console.log('new checkout', checkout)
}
```
### Example 2: Wait for Minimum Version
```js
await updater.wait({ length: 100, fork: 0 })
```
### Example 3: Observe Progress
```js
updater.on('updating', () => {
console.log('status', updater.status)
})
const interval = setInterval(() => {
console.log('download', updater.downloadProgress)
}, 500)
updater.on('update', () => clearInterval(interval))
```
### Example 4: Custom Hooks
```js
const updater = new PearUpdater(drive, {
directory: '/opt/pear',
onupdating: async () => console.log('pre-update'),
onupdate: async () => console.log('post-update'),
onapply: async () => console.log('apply')
})
```
## Best Practices
- **Provide a lockfile** to prevent multiple updaters from racing.
- **Use by-arch layout** to minimize update size.
- **Call `applyUpdate`** only after `update` completed.
- **Observe `update` events** for reactive UI or logging.
## Performance Notes
- `by-arch` diffs limit downloads to changed blobs.
- Large updates can trigger a full mirror fallback.
- Bundling uses `drive-bundler` and `bare-bundle` and may be CPU-heavy.
## Security Considerations
- Ensure the drive content is trusted (sign or verify checkouts externally).
- Avoid downgrades; updater enforces ABI compatibility and prevents rollback.
## Integration with Other Modules
### With pear-updater-bootstrap
`pear-updater-bootstrap` sets up a Hyperdrive and invokes `pear-updater` to perform the first update.
### With drive-bundler
`drive-bundler` creates runtime bundles used to boot the updated runtime.
## Error Handling
- Missing `directory` throws on construction.
- ABI incompatibility throws when no compatible update exists.
- Filesystem errors surface during swap updates or bundle writes.
## License
Apache-2.0
---
**Module Type**: Runtime Service | **Ecosystem Role**: Updater | **Dependencies**: drive-bundler, bare-bundle, localdrive
+154
View File
@@ -0,0 +1,154 @@
# pear-wakeups - Pear Wakeup Event Stream
## Overview
pear-wakeups provides a stream of wakeup events inside a Pear application. Wakeups are triggered by trusted `pear://` link clicks or detached runs, and include metadata such as link fragments and entrypoints. The module is a thin wrapper over `pear-messages` with a `type: 'pear/wakeup'` pattern.
### Key Features
- **Wakeup stream**: Listen for app wakeup events.
- **IPC-based**: Uses Pear runtime IPC.
- **Simple API**: Returns a readable stream or accepts a listener.
- **Standard payload**: Consistent `wakeup` object shape.
### Use Cases
- **Deep-link handling**: React to external link clicks.
- **Detached run signals**: Handle `pear run --detached` wakeups.
- **App focus events**: Use wakeups to bring UI to foreground.
## Installation
```bash
npm install pear-wakeups
```
## Quick Start
```js
const wakeups = require('pear-wakeups')
wakeups((wakeup) => {
console.log(wakeup.link, wakeup.entrypoint)
})
```
## Architecture
```mermaid
flowchart LR
A[Platform wakeup] --> B[pear-message bus]
B --> C[pear-wakeups]
C --> D[Readable stream]
```
## API Reference
### `const wakeups = require('pear-wakeups')`
Exports a single function.
### `wakeups([listener]) -> Readable`
Subscribe to wakeup events.
**Parameters:**
- `listener` (function, optional): Called for each wakeup.
**Returns:**
- `Readable` stream emitting wakeup objects.
**Throws:**
- Error if IPC is missing: `pear-wakeups is designed for Pear - IPC missing`.
## Wakeup Object Shape
```js
{
type: 'pear/wakeup',
link: <String>,
linkData: <String>,
fragment: <String>,
entrypoint: <String>
}
```
## Complete Examples
### Example 1: Stream Listener
```js
const wakeups = require('pear-wakeups')
const stream = wakeups()
stream.on('data', (w) => console.log('wakeup', w))
```
### Example 2: Listener Shortcut
```js
const wakeups = require('pear-wakeups')
wakeups((w) => {
console.log('link', w.link)
})
```
### Example 3: Parse Wakeup Link Data
```js
const wakeups = require('pear-wakeups')
wakeups((w) => {
const parts = w.linkData?.split('/') || []
console.log('entry', parts[0])
})
```
### Example 4: Pair with pear-link
```js
const wakeups = require('pear-wakeups')
const plink = require('pear-link')
wakeups((w) => {
const parsed = plink.parse(w.link)
console.log(parsed.drive.key)
})
```
## Best Practices
- **Filter by entrypoint** if multiple routes exist.
- **Normalize links** using `pear-link` when comparing wakeup links.
- **Avoid heavy work** in the listener to keep wakeup handling responsive.
## Performance Notes
- Wakeup events are low volume and lightweight.
## Security Considerations
- Treat wakeup payloads as untrusted; validate link data.
- Only trusted `pear://` links should trigger wakeups.
## Integration with Other Modules
### With pear-messages
`pear-wakeups` uses `pear-messages` with `{ type: 'pear/wakeup' }`.
### With pear-link
Parse wakeup `link` values for routing and metadata.
## Error Handling
- Missing IPC throws immediately; ensure you run inside Pear runtime.
## License
Apache-2.0
---
**Module Type**: Runtime Helper | **Ecosystem Role**: Wakeup Events | **Dependencies**: pear-messages