@squawk/airways
Advanced tools
+2
-1
@@ -5,4 +5,5 @@ /** | ||
| */ | ||
| export type { MatchRange } from '@squawk/search'; | ||
| export { createAirwayResolver } from './resolver.js'; | ||
| export type { AirwayResolver, AirwayResolverOptions, AirwayExpansionResult, AirwaySearchQuery, AirwayByFixResult, } from './resolver.js'; | ||
| export type { AirwayResolver, AirwayResolverOptions, AirwayExpansionResult, AirwaySearchQuery, AirwaySearchField, AirwaySearchResult, AirwayByFixResult, } 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,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,YAAY,EACV,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,GAClB,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,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,YAAY,EACV,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,eAAe,CAAC"} |
+0
-4
@@ -1,5 +0,1 @@ | ||
| /** | ||
| * @packageDocumentation | ||
| * Pure logic library for querying US airway data. | ||
| */ | ||
| export { createAirwayResolver } from './resolver.js'; |
+26
-5
@@ -0,1 +1,2 @@ | ||
| import type { MatchRange } from '@squawk/search'; | ||
| import type { Airway, AirwayType, AirwayWaypoint } from '@squawk/types'; | ||
@@ -19,6 +20,10 @@ /** | ||
| /** | ||
| * Options for a text search query against airway designations. | ||
| * The searchable field an {@link AirwaySearchResult} can match on. | ||
| */ | ||
| export type AirwaySearchField = 'designation'; | ||
| /** | ||
| * Options for a fuzzy text search query against airway designations. | ||
| */ | ||
| export interface AirwaySearchQuery { | ||
| /** Case-insensitive substring to match against airway designation. */ | ||
| /** Search text, matched fuzzily and case-insensitively against each airway's designation. */ | ||
| text: string; | ||
@@ -29,4 +34,19 @@ /** Maximum number of results to return. Defaults to 20. */ | ||
| types?: ReadonlySet<AirwayType>; | ||
| /** 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 airway result from a fuzzy {@link AirwayResolver.search}. | ||
| */ | ||
| export interface AirwaySearchResult { | ||
| /** The matched airway record. */ | ||
| airway: Airway; | ||
| /** Match strength in `[0, 1]`, where 1 is an exact designation match. */ | ||
| score: number; | ||
| /** Which field produced the best match, identifying what {@link AirwaySearchResult.ranges} index into. */ | ||
| matchedField: AirwaySearchField; | ||
| /** Matched character ranges within the best-matching field's text, for highlighting. */ | ||
| ranges: MatchRange[]; | ||
| } | ||
| /** | ||
| * Result from a reverse lookup of airways passing through a given fix. | ||
@@ -69,6 +89,7 @@ */ | ||
| /** | ||
| * Searches airways by designation using case-insensitive substring matching. | ||
| * Results are returned in alphabetical order by designation. | ||
| * Fuzzy-searches airways by designation. Results are scored and returned | ||
| * best-match first, each carrying the matched field and character ranges | ||
| * for highlighting. | ||
| */ | ||
| search(query: AirwaySearchQuery): Airway[]; | ||
| search(query: AirwaySearchQuery): AirwaySearchResult[]; | ||
| } | ||
@@ -75,0 +96,0 @@ /** |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAExE;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,oDAAoD;IACpD,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,oFAAoF;IACpF,SAAS,EAAE,cAAc,EAAE,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uFAAuF;IACvF,KAAK,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAE7C;;;;;;;;;;OAUG;IACH,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,qBAAqB,GAAG,SAAS,CAAC;IAElG;;;OAGG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAAC;IAE1C;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,EAAE,CAAC;CAC5C;AAOD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,cAAc,CA4GnF"} | ||
| {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAsB,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAExE;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,oDAAoD;IACpD,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,oFAAoF;IACpF,SAAS,EAAE,cAAc,EAAE,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,aAAa,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,6FAA6F;IAC7F,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uFAAuF;IACvF,KAAK,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;IAChC,oJAAoJ;IACpJ,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,KAAK,EAAE,MAAM,CAAC;IACd,0GAA0G;IAC1G,YAAY,EAAE,iBAAiB,CAAC;IAChC,wFAAwF;IACxF,MAAM,EAAE,UAAU,EAAE,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAE7C;;;;;;;;;;OAUG;IACH,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,qBAAqB,GAAG,SAAS,CAAC;IAElG;;;OAGG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAAC;IAE1C;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,iBAAiB,GAAG,kBAAkB,EAAE,CAAC;CACxD;AAOD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,cAAc,CAwGnF"} |
+15
-15
@@ -0,1 +1,2 @@ | ||
| import { fuzzySearch } from '@squawk/search'; | ||
| /** | ||
@@ -96,20 +97,19 @@ * Default maximum number of results for text search queries. | ||
| search(query) { | ||
| const limit = query.limit ?? DEFAULT_SEARCH_LIMIT; | ||
| const needle = query.text.toUpperCase(); | ||
| if (needle.length === 0) { | ||
| return []; | ||
| const options = { | ||
| keys: (airway) => [{ name: 'designation', text: airway.designation }], | ||
| limit: query.limit ?? DEFAULT_SEARCH_LIMIT, | ||
| minScore: query.minScore ?? 0, | ||
| }; | ||
| const types = query.types; | ||
| if (types) { | ||
| options.filter = (airway) => types.has(airway.type); | ||
| } | ||
| const results = []; | ||
| for (const airway of airways) { | ||
| if (query.types && !query.types.has(airway.type)) { | ||
| continue; | ||
| } | ||
| if (airway.designation.toUpperCase().includes(needle)) { | ||
| results.push(airway); | ||
| } | ||
| } | ||
| results.sort((a, b) => a.designation.localeCompare(b.designation)); | ||
| return results.slice(0, limit); | ||
| return fuzzySearch(airways, query.text, options).map((match) => ({ | ||
| airway: match.item, | ||
| score: match.score, | ||
| matchedField: match.field, | ||
| ranges: match.ranges, | ||
| })); | ||
| }, | ||
| }; | ||
| } |
+2
-1
| { | ||
| "name": "@squawk/airways", | ||
| "version": "0.4.7", | ||
| "version": "0.5.0", | ||
| "type": "module", | ||
@@ -44,2 +44,3 @@ "description": "Airway lookup, traversal, and expansion by designation, fix, or search", | ||
| "dependencies": { | ||
| "@squawk/search": "^0.1.0", | ||
| "@squawk/types": "^0.8.0" | ||
@@ -46,0 +47,0 @@ }, |
+25
-10
@@ -7,3 +7,3 @@ <h1><img src="../../../assets/squawk-logo.svg" alt="squawk logo" width="48" height="48" style="vertical-align: middle"> @squawk/airways</h1> | ||
| designation, expand route segments between fixes, find airways through a | ||
| specific fix, or search by designation. Contains no bundled data - accepts | ||
| specific fix, or fuzzy-search by designation. Contains no bundled data - accepts | ||
| an array of Airway records at initialization. For zero-config use, pair with | ||
@@ -39,4 +39,5 @@ `@squawk/airway-data`. | ||
| // Search by designation | ||
| // Fuzzy-search by designation (scored, best match first) | ||
| const results = resolver.search({ text: 'V1' }); | ||
| console.log(results[0]?.airway.designation, results[0]?.score); | ||
| ``` | ||
@@ -115,11 +116,25 @@ | ||
| Searches airways by designation using case-insensitive substring matching. | ||
| Results are returned in alphabetical order by designation. | ||
| Fuzzy-searches airways by designation. 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 airway designation | | ||
| | `limit` | number | Optional. Maximum number of results. Defaults to 20 | | ||
| | `types` | ReadonlySet\<AirwayType\> | Optional. When provided, only these airway types are returned | | ||
| | Property | Type | Description | | ||
| | ---------- | ------------------------- | ---------------------------------------------------------------------------------------- | | ||
| | `text` | string | Search text, matched fuzzily against each airway's designation | | ||
| | `limit` | number | Optional. Maximum number of results. Defaults to 20 | | ||
| | `types` | ReadonlySet\<AirwayType\> | Optional. When provided, only these airway types are returned | | ||
| | `minScore` | number | Optional. Minimum match score (exclusive) in `[0, 1]` a result must reach. Defaults to 0 | | ||
| Returns `Airway[]`. | ||
| Returns `AirwaySearchResult[]`, sorted by descending score, each containing: | ||
| - `airway` - the matched Airway record | ||
| - `score` - match strength in `[0, 1]`, where 1 is an exact designation match | ||
| - `matchedField` - which field produced the best match: `'designation'` | ||
| - `ranges` - matched character ranges within the best-matching field's text, for highlighting | ||
| ```typescript | ||
| const results = resolver.search({ text: 'V1', limit: 10 }); | ||
| for (const { airway, score } of results) { | ||
| console.log(airway.designation, score); | ||
| } | ||
| ``` |
18477
14.74%237
8.22%138
12.2%2
100%+ Added
+ Added