update
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
# pear-appdrive - Pear Application Drive
|
||||
|
||||
## Overview
|
||||
|
||||
pear-appdrive provides a read-only, minimal Hyperdrive-compatible class for Pear applications. It allows apps to read their packaged files.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install pear-appdrive
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
import AppDrive from 'pear-appdrive'
|
||||
|
||||
const drive = new AppDrive()
|
||||
await drive.ready()
|
||||
|
||||
const file = await drive.get('/file/from/app')
|
||||
console.log(file.toString())
|
||||
|
||||
await drive.close()
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Read-only
|
||||
- Minimal Hyperdrive compatibility
|
||||
|
||||
## License
|
||||
|
||||
Apache-2.0
|
||||
|
||||
---
|
||||
**Module Type**: Runtime | **Ecosystem Role**: App Filesystem | **Dependencies**: hyperdrive
|
||||
@@ -0,0 +1,26 @@
|
||||
# pear-appling - Pear Appling Template
|
||||
|
||||
## Overview
|
||||
|
||||
pear-appling is a template repository for creating Pear applings. It includes a CMake-based build flow.
|
||||
|
||||
## Building
|
||||
|
||||
```bash
|
||||
npm i -g bare-make
|
||||
npm i
|
||||
bare-make generate
|
||||
bare-make build
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Replace placeholders in `CMakeLists.txt`
|
||||
- Use with cmake-pear for packaging
|
||||
|
||||
## License
|
||||
|
||||
Apache-2.0
|
||||
|
||||
---
|
||||
**Module Type**: Template | **Ecosystem Role**: App Scaffold | **Dependencies**: bare-make
|
||||
@@ -0,0 +1,57 @@
|
||||
# pear-bridge - Local HTTP Bridge for Pear UI
|
||||
|
||||
## Overview
|
||||
|
||||
pear-bridge provides a local HTTP bridge for Pear desktop applications, used with Pear UI runtimes like pear-electron. It serves UI assets and routes requests.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install pear-bridge
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
```js
|
||||
import Runtime from 'pear-electron'
|
||||
import Bridge from 'pear-bridge'
|
||||
|
||||
const runtime = new Runtime()
|
||||
await runtime.ready()
|
||||
|
||||
const server = new Bridge()
|
||||
await server.ready()
|
||||
|
||||
const pipe = runtime.start({ info: server.info() })
|
||||
Pear.teardown(() => pipe.end())
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `new Bridge(opts)`
|
||||
|
||||
**Options:**
|
||||
- `mount` (string): Mount path for lookups
|
||||
- `waypoint` (string): Catch-all HTML path (relative to mount)
|
||||
- `bypass` (array): Mount bypass paths (default: ['/node_modules'])
|
||||
|
||||
### Methods
|
||||
|
||||
- `ready()` - Wait for server to listen
|
||||
- `close()` - Close server
|
||||
|
||||
### Properties
|
||||
|
||||
- `closed`, `opened`, `closing`, `opening`
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Use `waypoint` for SPA routing
|
||||
- Limit `bypass` to required paths
|
||||
|
||||
## License
|
||||
|
||||
Apache-2.0
|
||||
|
||||
---
|
||||
**Module Type**: Runtime | **Ecosystem Role**: UI Bridge | **Dependencies**: pear
|
||||
@@ -0,0 +1,196 @@
|
||||
# pear-build - Build Appling Artifacts for Pear Apps
|
||||
|
||||
## Overview
|
||||
|
||||
pear-build builds the app shell (appling) for a Pear application. It wraps `bare-build` in a structured operation stream so callers can observe progress and integrate build status into CLIs or UIs.
|
||||
|
||||
### Key Features
|
||||
|
||||
- **Opstream output**: Structured progress events (`init`, `build`, `complete`).
|
||||
- **Appling aware**: Reads `.pear/appling` metadata and builds a platform-specific target.
|
||||
- **Cross-platform defaults**: Automatically picks the host (`platform-arch`) and icon format.
|
||||
- **Build pipeline reuse**: Delegates the heavy work to `bare-build`.
|
||||
- **Pear-friendly**: Uses Pear conventions (appling layout, metadata, entitlements).
|
||||
|
||||
### Use Cases
|
||||
|
||||
- **CLI build commands**: Emit progress events without bespoke logging.
|
||||
- **CI packaging**: Build the app shell as part of release artifacts.
|
||||
- **Developer tooling**: Provide real-time build status in a UI.
|
||||
- **Custom installers**: Generate appling outputs for bundlers.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install pear-build
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
```js
|
||||
const build = require('pear-build')
|
||||
const path = require('bare-path')
|
||||
|
||||
const dotPear = path.join(process.cwd(), '.pear')
|
||||
const stream = build({ dotPear })
|
||||
|
||||
stream.on('data', (info) => {
|
||||
console.log(info.tag, info.data)
|
||||
})
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Caller] -->|build({ dotPear })| B[pear-build]
|
||||
B --> C[pear-opstream]
|
||||
B --> D[Read .pear/appling/package.json]
|
||||
B --> E[Resolve host + paths]
|
||||
B --> F[bare-build]
|
||||
F --> G[Target artifacts]
|
||||
C --> H[Progress events]
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `const build = require('pear-build')`
|
||||
|
||||
Exports a single function.
|
||||
|
||||
### `build({ dotPear }) -> Opstream`
|
||||
|
||||
Start a build for the appling located under `.pear`.
|
||||
|
||||
**Parameters:**
|
||||
- `dotPear` (string, required): Path to the `.pear` directory.
|
||||
|
||||
**Returns:**
|
||||
- `Opstream`: emits structured progress objects on `data`.
|
||||
|
||||
**Event Payloads (via `data`):**
|
||||
- `{ tag: 'init', data: { dotPear } }`
|
||||
- `{ tag: 'build', data: { target } }`
|
||||
- `{ tag: 'complete' }`
|
||||
|
||||
**Behavior Notes:**
|
||||
- Reads `.pear/appling/package.json` and expects `pear.build` metadata.
|
||||
- Uses `which-runtime` to compute `host` and build target.
|
||||
- Uses `bare-build` with `standalone: false` and `sign: false`.
|
||||
|
||||
## Complete Examples
|
||||
|
||||
### Example 1: Build and Print Progress
|
||||
|
||||
```js
|
||||
const build = require('pear-build')
|
||||
const path = require('bare-path')
|
||||
|
||||
const stream = build({ dotPear: path.join(process.cwd(), '.pear') })
|
||||
|
||||
stream.on('data', ({ tag, data }) => {
|
||||
if (tag === 'build') console.log('Target:', data.target)
|
||||
if (tag === 'complete') console.log('Build finished')
|
||||
})
|
||||
```
|
||||
|
||||
### Example 2: Integrate with a Logger
|
||||
|
||||
```js
|
||||
const build = require('pear-build')
|
||||
const path = require('bare-path')
|
||||
const pino = require('pino')
|
||||
const log = pino()
|
||||
|
||||
const stream = build({ dotPear: path.join(process.cwd(), '.pear') })
|
||||
stream.on('data', (info) => log.info(info))
|
||||
```
|
||||
|
||||
### Example 3: Surface Errors in a CLI
|
||||
|
||||
```js
|
||||
const build = require('pear-build')
|
||||
|
||||
const stream = build({ dotPear: './.pear' })
|
||||
stream.on('data', (evt) => console.log(evt.tag))
|
||||
stream.on('error', (err) => {
|
||||
console.error('Build failed:', err.message)
|
||||
process.exitCode = 1
|
||||
})
|
||||
```
|
||||
|
||||
### Example 4: Custom Output Location Awareness
|
||||
|
||||
```js
|
||||
const build = require('pear-build')
|
||||
|
||||
const stream = build({ dotPear: '/apps/hello/.pear' })
|
||||
stream.on('data', (evt) => {
|
||||
if (evt.tag === 'build') {
|
||||
console.log('Artifacts in:', evt.data.target)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
- **Validate `.pear` layout** before building; ensure `.pear/appling/package.json` exists.
|
||||
- **Listen for `error`** on the Opstream in CI to fail fast.
|
||||
- **Prefer structured logs** by printing `tag` and `data` fields.
|
||||
- **Run builds on matching host** to avoid unsupported targets.
|
||||
|
||||
## Performance Notes
|
||||
|
||||
- Build time depends on the size of the appling and native addons.
|
||||
- Repeated builds are best handled via upstream caching in CI.
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- Appling builds can execute build hooks; only build trusted app sources.
|
||||
- If distributing artifacts, verify provenance (signing handled outside pear-build).
|
||||
|
||||
## Integration with Other Modules
|
||||
|
||||
### With pear-bundle and pear-pack
|
||||
|
||||
```js
|
||||
const build = require('pear-build')
|
||||
const bundle = require('pear-bundle')
|
||||
|
||||
const stream = build({ dotPear: './.pear' })
|
||||
stream.on('data', async (evt) => {
|
||||
if (evt.tag === 'complete') {
|
||||
const packed = await bundle({ cache: true })
|
||||
console.log('Bundle size:', packed.bundle.byteLength)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### With pear-opstream Consumers
|
||||
|
||||
```js
|
||||
const build = require('pear-build')
|
||||
|
||||
const stream = build({ dotPear: './.pear' })
|
||||
stream.on('data', (evt) => {
|
||||
// forward to UI progress channel
|
||||
process.send?.(evt)
|
||||
})
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
Common failures include:
|
||||
|
||||
- **Missing appling metadata**: `.pear/appling/package.json` missing or invalid.
|
||||
- **Unsupported platform**: `which-runtime` returns a host not supported by appling.
|
||||
- **Filesystem errors**: insufficient permissions for `.pear/target`.
|
||||
|
||||
Handle these by attaching `error` handlers to the returned stream.
|
||||
|
||||
## License
|
||||
|
||||
Apache-2.0
|
||||
|
||||
---
|
||||
**Module Type**: Build Tool | **Ecosystem Role**: Pear Packaging | **Dependencies**: bare-build, pear-opstream
|
||||
@@ -0,0 +1,172 @@
|
||||
# pear-bundle - IPC Bundle Builder for Pear Apps
|
||||
|
||||
## Overview
|
||||
|
||||
pear-bundle requests a bundle from the Pear runtime over IPC. It is designed to run inside a Pear environment and returns a tracked reference to the bundle result, including the compiled bundle buffer and prebuilds.
|
||||
|
||||
### Key Features
|
||||
|
||||
- **Pear-aware**: Requires Pear IPC to be present at runtime.
|
||||
- **Simple API**: Single `bundle(opts)` entry point.
|
||||
- **Reference tracking**: Uses `pear-ref` to track the IPC resource lifecycle.
|
||||
- **Consistent options**: Accepts options compatible with `pear-pack` (plus caching).
|
||||
|
||||
### Use Cases
|
||||
|
||||
- **In-app bundling**: Generate bundles from within a Pear app.
|
||||
- **CLI tooling**: Delegate bundle creation to the Pear runtime.
|
||||
- **Caching**: Reuse cached bundles for faster rebuilds.
|
||||
- **Packaging pipelines**: Connect IPC bundles to release steps.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install pear-bundle
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
```js
|
||||
const bundle = require('pear-bundle')
|
||||
|
||||
const packed = await bundle({ cache: true, entry: '/boot.js' })
|
||||
console.log('Bundle bytes:', packed.bundle.byteLength)
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A[App code] --> B[pear-bundle]
|
||||
B --> C[global.Pear IPC]
|
||||
C --> D[Pear runtime]
|
||||
D --> E[Bundle + prebuilds]
|
||||
B --> F[pear-ref tracking]
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `const bundle = require('pear-bundle')`
|
||||
|
||||
Exports a single function.
|
||||
|
||||
### `await bundle(opts) -> { bundle, prebuilds, assets? }`
|
||||
|
||||
Request a bundle over Pear IPC.
|
||||
|
||||
**Parameters:**
|
||||
- `opts` (object): Options aligned with `pear-pack` (except `target`) plus `cache`.
|
||||
|
||||
**Common Options:**
|
||||
- `entry` (string): Bundle entrypoint (default `/boot.js`).
|
||||
- `builtins` (string[]): Builtins to include.
|
||||
- `hosts` (string[]): Host triplets (e.g. `darwin-arm64`).
|
||||
- `cache` (boolean): Cache bundle on disk instead of rebuilding.
|
||||
|
||||
**Returns:**
|
||||
- Object with `bundle` (Buffer) and `prebuilds` (Map). Some runtimes also return `assets` (Map).
|
||||
|
||||
**Throws:**
|
||||
- Error if IPC is missing: `pear-bundle is designed for Pear - IPC missing`.
|
||||
|
||||
## Complete Examples
|
||||
|
||||
### Example 1: Basic Bundle
|
||||
|
||||
```js
|
||||
const bundle = require('pear-bundle')
|
||||
|
||||
const packed = await bundle({ entry: '/boot.js' })
|
||||
console.log(packed.prebuilds.size)
|
||||
```
|
||||
|
||||
### Example 2: Enable Caching
|
||||
|
||||
```js
|
||||
const bundle = require('pear-bundle')
|
||||
|
||||
const packed = await bundle({ cache: true })
|
||||
console.log('Bundle cached, size:', packed.bundle.byteLength)
|
||||
```
|
||||
|
||||
### Example 3: Multi-host Build
|
||||
|
||||
```js
|
||||
const bundle = require('pear-bundle')
|
||||
|
||||
const packed = await bundle({
|
||||
hosts: ['darwin-arm64', 'linux-x64'],
|
||||
entry: '/boot.js'
|
||||
})
|
||||
```
|
||||
|
||||
### Example 4: Guard for Non-Pear Environments
|
||||
|
||||
```js
|
||||
const bundle = require('pear-bundle')
|
||||
|
||||
try {
|
||||
const packed = await bundle({ entry: '/boot.js' })
|
||||
console.log('OK', packed.bundle.byteLength)
|
||||
} catch (err) {
|
||||
if (/IPC missing/.test(err.message)) {
|
||||
console.error('Run inside Pear runtime')
|
||||
} else {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
- **Use in Pear runtime only**; check `global.Pear` if needed.
|
||||
- **Cache in CI** to speed up repeated builds.
|
||||
- **Pin hosts** when building for release to avoid accidental host mismatch.
|
||||
- **Persist bundles** after building to avoid IPC re-runs.
|
||||
|
||||
## Performance Notes
|
||||
|
||||
- IPC call overhead is small compared to bundle generation.
|
||||
- Caching can reduce builds from seconds to milliseconds.
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- IPC implies trust in the local Pear runtime; avoid untrusted IPC endpoints.
|
||||
- Validate bundle provenance before distribution.
|
||||
|
||||
## Integration with Other Modules
|
||||
|
||||
### With pear-pack
|
||||
|
||||
If you need to bundle outside Pear, use `pear-pack` with a drive:
|
||||
|
||||
```js
|
||||
const pack = require('pear-pack')
|
||||
// pack(drive, opts) for offline or custom bundling
|
||||
```
|
||||
|
||||
### With pear-build
|
||||
|
||||
```js
|
||||
const build = require('pear-build')
|
||||
const bundle = require('pear-bundle')
|
||||
|
||||
const stream = build({ dotPear: './.pear' })
|
||||
stream.on('data', async (evt) => {
|
||||
if (evt.tag === 'complete') await bundle({ cache: true })
|
||||
})
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
- **IPC missing**: Ensure the code runs in Pear runtime.
|
||||
- **Bundle errors**: Underlying runtime might reject invalid options or missing entry.
|
||||
|
||||
Handle with `try/catch` around `await bundle(...)` and surface useful diagnostics.
|
||||
|
||||
## License
|
||||
|
||||
Apache-2.0
|
||||
|
||||
---
|
||||
**Module Type**: Runtime Helper | **Ecosystem Role**: Pear Packaging | **Dependencies**: pear-ref
|
||||
@@ -0,0 +1,177 @@
|
||||
# pear-cmd - Pear Command Parser and Definitions
|
||||
|
||||
## Overview
|
||||
|
||||
pear-cmd provides the command parser and command definitions for the Pear CLI. It builds on `paparam` to parse arguments, expose common flags, and ship reusable definitions for the top-level `pear` command and `pear run` subcommand.
|
||||
|
||||
### Key Features
|
||||
|
||||
- **Unified parsing**: Single entry point for Pear CLI argument parsing.
|
||||
- **Reusable definitions**: Exposes `pear` and `run` command definitions.
|
||||
- **Paparam-based**: Lean declarative argument and flag specification.
|
||||
- **Hidden flags**: Includes advanced and legacy flags for compatibility.
|
||||
|
||||
### Use Cases
|
||||
|
||||
- **CLI implementation**: Parse args for `pear` commands.
|
||||
- **Embedding**: Reuse definitions in custom wrappers or tooling.
|
||||
- **Validation**: Standardize error messages and usage output.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install pear-cmd
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
```js
|
||||
const cmd = require('pear-cmd')
|
||||
|
||||
const parsed = cmd(process.argv.slice(2))
|
||||
console.log(parsed)
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[argv array] --> B[pear-cmd]
|
||||
B --> C[paparam command builder]
|
||||
C --> D[pear definitions]
|
||||
C --> E[run definitions]
|
||||
C --> F[parsed command object]
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `const cmd = require('pear-cmd')`
|
||||
|
||||
Returns a function that parses argv arrays.
|
||||
|
||||
### `cmd(argv) -> paparam.command`
|
||||
|
||||
Parse an argv array using Pear's command definition.
|
||||
|
||||
**Parameters:**
|
||||
- `argv` (string[]): Argument list (e.g. `process.argv.slice(2)`).
|
||||
|
||||
**Returns:**
|
||||
- `paparam.command`: Parsed command result with flags, args, and rest.
|
||||
|
||||
### `require('pear-cmd/pear')`
|
||||
|
||||
Returns the definition for the top-level `pear` command (flags only).
|
||||
|
||||
### `require('pear-cmd/run')`
|
||||
|
||||
Returns the definition for `pear run` command arguments and flags.
|
||||
|
||||
## Command Definitions
|
||||
|
||||
### Top-level `pear` flags (selected)
|
||||
|
||||
- `-v`: Print version.
|
||||
- `--log`, `--log-labels`, `--log-level`, `--log-fields`, `--log-verbose`.
|
||||
- `--sidecar`: Raw boot sidecar mode.
|
||||
- Hidden flags for legacy compatibility: `--run`, `--sandbox`, `--appling`.
|
||||
|
||||
### `pear run` flags (selected)
|
||||
|
||||
- `<link|dir>`: Link, alias, or directory.
|
||||
- `--dev`, `--devtools`, `--updates-diff`, `--no-updates`.
|
||||
- `--link <url>`: Simulate deep-link open.
|
||||
- `--store <path>`, `--tmp-store`.
|
||||
- `--unsafe-clear-app-storage`, `--unsafe-clear-preferences`.
|
||||
- `--checkout <n|release|latest>`, `--detached`, `--preflight`.
|
||||
|
||||
## Complete Examples
|
||||
|
||||
### Example 1: Parse Top-level Flags
|
||||
|
||||
```js
|
||||
const cmd = require('pear-cmd')
|
||||
|
||||
const parsed = cmd(['--log', '--log-level', '2'])
|
||||
console.log(parsed.flags.log)
|
||||
console.log(parsed.flags['log-level'])
|
||||
```
|
||||
|
||||
### Example 2: Reuse `pear run` Definition
|
||||
|
||||
```js
|
||||
const { command, arg, rest } = require('paparam')
|
||||
const runDef = require('pear-cmd/run')
|
||||
|
||||
const parser = command('run', ...runDef, arg('[cmd]'), rest('rest'))
|
||||
const res = parser.parse(['pear://key/app', '--devtools'])
|
||||
console.log(res.args[0])
|
||||
```
|
||||
|
||||
### Example 3: Show Usage for Invalid Args
|
||||
|
||||
```js
|
||||
const cmd = require('pear-cmd')
|
||||
|
||||
try {
|
||||
cmd(['--unknown'])
|
||||
} catch (err) {
|
||||
console.error(err.message)
|
||||
}
|
||||
```
|
||||
|
||||
### Example 4: Build a Wrapper CLI
|
||||
|
||||
```js
|
||||
const cmd = require('pear-cmd')
|
||||
|
||||
const parsed = cmd(process.argv.slice(2))
|
||||
if (parsed.flags.v) {
|
||||
console.log('v1.2.3')
|
||||
process.exit(0)
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
- **Use the provided definitions** to stay aligned with official CLI behavior.
|
||||
- **Pass raw argv arrays**; do not pre-strip flags unless you know the spec.
|
||||
- **Respect hidden flags** if you support legacy workflows.
|
||||
|
||||
## Performance Notes
|
||||
|
||||
- Parsing is lightweight and suitable for CLI startup paths.
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- Treat parsed values as untrusted input until validated.
|
||||
- Avoid directly executing user-provided paths or links without checks.
|
||||
|
||||
## Integration with Other Modules
|
||||
|
||||
### With pear-link
|
||||
|
||||
```js
|
||||
const cmd = require('pear-cmd')
|
||||
const plink = require('pear-link')
|
||||
|
||||
const parsed = cmd(['pear://key/app'])
|
||||
const target = plink.parse(parsed.args[0])
|
||||
console.log(target.drive.key)
|
||||
```
|
||||
|
||||
### With pear-run
|
||||
|
||||
Pear CLI implementations usually pair `pear-cmd` with `pear-run` or similar runner modules for execution.
|
||||
|
||||
## Error Handling
|
||||
|
||||
- `paparam` throws on invalid flags or missing required args.
|
||||
- Surface usage messages in CLI output for best UX.
|
||||
|
||||
## License
|
||||
|
||||
Apache-2.0
|
||||
|
||||
---
|
||||
**Module Type**: CLI Utility | **Ecosystem Role**: Pear CLI Parsing | **Dependencies**: paparam
|
||||
@@ -0,0 +1,28 @@
|
||||
# pear-constants - Pear Constants
|
||||
|
||||
## Overview
|
||||
|
||||
pear-constants provides constant values used across Pear apps and tooling.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install pear-constants
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const constants = require('pear-constants')
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- README minimal; inspect source for exported constants
|
||||
|
||||
## License
|
||||
|
||||
Apache-2.0
|
||||
|
||||
---
|
||||
**Module Type**: Utility | **Ecosystem Role**: Shared Constants | **Dependencies**: None
|
||||
@@ -0,0 +1,33 @@
|
||||
# pear-doctor - Pear Diagnostics App
|
||||
|
||||
## Overview
|
||||
|
||||
pear-doctor is a Pear application used to run diagnostic checks. It includes a companion “Nurse” UI for manual checks.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
pear run pear://<app-key>
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
```bash
|
||||
git clone https://github.com/holepunchto/pear-doctor
|
||||
cd pear-doctor
|
||||
npm install
|
||||
pear run --dev .
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Doctor performs platform checks
|
||||
- Nurse is a browser-based helper UI
|
||||
- Checklist persisted in localStorage
|
||||
|
||||
## License
|
||||
|
||||
Apache-2.0
|
||||
|
||||
---
|
||||
**Module Type**: Application | **Ecosystem Role**: Diagnostics | **Dependencies**: pear
|
||||
@@ -0,0 +1,30 @@
|
||||
# pear-errors - Pear Core Error Types
|
||||
|
||||
## Overview
|
||||
|
||||
pear-errors defines core error types used across Pear. It provides standardized errors for consistent handling.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install pear-errors
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const errors = require('pear-errors')
|
||||
|
||||
throw errors.INVALID_OPERATION('Not allowed')
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- README is minimal; see source for full list
|
||||
|
||||
## License
|
||||
|
||||
Apache-2.0
|
||||
|
||||
---
|
||||
**Module Type**: Utility | **Ecosystem Role**: Error Types | **Dependencies**: None
|
||||
@@ -0,0 +1,35 @@
|
||||
# pear-info - Pear Project Information
|
||||
|
||||
## Overview
|
||||
|
||||
pear-info streams Pear project information for a given Pear link. It exposes a stream that emits info as data becomes available.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install pear-info
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
import info from 'pear-info'
|
||||
|
||||
const link = 'pear://...'
|
||||
const stream = info(link, opts)
|
||||
|
||||
stream.on('data', (info) => {
|
||||
console.log(info)
|
||||
})
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Runs as a stream and emits incremental info
|
||||
|
||||
## License
|
||||
|
||||
Apache-2.0
|
||||
|
||||
---
|
||||
**Module Type**: Tooling | **Ecosystem Role**: App Metadata | **Dependencies**: None
|
||||
@@ -0,0 +1,34 @@
|
||||
# pear-init - Pear Project Initializer
|
||||
|
||||
## Overview
|
||||
|
||||
pear-init creates initial Pear project files via an interactive terminal flow. It emits status data as the user responds to prompts.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install pear-init
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
import init from 'pear-init'
|
||||
|
||||
const stream = init(link, opts)
|
||||
stream.on('data', (info) => {
|
||||
console.log(info)
|
||||
})
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Designed for terminal use only
|
||||
- Interacts with user via prompt
|
||||
|
||||
## License
|
||||
|
||||
Apache-2.0
|
||||
|
||||
---
|
||||
**Module Type**: Tooling | **Ecosystem Role**: Project Bootstrap | **Dependencies**: None
|
||||
@@ -0,0 +1,92 @@
|
||||
# pear-inspect - Remote Pear Debugging
|
||||
|
||||
## Overview
|
||||
|
||||
pear-inspect enables remote debugging of Pear apps by bridging HyperDHT and bare-inspector (Chrome DevTools Protocol). It lets you debug apps running on remote devices.
|
||||
|
||||
### Key Features
|
||||
|
||||
- **Remote inspector**: Debug over HyperDHT
|
||||
- **Inspector/Session roles**: App side + debugger side
|
||||
- **CDP compatible**: Use Chrome DevTools Protocol
|
||||
- **Works with pear://runtime**
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install pear-inspect
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
### App (Inspector)
|
||||
|
||||
```js
|
||||
import nodeInspector from 'inspector'
|
||||
import { Inspector } from 'pear-inspect'
|
||||
|
||||
const inspector = new Inspector({ inspector: nodeInspector })
|
||||
const inspectorKey = await inspector.enable()
|
||||
|
||||
console.log(`Inspector key: ${inspectorKey.toString('hex')}`)
|
||||
```
|
||||
|
||||
### Debugger (Session)
|
||||
|
||||
```js
|
||||
import { Session } from 'pear-inspect'
|
||||
|
||||
const session = new Session({ inspectorKey })
|
||||
session.on('info', ({ filename }) => console.log('entry:', filename))
|
||||
session.on('message', ({ id, result, error }) => console.log(result || error))
|
||||
|
||||
session.connect()
|
||||
session.post({ id: 1, method: 'Runtime.evaluate', params: { expression: '1 + 2' } })
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `new Inspector({ inspector, dhtServer, inspectorKey, filename })`
|
||||
|
||||
Creates an Inspector for the current process.
|
||||
|
||||
### `await inspector.enable()`
|
||||
|
||||
Enable inspection. Returns `inspectorKey`.
|
||||
|
||||
### `await inspector.disable()`
|
||||
|
||||
Disable inspection.
|
||||
|
||||
### `new Session({ inspectorKey, publicKey })`
|
||||
|
||||
Create a remote inspection session.
|
||||
|
||||
### `session.connect()`
|
||||
|
||||
Connect to inspector.
|
||||
|
||||
### `session.disconnect()`
|
||||
|
||||
Disconnect session.
|
||||
|
||||
### `session.post({ id, method, params })`
|
||||
|
||||
Send CDP method.
|
||||
|
||||
### Events
|
||||
|
||||
- `info`: `{ filename }`
|
||||
- `message`: `{ id, result, error }`
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Use `inspectorKey` for simple setups
|
||||
- Call `disconnect()` when DevTools closes
|
||||
|
||||
## License
|
||||
|
||||
Apache-2.0
|
||||
|
||||
---
|
||||
**Module Type**: Debugging | **Ecosystem Role**: Remote Inspector | **Dependencies**: hyperdht, bare-inspector
|
||||
@@ -0,0 +1,23 @@
|
||||
# pear-installer - Pear App Installer Helper
|
||||
|
||||
## Overview
|
||||
|
||||
pear-installer is used by Pear application installers. The README is minimal; this module serves as a helper for installers.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install pear-installer
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Intended for installer tooling
|
||||
- See source for APIs
|
||||
|
||||
## License
|
||||
|
||||
Apache-2.0
|
||||
|
||||
---
|
||||
**Module Type**: Tooling | **Ecosystem Role**: Installer Helper | **Dependencies**: None
|
||||
@@ -0,0 +1,182 @@
|
||||
# pear-link - Parse and Serialize Pear Links
|
||||
|
||||
## Overview
|
||||
|
||||
pear-link parses and serializes Pear links (`pear:`) and local file links (`file:`). It supports Pear-specific link formats with optional fork, length, and dhash parts, and integrates alias resolution via `pear-aliases`.
|
||||
|
||||
### Key Features
|
||||
|
||||
- **Pear URL parsing**: Supports `pear://` URLs with optional metadata.
|
||||
- **File URL handling**: Parses `file://` and filesystem paths.
|
||||
- **Alias support**: Resolve and serialize aliases using `pear-aliases`.
|
||||
- **Normalization**: Normalize links to stable forms for comparison.
|
||||
|
||||
### Use Cases
|
||||
|
||||
- **CLI parsing**: Accept links or filesystem paths in commands.
|
||||
- **App routing**: Handle deep links and link normalization.
|
||||
- **Share links**: Serialize drive keys into Pear links.
|
||||
- **Validation**: Produce explicit error messages for invalid links.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install pear-link
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
```js
|
||||
const plink = require('pear-link')
|
||||
|
||||
const parsed = plink.parse('pear://myapp/docs')
|
||||
console.log(parsed.drive.key)
|
||||
|
||||
const link = plink.serialize(parsed)
|
||||
console.log(link)
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Input link or path] --> B[pear-link]
|
||||
B --> C[URL parser]
|
||||
B --> D[pear-aliases]
|
||||
B --> E[hypercore-id-encoding]
|
||||
B --> F[Normalized object]
|
||||
```
|
||||
|
||||
## Pear Link Format
|
||||
|
||||
```
|
||||
pear://[<fork>.<length>.]<keyOrAlias>[.<dhash>]<path>[?<search>][#<lochash>]
|
||||
```
|
||||
|
||||
- `fork`: Hypercore fork id
|
||||
- `length`: Hypercore length
|
||||
- `keyOrAlias`: z32 or hex key, or alias
|
||||
- `dhash`: optional discovery hash
|
||||
|
||||
## API Reference
|
||||
|
||||
### `const plink = require('pear-link')`
|
||||
|
||||
Exports a singleton with `parse`, `serialize`, and `normalize`.
|
||||
|
||||
### `plink.parse(link) -> { protocol, pathname, search, hash, origin, drive }`
|
||||
|
||||
Parse a Pear or file link.
|
||||
|
||||
**Parameters:**
|
||||
- `link` (string): A `pear://` or `file://` link, or a filesystem path.
|
||||
|
||||
**Returns:**
|
||||
- `protocol` (string): `pear:` or `file:`
|
||||
- `pathname` (string): Path portion
|
||||
- `search` (string): Query string, including `?`
|
||||
- `hash` (string): Fragment, including `#`
|
||||
- `origin` (string): Normalized origin
|
||||
- `drive` (object): `{ key, length, fork, hash, alias }`
|
||||
|
||||
### `plink.serialize(objOrKey) -> string`
|
||||
|
||||
Serialize a parsed object or drive key into a Pear link.
|
||||
|
||||
**Parameters:**
|
||||
- Parsed object returned by `parse`, or a key buffer/string.
|
||||
|
||||
### `plink.normalize(link) -> string`
|
||||
|
||||
Normalize a link by removing trailing separators. `file://` links are normalized with `/` separators, filesystem paths use the platform separator.
|
||||
|
||||
## Complete Examples
|
||||
|
||||
### Example 1: Parse a Pear Link
|
||||
|
||||
```js
|
||||
const plink = require('pear-link')
|
||||
|
||||
const parsed = plink.parse('pear://myapp/docs?mode=help#intro')
|
||||
console.log(parsed.protocol)
|
||||
console.log(parsed.drive.alias)
|
||||
```
|
||||
|
||||
### Example 2: Parse a File Path
|
||||
|
||||
```js
|
||||
const plink = require('pear-link')
|
||||
|
||||
const parsed = plink.parse('/Users/me/projects/app')
|
||||
console.log(parsed.protocol) // file:
|
||||
```
|
||||
|
||||
### Example 3: Serialize from a Key
|
||||
|
||||
```js
|
||||
const plink = require('pear-link')
|
||||
|
||||
const link = plink.serialize('f1a2b3...')
|
||||
console.log(link) // pear://<key>
|
||||
```
|
||||
|
||||
### Example 4: Normalize for Comparisons
|
||||
|
||||
```js
|
||||
const plink = require('pear-link')
|
||||
|
||||
const a = plink.normalize('pear://myapp/docs/')
|
||||
const b = plink.normalize('pear://myapp/docs')
|
||||
console.log(a === b)
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
- **Normalize links** before comparisons or cache keys.
|
||||
- **Validate user input** by catching `ERR_INVALID_LINK`.
|
||||
- **Prefer aliases** for stable, human-readable links when available.
|
||||
- **Do not assume `file:`**: relative paths are resolved against cwd.
|
||||
|
||||
## Performance Notes
|
||||
|
||||
- Parsing uses `URL` and `hypercore-id-encoding`; overhead is minimal.
|
||||
- Alias resolution is map lookups and cheap.
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- Treat parsed paths as untrusted; sanitize before file access.
|
||||
- Avoid exposing raw drive keys in logs if they are sensitive.
|
||||
|
||||
## Integration with Other Modules
|
||||
|
||||
### With pear-cmd
|
||||
|
||||
```js
|
||||
const cmd = require('pear-cmd')
|
||||
const plink = require('pear-link')
|
||||
|
||||
const parsed = cmd(['pear://myapp'])
|
||||
const target = plink.parse(parsed.args[0])
|
||||
```
|
||||
|
||||
### With hypercore-id-encoding
|
||||
|
||||
`pear-link` uses `hypercore-id-encoding` for key normalization and encoding.
|
||||
|
||||
## Error Handling
|
||||
|
||||
Errors are thrown with `ERR_INVALID_LINK` from `pear-errors` when:
|
||||
|
||||
- Missing or invalid protocol
|
||||
- Invalid hostname parts
|
||||
- Non-integer fork/length
|
||||
- Unknown alias
|
||||
|
||||
Handle using `try/catch` around `parse` or `serialize`.
|
||||
|
||||
## License
|
||||
|
||||
Apache-2.0
|
||||
|
||||
---
|
||||
**Module Type**: Utility | **Ecosystem Role**: Link Parsing | **Dependencies**: pear-errors, pear-aliases, hypercore-id-encoding
|
||||
@@ -0,0 +1,183 @@
|
||||
# pear-pack - Bundle and Prebuild Generator for Pear
|
||||
|
||||
## Overview
|
||||
|
||||
pear-pack builds a portable bundle from a drive and extracts prebuilds and assets. It uses `bare-pack-drive` to package the module graph, then rewrites addon paths to hashed prebuild locations and returns a bundle buffer alongside prebuild and asset maps.
|
||||
|
||||
### Key Features
|
||||
|
||||
- **Drive-based bundling**: Works directly on a drive (e.g. Hyperdrive).
|
||||
- **Addon hashing**: Rewrites `.node`/`.bare` paths to content-hashed prebuilds.
|
||||
- **Asset extraction**: Captures asset files referenced in the bundle.
|
||||
- **Conditional resolution**: Uses module conditions and extensions per target hosts.
|
||||
- **Mount support**: Optionally rebundles under a mount path.
|
||||
|
||||
### Use Cases
|
||||
|
||||
- **Offline packaging**: Create bundles without a running Pear runtime.
|
||||
- **Multi-host releases**: Generate prebuilds for multiple targets.
|
||||
- **Custom packers**: Integrate with bespoke pipelines or CI.
|
||||
- **Asset capture**: Extract assets for separate distribution.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install pear-pack
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
```js
|
||||
const pack = require('pear-pack')
|
||||
const Hyperdrive = require('hyperdrive')
|
||||
|
||||
const drive = new Hyperdrive('./app-drive')
|
||||
await drive.ready()
|
||||
|
||||
const packed = await pack(drive, { entry: '/boot.js' })
|
||||
console.log(packed.bundle.byteLength)
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Drive] --> B[bare-pack-drive]
|
||||
B --> C[Bundle buffer]
|
||||
C --> D[bare-unpack]
|
||||
D --> E[Rewrite addon paths]
|
||||
D --> F[Collect assets]
|
||||
E --> G[Prebuild map]
|
||||
F --> H[Assets map]
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `const pack = require('pear-pack')`
|
||||
|
||||
Exports a single async function.
|
||||
|
||||
### `await pack(drive, opts) -> { bundle, prebuilds, assets }`
|
||||
|
||||
**Parameters:**
|
||||
- `drive` (object, required): Drive with `get(key)` (e.g. Hyperdrive).
|
||||
- `opts` (object, optional): Packaging options.
|
||||
|
||||
**Options:**
|
||||
- `entry` (string): Entry point (default `/boot.js`).
|
||||
- `hosts` (string[]|string): Target hosts (e.g. `darwin-arm64`).
|
||||
- `builtins` (string[]): Builtins to include.
|
||||
- `imports` (string[]): Extra imports to include.
|
||||
- `mount` (string): Mount prefix for rebundled paths.
|
||||
- `assetsPrefix` (string): Prefix for asset keys in the assets map.
|
||||
- `prebuildPrefix` (string): Prefix for rewritten prebuild paths.
|
||||
- `conditions` (string[]): Module resolution conditions (default `['node', 'bare']`).
|
||||
- `extensions` (string[]): Addon extensions (default `['.node', '.bare']`).
|
||||
|
||||
**Returns:**
|
||||
- `bundle` (Buffer): Rebundled bundle buffer.
|
||||
- `prebuilds` (Map): Maps rewritten prebuild path -> addon Buffer.
|
||||
- `assets` (Map): Maps asset path -> asset Buffer.
|
||||
|
||||
## Complete Examples
|
||||
|
||||
### Example 1: Bundle a Drive
|
||||
|
||||
```js
|
||||
const pack = require('pear-pack')
|
||||
const Hyperdrive = require('hyperdrive')
|
||||
|
||||
const drive = new Hyperdrive('./app-drive')
|
||||
await drive.ready()
|
||||
|
||||
const { bundle, prebuilds } = await pack(drive, { entry: '/boot.js' })
|
||||
console.log('Prebuilds:', prebuilds.size)
|
||||
```
|
||||
|
||||
### Example 2: Multi-host Prebuilds
|
||||
|
||||
```js
|
||||
const pack = require('pear-pack')
|
||||
|
||||
const packed = await pack(drive, {
|
||||
hosts: ['darwin-arm64', 'linux-x64'],
|
||||
entry: '/boot.js'
|
||||
})
|
||||
|
||||
for (const [path, buf] of packed.prebuilds) {
|
||||
console.log('Prebuild:', path, buf.length)
|
||||
}
|
||||
```
|
||||
|
||||
### Example 3: Collect Assets with Prefix
|
||||
|
||||
```js
|
||||
const pack = require('pear-pack')
|
||||
|
||||
const packed = await pack(drive, {
|
||||
assetsPrefix: '/assets',
|
||||
entry: '/boot.js'
|
||||
})
|
||||
|
||||
for (const [path] of packed.assets) {
|
||||
console.log('Asset:', path)
|
||||
}
|
||||
```
|
||||
|
||||
### Example 4: Mount Bundles Under a Prefix
|
||||
|
||||
```js
|
||||
const pack = require('pear-pack')
|
||||
|
||||
const packed = await pack(drive, {
|
||||
mount: '/app',
|
||||
entry: '/boot.js'
|
||||
})
|
||||
|
||||
// Bundle references now under /app
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
- **Pin `hosts`** to ensure the right prebuilds are captured.
|
||||
- **Use `assetsPrefix`** for predictable asset locations in release pipelines.
|
||||
- **Keep extensions list minimal** to avoid bundling unintended artifacts.
|
||||
- **Verify `entry`** exists in the drive and is a valid JS module.
|
||||
|
||||
## Performance Notes
|
||||
|
||||
- Bundling walks the full module graph; large apps can take seconds.
|
||||
- Prebuild hashing uses `sodium-native` and is CPU-bound for large addons.
|
||||
- Consider caching bundle output between builds if the drive is unchanged.
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- Treat drive contents as untrusted; validate or sandbox before bundling.
|
||||
- Addon prebuilds are binary artifacts; ensure they come from trusted sources.
|
||||
|
||||
## Integration with Other Modules
|
||||
|
||||
### With pear-bundle
|
||||
|
||||
Use `pear-bundle` inside Pear runtime when IPC is available. Use `pear-pack` when bundling offline.
|
||||
|
||||
### With bare-pack-drive
|
||||
|
||||
`pear-pack` delegates to `bare-pack-drive` and `bare-module-traverse` for resolution logic, so settings should align with those modules.
|
||||
|
||||
## Error Handling
|
||||
|
||||
Common errors:
|
||||
|
||||
- **Missing entry**: `drive.get` fails or entry path not found.
|
||||
- **Invalid addon**: prebuild extraction fails on non-addon binary.
|
||||
- **Unsupported host**: missing prebuilds for selected hosts.
|
||||
|
||||
Wrap `pack()` in `try/catch` and surface the failing path in error logs.
|
||||
|
||||
## License
|
||||
|
||||
Apache-2.0
|
||||
|
||||
---
|
||||
**Module Type**: Build Tool | **Ecosystem Role**: Pear Packaging | **Dependencies**: bare-pack-drive, bare-unpack, sodium-native
|
||||
Reference in New Issue
Block a user