{"id":16176,"library":"pear-api","title":"Pear API Base Class (Holepunch)","description":"The `pear-api` package provides the foundational base class for interacting with the Pear API, which is part of the Holepunch peer-to-peer (P2P) runtime and development platform. Currently at version 1.30.0, this library enables developers to build P2P applications, particularly focusing on User Interface integrations by abstracting complex underlying P2P mechanisms. The Pear ecosystem is actively maintained, with regular updates to its 1.x branch and a significant transition underway to a version 2, which introduces notable breaking changes and a shift towards modern JavaScript module standards. Key differentiators include its focus on enabling local-first, offline-first P2P applications and its design for extensibility within UI environments like Electron.","status":"active","version":"1.30.0","language":"javascript","source_language":"en","source_url":null,"tags":["javascript","pear","pear runtime","peer-to-peer","p2p","api","integration","extension"],"install":[{"cmd":"npm install pear-api","lang":"bash","label":"npm"},{"cmd":"yarn add pear-api","lang":"bash","label":"yarn"},{"cmd":"pnpm add pear-api","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"The primary API base class is typically imported as a named export. While v1 supports CommonJS, future major versions (v2+) are moving towards ESM-only.","wrong":"const PearAPI = require('pear-api');","symbol":"PearAPI","correct":"import { PearAPI } from 'pear-api';"},{"note":"Configuration utilities are often named exports from the main package or a subpath. Avoid direct subpath imports unless explicitly documented.","wrong":"import Config from 'pear-api/config';","symbol":"Config","correct":"import { Config } from 'pear-api';"},{"note":"Custom error classes or types related to the API are usually named exports. Ensure you're using ESM syntax for modern applications.","wrong":"const { PearError } = require('pear-api');","symbol":"PearError","correct":"import { PearError } from 'pear-api';"}],"quickstart":{"code":"import { PearAPI } from 'pear-api';\n\ninterface MyApiOptions {\n  authToken: string;\n  appId: string;\n}\n\ninterface MyP2PData {\n  id: string;\n  message: string;\n  timestamp: number;\n}\n\nclass MyPearAppAPI extends PearAPI {\n  private token: string;\n  private appId: string;\n\n  constructor(options: MyApiOptions) {\n    super(); // Initialize the base PearAPI class\n    this.token = options.authToken;\n    this.appId = options.appId;\n    console.log(`MyPearAppAPI initialized for app: ${this.appId}`);\n  }\n\n  async connect(): Promise<boolean> {\n    console.log('Attempting to connect to Pear network...');\n    // Simulate P2P network connection logic\n    await new Promise(resolve => setTimeout(resolve, 1000));\n    if (!this.token) {\n      console.error('Authentication token is missing.');\n      return false;\n    }\n    console.log('Successfully connected to Pear network.');\n    return true;\n  }\n\n  async publishData(data: MyP2PData): Promise<void> {\n    if (!(await this.connect())) {\n      throw new Error('Failed to connect, cannot publish data.');\n    }\n    console.log(`Publishing data [${data.id}]: ${data.message} at ${new Date(data.timestamp).toISOString()}`);\n    // Simulate data publishing to the P2P network\n    await new Promise(resolve => setTimeout(resolve, 500));\n    console.log('Data published.');\n  }\n\n  static async createAndRun(token: string): Promise<MyPearAppAPI> {\n    const api = new MyPearAppAPI({ authToken: token, appId: 'my-p2p-app' });\n    const connected = await api.connect();\n    if (connected) {\n      await api.publishData({ id: 'msg-1', message: 'Hello P2P world!', timestamp: Date.now() });\n    }\n    return api;\n  }\n}\n\n// Example usage with a dummy token\nMyPearAppAPI.createAndRun(process.env.PEAR_AUTH_TOKEN ?? 'dummy_auth_token_123')\n  .then(() => console.log('Pear application flow completed.'))\n  .catch(error => console.error('Pear application error:', error.message));","lang":"typescript","description":"This quickstart demonstrates how to extend the `PearAPI` base class to create a custom P2P application API, handle connection, and publish data, including error handling and simulated asynchronous operations."},"warnings":[{"fix":"Refer to the official Pear v2 Migration Guide (https://docs.pears.com/api/migration) for detailed steps, including updating your `package.json` entrypoint and adapting to new module structures like `pear-electron` and `pear-bridge`.","message":"Migrating from Pear v1 to v2 involves significant breaking changes. Specifically, many UI-related methods have been moved or renamed, and the application entrypoint has changed from supporting HTML in v1 to only JavaScript in v2.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Transition to using the `pear-runtime` module in your application code for starting and managing the Pear runtime, or consult documentation for the appropriate CLI alternatives for development and deployment.","message":"The `pear run` CLI command has been deprecated in favor of using the `pear-runtime` module for embeddable runtimes with P2P Over-The-Air (OTA) updates.","severity":"deprecated","affected_versions":">=1.10.0"},{"fix":"Ensure your project is configured for ESM. This often means setting `\"type\": \"module\"` in your `package.json`, using `.mjs` file extensions, and updating all `require()` statements to `import` statements. For TypeScript, configure `\"module\": \"NodeNext\"` or `\"moduleResolution\": \"NodeNext\"` in `tsconfig.json`.","message":"Future major versions of Pear modules, including `pear-api`, are increasingly adopting an ESM-only (ECMAScript Modules) export strategy. Projects using CommonJS (`require()`) might encounter `ERR_REQUIRE_ESM`.","severity":"gotcha","affected_versions":">=2.0.0"},{"fix":"Implement proper teardown logic using `Pear.teardown(cb)` and ensure all long-lived resources like Hyperswarm instances (`swarm.destroy()`) or worker pipes (`pipe.end()`) are gracefully closed to prevent resource leaks or application hangs. Refer to Pear troubleshooting documentation for common patterns.","message":"The `pear-api` package, as a base class for P2P applications, requires careful handling of resource cleanup (e.g., network connections, database instances) during application teardown to prevent hanging processes or resource locks.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"Always instantiate the `PearAPI` class (or its subclasses) using `new`, e.g., `const api = new PearAPI();` or `class MyAPI extends PearAPI { ... }` then `new MyAPI();`.","cause":"Attempting to call `PearAPI()` directly instead of instantiating it with the `new` keyword.","error":"TypeError: Class constructor PearAPI cannot be invoked without 'new'"},{"fix":"Verify that your module import statement is correct (`import { PearAPI } from 'pear-api';`). If you are in a CommonJS context and need an ESM-only module, consider migrating your project to ESM or using dynamic `import()` within an `async` function.","cause":"This typically occurs in a CommonJS environment when an ESM-only version of `pear-api` is used, or the `PearAPI` class was not correctly imported.","error":"ReferenceError: PearAPI is not defined"},{"fix":"Ensure that your API key or token is correctly provided during the `PearAPI` constructor or connection method. Double-check its validity, expiration, and required permissions according to your Pear API provider's documentation. Use environment variables for sensitive credentials.","cause":"The base `PearAPI` or its derived classes often require an authentication token or key, which was either missing, expired, or invalid during initialization or an API call.","error":"Error: Authentication failed: Invalid API key or token"}],"ecosystem":"npm"}