Repository navigation
Fix issues found during the connection-reuse review - #56
Merged
Merged
Conversation
The cache was keyed by IP address alone, so the result of lookup(ip, selectField) or lookup(ip, undefined, fields) was stored under the bare address and returned by a later full lookup of the same address, and a full result was returned for a later filtered lookup. bulkLookup() with fields stored filtered results the same way. Keys now include the selection: a full lookup keeps the address as its key, a single field is keyed as address/field and a field list as address?fields=a,b with the fields sorted, so the same selection in another order shares one entry. Bulk entries whose response lacks the ip field are returned but not cached, because they cannot be attributed to an address. Parameters are validated before the cache is consulted, and the empty if block around the fields validation in bulkLookup() is replaced by a plain call. Tests cover both directions for lookup() and bulkLookup(), and the README describes the keying. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The two "should not cache the information" tests performed the lookup on an instance created with ttl: 1 but then read the cache of the shared instance, which was empty regardless, so they passed without checking anything. They now wait for the entry to expire, check the cache of the instance they used and verify that the next lookup is sent to the API again. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The API returns threat.is_vpn, threat.scores (vpn_score, proxy_score, threat_score and trust_score), a top-level region_type, count as a string, and null for city, region, region_code, region_type, postal and every time_zone value when an address has no known location. None of this was declared. LookupResponse now carries these fields: the new keys are optional, the location fields are nullable and count is typed as the string the API has always sent. The README documents them and the tests check them against the sample responses, including the compile-time types. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Requests went out with undici's default User-Agent. Every request now identifies the library as ipdata-node/<version>, with the version read from package.json at runtime; the file ships with every install, so no build step or additional dependency is needed. Tests match the header on the GET of lookup() and the POST of bulkLookup(). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The badge referenced a workflow named CI, which does not exist, so it rendered as broken. It now uses the badge of .github/workflows/default.yml and links to that workflow's runs. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
undici's ProxyAgent and EnvHttpProxyAgent take the ALPN protocols of
the connection tunnelled through the proxy from requestTls, so
negotiating HTTP/2 with the API needs requestTls: { allowH2: true }
next to allowH2: true. The README dispatcher section says so and the
proxy example shows it.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The lint script ran eslint --fix, so linting rewrote files in place, also in CI where the result is discarded. npm run lint now reports problems without touching files, which is what both workflows need, and npm run lint:fix applies the automatic fixes locally. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
npm audit fix refreshes the transitive development dependencies that have fixed releases within the ranges package.json already allows: @babel/core and its helpers, baseline-browser-mapping, brace-expansion, browserslist, flatted, handlebars, js-yaml, minimatch 3.1.5 and 9.0.9, picomatch and ts-jest, among others. This clears every high and critical advisory; package.json is unchanged. Two advisories have no fix compatible with jest 29 and eslint 8: deepmerge (through jest-config) and the remaining minimatch report, which is only fixed in minimatch 11. npm lists every package that depends on them, which is why the report now shows more, lower severity entries than before. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.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
Follow-up to #55 that fixes the issues noticed during that review: the cache key ignored the requested fields,
LookupResponselagged the API, two cache tests checked the wrong instance, the README badge named a workflow that does not exist,bulkLookup()validatedfieldsinside an emptyif,npm run lintrewrote files in CI, requests carried no libraryUser-Agent, and the development dependencies had open audit advisories. No version change; every public API change is additive, and every behavioural change comes with tests (58 become 74).Changes
lookup(ip, selectField)andlookup(ip, undefined, fields)results were cached under the bare IP address and served to a later full lookup of the same address, and the other way round;bulkLookup(ips, fields)did the same. Full lookups keep the address as their key (ipdata.cache.get('1.1.1.1')still works), a single field is keyedaddress/fieldand a field listaddress?fields=a,bwith the fields sorted, so the same selection in another order shares one entry. Bulk entries whose response has noip(afieldslist that leaves it out) are returned but no longer cached. Parameters are validated before the cache is consulted, so an invalid field now throws even when the address is cached. The README's Caching section describes the keying.LookupResponsefollows the API. Newthreat.is_vpn?: boolean,threat.scores?: { vpn_score, proxy_score, threat_score, trust_score }andregion_type?: string | null;city,region,region_code,postaland everytime_zonevalue are typed nullable, as the API sends them for addresses without a known location;countis typedstring, which is what the API has always returned. Documented under Response Fields in the README..github/workflows/default.yml(theLint and Testworkflow) instead of a workflow namedCI, so it renders again.bulkLookup()fields validation. The emptyifaround the validation call is replaced by a plain call; the validators are nowvalidateSelectField/validateFieldsand return nothing instead oftrue.npm run lintiseslint "src/**"without--fix, so the lint job in both workflows no longer rewrites files;npm run lint:fixapplies the automatic fixes locally. The workflow files are unchanged.User-Agent: ipdata-node/<version>, with the version read frompackage.jsonat runtime; the file ships with every install, so this needs no build step and no new dependency. Tests match the header on the GET oflookup()and the POST ofbulkLookup().npm audit fix(without--force;package.jsonunchanged) updates the transitive tooling dependencies that have fixed releases:@babel/coreand helpers,baseline-browser-mapping,brace-expansion,browserslist,flatted,handlebars,js-yaml,minimatch3.1.5 / 9.0.9,picomatch,ts-jest. Every high and critical advisory is cleared; the two that remain are listed below.ProxyAgentandEnvHttpProxyAgenttake the ALPN protocols of the TLS connection tunnelled through the proxy fromrequestTls, so negotiating HTTP/2 with the API needsrequestTls: { allowH2: true }next toallowH2: true; the dispatcher section says so and the proxy example shows it.Not changed
deepmerge >=4.2.0(throughjest-config; the only fix is a downgrade to jest 25) andminimatch <11.0.1(fixed only in minimatch 11, which eslint 8 and jest 29 do not use). npm lists every package that depends on them, sonpm auditnow shows 38 low/moderate entries where it showed 16 before, with 0 high and 0 critical.region_typeis not added to theselectField/fieldsallow-list: the type change reflects the field in full responses, and the sample responses do not show whether the API accepts it as a filter.tsconfig.base.jsonstill targets ES2015 withlib: ["es2015"]; changing the compile target is unrelated to these fixes and deserves its own change.import/no-named-as-defaultlint warning on the test file's import line is untouched.Verification
Node v22.23.4, npm 10.9.9, run on the final tree before pushing:
rm -rf node_modules && npm cinpm run buildnpm run lintimport/no-named-as-default)npm testTests: 74 passed, 74 total(58 before)npm auditnpm pack --dry-runlib/*,LICENSE,README.md,package.json, so the runtimerequire('../package.json')resolves in the published layoutCI:
Lint and Test(default.yml) for heade9d7766, both runs green at the first attempt with the jobslint,test (20),test (22)andtest (24): push run #34 https://github.com/ipdata/node/actions/runs/41640659264 and pull_request run #35 https://github.com/ipdata/node/actions/runs/41640843022. No follow-up commits were needed.🤖 Generated with Claude Code