@squawk/procedures
Advanced tools
+2
-1
@@ -6,4 +6,5 @@ /** | ||
| */ | ||
| export type { MatchRange } from '@squawk/search'; | ||
| export { createProcedureResolver } from './resolver.js'; | ||
| export type { ProcedureResolver, ProcedureResolverOptions, ProcedureExpansionResult, ProcedureSearchQuery, } from './resolver.js'; | ||
| export type { ProcedureResolver, ProcedureResolverOptions, ProcedureExpansionResult, ProcedureSearchField, ProcedureSearchQuery, ProcedureSearchResult, } 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;;;;GAIG;AACH,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,YAAY,EACV,iBAAiB,EACjB,wBAAwB,EACxB,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,eAAe,CAAC"} | ||
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,YAAY,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,YAAY,EACV,iBAAiB,EACjB,wBAAwB,EACxB,wBAAwB,EACxB,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,eAAe,CAAC"} |
+0
-5
@@ -1,6 +0,1 @@ | ||
| /** | ||
| * @packageDocumentation | ||
| * Pure logic library for querying US instrument procedure data (SIDs, | ||
| * STARs, and Instrument Approach Procedures) sourced from FAA CIFP. | ||
| */ | ||
| export { createProcedureResolver } from './resolver.js'; |
+26
-6
@@ -0,1 +1,2 @@ | ||
| import type { MatchRange } from '@squawk/search'; | ||
| import type { ApproachType, Procedure, ProcedureLeg, ProcedureType } from '@squawk/types'; | ||
@@ -19,6 +20,10 @@ /** | ||
| /** | ||
| * Options for a text search query against procedure names and identifiers. | ||
| * The searchable fields a procedure {@link ProcedureSearchResult} can match on. | ||
| */ | ||
| export type ProcedureSearchField = 'identifier' | 'name'; | ||
| /** | ||
| * Options for a fuzzy text search query against procedure identifiers and names. | ||
| */ | ||
| export interface ProcedureSearchQuery { | ||
| /** Case-insensitive substring matched against name and identifier. */ | ||
| /** Search text, matched fuzzily and case-insensitively against each procedure's identifier and name. */ | ||
| text: string; | ||
@@ -31,4 +36,19 @@ /** Maximum number of results to return. Defaults to 20. */ | ||
| approachType?: ApproachType; | ||
| /** 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 procedure result from a fuzzy {@link ProcedureResolver.search}. | ||
| */ | ||
| export interface ProcedureSearchResult { | ||
| /** The matched procedure record. */ | ||
| procedure: Procedure; | ||
| /** Match strength in `[0, 1]`, where 1 is an exact identifier or name match. */ | ||
| score: number; | ||
| /** Which field produced the best match, identifying what {@link ProcedureSearchResult.ranges} index into. */ | ||
| matchedField: ProcedureSearchField; | ||
| /** Matched character ranges within the best-matching field's text, for highlighting. */ | ||
| ranges: MatchRange[]; | ||
| } | ||
| /** | ||
| * A stateless resolver providing instrument procedure lookup, filtering, | ||
@@ -90,7 +110,7 @@ * and expansion methods against a pre-indexed dataset. | ||
| /** | ||
| * Searches procedures by name or identifier using case-insensitive | ||
| * substring matching. Results are returned sorted by airport then | ||
| * identifier. | ||
| * Fuzzy-searches procedures across identifier and name. Results are scored and | ||
| * returned best-match first, each carrying the matched field and character | ||
| * ranges for highlighting. | ||
| */ | ||
| search(query: ProcedureSearchQuery): Procedure[]; | ||
| search(query: ProcedureSearchQuery): ProcedureSearchResult[]; | ||
| } | ||
@@ -97,0 +117,0 @@ /** |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,SAAS,EAET,YAAY,EAEZ,aAAa,EACd,MAAM,eAAe,CAAC;AAEvB;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,+DAA+D;IAC/D,IAAI,EAAE,SAAS,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,uCAAuC;IACvC,SAAS,EAAE,SAAS,CAAC;IACrB,2EAA2E;IAC3E,IAAI,EAAE,YAAY,EAAE,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,uEAAuE;IACvE,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,CAAC;IAE9C;;;OAGG;IACH,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;IAErF;;;OAGG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,CAAC;IAE1C;;;;;OAKG;IACH,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,CAAC;IAEnE;;OAEG;IACH,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,SAAS,EAAE,CAAC;IAEzC;;OAEG;IACH,cAAc,CAAC,YAAY,EAAE,YAAY,GAAG,SAAS,EAAE,CAAC;IAExD;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CACJ,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,cAAc,CAAC,EAAE,MAAM,GACtB,wBAAwB,GAAG,SAAS,CAAC;IAExC;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,oBAAoB,GAAG,SAAS,EAAE,CAAC;CAClD;AAOD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,wBAAwB,GAAG,iBAAiB,CAkJ5F"} | ||
| {"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,EACV,YAAY,EACZ,SAAS,EAET,YAAY,EAEZ,aAAa,EACd,MAAM,eAAe,CAAC;AAEvB;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,+DAA+D;IAC/D,IAAI,EAAE,SAAS,EAAE,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,uCAAuC;IACvC,SAAS,EAAE,SAAS,CAAC;IACrB,2EAA2E;IAC3E,IAAI,EAAE,YAAY,EAAE,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,YAAY,GAAG,MAAM,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,wGAAwG;IACxG,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,uEAAuE;IACvE,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,oJAAoJ;IACpJ,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,oCAAoC;IACpC,SAAS,EAAE,SAAS,CAAC;IACrB,gFAAgF;IAChF,KAAK,EAAE,MAAM,CAAC;IACd,6GAA6G;IAC7G,YAAY,EAAE,oBAAoB,CAAC;IACnC,wFAAwF;IACxF,MAAM,EAAE,UAAU,EAAE,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,CAAC;IAE9C;;;OAGG;IACH,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;IAErF;;;OAGG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,CAAC;IAE1C;;;;;OAKG;IACH,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,CAAC;IAEnE;;OAEG;IACH,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,SAAS,EAAE,CAAC;IAEzC;;OAEG;IACH,cAAc,CAAC,YAAY,EAAE,YAAY,GAAG,SAAS,EAAE,CAAC;IAExD;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CACJ,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,cAAc,CAAC,EAAE,MAAM,GACtB,wBAAwB,GAAG,SAAS,CAAC;IAExC;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,oBAAoB,GAAG,qBAAqB,EAAE,CAAC;CAC9D;AAOD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,wBAAwB,GAAG,iBAAiB,CAyI5F"} |
+20
-25
@@ -0,1 +1,2 @@ | ||
| import { fuzzySearch } from '@squawk/search'; | ||
| /** | ||
@@ -119,28 +120,22 @@ * 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: (proc) => [ | ||
| { name: 'identifier', text: proc.identifier }, | ||
| { name: 'name', text: proc.name }, | ||
| ], | ||
| limit: query.limit ?? DEFAULT_SEARCH_LIMIT, | ||
| minScore: query.minScore ?? 0, | ||
| }; | ||
| const type = query.type; | ||
| const approachType = query.approachType; | ||
| if (type !== undefined || approachType !== undefined) { | ||
| options.filter = (proc) => (type === undefined || proc.type === type) && | ||
| (approachType === undefined || proc.approachType === approachType); | ||
| } | ||
| const results = []; | ||
| for (const proc of procedures) { | ||
| if (query.type !== undefined && proc.type !== query.type) { | ||
| continue; | ||
| } | ||
| if (query.approachType !== undefined && proc.approachType !== query.approachType) { | ||
| continue; | ||
| } | ||
| if (proc.identifier.toUpperCase().includes(needle) || | ||
| proc.name.toUpperCase().includes(needle)) { | ||
| results.push(proc); | ||
| } | ||
| } | ||
| results.sort((a, b) => { | ||
| const airportDiff = (a.airports[0] ?? '').localeCompare(b.airports[0] ?? ''); | ||
| if (airportDiff !== 0) { | ||
| return airportDiff; | ||
| } | ||
| return a.identifier.localeCompare(b.identifier); | ||
| }); | ||
| return results.slice(0, limit); | ||
| return fuzzySearch(procedures, query.text, options).map((match) => ({ | ||
| procedure: match.item, | ||
| score: match.score, | ||
| matchedField: match.field, | ||
| ranges: match.ranges, | ||
| })); | ||
| }, | ||
@@ -147,0 +142,0 @@ }; |
+2
-1
| { | ||
| "name": "@squawk/procedures", | ||
| "version": "0.5.7", | ||
| "version": "0.6.0", | ||
| "type": "module", | ||
@@ -44,2 +44,3 @@ "description": "Instrument procedure lookup and expansion for SIDs, STARs, and Instrument Approach Procedures (IAPs)", | ||
| "dependencies": { | ||
| "@squawk/search": "^0.1.0", | ||
| "@squawk/types": "^0.8.0" | ||
@@ -46,0 +47,0 @@ }, |
+26
-11
@@ -9,3 +9,3 @@ <h1><img src="../../../assets/squawk-logo.svg" alt="squawk logo" width="48" height="48" style="vertical-align: middle"> @squawk/procedures</h1> | ||
| identifier, by airport, by runway, by approach type; expand a procedure into | ||
| an ordered leg sequence; or search by name. Contains no bundled data - accepts | ||
| an ordered leg sequence; or fuzzy-search by identifier and name. Contains no bundled data - accepts | ||
| an array of `Procedure` records at initialization. For zero-config use, pair | ||
@@ -52,4 +52,5 @@ with `@squawk/procedure-data`. | ||
| // Search by name or identifier | ||
| // Fuzzy-search by identifier or name (scored, best match first) | ||
| const results = resolver.search({ text: 'AALLE', type: 'STAR' }); | ||
| console.log(results[0]?.procedure.identifier, results[0]?.score); | ||
| ``` | ||
@@ -149,12 +150,26 @@ | ||
| Searches procedures by name or identifier using case-insensitive substring | ||
| matching. Results are sorted by airport then identifier. | ||
| Fuzzy-searches procedures across identifier and name. 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 name or identifier | | ||
| | `limit` | number | Optional. Maximum number of results. Defaults to 20 | | ||
| | `type` | ProcedureType | Optional. Restrict to `'SID'`, `'STAR'`, or `'IAP'` only | | ||
| | `approachType` | ApproachType | Optional. Restrict to IAPs of a given approach classification | | ||
| | Property | Type | Description | | ||
| | -------------- | ------------- | ---------------------------------------------------------------------------------------- | | ||
| | `text` | string | Search text, matched fuzzily against each procedure's identifier and name | | ||
| | `limit` | number | Optional. Maximum number of results. Defaults to 20 | | ||
| | `type` | ProcedureType | Optional. Restrict to `'SID'`, `'STAR'`, or `'IAP'` only | | ||
| | `approachType` | ApproachType | Optional. Restrict to IAPs of a given approach classification | | ||
| | `minScore` | number | Optional. Minimum match score (exclusive) in `[0, 1]` a result must reach. Defaults to 0 | | ||
| Returns `Procedure[]`. | ||
| Returns `ProcedureSearchResult[]`, sorted by descending score, each containing: | ||
| - `procedure` - the matched Procedure record | ||
| - `score` - match strength in `[0, 1]`, where 1 is an exact identifier or name match | ||
| - `matchedField` - which field produced the best match: `'identifier'` or `'name'` | ||
| - `ranges` - matched character ranges within the best-matching field's text, for highlighting | ||
| ```typescript | ||
| const results = resolver.search({ text: 'AALLE', type: 'STAR' }); | ||
| for (const { procedure, score, matchedField } of results) { | ||
| console.log(procedure.identifier, score, `(matched ${matchedField})`); | ||
| } | ||
| ``` |
25997
9.87%355
3.2%173
9.49%2
100%+ Added
+ Added