Package Development & Publishing Guide
Developer Guide: Gridwise npm Package & CI Infrastructure
This guide explains how gridwise is structured as an npm package, how continuous integration (CI) tests run, useful scripts for package development, and step-by-step procedures for adding or modifying code in the repository.
1. Package Architecture Overview
Gridwise is published as a modern ES Module (ESM) npm package.
File & Directory Layout
gridwise/
├── src/ # Core library source code (scan, sort, reduce, WGSL shaders, buffers)
├── index.mjs # Main package ES Module entry point (re-exports public primitives)
├── index.d.ts # TypeScript type definitions
├── package.json # Package manifest, metadata, scripts, and export mappings
├── package-lock.json # Deterministic dependency lockfile
├── README.md # Package documentation displayed on npmjs.com
├── LICENSE.txt # Apache-2.0 license
├── .github/workflows/ # GitHub Actions CI workflow definitions
├── examples/ # Code examples and regression test scripts
└── misc/ # Utility scripts (headless runner, package verification)
Key package.json Fields
"type": "module": Instructs Node.js and bundlers to treat all.mjsand.jsfiles as native ES Modules."main": "./index.mjs"&"types": "./index.d.ts": Specifies main JS and TypeScript entry points."exports": Declares modern conditional exports:"exports": { ".": { "types": "./index.d.ts", "import": "./index.mjs" } }"files": ["src/", "index.mjs", "index.d.ts", "LICENSE.txt", "README.md"]: Defines the whitelist of directories and files included in the published npm package tarball."sideEffects": false: Enables tree-shaking for web bundlers (Vite, Rollup, Webpack).
2. Helpful Development & Verification Scripts
The repository includes several npm scripts and helper tools for local development and testing:
| Script Command | What It Does | When To Use |
|---|---|---|
npm run test:wgsl |
Runs WGSL helper function tests in both hardware and emulated subgroup modes. | Use when modifying WGSL shader logic, subgroup helpers, or WGSL functions in src/wgslFunctions.mjs. |
npm run test:node |
Runs the full 54-test correctness regression suite in Node.js via webgpu (Dawn). |
Use as your primary test command when modifying primitive algorithms (DLDFScan, OneSweepSort, etc.). |
npm run test:node:update-baseline |
Updates local GPU performance baselines in examples/perf_baseline.json. |
Use when making intentional performance optimizations or after benchmarking on a new GPU. |
npm run test:package |
Builds a package tarball (npm pack), extracts it in an isolated temporary directory, and verifies ES Module exports. |
Use before pushing or publishing to ensure no exported symbols or package files are broken. |
node misc/run_headless_tests.js |
Launches a headless Chrome browser (Puppeteer) to execute browser-based regression tests. | Use to verify WebGPU execution inside a real browser environment. |
npm pack --dry-run |
Previews the exact list of files, unpacked size, and structure of the npm tarball without saving to disk. | Use whenever modifying package.json "files" or adding new top-level package files. |
3. Automated CI / Pull Request Checks
Whenever code is pushed to main or a pull request is opened, GitHub Actions automatically executes the workflow defined in .github/workflows/test.yml.
CI Environment Details
- Runner:
macos-latest(Apple Silicon runner with Metal GPU acceleration). - Execution Steps:
actions/checkout@v4— Checks out the repo code.actions/setup-node@v4— Sets up Node.js 22 environment.npm ci— Installs exact dependencies frompackage-lock.json.node misc/run_headless_tests.js— Executes browser regression tests.npm run test:node— Executes Node WebGPU correctness and timing checks.npm run test:wgsl— Executes WGSL function tests.
4. Developer Workflows & Guidelines
Scenario A: Adding a New Source File
- Place the new
.mjsfile inside thesrc/directory (e.g.,src/my_new_primitive.mjs). - Package inclusion: Because
package.json"files"specifies"src/", any file insidesrc/is automatically included in the npm package when published. You do not need to updatepackage.json. - Public API Exports: If the new file contains public classes or functions:
- Export them in
index.mjs(e.g.,export { MyPrimitive } from "./src/my_new_primitive.mjs";). - Add TypeScript type definitions to
index.d.ts. - Add the export name to the
expectedExportslist inmisc/test_package.mjs.
- Export them in
Scenario B: Adding or Updating Dependencies
- To add a runtime or development dependency:
npm install <package-name> # Runtime dependency npm install --save-dev <package-name> # Development dependency - Lockfile: Always commit both
package.jsonANDpackage-lock.json. This guarantees repeatable builds for CI and other contributors.
Scenario C: Modifying Existing Code / Primitives
- Make your code changes in
src/orexamples/. - Run local tests:
npm run test:wgsl npm run test:node npm run test:package - Commit and push your changes.
Scenario D: Publishing a New Release to npmjs.com
- Verify package integrity:
npm run test:package(Note:
"prepublishOnly": "npm run test:package"is configured inpackage.json, sonpm publishwill automatically run this test and abort if anything fails). - Bump version number:
npm version patch # For bug fixes (0.1.0 -> 0.1.1) npm version minor # For new features (0.1.0 -> 0.2.0) npm version major # For breaking changes (0.1.0 -> 1.0.0) - Publish to npm:
npm publish