@squawk/fixes
Advanced tools
+2
-1
@@ -5,4 +5,5 @@ /** | ||
| */ | ||
| export type { MatchRange } from '@squawk/search'; | ||
| export { createFixResolver } from './resolver.js'; | ||
| export type { FixResolver, FixResolverOptions, NearestFixQuery, NearestFixResult, FixSearchQuery, } from './resolver.js'; | ||
| export type { FixResolver, FixResolverOptions, NearestFixQuery, NearestFixResult, FixSearchQuery, FixSearchField, FixSearchResult, } from './resolver.js'; | ||
| //# sourceMappingURL=index.d.ts.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,YAAY,EACV,WAAW,EACX,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,cAAc,GACf,MAAM,eAAe,CAAC"} | ||
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,YAAY,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,YAAY,EACV,WAAW,EACX,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,eAAe,GAChB,MAAM,eAAe,CAAC"} |
+0
-4
@@ -1,5 +0,1 @@ | ||
| /** | ||
| * @packageDocumentation | ||
| * Pure logic library for querying US fix/waypoint data. | ||
| */ | ||
| export { createFixResolver } from './resolver.js'; |
+26
-5
@@ -0,1 +1,2 @@ | ||
| import type { MatchRange } from '@squawk/search'; | ||
| import type { Fix, FixUseCode } from '@squawk/types'; | ||
@@ -34,6 +35,10 @@ /** | ||
| /** | ||
| * Options for a text search query against fix identifiers. | ||
| * The searchable field a {@link FixSearchResult} can match on. | ||
| */ | ||
| export type FixSearchField = 'identifier'; | ||
| /** | ||
| * Options for a fuzzy text search query against fix identifiers. | ||
| */ | ||
| export interface FixSearchQuery { | ||
| /** Case-insensitive substring to match against fix identifier. */ | ||
| /** Search text, matched fuzzily and case-insensitively against each fix's identifier. */ | ||
| text: string; | ||
@@ -44,4 +49,19 @@ /** Maximum number of results to return. Defaults to 20. */ | ||
| useCodes?: ReadonlySet<FixUseCode>; | ||
| /** Minimum match score (exclusive) in `[0, 1]` a result must reach. Defaults to 0, which keeps every match. Raise it to drop weak fuzzy matches. */ | ||
| minScore?: number; | ||
| } | ||
| /** | ||
| * A scored fix result from a fuzzy {@link FixResolver.search}. | ||
| */ | ||
| export interface FixSearchResult { | ||
| /** The matched fix record. */ | ||
| fix: Fix; | ||
| /** Match strength in `[0, 1]`, where 1 is an exact identifier match. */ | ||
| score: number; | ||
| /** Which field produced the best match, identifying what {@link FixSearchResult.ranges} index into. */ | ||
| matchedField: FixSearchField; | ||
| /** Matched character ranges within the best-matching field's text, for highlighting. */ | ||
| ranges: MatchRange[]; | ||
| } | ||
| /** | ||
| * A stateless resolver providing fix lookup methods. | ||
@@ -62,6 +82,7 @@ */ | ||
| /** | ||
| * Searches fixes by identifier using case-insensitive substring matching. | ||
| * Results are returned in alphabetical order by identifier. | ||
| * Fuzzy-searches fixes by identifier. Results are scored and returned | ||
| * best-match first, each carrying the matched field and character ranges | ||
| * for highlighting. | ||
| */ | ||
| search(query: FixSearchQuery): Fix[]; | ||
| search(query: FixSearchQuery): FixSearchResult[]; | ||
| } | ||
@@ -68,0 +89,0 @@ /** |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,iDAAiD;IACjD,IAAI,EAAE,GAAG,EAAE,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,4CAA4C;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,0DAA0D;IAC1D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sFAAsF;IACtF,QAAQ,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,8BAA8B;IAC9B,GAAG,EAAE,GAAG,CAAC;IACT,0DAA0D;IAC1D,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sFAAsF;IACtF,QAAQ,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,EAAE,CAAC;IAE9B;;;OAGG;IACH,OAAO,CAAC,KAAK,EAAE,eAAe,GAAG,gBAAgB,EAAE,CAAC;IAEpD;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,cAAc,GAAG,GAAG,EAAE,CAAC;CACtC;AAiBD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,WAAW,CAgE1E"} | ||
| {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAsB,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,iDAAiD;IACjD,IAAI,EAAE,GAAG,EAAE,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,4CAA4C;IAC5C,GAAG,EAAE,MAAM,CAAC;IACZ,0DAA0D;IAC1D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sFAAsF;IACtF,QAAQ,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,8BAA8B;IAC9B,GAAG,EAAE,GAAG,CAAC;IACT,0DAA0D;IAC1D,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,YAAY,CAAC;AAE1C;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,yFAAyF;IACzF,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sFAAsF;IACtF,QAAQ,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;IACnC,oJAAoJ;IACpJ,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,8BAA8B;IAC9B,GAAG,EAAE,GAAG,CAAC;IACT,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,uGAAuG;IACvG,YAAY,EAAE,cAAc,CAAC;IAC7B,wFAAwF;IACxF,MAAM,EAAE,UAAU,EAAE,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,EAAE,CAAC;IAE9B;;;OAGG;IACH,OAAO,CAAC,KAAK,EAAE,eAAe,GAAG,gBAAgB,EAAE,CAAC;IAEpD;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,cAAc,GAAG,eAAe,EAAE,CAAC;CAClD;AAiBD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,WAAW,CA4D1E"} |
+15
-15
| import { greatCircle } from '@squawk/geo'; | ||
| import { fuzzySearch } from '@squawk/search'; | ||
| /** | ||
@@ -67,20 +68,19 @@ * Default maximum distance in nautical miles for nearest-fix queries. | ||
| search(query) { | ||
| const limit = query.limit ?? DEFAULT_SEARCH_LIMIT; | ||
| const needle = query.text.toUpperCase(); | ||
| if (needle.length === 0) { | ||
| return []; | ||
| const options = { | ||
| keys: (fix) => [{ name: 'identifier', text: fix.identifier }], | ||
| limit: query.limit ?? DEFAULT_SEARCH_LIMIT, | ||
| minScore: query.minScore ?? 0, | ||
| }; | ||
| const useCodes = query.useCodes; | ||
| if (useCodes) { | ||
| options.filter = (fix) => useCodes.has(fix.useCode); | ||
| } | ||
| const results = []; | ||
| for (const fix of fixes) { | ||
| if (query.useCodes && !query.useCodes.has(fix.useCode)) { | ||
| continue; | ||
| } | ||
| if (fix.identifier.toUpperCase().includes(needle)) { | ||
| results.push(fix); | ||
| } | ||
| } | ||
| results.sort((a, b) => a.identifier.localeCompare(b.identifier)); | ||
| return results.slice(0, limit); | ||
| return fuzzySearch(fixes, query.text, options).map((match) => ({ | ||
| fix: match.item, | ||
| score: match.score, | ||
| matchedField: match.field, | ||
| ranges: match.ranges, | ||
| })); | ||
| }, | ||
| }; | ||
| } |
+2
-1
| { | ||
| "name": "@squawk/fixes", | ||
| "version": "0.3.7", | ||
| "version": "0.4.0", | ||
| "type": "module", | ||
@@ -45,2 +45,3 @@ "description": "Fix/waypoint queries by identifier, location, or name search", | ||
| "@squawk/geo": "^0.4.3", | ||
| "@squawk/search": "^0.1.0", | ||
| "@squawk/types": "^0.8.0" | ||
@@ -47,0 +48,0 @@ }, |
+25
-10
@@ -6,3 +6,3 @@ <h1><img src="../../../assets/squawk-logo.svg" alt="squawk logo" width="48" height="48" style="vertical-align: middle"> @squawk/fixes</h1> | ||
| Pure logic library for querying US fix/waypoint data. Look up fixes by | ||
| identifier, geographic proximity, or identifier search. Contains no bundled | ||
| identifier, geographic proximity, or fuzzy identifier search. Contains no bundled | ||
| data - accepts an array of Fix records at initialization. For zero-config use, | ||
@@ -30,4 +30,5 @@ pair with `@squawk/fix-data`. | ||
| // Search by identifier | ||
| // Fuzzy-search by identifier (scored, best match first) | ||
| const results = resolver.search({ text: 'BOS' }); | ||
| console.log(results[0]?.fix.identifier, results[0]?.score); | ||
| ``` | ||
@@ -105,11 +106,25 @@ | ||
| Searches fixes by identifier using case-insensitive substring matching. | ||
| Results are returned in alphabetical order by identifier. | ||
| Fuzzy-searches fixes by identifier. Matching is case-insensitive and tolerant of | ||
| prefixes, substrings, subsequences, and small typos. Results are scored and | ||
| returned best-match first. | ||
| | Property | Type | Description | | ||
| | ---------- | ------------------------ | --------------------------------------------------------------------- | | ||
| | `text` | string | Case-insensitive substring to match against fix identifier | | ||
| | `limit` | number | Optional. Maximum number of results. Defaults to 20 | | ||
| | `useCodes` | ReadonlySet\<FixUseCode> | Optional. When provided, only fixes with these use codes are returned | | ||
| | Property | Type | Description | | ||
| | ---------- | ------------------------ | ---------------------------------------------------------------------------------------- | | ||
| | `text` | string | Search text, matched fuzzily against each fix's identifier | | ||
| | `limit` | number | Optional. Maximum number of results. Defaults to 20 | | ||
| | `useCodes` | ReadonlySet\<FixUseCode> | Optional. When provided, only fixes with these use codes are returned | | ||
| | `minScore` | number | Optional. Minimum match score (exclusive) in `[0, 1]` a result must reach. Defaults to 0 | | ||
| Returns `Fix[]`. | ||
| Returns `FixSearchResult[]`, sorted by descending score, each containing: | ||
| - `fix` - the matched Fix record | ||
| - `score` - match strength in `[0, 1]`, where 1 is an exact identifier match | ||
| - `matchedField` - which field produced the best match: `'identifier'` | ||
| - `ranges` - matched character ranges within the best-matching field's text, for highlighting | ||
| ```typescript | ||
| const results = resolver.search({ text: 'BOS', limit: 10 }); | ||
| for (const { fix, score } of results) { | ||
| console.log(fix.identifier, score); | ||
| } | ||
| ``` |
16286
16.09%199
9.94%128
13.27%3
50%+ Added
+ Added