Skip to content

perf(deps): drop node-fetch in favour of the platform fetch - #116

Merged
yeboster merged 1 commit into
mainfrom
perf/native-fetch
Aug 28, 2026
Merged

perf(deps): drop node-fetch in favour of the platform fetch#116
yeboster merged 1 commit into
mainfrom
perf/native-fetch

Conversation

@yeboster

Copy link
Copy Markdown
Contributor

Summary

node-fetch was the single largest entry in the bundle at 302 KB minified — 18% of the total — and it dragged whatwg-url, form-data and mime-db in with it. Every runtime this package supports already ships a global fetch: stable in Node since v18, and present in every browser target. The dependency bought nothing.

Bundle impact

Measured with esbuild (--bundle --minify --format=esm) over dist/index.js:

minified gzipped
before 1,685,983 438,782
after 1,333,533 345,961
delta −352,450 (−20.9%) −92,821 (−21.2%)

The saving exceeds node-fetch's own 302 KB because form-data and mime-db leave with it.

Changes beyond the swap

Request timeouts. Added a 30s AbortSignal timeout. promiseRetry only advances when the underlying promise settles, so a request that never settled previously pinned the entire retry chain open indefinitely — an unbounded resource hold with no way to cancel.

Removed dead error handling in MetaNamesContractRepository.getStateAvlValue. The FetchError branch could never execute, for two independent reasons:

  1. The guarded call was returned without await, so the rejection escaped the try entirely.
  2. node-fetch sets FetchError#code for system errors (ENOTFOUND, ECONNRESET), never HTTP statuses — so code === '404' never held even if it had been reachable.

A missing AVL value is already reported as undefined by getRequest, which resolves a body only on HTTP 200. The call is now awaited and genuine transport failures go to console.error.

Test environment jsdom → node, dropping jest-environment-jsdom. jsdom does not implement fetch, so it would have failed every network test after this change. No test in the suite touches a DOM API — jsdom was masking the fact that the package depended on a non-browser fetch.

Verification

  • npx tsc --noEmit → clean.
  • npx jest -i255/255 passing, all 20 suites green.

Worth noting: on main the live-testnet integration suites fail intermittently (two different suites failed on consecutive runs of unmodified main). They now pass consistently. The domain-lookup suite went from timing out at 40s to passing in 1.2s.

Compatibility

Requires Node ≥ 20 (engines.node declares this). No public API change — getRequest gains an optional timeoutMs parameter with a default.

https://claude.ai/code/session_01GceWCwGXu66D1xEBDxZWBb

@github-actions

Copy link
Copy Markdown

Total Coverage: 87.21%

Coverage Report
File Branch Funcs Lines Uncovered Lines
src
   actions.ts 100% 100% 100%
   index.ts 100% 100% 100%
   interface.ts 100% 100% 100%
   meta-names-sdk.ts 75% 75% 95.65% 22, 44, 45
   partisia-name-system.ts 58% 87.50% 84.07% 106, 114, 12, 139, 152, 160, 164, 169, 170, 171, 178, 180, 188, 189, 19, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 22, 220, 221, 222, 29, 33, 42, 49, 54, 55, 7, 78, 82
   version.ts 100% 100% 100%
src/actions
   domain.ts 64.29% 100% 100% 35, 44, 56, 71, 74
   record.ts 77.78% 100% 100% 14, 48
src/models
   domain.ts 100% 83.33% 95.95% 45, 46, 47
   index.ts 100% 100% 100%
src/models/helpers
   domain.ts 100% 100% 100%
src/providers
   config.ts 66.67% 100% 98.11% 40, 49, 50
   index.ts 100% 100% 100%
   secrets.ts 45.45% 62.50% 78.57% 19, 23, 24, 25, 26, 27, 29, 30, 44, 50, 51, 52, 53, 56, 57, 58, 59, 62, 63, 64, 65
src/providers/config
   mainnet.ts 100% 100% 100%
   testnet.ts 100% 100% 100%
src/repositories
   contract-repository.ts 75.81% 100% 98.19% 103, 114, 123, 124, 126, 127, 129, 130, 132, 133, 142, 158, 180, 196, 34, 46, 47, 57, 63
   domain-repository.ts 60% 100% 100% 102, 113, 117, 118, 133, 142, 150, 176, 220, 225, 240, 256, 262, 269, 34, 53, 54, 96, 98, 99
   index.ts 100% 75% 100%
   record-repository.ts 71.43% 100% 100% 24, 34, 50, 60
src/repositories/contracts
   meta-names-contract-repository.ts 84.62% 88.89% 86.14% 57, 58, 59, 60, 61, 62, 63, 64, 78, 79, 80, 81, 82, 83, 84, 94
src/repositories/helpers
   avl-client.ts 80% 77.78% 61.62% 16, 22, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 95
   client.ts 90% 100% 100% 44
   contract.ts 75% 100% 92.45% 41, 42, 43, 44, 45, 50
src/transactions
   helper.ts 76.92% 85.71% 93.18% 51, 52, 53, 54, 55, 56, 57, 79, 79
   index.ts 50% 25% 31.72% 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 13, 132, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 93, 94, 95, 96, 97, 98, 99
   ledger.ts 100% 0% 43.62% 100, 101, 102, 103, 104, 105, 106, 11, 116, 117, 118, 119, 12, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 13, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 14, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 15, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 16, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 17, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 18, 180, 181, 182, 183, 184, 185, 186, 187, 188, 19, 20, 21, 26, 27, 28, 29, 30, 83, 84, 85, 86, 87, 88, 89, 97, 98, 99
src/validators
   base-validator.ts 100% 100% 100%
   domain-validator.ts 87.50% 100% 100% 29, 30, 31
   index.ts 100% 100% 100%
   record-validator.ts 100% 100% 100%
src/validators/records
   default-validator.ts 100% 100% 100%
   discord-validator.ts 100% 100% 100%
   email-validator.ts 100% 100% 100%
   main-validator.ts 100% 100% 100%
   price-validator.ts 100% 100% 100%
   regex-validator.ts 100% 100% 100%
   twitter-validator.ts 100% 100% 100%
   uri-validator.ts 100% 100% 100%
   wallet-validator.ts 100% 100% 100%
test
test/helpers
   config.ts 0% 100% 100% 7
   helper.ts 100% 60% 68% 25, 26, 27, 28, 29, 30, 31, 32, 35, 36, 37, 38, 39, 40, 41, 42
   index.ts 100% 100% 100%

node-fetch was the single largest entry in the bundle at 302 KB minified,
and pulling it in also dragged along whatwg-url, form-data and mime-db.
Every runtime this package supports already ships a global fetch: it is
stable in Node from v18 and available in every browser target, so the
dependency bought nothing.

Bundling `dist/index.js` with esbuild (minified, esm):

  before  1,685,983 bytes  (438,782 gzipped)
  after   1,333,533 bytes  (345,961 gzipped)
  delta    -352,450 bytes  (-20.9%), -92,821 gzipped (-21.2%)

The saving exceeds node-fetch's own 302 KB because form-data and mime-db
leave with it.

Alongside the swap:

- Add a 30s AbortSignal timeout to requests. `promiseRetry` only advances
  when the underlying promise settles, so a request that never settled
  previously pinned the whole retry chain open indefinitely.

- Remove the dead FetchError branch in MetaNamesContractRepository. It
  could never run for two independent reasons: the guarded call was
  returned without `await`, so rejections escaped the try/catch entirely,
  and node-fetch sets FetchError#code for system errors such as ENOTFOUND
  rather than HTTP statuses, so `code === '404'` never held. A missing AVL
  value is already reported as `undefined` by `getRequest`, which resolves
  a body only on HTTP 200. The call is now awaited and transport failures
  are logged via console.error.

- Drop jest-environment-jsdom. main already runs the suite on the node
  environment; jsdom does not implement fetch either, so the dependency is
  now dead weight and its removal is what the environment switch was for.

Rebased onto main after #115. Full suite is 255/255 passing; test wall time
for the lookup suite dropped from 40s (timing out) to 1.2s.

Requires Node >= 20, already declared in engines.

Claude-Session: https://claude.ai/code/session_01GceWCwGXu66D1xEBDxZWBb
@github-actions

Copy link
Copy Markdown

Total Coverage: 87.12%

Coverage Report
File Branch Funcs Lines Uncovered Lines
src
   actions.ts 100% 100% 100%
   index.ts 100% 100% 100%
   interface.ts 100% 100% 100%
   meta-names-sdk.ts 75% 75% 95.65% 22, 44, 45
   partisia-name-system.ts 58% 87.50% 84.07% 106, 114, 12, 139, 152, 160, 164, 169, 170, 171, 178, 180, 188, 189, 19, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 22, 220, 221, 222, 29, 33, 42, 49, 54, 55, 7, 78, 82
   version.ts 100% 100% 100%
src/actions
   domain.ts 64.29% 100% 100% 35, 44, 56, 71, 74
   record.ts 77.78% 100% 100% 14, 48
src/models
   domain.ts 100% 83.33% 95.95% 45, 46, 47
   index.ts 100% 100% 100%
src/models/helpers
   domain.ts 100% 100% 100%
src/providers
   config.ts 66.67% 100% 98.11% 40, 49, 50
   index.ts 100% 100% 100%
   secrets.ts 45.45% 62.50% 78.57% 19, 23, 24, 25, 26, 27, 29, 30, 44, 50, 51, 52, 53, 56, 57, 58, 59, 62, 63, 64, 65
src/providers/config
   mainnet.ts 100% 100% 100%
   testnet.ts 100% 100% 100%
src/repositories
   contract-repository.ts 75.81% 100% 98.19% 103, 114, 123, 124, 126, 127, 129, 130, 132, 133, 142, 158, 180, 196, 34, 46, 47, 57, 63
   domain-repository.ts 60% 100% 100% 102, 113, 117, 118, 133, 142, 150, 176, 220, 225, 240, 256, 262, 269, 34, 53, 54, 96, 98, 99
   index.ts 100% 75% 100%
   record-repository.ts 71.43% 100% 100% 24, 34, 50, 60
src/repositories/contracts
   meta-names-contract-repository.ts 84.62% 88.89% 86.14% 57, 58, 59, 60, 61, 62, 63, 64, 78, 79, 80, 81, 82, 83, 84, 94
src/repositories/helpers
   avl-client.ts 80% 77.78% 61.62% 16, 22, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 95
   client.ts 90% 100% 100% 44
   contract.ts 75% 100% 92.45% 41, 42, 43, 44, 45, 50
src/transactions
   helper.ts 76.92% 85.71% 93.18% 51, 52, 53, 54, 55, 56, 57, 79, 79
   index.ts 20% 25% 37.35% 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 13, 14, 142, 147, 15, 16, 160, 161, 162, 164, 164, 165, 166, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 93, 94, 95, 96, 97, 98, 99
   ledger.ts 100% 0% 43.62% 100, 101, 102, 103, 104, 105, 106, 11, 116, 117, 118, 119, 12, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 13, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 14, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 15, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 16, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 17, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 18, 180, 181, 182, 183, 184, 185, 186, 187, 188, 19, 20, 21, 26, 27, 28, 29, 30, 83, 84, 85, 86, 87, 88, 89, 97, 98, 99
src/validators
   base-validator.ts 100% 100% 100%
   domain-validator.ts 87.50% 100% 100% 29, 30, 31
   index.ts 100% 100% 100%
   record-validator.ts 100% 100% 100%
src/validators/records
   default-validator.ts 100% 100% 100%
   discord-validator.ts 100% 100% 100%
   email-validator.ts 100% 100% 100%
   main-validator.ts 100% 100% 100%
   price-validator.ts 100% 100% 100%
   regex-validator.ts 100% 100% 100%
   twitter-validator.ts 100% 100% 100%
   uri-validator.ts 100% 100% 100%
   wallet-validator.ts 100% 100% 100%
test
test/helpers
   config.ts 0% 100% 100% 7
   helper.ts 100% 60% 68% 25, 26, 27, 28, 29, 30, 31, 32, 35, 36, 37, 38, 39, 40, 41, 42
   index.ts 100% 100% 100%

@yeboster
yeboster merged commit d6e159c into main Aug 28, 2026
8 checks passed
@yeboster
yeboster deleted the perf/native-fetch branch August 28, 2026 20:16
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.

1 participant