@ham2k/extension-sdk 0.12.0 → 0.12.2

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/dist/dxcc.js CHANGED
@@ -3,7 +3,14 @@ import { annotateFromCountryFile, useBuiltinCountryFile } from "@ham2k/lib-count
3
3
  import { DXCC_BY_CODE } from "@ham2k/lib-dxcc-data";
4
4
  useBuiltinCountryFile();
5
5
  function annotateCallAgainstCountryFile(call, options) {
6
- return annotateFromCountryFile(parseCallsign(call), options);
6
+ const annotated = annotateFromCountryFile(parseCallsign(call), options);
7
+ return annotated.tz ? { ...annotated, tz: ordinarySignTz(annotated.tz) } : annotated;
8
+ }
9
+ function ordinarySignTz(tz) {
10
+ const match = /^GMT([+-]?\d+(?:\.\d+)?)$/.exec(tz);
11
+ if (!match) return tz;
12
+ const offset = -Number(match[1]);
13
+ return offset > 0 ? `GMT+${offset}` : `GMT${offset === 0 ? 0 : offset}`;
7
14
  }
8
15
  function entityPrefixForCall(call) {
9
16
  if (!call) return void 0;
@@ -76,6 +76,7 @@ function resolveExportSettings(definition, global = {}, overrides = {}) {
76
76
  }
77
77
  return resolved;
78
78
  }
79
+ const PRIVATE_STATION_FIELDS = ["name", "city", "street", "postal", "email", "qslVia", "url", "notes", "lat", "lon", "multiIdentifier"];
79
80
  function exportQso(qso, settings) {
80
81
  const copy = { ...qso };
81
82
  for (const side of ["their", "our"]) {
@@ -83,11 +84,11 @@ function exportQso(qso, settings) {
83
84
  const station = { ...copy[side] };
84
85
  if (settings.includeLookupData === false) delete station.guess;
85
86
  if (settings.includePrivateData === false) {
86
- for (const key of ["name", "city", "email", "notes", "lat", "lon", "multiIdentifier"]) delete station[key];
87
+ for (const key of PRIVATE_STATION_FIELDS) delete station[key];
87
88
  if (typeof station.grid === "string") station.grid = station.grid.slice(0, 6);
88
89
  if (station.guess && typeof station.guess === "object") {
89
90
  const guess = { ...station.guess };
90
- for (const key of ["name", "city", "email", "notes", "lat", "lon", "multiIdentifier"]) delete guess[key];
91
+ for (const key of PRIVATE_STATION_FIELDS) delete guess[key];
91
92
  if (typeof guess.grid === "string") guess.grid = guess.grid.slice(0, 6);
92
93
  station.guess = guess;
93
94
  }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- // @ham2k/extension-sdk 0.12.0
1
+ // @ham2k/extension-sdk 0.12.2
2
2
  /** Experimental v1 panel scene contract. All coordinates are in the scene's viewBox. */
3
3
  export interface PanelScene {
4
4
  version: 1;
package/docs/hooks.md CHANGED
@@ -209,9 +209,11 @@ interface LookupServiceHook {
209
209
  **locationScope merge rules** (`CallInfo.locationScope`, ranked
210
210
  `qth < prefixed < portable`, most general to most specific):
211
211
  - A result whose `locationScope` is strictly more specific than the current
212
- guess's clears all location fields (`locSource, lat, lon, grid, city,
213
- state, county, country`) before merging the result in, and the guess
214
- adopts the more specific scope.
212
+ guess's clears all location fields (`locSource, lat, lon, grid, street,
213
+ city, state, postal, county, country`) before merging the result in, and
214
+ the guess adopts the more specific scope. `street` and `postal` are the
215
+ mailing address's own lines, grouped with the town they complete so an
216
+ address never puts one source's street on another source's town.
215
217
  - Otherwise, priority order applies as usual: a field already present in the
216
218
  guess is never overwritten by a later (lower-priority) result. A
217
219
  location field additionally requires the result's own scope to be at
@@ -231,13 +233,22 @@ interface LookupServiceHook {
231
233
  - Grid/lat-lon reconciliation, scoped to fields the result actually set:
232
234
  grid-only → lat/lon computed from the grid; lat/lon-only → a 6-digit grid
233
235
  computed from them; both given → taken verbatim. Setting grid/lat/lon
234
- clears city/state/country/county unless the *same* result also supplies
235
- them. The converse clause — a town write clearing grid/lat/lon — can only
236
+ clears street/city/state/postal/country/county unless the *same* result
237
+ also supplies them. The converse clause — a town write clearing grid/lat/lon — can only
236
238
  sweep a leftover half lat/lon pair: the group rule above blocks a town
237
239
  from landing at all where a full pin already stands.
238
240
  - `notes`/`history` are per-`CallInfoLookup` fields, not part of the merged
239
241
  `guess` — they simply accumulate, unconditionally, in the returned
240
242
  `lookups[]` array.
243
+ - **`cqZone`, `ituZone` and `tz` are the exception to first-answer-wins.** The
244
+ pre-step can only answer them for a whole entity or call area (a W6 call
245
+ reads CQ zone 3 wherever the station lives), so once every hook has run,
246
+ a value the pre-step still holds goes to the first hook result that
247
+ carried one (`preferStationValues`) — only while the guess's scope is
248
+ `qth`, since on a portable or prefixed contact a source describes the
249
+ home QTH. `tz` is a UTC offset with its ordinary sign, `"GMT-5"` being
250
+ five hours behind; the SDK's `annotateCallAgainstCountryFile` flips the
251
+ country file's west-positive offsets to match.
241
252
  - **`locSource: 'prefix'` is reserved**, and a `lat`/`lon` merged under it is
242
253
  never read as a coordinate (`locationFromGuess`, halo_core). It marks
243
254
  lib-country-files' DXCC entity centroid, whose longitude follows cty.dat's
@@ -518,6 +529,18 @@ SOTLAS's `az.sotl.as`, used with the operators' permission) and `pota` (both
518
529
  types, via `services.ham2k.net/lookups/outlines/pota/`, which links parks to
519
530
  OpenStreetMap shapes; a park not yet linked answers 404).
520
531
 
532
+ **POTA is the one exception, and the core makes it, not the hook.** For a
533
+ POTA suggestion's dashed outline the core skips `geojsonUrlForRef` and reads
534
+ `services.ham2k.net`'s grid bundles instead — every outlined park touching a
535
+ Maidenhead cell, simplified and clipped to it, one cached document per cell
536
+ (500 m blocks below GL zoom 9, 10 m squares from 9). A long trail's whole
537
+ outline runs to megabytes; its pieces in a cell, to kilobytes. The same
538
+ bundles add to `suggest`'s answers the parks whose outline, not just whose
539
+ point, is near: within 5 km for the nearby list, touching the view for a pan
540
+ close in (from about GL zoom 10; see `suggest` below). An open card's POTA suggestion is drawn solid from the
541
+ same pieces; the operation's own references still come from
542
+ `geojsonUrlForRef`.
543
+
521
544
  **An activation radius is a circle, drawn the same way.** A reference that
522
545
  carries `activationRadiusInMeters` or `activationRadiusInFeet` — how far from
523
546
  its point the program lets an activator be — is circled on both maps, in the
@@ -665,7 +688,12 @@ an app that sends `bounds` answers that call, so an extension that calls it
665
688
  only then runs on older apps unchanged, and one that predates `bounds` answers
666
689
  with what is nearest the view's centre. Measure `distance` from the `location`
667
690
  given either way; the core re-measures a panned answer from the operation's own
668
- place before any card shows it. Called with no
691
+ place before any card shows it. For POTA only, the core also adds the parks
692
+ whose OUTLINE is near (from the grid bundles above) to the nearby list and to a
693
+ pan, labelled by POTA's own `decorateRef`, and gives a park POTA already
694
+ suggested the nearer of its point's and its outline's distance — so `pota`'s
695
+ `suggest` keeps answering by point, and a trail whose point is a state away
696
+ still reaches an operator standing on it. Called with no
669
697
  `searchTerm` for nearby suggestions, or with one for name/code search — an
670
698
  extension may honor either, both, or neither (returning `[]`). `scoped` is
671
699
  true when THIS extension alone was asked — the operator tapped its "Activity
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ham2k/extension-sdk",
3
- "version": "0.12.0",
3
+ "version": "0.12.2",
4
4
  "description": "Write extensions for the Ham2K Logger: typed hook contracts and the host API",
5
5
  "keywords": [
6
6
  "ham2k",