Migrate from CommonJS to ESM - #2
Open
RichardLitt wants to merge 5 commits into
Open
Conversation
Wires up `npm test` (and `npm run test:spec`) using the `node:test` module, avoiding a new dependency. Covers the pure functions in helpers.js, the lookups in bandingCodes.js, and the main predicates in filters.js (dateFilter, completeChecklistFilter, locationFilter). Fixture lives in test/fixtures/ so tests don't depend on the large committed data files.
Adds ebd_*.{txt,csv}, MyEBirdData.csv, results.{csv,json}, and .DS_Store
to .gitignore so these don't sneak into a future `git add .`. Several
multi-megabyte files were already sitting untracked at the repo root.
@turf/center-of-mass returned a point in New York for West Haven, VT (the town has a complex border on Lake Champlain). turf.center returns the bounding-box center, which lands inside the polygon. Drops the now- unused @turf/center-of-mass import.
Mechanical conversion of the entire ebird-ext source to ECMAScript
modules. Adds "type": "module" to package.json so Node treats every
.js file as ESM.
- `require` / `module.exports` -> `import` / `export` throughout
- Local imports include the explicit `.js` extension (required by Node ESM)
- JSON imports use `with { type: 'json' }` (Node 18.20+ / 20.10+)
- `require('fs').promises` -> `import { promises as fs } from 'node:fs'`
- `__dirname` in scripts/arizona-records/BRCRecordsInJSonToCSV.js
reconstructed from `import.meta.url`
- index.js and hotspots.js export both named bindings and a default
object so existing React-site `import x from './ebird-ext/index.js'`
imports keep working alongside named imports from tests + CLI
- Two scripts that conditionally `require()` JSON files generated on
demand by readEBirdDb.js (joinTownJson.js, region-counts/joinRegionJson.js,
read250.js, readTownStats.js) use `createRequire` from `node:module`
so the conditional loading pattern survives intact
- One naming collision fixed: scripts/json2csv.js imports the json2csv
package as `json2csvPkg` to avoid shadowing a local `json2csv`
Transform variable
No behavior changes. 24 existing tests still pass.
Known follow-ups (deferred to hygiene phase):
- The parent site (birdinginvermont.com) bundles ebird-ext via Webpack
5.89; `with { type: 'json' }` requires Webpack 5.91+. The site won't
pick up these ESM changes until its submodule ref is bumped, at which
point Webpack also needs upgrading.
- `meow` is referenced by cli.js / norwich.js but missing from
package.json dependencies (pre-existing).
- The fs/io paths in index.js and hotspots.js still crash if imported
by a browser (pre-existing; will be addressed by splitting I/O into a
Node-only module).
This was referenced May 23, 2026
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
Mechanical conversion of the entire ebird-ext source to ECMAScript modules. Adds
"type": "module"topackage.jsonso Node treats every.jsfile as ESM.require/module.exports→import/exportthroughout.jsextension (required by Node ESM)with { type: 'json' }(Node 18.20+ / 20.10+)require('fs').promises→import { promises as fs } from 'node:fs'__dirnameinscripts/arizona-records/BRCRecordsInJSonToCSV.jsreconstructed fromimport.meta.urlindex.jsandhotspots.jsexport both named bindings and a default object so existing React-siteimport x from './ebird-ext/index.js'imports keep working alongside named imports from tests + CLIrequire()JSON files generated on demand byreadEBirdDb.js(joinTownJson.js,region-counts/joinRegionJson.js,read250.js,readTownStats.js) usecreateRequirefromnode:moduleso the conditional loading pattern survives intactscripts/json2csv.jsimports thejson2csvpackage asjson2csvPkgto avoid shadowing a localjson2csvTransform variableNo behavior changes. 24 existing tests still pass.
Test plan
npm test— 24/24 passingnode --checkpasses on every.jsfilenode -e "import main from './index.js'; ..."loadsindex.jsand shows all 25 exportsnpm run build. Will need a follow-up PR there to bump Webpack 5.89 → 5.91+ forwith { type: 'json' }support before the submodule ref is updated.Known follow-ups (deferred to hygiene phase)
meowis referenced bycli.js/norwich.jsbut missing frompackage.json(pre-existing bug)fs/IO paths inindex.jsandhotspots.jsstill crash if imported by a browser (pre-existing; splitting I/O into a Node-only module is planned for the hygiene/refactor phase)