@squawk/fixes 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +94 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/resolver.d.ts +86 -0
- package/dist/resolver.d.ts.map +1 -0
- package/dist/resolver.js +86 -0
- package/package.json +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# @squawk/fixes
|
|
2
|
+
|
|
3
|
+
Pure logic library for querying US fix/waypoint data. Look up fixes by
|
|
4
|
+
identifier, geographic proximity, or identifier search. Contains no bundled
|
|
5
|
+
data - accepts an array of Fix records at initialization. For zero-config use,
|
|
6
|
+
pair with `@squawk/fix-data`.
|
|
7
|
+
|
|
8
|
+
## Usage
|
|
9
|
+
|
|
10
|
+
```typescript
|
|
11
|
+
import { usBundledFixes } from '@squawk/fix-data';
|
|
12
|
+
import { createFixResolver } from '@squawk/fixes';
|
|
13
|
+
|
|
14
|
+
const resolver = createFixResolver({ data: usBundledFixes.records });
|
|
15
|
+
|
|
16
|
+
// Look up by identifier
|
|
17
|
+
const merit = resolver.byIdent('MERIT');
|
|
18
|
+
|
|
19
|
+
// Find nearest fixes to a position
|
|
20
|
+
const nearby = resolver.nearest({ lat: 40.6413, lon: -73.7781 });
|
|
21
|
+
for (const result of nearby) {
|
|
22
|
+
console.log(result.fix.identifier, result.distanceNm, 'nm');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Search by identifier
|
|
26
|
+
const results = resolver.search({ text: 'BOS' });
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Consumers who have their own fix data can use this package standalone:
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import { createFixResolver } from '@squawk/fixes';
|
|
33
|
+
|
|
34
|
+
const resolver = createFixResolver({ data: myFixes });
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## API
|
|
38
|
+
|
|
39
|
+
### `createFixResolver(options)`
|
|
40
|
+
|
|
41
|
+
Creates a resolver object from an array of Fix records.
|
|
42
|
+
|
|
43
|
+
**Parameters:**
|
|
44
|
+
|
|
45
|
+
- `options.data` - an array of `Fix` objects (from `@squawk/types`)
|
|
46
|
+
|
|
47
|
+
**Returns:** `FixResolver` - an object with the lookup methods described below.
|
|
48
|
+
|
|
49
|
+
### `resolver.byIdent(ident)`
|
|
50
|
+
|
|
51
|
+
Looks up fixes by identifier (e.g. "MERIT", "BOSCO"). Multiple fixes can share
|
|
52
|
+
the same identifier in different ICAO regions. Case-insensitive.
|
|
53
|
+
Returns `Fix[]`.
|
|
54
|
+
|
|
55
|
+
### `resolver.nearest(query)`
|
|
56
|
+
|
|
57
|
+
Finds fixes nearest to a geographic position, sorted by distance ascending.
|
|
58
|
+
|
|
59
|
+
| Property | Type | Description |
|
|
60
|
+
| --------------- | ------------------------ | --------------------------------------------------------------------- |
|
|
61
|
+
| `lat` | number | Latitude in decimal degrees (WGS84) |
|
|
62
|
+
| `lon` | number | Longitude in decimal degrees (WGS84) |
|
|
63
|
+
| `maxDistanceNm` | number | Optional. Maximum distance in nautical miles. Defaults to 30 |
|
|
64
|
+
| `limit` | number | Optional. Maximum number of results. Defaults to 10 |
|
|
65
|
+
| `useCodes` | ReadonlySet\<FixUseCode> | Optional. When provided, only fixes with these use codes are returned |
|
|
66
|
+
|
|
67
|
+
Returns `NearestFixResult[]`, each containing:
|
|
68
|
+
|
|
69
|
+
- `fix` - the matched Fix record
|
|
70
|
+
- `distanceNm` - great-circle distance in nautical miles (rounded to 2 decimal places)
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
// Find the 5 nearest waypoints within 50 nm
|
|
74
|
+
const nearby = resolver.nearest({
|
|
75
|
+
lat: 40.6413,
|
|
76
|
+
lon: -73.7781,
|
|
77
|
+
maxDistanceNm: 50,
|
|
78
|
+
limit: 5,
|
|
79
|
+
useCodes: new Set(['WP']),
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### `resolver.search(query)`
|
|
84
|
+
|
|
85
|
+
Searches fixes by identifier using case-insensitive substring matching.
|
|
86
|
+
Results are returned in alphabetical order by identifier.
|
|
87
|
+
|
|
88
|
+
| Property | Type | Description |
|
|
89
|
+
| ---------- | ------------------------ | --------------------------------------------------------------------- |
|
|
90
|
+
| `text` | string | Case-insensitive substring to match against fix identifier |
|
|
91
|
+
| `limit` | number | Optional. Maximum number of results. Defaults to 20 |
|
|
92
|
+
| `useCodes` | ReadonlySet\<FixUseCode> | Optional. When provided, only fixes with these use codes are returned |
|
|
93
|
+
|
|
94
|
+
Returns `Fix[]`.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
* Pure logic library for querying US fix/waypoint data.
|
|
4
|
+
*/
|
|
5
|
+
export { createFixResolver } from './resolver.js';
|
|
6
|
+
export type { FixResolver, FixResolverOptions, NearestFixQuery, NearestFixResult, FixSearchQuery, } from './resolver.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { Fix, FixUseCode } from '@squawk/types';
|
|
2
|
+
/**
|
|
3
|
+
* Options for creating a fix resolver.
|
|
4
|
+
*/
|
|
5
|
+
export interface FixResolverOptions {
|
|
6
|
+
/** Array of Fix records to index for queries. */
|
|
7
|
+
data: Fix[];
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* A query to find fixes near a geographic position.
|
|
11
|
+
*/
|
|
12
|
+
export interface NearestFixQuery {
|
|
13
|
+
/** Latitude in decimal degrees (WGS84). */
|
|
14
|
+
lat: number;
|
|
15
|
+
/** Longitude in decimal degrees (WGS84). */
|
|
16
|
+
lon: number;
|
|
17
|
+
/** Maximum distance in nautical miles. Defaults to 30. */
|
|
18
|
+
maxDistanceNm?: number;
|
|
19
|
+
/** Maximum number of results to return. Defaults to 10. */
|
|
20
|
+
limit?: number;
|
|
21
|
+
/** Optional set of use codes to include. When omitted, all use codes are included. */
|
|
22
|
+
useCodes?: ReadonlySet<FixUseCode>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A fix result with distance information from a nearest-fix query.
|
|
26
|
+
*/
|
|
27
|
+
export interface NearestFixResult {
|
|
28
|
+
/** The matched fix record. */
|
|
29
|
+
fix: Fix;
|
|
30
|
+
/** Distance in nautical miles from the query position. */
|
|
31
|
+
distanceNm: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Options for a text search query against fix identifiers.
|
|
35
|
+
*/
|
|
36
|
+
export interface FixSearchQuery {
|
|
37
|
+
/** Case-insensitive substring to match against fix identifier. */
|
|
38
|
+
text: string;
|
|
39
|
+
/** Maximum number of results to return. Defaults to 20. */
|
|
40
|
+
limit?: number;
|
|
41
|
+
/** Optional set of use codes to include. When omitted, all use codes are included. */
|
|
42
|
+
useCodes?: ReadonlySet<FixUseCode>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* A stateless resolver providing fix lookup methods.
|
|
46
|
+
*/
|
|
47
|
+
export interface FixResolver {
|
|
48
|
+
/**
|
|
49
|
+
* Looks up fixes by identifier (e.g. "MERIT", "BOSCO").
|
|
50
|
+
* Multiple fixes can share the same identifier in different ICAO regions.
|
|
51
|
+
* Returns an empty array if no match is found.
|
|
52
|
+
*/
|
|
53
|
+
byIdent(ident: string): Fix[];
|
|
54
|
+
/**
|
|
55
|
+
* Finds fixes nearest to a geographic position, sorted by distance.
|
|
56
|
+
* Results are filtered by max distance and limited to the requested count.
|
|
57
|
+
*/
|
|
58
|
+
nearest(query: NearestFixQuery): NearestFixResult[];
|
|
59
|
+
/**
|
|
60
|
+
* Searches fixes by identifier using case-insensitive substring matching.
|
|
61
|
+
* Results are returned in alphabetical order by identifier.
|
|
62
|
+
*/
|
|
63
|
+
search(query: FixSearchQuery): Fix[];
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Creates a stateless fix resolver. The resolver accepts an array of
|
|
67
|
+
* Fix records at initialization (typically from `@squawk/fix-data`)
|
|
68
|
+
* and returns an object with methods for looking up fixes by identifier,
|
|
69
|
+
* proximity, or identifier search.
|
|
70
|
+
*
|
|
71
|
+
* The resolver builds internal indexes at creation time for fast lookups
|
|
72
|
+
* by identifier. Proximity and text searches iterate over the full dataset.
|
|
73
|
+
*
|
|
74
|
+
* ```typescript
|
|
75
|
+
* import { usBundledFixes } from '@squawk/fix-data';
|
|
76
|
+
* import { createFixResolver } from '@squawk/fixes';
|
|
77
|
+
*
|
|
78
|
+
* const resolver = createFixResolver({ data: usBundledFixes.records });
|
|
79
|
+
*
|
|
80
|
+
* const merit = resolver.byIdent('MERIT');
|
|
81
|
+
* const nearby = resolver.nearest({ lat: 40.6413, lon: -73.7781 });
|
|
82
|
+
* const results = resolver.search({ text: 'BOS' });
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
export declare function createFixResolver(options: FixResolverOptions): FixResolver;
|
|
86
|
+
//# sourceMappingURL=resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAKrD;;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"}
|
package/dist/resolver.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { distance } from '@squawk/units';
|
|
2
|
+
const { greatCircleDistanceNm } = distance;
|
|
3
|
+
/**
|
|
4
|
+
* Default maximum distance in nautical miles for nearest-fix queries.
|
|
5
|
+
*/
|
|
6
|
+
const DEFAULT_MAX_DISTANCE_NM = 30;
|
|
7
|
+
/**
|
|
8
|
+
* Default maximum number of results for nearest-fix queries.
|
|
9
|
+
*/
|
|
10
|
+
const DEFAULT_NEAREST_LIMIT = 10;
|
|
11
|
+
/**
|
|
12
|
+
* Default maximum number of results for text search queries.
|
|
13
|
+
*/
|
|
14
|
+
const DEFAULT_SEARCH_LIMIT = 20;
|
|
15
|
+
/**
|
|
16
|
+
* Creates a stateless fix resolver. The resolver accepts an array of
|
|
17
|
+
* Fix records at initialization (typically from `@squawk/fix-data`)
|
|
18
|
+
* and returns an object with methods for looking up fixes by identifier,
|
|
19
|
+
* proximity, or identifier search.
|
|
20
|
+
*
|
|
21
|
+
* The resolver builds internal indexes at creation time for fast lookups
|
|
22
|
+
* by identifier. Proximity and text searches iterate over the full dataset.
|
|
23
|
+
*
|
|
24
|
+
* ```typescript
|
|
25
|
+
* import { usBundledFixes } from '@squawk/fix-data';
|
|
26
|
+
* import { createFixResolver } from '@squawk/fixes';
|
|
27
|
+
*
|
|
28
|
+
* const resolver = createFixResolver({ data: usBundledFixes.records });
|
|
29
|
+
*
|
|
30
|
+
* const merit = resolver.byIdent('MERIT');
|
|
31
|
+
* const nearby = resolver.nearest({ lat: 40.6413, lon: -73.7781 });
|
|
32
|
+
* const results = resolver.search({ text: 'BOS' });
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export function createFixResolver(options) {
|
|
36
|
+
const fixes = options.data;
|
|
37
|
+
const byIdentMap = new Map();
|
|
38
|
+
for (const fix of fixes) {
|
|
39
|
+
const key = fix.identifier.toUpperCase();
|
|
40
|
+
let arr = byIdentMap.get(key);
|
|
41
|
+
if (!arr) {
|
|
42
|
+
arr = [];
|
|
43
|
+
byIdentMap.set(key, arr);
|
|
44
|
+
}
|
|
45
|
+
arr.push(fix);
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
byIdent(ident) {
|
|
49
|
+
return byIdentMap.get(ident.toUpperCase()) ?? [];
|
|
50
|
+
},
|
|
51
|
+
nearest(query) {
|
|
52
|
+
const maxDist = query.maxDistanceNm ?? DEFAULT_MAX_DISTANCE_NM;
|
|
53
|
+
const limit = query.limit ?? DEFAULT_NEAREST_LIMIT;
|
|
54
|
+
const results = [];
|
|
55
|
+
for (const fix of fixes) {
|
|
56
|
+
if (query.useCodes && !query.useCodes.has(fix.useCode)) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
const dist = greatCircleDistanceNm(query.lat, query.lon, fix.lat, fix.lon);
|
|
60
|
+
if (dist <= maxDist) {
|
|
61
|
+
results.push({ fix, distanceNm: Math.round(dist * 100) / 100 });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
results.sort((a, b) => a.distanceNm - b.distanceNm);
|
|
65
|
+
return results.slice(0, limit);
|
|
66
|
+
},
|
|
67
|
+
search(query) {
|
|
68
|
+
const limit = query.limit ?? DEFAULT_SEARCH_LIMIT;
|
|
69
|
+
const needle = query.text.toUpperCase();
|
|
70
|
+
if (needle.length === 0) {
|
|
71
|
+
return [];
|
|
72
|
+
}
|
|
73
|
+
const results = [];
|
|
74
|
+
for (const fix of fixes) {
|
|
75
|
+
if (query.useCodes && !query.useCodes.has(fix.useCode)) {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (fix.identifier.toUpperCase().includes(needle)) {
|
|
79
|
+
results.push(fix);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
results.sort((a, b) => a.identifier.localeCompare(b.identifier));
|
|
83
|
+
return results.slice(0, limit);
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@squawk/fixes",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Fix/waypoint queries by identifier, location, or name search",
|
|
6
|
+
"author": "Neil Cochran",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"homepage": "https://github.com/neilcochran/squawk",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/neilcochran/squawk.git",
|
|
12
|
+
"directory": "packages/fixes"
|
|
13
|
+
},
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=22"
|
|
16
|
+
},
|
|
17
|
+
"typedocMain": "src/index.ts",
|
|
18
|
+
"main": "./dist/index.js",
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"import": "./dist/index.js",
|
|
23
|
+
"types": "./dist/index.d.ts"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"!dist/**/*.spec.*"
|
|
29
|
+
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsc",
|
|
32
|
+
"test": "node --test 'dist/**/*.spec.js'",
|
|
33
|
+
"lint": "tsc --noEmit && eslint src"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@squawk/types": "*",
|
|
37
|
+
"@squawk/units": "*"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@squawk/fix-data": "*",
|
|
41
|
+
"@types/node": "^25.5.2"
|
|
42
|
+
},
|
|
43
|
+
"keywords": [
|
|
44
|
+
"aviation",
|
|
45
|
+
"typescript",
|
|
46
|
+
"fix",
|
|
47
|
+
"waypoint",
|
|
48
|
+
"intersection",
|
|
49
|
+
"faa",
|
|
50
|
+
"nasr"
|
|
51
|
+
],
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"access": "public"
|
|
54
|
+
}
|
|
55
|
+
}
|