Skip to content

Make morphology parsers safe to bundle in browser/React Native - #53

Merged
willwade merged 3 commits into
AACTools:mainfrom
sonicbaume:fix/browser-safe-grid3-verbs-parser
Oct 13, 2026
Merged

willwade merged 3 commits into
AACTools:mainfrom
sonicbaume:fix/browser-safe-grid3-verbs-parser

Conversation

@chrisbaume

@chrisbaume chrisbaume commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

This update uses the file and zip adapters in Grid3VerbsParser and TDSnapLexiconParser so that it can compile for React Native. However, it makes MetricsCalculator.analyze async which is a breaking change.

AI summary

Problem

Importing the browser or metrics entry points fails to bundle under Metro (Expo / React Native) with:

Unable to resolve module path from .../grid3VerbsParser.js: path could not be found...
It failed because the native React runtime does not include the Node standard library.

Grid3VerbsParser statically imported Node's path and adm-zip, and
TDSnapLexiconParser statically required better-sqlite3. adm-zip and
better-sqlite3 themselves pull in Node builtins (path, fs), so Metro fails
on the next module as soon as one is fixed.

Import stack for reference:

node_modules/@willwade/aac-processors/dist/utilities/analytics/morphology/grid3VerbsParser.js
 | import "path"
node_modules/@willwade/aac-processors/dist/utilities/analytics/metrics/core.js
 | import "../morphology/grid3VerbsParser"
node_modules/@willwade/aac-processors/dist/metrics.js
 | import "./utilities/analytics/metrics/core"

Fix

Route all I/O through the library's existing FileAdapter / ZipAdapter
abstractions (src/utils/io.ts, src/utils/zip.ts, src/utils/sqlite.ts)
instead of touching Node modules directly:

  • Grid3VerbsParser now takes a FileAdapter (default defaultFileAdapter).
  • Zips are read via getZipAdapter(...) — adm-zip on Node, jszip in the
    browser.
  • Path helpers and file-system operations come from the FileAdapter.
  • TDSnapLexiconParser takes a FileAdapter and opens databases via
    openSqliteDatabase(...) — better-sqlite3 on Node, sql.js in the browser.

Breaking change

Because the adapters are asynchronous, these methods now return promises:
Grid3VerbsParser.parseXmlFileDetailed / parseZip / parseZipDetailed /
parseCustomDirectory, TDSnapLexiconParser.parseDb,
WordFormGenerator.generateFromPos, and MetricsCalculator.analyze.
Call sites in the CLI and tests have been updated accordingly.

Verification

  • npm run type-check (both tsconfig.json and tsconfig.test.json) — pass
  • npm run lint — 0 errors
  • npm run test:ci — 92 suites, 847 passed, 1 skipped
  • End-to-end: with this change applied to @willwade/aac-processors@0.3.7, an
    Expo SDK 57 iOS production bundle builds successfully (it previously failed
    with Unable to resolve module path).

Grid3VerbsParser statically imported Node's `path` and `adm-zip`, and
TDSnapLexiconParser statically required `better-sqlite3`. Metro cannot
resolve those builtins/Node-only packages for native (and they rely on
Node shims on web), so importing the `browser` or `metrics` entry points
failed with "Unable to resolve module path"/"fs".

- Resolve `join`/`dirname`/`basename` via the existing FileAdapter
  (defaultFileAdapter), which loads `path` lazily.
- Load `adm-zip` and `fs` through getNodeRequire() instead of static
  `import`/`require`, mirroring utils/zip.ts and utils/io.ts.
- Use the existing requireBetterSqlite3() helper in TDSnapLexiconParser.

The Node-only code paths keep working; the modules can now be bundled for
web and native.
@willwade

Copy link
Copy Markdown
Collaborator

Merged — thanks Chris, this is exactly the right approach (routing through the FileAdapter/ZipAdapter abstractions rather than platform conditionals). Released as 0.4.0 since analyze() et al are now async (breaking under 0.x); I've patched aac-board-viewer in lockstep. One heads-up for your Expo use: the TD Snap lexicon path goes through sql.js on non-Node runtimes, which needs WebAssembly — if your app exercises tdsnapLexiconPath at runtime (rather than just bundling the metrics entry), worth a quick device test. Thanks again!

@willwade
willwade marked this pull request as ready for review October 13, 2026 11:44
@willwade
willwade merged commit 171372e into AACTools:main Oct 13, 2026
2 checks passed
@chrisbaume

Copy link
Copy Markdown
Contributor Author

Thanks. I've not added support for sqlite based formats yet but when I do I'll probably use a similar adapter approach so that I can use my own adapter that wraps Expo SQLite

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants