| … | … | @@ -36,16 +36,223 @@ jobs: |
| 36 | 36 | |
| 37 | 37 | ## API Documentation |
| 38 | 38 | |
| 39 | _To be enriched in Phase 1B with deep code analysis_ | |
| 39 | ### GitHub Actions Workflows | |
| 40 | ||
| 41 | This repository provides shared GitHub Actions for **package maintainers** building native modules across multiple platforms. | |
| 42 | ||
| 43 | **Available Actions:** | |
| 44 | ||
| 45 | #### 1. compile-prebuilds | |
| 46 | ||
| 47 | Compiles native addons for specific platform/architecture combinations. | |
| 48 | ||
| 49 | **Inputs:** | |
| 50 | - `platform` (required) - Target platform: `linux`, `darwin`, `win32`, `android`, `ios` | |
| 51 | - `arch` (required) - Target architecture: `x64`, `arm64`, `arm`, `ia32` | |
| 52 | - `flags` (optional) - Additional build system flags | |
| 53 | - `tags` (optional) - Additional tags for uploaded prebuilds | |
| 54 | - `upload` (optional) - Upload compiled prebuilds (default: `false`) | |
| 55 | ||
| 56 | **Process:** | |
| 57 | 1. Installs `bare-make` globally | |
| 58 | 2. Generates build files for platform/arch | |
| 59 | 3. Compiles with `bare-make build` | |
| 60 | 4. Installs artifacts locally | |
| 61 | 5. Optionally uploads via `upload-prebuilds` action | |
| 62 | ||
| 63 | **Example Usage:** | |
| 64 | ```yaml | |
| 65 | name: Build Prebuilds | |
| 66 | ||
| 67 | on: push | |
| 68 | ||
| 69 | jobs: | |
| 70 | build: | |
| 71 | strategy: | |
| 72 | matrix: | |
| 73 | platform: [linux, darwin, win32] | |
| 74 | arch: [x64, arm64] | |
| 75 | uses: holepunchto/actions/.github/workflows/compile-prebuilds.yml@v1 | |
| 76 | with: | |
| 77 | platform: ${{ matrix.platform }} | |
| 78 | arch: ${{ matrix.arch }} | |
| 79 | upload: true | |
| 80 | ``` | |
| 81 | ||
| 82 | #### 2. merge-prebuilds | |
| 83 | ||
| 84 | Combines prebuilt artifacts from different platform builds into unified output. | |
| 85 | ||
| 86 | **Use Case:** After matrix build completes, merge all platform binaries. | |
| 87 | ||
| 88 | #### 3. upload-prebuilds | |
| 89 | ||
| 90 | Publishes compiled binaries to npm registry or storage. | |
| 91 | ||
| 92 | **Use Case:** Distribute prebuilds with npm package. | |
| 93 | ||
| 94 | ### 13 Platform Targets | |
| 95 | ||
| 96 | **Android (4):** | |
| 97 | - `android-arm` | |
| 98 | - `android-arm64` | |
| 99 | - `android-ia32` | |
| 100 | - `android-x64` | |
| 101 | ||
| 102 | **iOS (3):** | |
| 103 | - `ios-arm64` | |
| 104 | - `ios-arm64-simulator` | |
| 105 | - `ios-x64-simulator` | |
| 106 | ||
| 107 | **macOS (2):** | |
| 108 | - `darwin-arm64` (M1/M2 Apple Silicon) | |
| 109 | - `darwin-x64` (Intel) | |
| 110 | ||
| 111 | **Linux (2):** | |
| 112 | - `linux-arm64` | |
| 113 | - `linux-x64` | |
| 114 | ||
| 115 | **Windows (2):** | |
| 116 | - `win32-arm64` | |
| 117 | - `win32-x64` | |
| 40 | 118 | |
| 41 | 119 | ## Usage Examples |
| 42 | 120 | |
| 43 | _To be added in Phase 1B_ | |
| 121 | ### Example 1: Full Matrix Build | |
| 122 | ||
| 123 | ```yaml | |
| 124 | name: Build All Platforms | |
| 125 | ||
| 126 | on: | |
| 127 | release: | |
| 128 | types: [created] | |
| 129 | ||
| 130 | jobs: | |
| 131 | build-prebuilds: | |
| 132 | runs-on: ubuntu-latest | |
| 133 | strategy: | |
| 134 | matrix: | |
| 135 | include: | |
| 136 | - platform: linux | |
| 137 | arch: x64 | |
| 138 | - platform: linux | |
| 139 | arch: arm64 | |
| 140 | - platform: darwin | |
| 141 | arch: x64 | |
| 142 | - platform: darwin | |
| 143 | arch: arm64 | |
| 144 | - platform: win32 | |
| 145 | arch: x64 | |
| 146 | - platform: win32 | |
| 147 | arch: arm64 | |
| 148 | - platform: android | |
| 149 | arch: arm | |
| 150 | - platform: android | |
| 151 | arch: arm64 | |
| 152 | - platform: android | |
| 153 | arch: ia32 | |
| 154 | - platform: android | |
| 155 | arch: x64 | |
| 156 | - platform: ios | |
| 157 | arch: arm64 | |
| 158 | - platform: ios | |
| 159 | arch: arm64-simulator | |
| 160 | - platform: ios | |
| 161 | arch: x64-simulator | |
| 162 | ||
| 163 | uses: holepunchto/actions/.github/workflows/compile-prebuilds.yml@v1 | |
| 164 | with: | |
| 165 | platform: ${{ matrix.platform }} | |
| 166 | arch: ${{ matrix.arch }} | |
| 167 | upload: true | |
| 168 | secrets: inherit | |
| 169 | ||
| 170 | merge-and-publish: | |
| 171 | needs: build-prebuilds | |
| 172 | runs-on: ubuntu-latest | |
| 173 | uses: holepunchto/actions/.github/workflows/merge-prebuilds.yml@v1 | |
| 174 | ``` | |
| 175 | ||
| 176 | ### Example 2: Selective Platform Build | |
| 177 | ||
| 178 | ```yaml | |
| 179 | # Only build for common desktop platforms | |
| 180 | jobs: | |
| 181 | build: | |
| 182 | strategy: | |
| 183 | matrix: | |
| 184 | platform: [linux, darwin, win32] | |
| 185 | arch: [x64, arm64] | |
| 186 | uses: holepunchto/actions/.github/workflows/compile-prebuilds.yml@v1 | |
| 187 | with: | |
| 188 | platform: ${{ matrix.platform }} | |
| 189 | arch: ${{ matrix.arch }} | |
| 190 | ``` | |
| 191 | ||
| 192 | **Use Case:** Reduce build time by targeting only necessary platforms. | |
| 193 | ||
| 194 | ### Example 3: Custom Build Flags | |
| 195 | ||
| 196 | ```yaml | |
| 197 | jobs: | |
| 198 | build: | |
| 199 | uses: holepunchto/actions/.github/workflows/compile-prebuilds.yml@v1 | |
| 200 | with: | |
| 201 | platform: linux | |
| 202 | arch: x64 | |
| 203 | flags: --debug # Custom bare-make flags | |
| 204 | tags: debug,nightly | |
| 205 | ``` | |
| 206 | ||
| 207 | ## Package Size Impact | |
| 208 | ||
| 209 | **Why This Matters for App Developers:** | |
| 210 | ||
| 211 | When you `npm install` packages like `sodium-native`, `bare-tls`, or `hyperswarm`, you download **all 13 platform prebuilds** that were created using these GitHub Actions. | |
| 212 | ||
| 213 | **Size Breakdown:** | |
| 214 | - Each native module: ~1-2 MB per platform × 13 platforms = 13-26 MB | |
| 215 | - Typical app with 20+ native modules: 260-520 MB | |
| 216 | - **After platform-specific pruning:** 20-40 MB | |
| 217 | ||
| 218 | **Optimization Strategy:** | |
| 219 | ||
| 220 | 1. **Package Maintainers (using these actions):** Build all 13 platforms for maximum compatibility | |
| 221 | ||
| 222 | 2. **App Developers (using the packages):** Prune to single platform before deployment | |
| 223 | ||
| 224 | ```bash | |
| 225 | # Remove 12 other platforms before pear stage | |
| 226 | node prune-prebuilds.js | |
| 227 | pear stage myapp . | |
| 228 | # Result: 82% size reduction | |
| 229 | ``` | |
| 230 | ||
| 231 | See: [pear](../pear/skills.md) and [pear-pack](../pear-pack/skills.md) for optimization guides. | |
| 232 | ||
| 233 | ## Workflow Comparison | |
| 234 | ||
| 235 | **For Package Maintainers:** | |
| 236 | ``` | |
| 237 | Code → holepunchto/actions → Build 13 platforms → Publish to npm | |
| 238 | ``` | |
| 239 | ||
| 240 | **For App Developers:** | |
| 241 | ``` | |
| 242 | npm install → Download all platforms → Prune to 1 platform → pear stage → Deploy | |
| 243 | ``` | |
| 44 | 244 | |
| 45 | 245 | ## Semantic Type |
| 46 | 246 | |
| 47 | _To be classified in Phase 2_ | |
| 247 | **Category:** CI/CD Infrastructure, Build Automation | |
| 248 | ||
| 249 | **Use Case:** Native module compilation, cross-platform builds, prebuild distribution | |
| 250 | ||
| 251 | **Target Audience:** Package maintainers, not app developers | |
| 48 | 252 | |
| 49 | 253 | ## Related Packages |
| 50 | 254 | |
| 51 | _To be analyzed in Phase 2_ | |
| 255 | - **bare-make** - Build system used by compile-prebuilds action | |
| 256 | - **bare-addon** - Template for native addons (uses these actions) | |
| 257 | - **pear-pack** - App bundling with prebuild filtering | |
| 258 | - **pear** - CLI for deploying apps with optimized prebuilds |
| … | … | @@ -51,16 +51,107 @@ const packed = await bundle(opts) |
| 51 | 51 | |
| 52 | 52 | ## API Documentation |
| 53 | 53 | |
| 54 | _To be enriched in Phase 1B with deep code analysis_ | |
| 54 | ### `bundle(opts) -> Buffer` | |
| 55 | ||
| 56 | Generates a bare-bundle from a Pear application entrypoint. | |
| 57 | ||
| 58 | **Options:** | |
| 59 | - `cache` - Enable caching (default: `false`) | |
| 60 | - `prebuilds` - Path to prebuilds directory | |
| 61 | - `entry` - Application entrypoint (default: `/boot.js`) | |
| 62 | - `builtins` - Array of builtin modules | |
| 63 | ||
| 64 | **Returns:** Buffer containing bundled application | |
| 55 | 65 | |
| 56 | 66 | ## Usage Examples |
| 57 | 67 | |
| 58 | _To be added in Phase 1B_ | |
| 68 | ### Example 1: Basic Bundle Generation | |
| 69 | ||
| 70 | ```javascript | |
| 71 | import bundle from 'pear-bundle' | |
| 72 | ||
| 73 | const opts = { | |
| 74 | cache: false, | |
| 75 | prebuilds: 'path/to/prebuilds', | |
| 76 | entry: '/boot.js', | |
| 77 | builtins: [] | |
| 78 | } | |
| 79 | ||
| 80 | const packed = await bundle(opts) | |
| 81 | console.log('Bundle size:', packed.length) | |
| 82 | ``` | |
| 83 | ||
| 84 | ### Example 2: Cached Bundle Build | |
| 85 | ||
| 86 | ```javascript | |
| 87 | const packed = await bundle({ | |
| 88 | cache: true, // Reuse previous build artifacts | |
| 89 | entry: '/index.js' | |
| 90 | }) | |
| 91 | ``` | |
| 92 | ||
| 93 | **Use Case:** Speed up repeated builds during development. | |
| 94 | ||
| 95 | ### Example 3: Custom Builtins | |
| 96 | ||
| 97 | ```javascript | |
| 98 | const packed = await bundle({ | |
| 99 | entry: '/boot.js', | |
| 100 | builtins: ['hypercore', 'hyperswarm'] // Pre-bundle these modules | |
| 101 | }) | |
| 102 | ``` | |
| 103 | ||
| 104 | ## Bare-Bundle Format | |
| 105 | ||
| 106 | Pear-bundle generates **bare-bundle** format, inspired by Electron's ASAR: | |
| 107 | ||
| 108 | **Benefits:** | |
| 109 | - Single-file distribution | |
| 110 | - Fast module resolution | |
| 111 | - Potential compression (unexplored) | |
| 112 | - Content-addressable modules | |
| 113 | ||
| 114 | **Format:** Per [bare-bundle](https://github.com/holepunchto/bare-bundle) specification. | |
| 115 | ||
| 116 | ## Optimization Potential (Unexplored) | |
| 117 | ||
| 118 | **Theory:** bare-bundle format might provide additional compression beyond file-level optimization. | |
| 119 | ||
| 120 | **Comparison:** | |
| 121 | ||
| 122 | | Approach | JavaScript Size | Notes | | |
| 123 | |----------|-----------------|-------| | |
| 124 | | Raw files | ~6 MB | Individual .js files | | |
| 125 | | bare-bundle | ~6 MB | Single bundle file | | |
| 126 | | bare-bundle + compression | ??? | Not tested | | |
| 127 | ||
| 128 | **Status:** Compression potential not yet tested in production. Manual prebuild pruning achieves 82% size reduction - bare-bundle compression might provide additional 10-20% JavaScript savings. | |
| 129 | ||
| 130 | **Worth Exploring:** For production deployments where every MB matters. | |
| 131 | ||
| 132 | ## Integration with pear-pack | |
| 133 | ||
| 134 | pear-bundle focuses on **JavaScript bundling**, while pear-pack handles both: | |
| 135 | - JavaScript bundling (via pear-bundle internally) | |
| 136 | - Prebuild management (native modules) | |
| 137 | ||
| 138 | **Workflow:** | |
| 139 | ``` | |
| 140 | pear-bundle → JavaScript bundle | |
| 141 | pear-pack → JavaScript bundle + filtered prebuilds | |
| 142 | pear stage → Upload to DHT (uses pear-pack internally) | |
| 143 | ``` | |
| 59 | 144 | |
| 60 | 145 | ## Semantic Type |
| 61 | 146 | |
| 62 | _To be classified in Phase 2_ | |
| 147 | **Category:** Pear Build Tools | |
| 148 | ||
| 149 | **Use Case:** JavaScript bundling, module compilation, build optimization | |
| 63 | 150 | |
| 64 | 151 | ## Related Packages |
| 65 | 152 | |
| 66 | _To be analyzed in Phase 2_ | |
| 153 | - **bare-bundle** - Core bundle format specification | |
| 154 | - **bare-bundle-compile** - Compile CommonJS to single module | |
| 155 | - **pear-pack** - Higher-level bundling with prebuild management | |
| 156 | - **drive-bundler** - Extract bundles from drives | |
| 157 | - **bare-pack** - Bundle packing for Bare runtime |
| … | … | @@ -55,16 +55,127 @@ Creates a bundle buffer and Map of prebuild buffers. |
| 55 | 55 | |
| 56 | 56 | ## API Documentation |
| 57 | 57 | |
| 58 | _To be enriched in Phase 1B with deep code analysis_ | |
| 58 | ### `pearPack(drive, opts) -> { bundle, prebuilds }` | |
| 59 | ||
| 60 | Creates a bundle buffer and Map of prebuild buffers from a Pear application. | |
| 61 | ||
| 62 | **Options:** | |
| 63 | ||
| 64 | - `target` - Target host architecture(s), may be single value or array | |
| 65 | - Examples: `'linux-x64'`, `['linux-x64', 'darwin-arm64']` | |
| 66 | - **Use this to filter prebuilds to specific platforms!** | |
| 67 | - `builtins` - Array of builtin modules to include | |
| 68 | - `entry` - Bundle entrypoint (default: `/boot.js`) | |
| 69 | - `conditionals` - Additional prefixed conditionals (default: `['node', 'bare']`) | |
| 70 | - `extensions` - Supported addon extensions (default: `['.node', '.bare']`) | |
| 71 | ||
| 72 | **Returns:** | |
| 73 | ```javascript | |
| 74 | { | |
| 75 | bundle: Buffer, // Bundled JavaScript code | |
| 76 | prebuilds: Map<key, Buffer> // Platform-specific native modules | |
| 77 | } | |
| 78 | ``` | |
| 59 | 79 | |
| 60 | 80 | ## Usage Examples |
| 61 | 81 | |
| 62 | _To be added in Phase 1B_ | |
| 82 | ### Example 1: Platform-Specific Bundle | |
| 83 | ||
| 84 | ```javascript | |
| 85 | import pearPack from 'pear-pack' | |
| 86 | import Localdrive from 'localdrive' | |
| 87 | ||
| 88 | const drive = new Localdrive('./myapp') | |
| 89 | ||
| 90 | // Create linux-x64 specific bundle | |
| 91 | const { bundle, prebuilds } = await pearPack(drive, { | |
| 92 | target: 'linux-x64', // Only include linux-x64 prebuilds | |
| 93 | entry: '/index.js' | |
| 94 | }) | |
| 95 | ||
| 96 | console.log('Bundle size:', bundle.length) | |
| 97 | console.log('Prebuilds:', prebuilds.size) | |
| 98 | ``` | |
| 99 | ||
| 100 | **Use Case:** Build platform-specific distributions programmatically instead of manual prebuild pruning. | |
| 101 | ||
| 102 | ### Example 2: Multi-Platform Bundle | |
| 103 | ||
| 104 | ```javascript | |
| 105 | // Create bundle for multiple platforms | |
| 106 | const { bundle, prebuilds } = await pearPack(drive, { | |
| 107 | target: ['linux-x64', 'darwin-arm64', 'win32-x64'], | |
| 108 | entry: '/index.js' | |
| 109 | }) | |
| 110 | ||
| 111 | // This includes prebuilds for Linux, macOS M1/M2, and Windows | |
| 112 | ``` | |
| 113 | ||
| 114 | **Use Case:** Create universal bundles for specific platform combinations. | |
| 115 | ||
| 116 | ### Example 3: Minimal Bundle (No Prebuilds) | |
| 117 | ||
| 118 | ```javascript | |
| 119 | // Bundle without any native modules (smallest size) | |
| 120 | const { bundle, prebuilds } = await pearPack(drive, { | |
| 121 | target: [], // No platform-specific prebuilds | |
| 122 | entry: '/index.js' | |
| 123 | }) | |
| 124 | ||
| 125 | // App must handle missing native modules gracefully | |
| 126 | ``` | |
| 127 | ||
| 128 | **Use Case:** Distribute minimal JavaScript-only bundle, download natives on-demand at runtime. | |
| 129 | ||
| 130 | ## Package Size Optimization | |
| 131 | ||
| 132 | **Problem:** Native module prebuilds bloat package size from ~10 MB → 300+ MB | |
| 133 | ||
| 134 | **Solutions:** | |
| 135 | ||
| 136 | ### 1. Use `target` Option (Programmatic) | |
| 137 | ||
| 138 | ```javascript | |
| 139 | const opts = { | |
| 140 | target: process.platform + '-' + process.arch, // Current platform only | |
| 141 | entry: '/index.js' | |
| 142 | } | |
| 143 | ||
| 144 | const packed = await pearPack(drive, opts) | |
| 145 | // Result: ~50-60 MB for single platform | |
| 146 | ``` | |
| 147 | ||
| 148 | ### 2. Manual Prebuild Pruning (Alternative) | |
| 149 | ||
| 150 | If not using pear-pack programmatically, use a pruning script before `pear stage`: | |
| 151 | ||
| 152 | ```bash | |
| 153 | npm run prune # Remove other platform prebuilds | |
| 154 | pear stage myapp . | |
| 155 | ``` | |
| 156 | ||
| 157 | See: [pear skills](../pear/skills.md) for complete pruning script. | |
| 158 | ||
| 159 | ## Performance Comparison | |
| 160 | ||
| 161 | | Method | Size (Linux x64) | Platforms | Notes | | |
| 162 | |--------|------------------|-----------|-------| | |
| 163 | | All prebuilds | 304 MB | 13 | Default npm install | | |
| 164 | | `target: 'linux-x64'` | ~53 MB | 1 | pear-pack filtering | | |
| 165 | | Manual pruning | ~53 MB | 1 | Equivalent to target option | | |
| 166 | | No prebuilds | ~13 MB | 0 | Runtime download needed | | |
| 167 | ||
| 168 | **Recommendation:** Use `target` option when building programmatically, or manual pruning for CLI workflows. | |
| 63 | 169 | |
| 64 | 170 | ## Semantic Type |
| 65 | 171 | |
| 66 | _To be classified in Phase 2_ | |
| 172 | **Category:** Pear Build Tools | |
| 173 | ||
| 174 | **Use Case:** Bundle generation, package optimization, platform-specific builds | |
| 67 | 175 | |
| 68 | 176 | ## Related Packages |
| 69 | 177 | |
| 70 | _To be analyzed in Phase 2_ | |
| 178 | - **pear** - Main CLI that uses pear-pack internally | |
| 179 | - **pear-bundle** - Bare-bundle generation (alternative approach) | |
| 180 | - **bare-pack** - Lower-level bundle packing | |
| 181 | - **drive-bundler** - Extract bundles from drives |
| … | … | @@ -145,31 +145,212 @@ _Extracted from code analysis_ |
| 145 | 145 | |
| 146 | 146 | _See [api-extract.json](./api-extract.json) for detailed API information._ |
| 147 | 147 | |
| 148 | ## CLI Commands | |
| 148 | 149 | |
| 149 | ## Usage Examples | |
| 150 | ### Core Commands | |
| 150 | 151 | |
| 151 | _Extracted from README_ | |
| 152 | ```bash | |
| 153 | # Initialize Pear | |
| 154 | npx pear | |
| 152 | 155 | |
| 153 | ### Example 1 | |
| 156 | # Run app in development mode | |
| 157 | pear run -d <dir> | |
| 154 | 158 | |
| 155 | ```javascript | |
| 156 | This installs Pear onto the system. | |
| 159 | # Stage app to DHT | |
| 160 | pear stage <channel> <dir> | |
| 157 | 161 | |
| 158 | To complete the setup, be sure to follow instructions for setting `PATH` as output by the `npx pear` command. | |
| 162 | # Seed app on network | |
| 163 | pear seed <channel> <dir> | |
| 159 | 164 | |
| 160 | ### Help | |
| 165 | # Dump app from pear:// link | |
| 166 | pear dump <link> <dir> | |
| 167 | ||
| 168 | # Release version | |
| 169 | pear release <channel> | |
| 170 | ||
| 171 | # Get app info | |
| 172 | pear info <channel> | |
| 161 | 173 | ``` |
| 162 | 174 | |
| 163 | ### Example 2 | |
| 175 | ## Package Size Optimization | |
| 176 | ||
| 177 | ### Problem: Native Module Prebuilds | |
| 178 | ||
| 179 | Pear apps using native modules (hypercore, hyperswarm, etc.) include prebuilds for **13 platforms**: | |
| 180 | - Android: arm, arm64, ia32, x64 | |
| 181 | - iOS: arm64, arm64-simulator, x64-simulator | |
| 182 | - macOS: arm64 (M1/M2), x64 (Intel) | |
| 183 | - Linux: arm64, x64 | |
| 184 | - Windows: arm64, x64 | |
| 185 | ||
| 186 | **Impact:** A typical app grows from ~10 MB to 300+ MB with all platform binaries. | |
| 187 | ||
| 188 | ### Solution: Platform-Specific Pruning | |
| 189 | ||
| 190 | **Script:** Remove prebuilds for platforms you don't need before staging. | |
| 164 | 191 | |
| 165 | 192 | ```javascript |
| 193 | #!/usr/bin/env node | |
| 194 | const fs = require('fs') | |
| 195 | const path = require('path') | |
| 196 | const os = require('os') | |
| 197 | ||
| 198 | const currentPlatform = `${os.platform()}-${os.arch()}` | |
| 199 | ||
| 200 | function prunePrebuilds(dir, depth = 0) { | |
| 201 | if (depth > 10) return | |
| 202 | ||
| 203 | const entries = fs.readdirSync(dir, { withFileTypes: true }) | |
| 204 | ||
| 205 | for (const entry of entries) { | |
| 206 | const fullPath = path.join(dir, entry.name) | |
| 207 | ||
| 208 | if (!entry.isDirectory()) continue | |
| 209 | ||
| 210 | if (entry.name === 'prebuilds') { | |
| 211 | // Remove other platform prebuilds | |
| 212 | const platforms = fs.readdirSync(fullPath) | |
| 213 | for (const platform of platforms) { | |
| 214 | if (platform !== currentPlatform) { | |
| 215 | fs.rmSync(path.join(fullPath, platform), { recursive: true }) | |
| 216 | } | |
| 217 | } | |
| 218 | } else if (entry.name === 'node_modules') { | |
| 219 | prunePrebuilds(fullPath, depth + 1) | |
| 220 | } else if (entry.name.startsWith('@')) { | |
| 221 | // Scoped package namespace | |
| 222 | prunePrebuilds(fullPath, depth) | |
| 223 | } else { | |
| 224 | // Check for nested node_modules | |
| 225 | const nested = path.join(fullPath, 'node_modules') | |
| 226 | if (fs.existsSync(nested)) { | |
| 227 | prunePrebuilds(nested, depth + 1) | |
| 228 | } | |
| 229 | } | |
| 230 | } | |
| 231 | } | |
| 232 | ||
| 233 | prunePrebuilds('./node_modules') | |
| 234 | ``` | |
| 166 | 235 | |
| 236 | **Results:** 82-85% size reduction (300 MB → 50-60 MB) | |
| 237 | ||
| 238 | **Integration:** | |
| 239 | ```json | |
| 240 | { | |
| 241 | "scripts": { | |
| 242 | "prune": "node prune-prebuilds.js", | |
| 243 | "stage": "npm run prune && pear stage myapp ." | |
| 244 | } | |
| 245 | } | |
| 167 | 246 | ``` |
| 168 | 247 | |
| 169 | ### Example 3 | |
| 248 | ### .pearignore Optimization | |
| 170 | 249 | |
| 171 | ```javascript | |
| 250 | **.pearignore** - Exclude unnecessary files: | |
| 251 | ``` | |
| 252 | # CRITICAL: Do NOT ignore node_modules (module resolution bug) | |
| 253 | ||
| 254 | # Development files | |
| 255 | .git | |
| 256 | .gitignore | |
| 257 | *.log | |
| 258 | ||
| 259 | # Test files | |
| 260 | test/ | |
| 261 | **/test/ | |
| 262 | **/*.test.js | |
| 263 | ||
| 264 | # Documentation | |
| 265 | docs/ | |
| 266 | **/*.md | |
| 267 | !README.md | |
| 268 | ||
| 269 | # Unnecessary files in node_modules | |
| 270 | node_modules/**/.github | |
| 271 | node_modules/**/test | |
| 272 | node_modules/**/examples | |
| 273 | node_modules/**/*.md | |
| 274 | node_modules/**/LICENSE | |
| 275 | node_modules/**/CHANGELOG* | |
| 276 | node_modules/**/*.map | |
| 277 | ``` | |
| 278 | ||
| 279 | **Note:** Never ignore `node_modules` entirely - module resolution under `pear://` protocol requires it. | |
| 280 | ||
| 281 | ## Usage Examples | |
| 282 | ||
| 283 | ### Example 1: Basic App Development | |
| 284 | ||
| 285 | ```bash | |
| 286 | # Create app | |
| 287 | mkdir myapp && cd myapp | |
| 288 | npm init -y | |
| 289 | ||
| 290 | # Install dependencies | |
| 291 | npm install hypercore hyperswarm | |
| 292 | ||
| 293 | # Create index.js | |
| 294 | echo 'console.log("Hello Pear!")' > index.js | |
| 295 | ||
| 296 | # Add pear config to package.json | |
| 297 | cat > package.json <<EOF | |
| 298 | { | |
| 299 | "name": "myapp", | |
| 300 | "pear": { | |
| 301 | "type": "terminal" | |
| 302 | } | |
| 303 | } | |
| 304 | EOF | |
| 305 | ||
| 306 | # Test locally | |
| 307 | pear run -d . | |
| 308 | ||
| 309 | # Optimize and stage | |
| 310 | npm run prune # If using prune script | |
| 311 | pear stage myapp . | |
| 312 | ||
| 313 | # Seed on network | |
| 314 | pear seed myapp . | |
| 315 | ``` | |
| 316 | ||
| 317 | ### Example 2: Platform-Specific Distribution | |
| 318 | ||
| 319 | ```bash | |
| 320 | # Linux x64 (most common) | |
| 321 | node prune-prebuilds.js # Auto-detects linux-x64 | |
| 322 | pear stage myapp-linux . | |
| 323 | ||
| 324 | # macOS arm64 (on Mac M1/M2) | |
| 325 | node prune-prebuilds.js # Auto-detects darwin-arm64 | |
| 326 | pear stage myapp-macos . | |
| 327 | ||
| 328 | # Windows x64 (on Windows or cross-compile) | |
| 329 | node prune-prebuilds.js # Auto-detects win32-x64 | |
| 330 | pear stage myapp-windows . | |
| 331 | ``` | |
| 332 | ||
| 333 | ### Example 3: Production Release Workflow | |
| 334 | ||
| 335 | ```bash | |
| 336 | # 1. Optimize | |
| 337 | npm run prune | |
| 338 | ||
| 339 | # 2. Test locally | |
| 340 | pear run -d . | |
| 341 | ||
| 342 | # 3. Stage to DHT | |
| 343 | pear stage myapp . | |
| 344 | ||
| 345 | # 4. Test from DHT (different directory) | |
| 346 | cd /tmp && pear dump pear://... test && cd test | |
| 347 | pear run . | |
| 348 | ||
| 349 | # 5. Mark as release | |
| 350 | pear release myapp | |
| 172 | 351 | |
| 352 | # 6. Verify | |
| 353 | pear info myapp | |
| 173 | 354 | ``` |
| 174 | 355 | |
| 175 | 356 |