feat!: add browser support with unified MBTiles.open() API#1
Merged
gmaclennan merged 22 commits intomainfrom Mar 17, 2026
Merged
feat!: add browser support with unified MBTiles.open() API#1gmaclennan merged 22 commits intomainfrom
gmaclennan merged 22 commits intomainfrom
Conversation
- Add browser entry point (index.browser.js) with async MBTiles.open() factory
that accepts File, ArrayBuffer, or Uint8Array sources
- Extract shared validation logic into lib/validate.js, accepting a query
function adapter so both better-sqlite3 and sqlite-wasm can use it
- Simplify lib/schema.js to a thin wrapper over shared validate
- Add conditional exports in package.json ("browser" → index.browser.js)
- Migrate tests from node:test to vitest with both node and browser projects
- Add browser tests via @vitest/browser with Playwright (chromium)
- Add GitHub Actions CI workflow for node (v20, v22) and browser tests
- Remove Buffer dependency from shared code for browser compatibility
https://claude.ai/code/session_01MQtSRZzGmAprLcBNK22mio
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
This comment has been minimized.
This comment has been minimized.
- Remove lib/schema.js, inline the one-line adapter into index.js - Create test/shared.js with registerSharedTests() that both node and browser test files use, ensuring feature parity between environments - Both environments now run identical tests for getTile, iterator, metadata, error handling, and close behavior - Add platform-specific browser instances: webkit on macOS, firefox locally (skipped in CI due to flakiness) - Update CI workflow following zip-writer pattern: Playwright browser caching, npm caching via setup-node, ubuntu + macOS matrix https://claude.ai/code/session_01MQtSRZzGmAprLcBNK22mio
Add comprehensive tests for validate.js covering: - Missing tiles/metadata tables and wrong column types - Missing name metadata, PBF without json metadata - Invalid minzoom/maxzoom/bounds/center string values - Explicit vs derived minzoom, maxzoom, bounds, center - JSON metadata merging precedence - Format detection, scheme override, center zoom calculation Fix bug where explicit minzoom=0 was ignored because `!0 === true`. Changed `!metadata['minzoom']` to `metadata['minzoom'] == null`. Also add test for node constructor accepting a Database instance. https://claude.ai/code/session_01MQtSRZzGmAprLcBNK22mio
- actions/checkout@v4 → v6 - actions/setup-node@v4 → v6 (caching enabled by default) - actions/cache@v4 → v5 - Add Node 24 to test matrix - Remove branch filter from pull_request trigger - Remove claude/** from push trigger https://claude.ai/code/session_01MQtSRZzGmAprLcBNK22mio
Use vite@7 instead of v8 to avoid socket security warnings. Remove legacy test/test.js (node:test based) now replaced by vitest-based test/test.test.js. https://claude.ai/code/session_01MQtSRZzGmAprLcBNK22mio
Vite must remain a devDependency (pinned to v7) so npm ci installs it in CI. The previous commit incorrectly removed it entirely. https://claude.ai/code/session_01MQtSRZzGmAprLcBNK22mio
Vite v7 pre-bundles @sqlite.org/sqlite-wasm by default, which breaks the wasm file's import.meta.url resolution. Add optimizeDeps.exclude and COOP/COEP headers to match mbtiles-viewer's working config. https://claude.ai/code/session_01MQtSRZzGmAprLcBNK22mio
Cover both Node.js and browser entry points, document the bundler configuration needed for @sqlite.org/sqlite-wasm (optimizeDeps.exclude), and expand API documentation with metadata properties, coordinate system notes, and platform differences. https://claude.ai/code/session_01MQtSRZzGmAprLcBNK22mio
- Return Uint8Array from Node entry point instead of Buffer for consistent API across platforms - Add private symbol guard to browser MBTiles constructor to enforce use of MBTiles.open() - Update README to reflect unified Uint8Array type https://claude.ai/code/session_01MQtSRZzGmAprLcBNK22mio
Create a Uint8Array view over the Buffer's underlying ArrayBuffer rather than copying the bytes, for zero-copy performance. https://claude.ai/code/session_01MQtSRZzGmAprLcBNK22mio
Drop the Node-only readableStream() method. Consumers can use the sync iterator directly or wrap with Readable.from() if needed. https://claude.ai/code/session_01MQtSRZzGmAprLcBNK22mio
Rename test.test.js → node.test.js and test.browser.test.js → browser.test.js for clarity. Update vitest config globs to match. https://claude.ai/code/session_01MQtSRZzGmAprLcBNK22mio
When running in a Web Worker with OPFS support, MBTiles.open() now copies the file to the Origin Private File System and opens it with OpfsDb, avoiding loading the entire database into wasm memory. Falls back to sqlite3_deserialize when OPFS is unavailable. close() is now async in the browser to handle OPFS file cleanup. https://claude.ai/code/session_01MQtSRZzGmAprLcBNK22mio
Add a browser test that spawns a Web Worker, opens an MBTiles file via OPFS (OpfsDb), reads a tile, and verifies the data. This exercises the OPFS code path that the main-thread tests cannot. Move better-sqlite3 and @sqlite.org/sqlite-wasm to optionalDependencies so browser-only consumers don't need a C++ compiler for better-sqlite3, and Node-only consumers don't download the wasm file unnecessarily. https://claude.ai/code/session_01MQtSRZzGmAprLcBNK22mio
MBTiles.open() now accepts a string (OPFS file path) to open directly with OpfsDb, leaving file management to the consumer. Non-string sources (File, ArrayBuffer, Uint8Array) still use sqlite3_deserialize in-memory. close() is sync again since there's no OPFS cleanup to do. The OPFS worker test is skipped when crossOriginIsolated is false (requires COOP/COEP headers for SharedArrayBuffer). https://claude.ai/code/session_01MQtSRZzGmAprLcBNK22mio
…lution The package was in optionalDependencies which caused vite to fail resolving the import in CI. It's a required runtime dependency for the browser entry point, so it belongs in dependencies. Only better-sqlite3 needs to be optional (native compilation, not used in browsers). https://claude.ai/code/session_01MQtSRZzGmAprLcBNK22mio
… plugin - Add configureServer plugin to set COOP/COEP headers for cross-origin isolation - Add --enable-features=SharedArrayBuffer Chromium launch arg to ensure SharedArrayBuffer is available (vitest browser mode ignores server.headers) - Remove skipIf condition from OPFS worker test so it always runs https://claude.ai/code/session_01MQtSRZzGmAprLcBNK22mio
…ers)" This reverts commit f16bca2.
- Add server.headers for COOP/COEP alongside configureServer middleware to ensure cross-origin isolation headers reach all browsers - Clean up stale OPFS files before writing to avoid lock conflicts - Add retry logic for createSyncAccessHandle() to handle transient WebKit OPFS errors https://claude.ai/code/session_01MQtSRZzGmAprLcBNK22mio
gmaclennan
pushed a commit
that referenced
this pull request
Mar 17, 2026
## Optic Release Automation This **draft** PR is opened by Github action [optic-release-automation-action](https://github.com/nearform-actions/optic-release-automation-action). A new **draft** GitHub release [v2.0.0](https://github.com/digidem/mbtiles-reader/releases/tag/untagged-b38177ed612fac3ea7fc) has been created. Release author: @gmaclennan #### If you want to go ahead with the release, please merge this PR. When you merge: - The GitHub release will be published - No npm package will be published as configured - No major or minor tags will be updated as configured #### If you close the PR - The new draft release will be deleted and nothing will change ## What's Changed * feat!: add browser support with unified MBTiles.open() API by @gmaclennan in #1 * chore: add release workflow by @gmaclennan in #2 * chore: update deps by @gmaclennan in #3 ## New Contributors * @gmaclennan made their first contribution in #1 **Full Changelog**: v1.0.0...v2.0.0 <!-- <release-meta>{"id":297911516,"version":"v2.0.0","npmTag":"latest","opticUrl":"https://optic-zf3votdk5a-ew.a.run.app/api/generate/"}</release-meta> --> Co-authored-by: gmaclennan <actions@users.noreply.github.com>
This was referenced Mar 17, 2026
gmaclennan
pushed a commit
that referenced
this pull request
Mar 17, 2026
## Optic Release Automation This **draft** PR is opened by Github action [optic-release-automation-action](https://github.com/nearform-actions/optic-release-automation-action). A new **draft** GitHub release [v2.0.1](https://github.com/digidem/mbtiles-reader/releases/tag/untagged-29d8d7326e05e2099730) has been created. Release author: @gmaclennan #### If you want to go ahead with the release, please merge this PR. When you merge: - The GitHub release will be published - No npm package will be published as configured - No major or minor tags will be updated as configured #### If you close the PR - The new draft release will be deleted and nothing will change ## What's Changed * feat!: add browser support with unified MBTiles.open() API by @gmaclennan in #1 * chore: add release workflow by @gmaclennan in #2 * chore: update deps by @gmaclennan in #3 * [OPTIC-RELEASE-AUTOMATION] release/v2.0.0 by @optic-release-automation[bot] in #4 * chore: add repository to package.json by @gmaclennan in #5 ## New Contributors * @gmaclennan made their first contribution in #1 * @optic-release-automation[bot] made their first contribution in #4 **Full Changelog**: v1.0.0...v2.0.1 <!-- <release-meta>{"id":297980268,"version":"v2.0.1","npmTag":"latest","opticUrl":"https://optic-zf3votdk5a-ew.a.run.app/api/generate/"}</release-meta> --> Co-authored-by: gmaclennan <actions@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
@sqlite.org/sqlite-wasmvia conditional"browser"exportnew MBTiles()constructor with asyncMBTiles.open()on both platforms, unifying the API across Node.js and browserArrayBufferandUint8Array; Node.js also accepts file paths andbetter-sqlite3Database instances; browser also acceptsFileand OPFS paths (in a Worker)lib/validate.jstypesfields for correct TypeScript resolution withmoduleResolution: "bundler"Breaking changes
new MBTiles(path)→await MBTiles.open(path)— the constructor is now private on both platformsbetter-sqlite3moved fromdependenciestooptionalDependenciesTest plan
npm run test:node) — 34 testsnpm run test:browser) — Playwright chromium/firefox/webkitnpx publintreports no issuesmoduleResolution: "nodenext","bundler", and"bundler"withcustomConditions: ["browser"]🤖 Generated with Claude Code