|
| 1 | +# GitHub Copilot Instructions for pkg |
| 2 | + |
| 3 | +This is a TypeScript-based Node.js project that packages Node.js applications into standalone executables. The project is maintained by the yao-pkg organization and is a fork of the original vercel/pkg project. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +`pkg` is a command-line tool that: |
| 8 | + |
| 9 | +- Packages Node.js projects into executables for multiple platforms (Linux, macOS, Windows) |
| 10 | +- Supports multiple Node.js versions (node18, node20, etc.) |
| 11 | +- Uses virtual filesystem to bundle application files |
| 12 | +- Compiles JavaScript to V8 bytecode for distribution |
| 13 | +- Supports native addons (.node files) |
| 14 | +- Provides compression options (Brotli, GZip) |
| 15 | + |
| 16 | +## Repository Structure |
| 17 | + |
| 18 | +- `lib/`: TypeScript source code for the main packaging logic |
| 19 | +- `lib-es5/`: Compiled JavaScript output (generated, do not edit directly) |
| 20 | +- `prelude/`: Bootstrap code injected into packaged executables |
| 21 | +- `dictionary/`: Package-specific configuration files for known npm packages |
| 22 | +- `test/`: Comprehensive test suite with numbered test directories |
| 23 | +- `examples/`: Example projects demonstrating pkg usage |
| 24 | +- `.github/workflows/`: CI/CD configuration using GitHub Actions |
| 25 | + |
| 26 | +## Development Workflow |
| 27 | + |
| 28 | +### Building |
| 29 | + |
| 30 | +Before running tests or making changes, always build the project: |
| 31 | + |
| 32 | +```bash |
| 33 | +npm run build |
| 34 | +``` |
| 35 | + |
| 36 | +This compiles TypeScript from `lib/` to `lib-es5/` using the TypeScript compiler. |
| 37 | + |
| 38 | +For continuous development with auto-rebuild: |
| 39 | + |
| 40 | +```bash |
| 41 | +npm run start |
| 42 | +``` |
| 43 | + |
| 44 | +### Code Standards |
| 45 | + |
| 46 | +#### Required Before Each Commit |
| 47 | + |
| 48 | +- Run `npm run lint` to check both code style and ESLint rules |
| 49 | +- Run `npm run fix` to automatically fix formatting and linting issues |
| 50 | +- All changes must pass CI checks (linting, building, and tests) |
| 51 | + |
| 52 | +#### Formatting |
| 53 | + |
| 54 | +- Uses Prettier for code formatting |
| 55 | +- Single quotes for strings (configured in package.json) |
| 56 | +- Run `npm run lint:style` to check formatting |
| 57 | +- Format files with: `prettier -w "{lib,prelude,test}/**/*.{ts,js}"` |
| 58 | + |
| 59 | +#### Linting |
| 60 | + |
| 61 | +- Uses ESLint with TypeScript support |
| 62 | +- Configuration: `eslint-config-airbnb-typescript` and `eslint-config-prettier` |
| 63 | +- Run `npm run lint:code` to check for linting issues |
| 64 | +- Console statements are disallowed in production code (lint error), but allowed in test files and scripts |
| 65 | + |
| 66 | +### Testing |
| 67 | + |
| 68 | +The test suite is extensive and organized in numbered directories: |
| 69 | + |
| 70 | +```bash |
| 71 | +# Build first (required) |
| 72 | +npm run build |
| 73 | + |
| 74 | +# Run all tests |
| 75 | +npm test |
| 76 | + |
| 77 | +# Run tests for specific Node.js version |
| 78 | +npm run test:18 # Test with Node.js 18 |
| 79 | +npm run test:20 # Test with Node.js 20 |
| 80 | +npm run test:host # Test with host Node.js version |
| 81 | + |
| 82 | +# Run specific test pattern |
| 83 | +node test/test.js node20 no-npm test-50-* |
| 84 | +``` |
| 85 | + |
| 86 | +#### Test Organization |
| 87 | + |
| 88 | +- Tests are in `test/test-XX-*/` directories where XX indicates execution order |
| 89 | +- Each test directory contains a `main.js` file that runs the test |
| 90 | +- Tests use `utils.js` for common testing utilities |
| 91 | +- Special tests: |
| 92 | + - `test-79-npm/`: Tests integration with popular npm packages (only-npm) |
| 93 | + - `test-42-fetch-all/`: Verifies patches exist for all Node.js versions |
| 94 | + - `test-46-multi-arch/`: Tests cross-compilation for multiple architectures |
| 95 | + |
| 96 | +#### Writing Tests |
| 97 | + |
| 98 | +When adding new tests: |
| 99 | + |
| 100 | +1. Create a directory named `test-XX-descriptive-name/` |
| 101 | +2. Create a `main.js` file that uses the test utilities |
| 102 | +3. Use `utils.pkg.sync()` to invoke pkg within the test |
| 103 | +4. Verify output files are created correctly |
| 104 | +5. Clean up using `utils.filesAfter()` |
| 105 | + |
| 106 | +Example test structure: |
| 107 | + |
| 108 | +```javascript |
| 109 | +#!/usr/bin/env node |
| 110 | +'use strict'; |
| 111 | +const assert = require('assert'); |
| 112 | +const utils = require('../utils.js'); |
| 113 | + |
| 114 | +assert(!module.parent); |
| 115 | +assert(__dirname === process.cwd()); |
| 116 | + |
| 117 | +// Test implementation here |
| 118 | +``` |
| 119 | + |
| 120 | +### TypeScript Guidelines |
| 121 | + |
| 122 | +1. **Strict mode**: The project uses TypeScript strict mode |
| 123 | +2. **Target**: ES2017 (check tsconfig.json) |
| 124 | +3. **Module system**: CommonJS (not ES modules) |
| 125 | +4. **Type definitions**: Include type definitions for all public APIs |
| 126 | +5. **Source files**: All TypeScript files should be in `lib/` directory |
| 127 | +6. **No direct editing**: Never edit files in `lib-es5/` directly |
| 128 | + |
| 129 | +### Key Files and Conventions |
| 130 | + |
| 131 | +- `lib/index.js`: Main entry point for the pkg API |
| 132 | +- `lib/bin.js`: CLI entry point |
| 133 | +- `prelude/bootstrap.js`: Code injected into every packaged executable |
| 134 | +- `dictionary/*.js`: Special handling for specific npm packages |
| 135 | + |
| 136 | +### Dependencies |
| 137 | + |
| 138 | +- **Runtime dependencies**: Keep minimal, as they affect all packaged apps |
| 139 | +- **Native modules**: Be aware of `.node` file handling and extraction |
| 140 | +- **pkg-fetch dependency**: Used to download pre-compiled Node.js binaries |
| 141 | +- Always use exact or caret ranges for dependencies |
| 142 | + |
| 143 | +## Release Process |
| 144 | + |
| 145 | +The project uses `release-it` with conventional commits: |
| 146 | + |
| 147 | +```bash |
| 148 | +npm run release |
| 149 | +``` |
| 150 | + |
| 151 | +This interactive process: |
| 152 | + |
| 153 | +1. Runs linting checks |
| 154 | +2. Generates changelog using conventional commits |
| 155 | +3. Creates a git tag with format `v${version}` |
| 156 | +4. Pushes to GitHub and creates a release |
| 157 | +5. Publishes to npm under `@yao-pkg/pkg` |
| 158 | + |
| 159 | +### Commit Message Format |
| 160 | + |
| 161 | +Follow conventional commits format: |
| 162 | + |
| 163 | +- `feat: description` - New features |
| 164 | +- `fix: description` - Bug fixes |
| 165 | +- `refactor: description` - Code refactoring |
| 166 | +- `test: description` - Test additions |
| 167 | +- `chore: description` - Maintenance tasks |
| 168 | +- `docs: description` - Documentation changes |
| 169 | + |
| 170 | +## Common Issues and Gotchas |
| 171 | + |
| 172 | +### Virtual Filesystem |
| 173 | + |
| 174 | +- Packaged apps have files at `/snapshot/` prefix (or `C:\snapshot\` on Windows) |
| 175 | +- Use `__dirname` or `__filename` for files packaged in the snapshot |
| 176 | +- Use `process.cwd()` for runtime filesystem access |
| 177 | +- Path handling differs between packaged and non-packaged execution |
| 178 | + |
| 179 | +### Native Addons |
| 180 | + |
| 181 | +- Native addons are extracted to `$HOME/.cache/pkg/` at runtime |
| 182 | +- Must match the Node.js version specified in `--target` |
| 183 | +- `linuxstatic` target cannot load native bindings |
| 184 | +- Add `.node` files to `assets` if not detected automatically |
| 185 | + |
| 186 | +### Cross-Compilation |
| 187 | + |
| 188 | +- Bytecode generation requires running target architecture binary |
| 189 | +- Use `--no-bytecode` to disable bytecode compilation for cross-arch builds |
| 190 | +- Consider using QEMU for emulation on Linux |
| 191 | +- macOS arm64 can build x64 using Rosetta 2 |
| 192 | + |
| 193 | +### ESM Support |
| 194 | + |
| 195 | +- ESM modules require `--options experimental-require-module` (Node.js < 22.12.0) |
| 196 | +- Some packages may need special handling in dictionary files |
| 197 | +- Check existing dictionary files for examples |
| 198 | + |
| 199 | +## Best Practices for Contributing |
| 200 | + |
| 201 | +1. **Read existing code**: Look at similar functionality before implementing new features |
| 202 | +2. **Add tests**: Every new feature or bug fix should include a test |
| 203 | +3. **Update documentation**: Update README.md and DEVELOPMENT.md as needed |
| 204 | +4. **Check CI**: Ensure all CI checks pass before requesting review |
| 205 | +5. **Small PRs**: Keep pull requests focused and reasonably sized |
| 206 | +6. **Follow patterns**: Match existing code style and patterns |
| 207 | +7. **Test cross-platform**: Test on Linux, macOS, and Windows when possible |
| 208 | + |
| 209 | +## Platform-Specific Considerations |
| 210 | + |
| 211 | +### Linux |
| 212 | + |
| 213 | +- Supports both dynamic and static linking |
| 214 | +- `linuxstatic` target for maximum portability |
| 215 | +- Configure binfmt with QEMU for cross-arch testing |
| 216 | + |
| 217 | +### macOS |
| 218 | + |
| 219 | +- `arm64` support is experimental |
| 220 | +- Code signing required for arm64 binaries |
| 221 | +- Use `codesign` or `ldid` for signing |
| 222 | + |
| 223 | +### Windows |
| 224 | + |
| 225 | +- `.exe` extension required |
| 226 | +- Native modules must match target architecture |
| 227 | +- Consider post-processing with `resedit` for custom metadata |
| 228 | + |
| 229 | +## CI/CD |
| 230 | + |
| 231 | +The project uses GitHub Actions workflows: |
| 232 | + |
| 233 | +- **ci.yml**: Runs linting and builds on multiple Node.js versions and OS platforms |
| 234 | +- **test.yml**: Reusable workflow for running tests |
| 235 | +- Matrix strategy tests: Node.js 18.x, 20.x on ubuntu-latest, windows-latest, macos-latest |
| 236 | +- Linting only runs on ubuntu-latest with Node.js 18.x |
| 237 | + |
| 238 | +## Support and Resources |
| 239 | + |
| 240 | +- **Issues**: Report bugs and feature requests on GitHub |
| 241 | +- **Discussions**: Use GitHub Discussions for questions |
| 242 | +- **Documentation**: See README.md for user documentation |
| 243 | +- **Development Guide**: See DEVELOPMENT.md for development details |
| 244 | +- **Related Projects**: |
| 245 | + - [pkg-fetch](https://github.com/yao-pkg/pkg-fetch) - Pre-compiled Node.js binaries |
| 246 | + - [pkg-binaries](https://github.com/yao-pkg/pkg-binaries) - Binaries for unsupported architectures |
| 247 | + |
| 248 | +## Important Notes for Copilot Coding Agent |
| 249 | + |
| 250 | +1. **Always build before testing**: Run `npm run build` before running any tests |
| 251 | +2. **Use correct Node.js version**: The project requires Node.js >= 18.0.0 |
| 252 | +3. **Respect TypeScript compilation**: Edit `lib/*.ts` files, not `lib-es5/*.js` files |
| 253 | +4. **Maintain test numbering**: When adding tests, choose appropriate test number (XX in test-XX-name) |
| 254 | +5. **Check existing dictionary files**: Before adding new package support, review existing dictionary files for patterns |
| 255 | +6. **Preserve backward compatibility**: This tool is widely used; breaking changes need careful consideration |
| 256 | +7. **Cross-platform testing**: When possible, verify changes work on Linux, macOS, and Windows |
| 257 | +8. **Native addon handling**: Be extra careful with changes affecting native addon loading and extraction |
| 258 | +9. **Snapshot filesystem**: Changes to virtual filesystem handling require thorough testing |
| 259 | +10. **Performance matters**: Packaging time and executable size are important metrics |
| 260 | + |
| 261 | +## Git Workflow |
| 262 | + |
| 263 | +- **Default branch**: `main` |
| 264 | +- **Branch protection**: Requires passing CI checks |
| 265 | +- **Tag format**: `v${version}` (e.g., v6.10.0) |
| 266 | +- **Commit style**: Conventional commits for changelog generation |
0 commit comments