@ham2k/extension-sdk 0.5.2 → 0.5.4
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/index.d.ts +21 -2
- package/docs/distribution.md +65 -0
- package/docs/hooks.md +44 -8
- package/docs/templates.md +3 -2
- package/package.json +1 -1
- package/samples/k2hrc-svg-scenes/README.md +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @ham2k/extension-sdk 0.5.
|
|
1
|
+
// @ham2k/extension-sdk 0.5.4
|
|
2
2
|
/** Experimental v1 scene contract. All coordinates are in the scene's viewBox. */
|
|
3
3
|
export interface SvgScene {
|
|
4
4
|
version: 1;
|
|
@@ -231,7 +231,26 @@ export interface HookContext {
|
|
|
231
231
|
getOperation?(uuid: string): Promise<Record<string, JSONValue> | null>;
|
|
232
232
|
getQsos?(operationUuid: string): Promise<Record<string, JSONValue>[] | null>;
|
|
233
233
|
getSpotsForCall?(call: string, maxAgeMinutes?: number): Promise<Spot[]>;
|
|
234
|
-
getHistoryForCall?(call: string): Promise<Record<string, JSONValue>[]>;
|
|
234
|
+
getHistoryForCall?(call: string, options?: HistoryForCallOptions): Promise<Record<string, JSONValue>[]>;
|
|
235
|
+
}
|
|
236
|
+
export interface HistoryForCallOptions {
|
|
237
|
+
refType?: string | string[];
|
|
238
|
+
refPrefix?: string | string[];
|
|
239
|
+
operation?: string | string[];
|
|
240
|
+
excludeOperation?: string | string[];
|
|
241
|
+
fromDate?: string;
|
|
242
|
+
toDate?: string;
|
|
243
|
+
fromDateMillis?: number;
|
|
244
|
+
toDateMillis?: number;
|
|
245
|
+
fromTime?: string;
|
|
246
|
+
toTime?: string;
|
|
247
|
+
fromTimeMillis?: number;
|
|
248
|
+
toTimeMillis?: number;
|
|
249
|
+
band?: string | string[];
|
|
250
|
+
excludeBand?: string | string[];
|
|
251
|
+
mode?: string | string[];
|
|
252
|
+
excludeMode?: string | string[];
|
|
253
|
+
limit?: number;
|
|
235
254
|
}
|
|
236
255
|
export type LookupResult = (CallInfoLookup & {
|
|
237
256
|
locAccuracy?: number;
|
package/docs/distribution.md
CHANGED
|
@@ -393,6 +393,71 @@ as a constant inside the extension that uses it, because these bundles are
|
|
|
393
393
|
served to anyone who asks and a `.h2kext` is a zip. An installed extension
|
|
394
394
|
sees no build secret, whatever key it claims and wherever it came from.
|
|
395
395
|
|
|
396
|
+
### The upgrade to catalog extensions
|
|
397
|
+
|
|
398
|
+
An install that has been running the app's own extensions is offered the move
|
|
399
|
+
at start, and again the moment the catalog experiment is switched on: that
|
|
400
|
+
switch is the operator asking for catalog extensions, and being made to
|
|
401
|
+
relaunch before anything is offered reads as nothing having happened. The
|
|
402
|
+
switch withdraws nothing by itself; only a taken upgrade does, and the offer
|
|
403
|
+
may be deferred either way. A catalog that cannot be reached says so in the
|
|
404
|
+
footer when the operator asked, and says nothing at a launch nobody was
|
|
405
|
+
watching.
|
|
406
|
+
|
|
407
|
+
Accepting installs the pre-loads, then fetches the catalog's twin of every
|
|
408
|
+
other built-in the operator had switched on — `wca` becomes `ham2k-wca` —
|
|
409
|
+
carrying its settings and credentials the same way. Nothing is withdrawn until
|
|
410
|
+
that finishes; a download that fails puts the app's own extensions back in use
|
|
411
|
+
and the offer returns next launch. Twins that did arrive stay on disk, unused
|
|
412
|
+
until an upgrade completes — the built-in each one supersedes is what runs
|
|
413
|
+
meanwhile.
|
|
414
|
+
|
|
415
|
+
A bundle the engine will not evaluate takes the whole runtime with it, so the
|
|
416
|
+
upgrade puts that one aside — the boot names the bundle it died on — and
|
|
417
|
+
restarts once more. What boots then is the upgrade minus that extension, named
|
|
418
|
+
in the dialog in a sentence of its own. Refused rather than
|
|
419
|
+
withdrawn: the panel still lists it, badged, because the row is where an
|
|
420
|
+
operator sees that something they installed is doing nothing, and updating it
|
|
421
|
+
there is what lifts the refusal. Keyed by the VERSION that failed, so a fixed
|
|
422
|
+
release arrives as an ordinary update and clears it. Only an INSTALLED
|
|
423
|
+
extension is ever put aside; a built-in that
|
|
424
|
+
will not evaluate is a defect in the app, and skipping it would ship an
|
|
425
|
+
install quietly missing part of itself.
|
|
426
|
+
|
|
427
|
+
A refusal is kept even when putting the bundle aside did not get a runtime
|
|
428
|
+
back: it still will not evaluate, and an extension with no built-in behind it
|
|
429
|
+
is in the reverted set too, so re-admitting it there would kill the boot that
|
|
430
|
+
was about to give the operator everything back. Every dialog, and the notice
|
|
431
|
+
that stands in for one, names what stayed out — except a downloaded copy the
|
|
432
|
+
revert superseded, whose built-in is running again. Uninstalling clears the
|
|
433
|
+
record, so a reinstall of the same bytes gets its chance.
|
|
434
|
+
|
|
435
|
+
A refused extension is treated like a revoked one in everything else: it
|
|
436
|
+
keeps its switch, and its downloaded data expires on the same clock as any
|
|
437
|
+
extension the app is not loading.
|
|
438
|
+
|
|
439
|
+
What this does NOT cover is a failure that names no bundle. Only a bundle
|
|
440
|
+
that fails while it is being EVALUATED names itself: a kernel that will not
|
|
441
|
+
load, or an extension that throws while ACTIVATING, takes the generation down
|
|
442
|
+
under a name that is not a key. Those revert the whole upgrade as before, and
|
|
443
|
+
it is offered again at the next launch.
|
|
444
|
+
|
|
445
|
+
The upgrade restarts the extension runtime, which takes the footer items of
|
|
446
|
+
the generation going down with it: a data file's import raises an error rather
|
|
447
|
+
than returning into a torn-down runtime, so its progress line is cleared and
|
|
448
|
+
the file is left unstamped for the next sweep instead of recorded as fresh
|
|
449
|
+
with nothing imported.
|
|
450
|
+
|
|
451
|
+
A few built-ins have no twin on purpose — `qp`, which the catalog carries as
|
|
452
|
+
one extension per party instead — and the app names them itself
|
|
453
|
+
(`kBuiltInsWithoutTwin`). Those are withdrawn without asking the catalog, and
|
|
454
|
+
the dialog that reports the upgrade finished names each one the operator had
|
|
455
|
+
switched on, since it is where they learn it is gone. Any other twin missing
|
|
456
|
+
from the listing fails the upgrade and is asked for again next launch: a
|
|
457
|
+
listing lacks a key the same way whether the catalog will never serve it or has
|
|
458
|
+
not published it yet, and only the app knows which. A built-in retired from the
|
|
459
|
+
catalog on purpose joins that list in the same change.
|
|
460
|
+
|
|
396
461
|
### Installing from the catalog
|
|
397
462
|
|
|
398
463
|
**Settings → Extensions → Catalog** lists what [catalog.ham2k.net](https://catalog.ham2k.net)
|
package/docs/hooks.md
CHANGED
|
@@ -51,8 +51,9 @@ hook method receives `(args, ctx)` where `ctx: HookContext` is:
|
|
|
51
51
|
reads above it is cheap enough for the lookup path; it resolves `[]`
|
|
52
52
|
whenever the cache is cold or the host keeps no spots. Used by
|
|
53
53
|
`spot-history` to pull a hunted park or summit into the QSO being logged.
|
|
54
|
-
* `getHistoryForCall?(call)` —
|
|
55
|
-
|
|
54
|
+
* `getHistoryForCall?(call, options?)` — the most recent non-deleted contacts
|
|
55
|
+
logged with `call` (five unless `limit` says otherwise, never more than
|
|
56
|
+
50), across every operation, newest first, as raw QSON — the one log read
|
|
56
57
|
that is cross-operation rather than scoped to a single one, since it
|
|
57
58
|
answers "who is this station" from the whole log rather than "what's in
|
|
58
59
|
this operation". Resolves `[]` for no match or no log access; unlike
|
|
@@ -60,6 +61,25 @@ hook method receives `(args, ctx)` where `ctx: HookContext` is:
|
|
|
60
61
|
Used by `call-history` to fold the most recent past QSO's fields into a
|
|
61
62
|
lookup result.
|
|
62
63
|
|
|
64
|
+
`options` (`HistoryForCallOptions` in `types.ts`) narrow the history
|
|
65
|
+
before it is ordered and limited, so `{ refType: 'cwt' }` finds last
|
|
66
|
+
month's CWT exchange behind a week of POTA contacts. The filters are
|
|
67
|
+
`refType` (a ref in the QSO's own `refs`), `refPrefix` (a ref whose `ref`
|
|
68
|
+
starts with it, ignoring ASCII case; with `refType`, the same ref must pass
|
|
69
|
+
both, so `{ refType: 'potaActivation', refPrefix: 'FR-' }` finds French
|
|
70
|
+
parks), `operation`/`excludeOperation`,
|
|
71
|
+
`band`/`excludeBand`, `mode`/`excludeMode` (`SSB` also matches its
|
|
72
|
+
sidebands, and `CW`/`PHONE`/`DATA` match their whole family), whole UTC
|
|
73
|
+
days through `fromDate`/`toDate` or `fromDateMillis`/`toDateMillis`, and
|
|
74
|
+
exact instants through `fromTime`/`toTime` or
|
|
75
|
+
`fromTimeMillis`/`toTimeMillis`. All the bounds are inclusive. A malformed
|
|
76
|
+
option, an unknown one, or an include option given no values
|
|
77
|
+
(`operation: []`) rejects the call instead of answering an unfiltered
|
|
78
|
+
history. Hosts older than these options ignore them and answer the latest
|
|
79
|
+
five contacts unfiltered, so a caller re-checks on the results whatever it
|
|
80
|
+
relies on — and an empty answer there means "none among the latest five",
|
|
81
|
+
not "none at all".
|
|
82
|
+
|
|
63
83
|
Status legend: ✅ implemented · 🔜 planned (design in DESIGN.md §4).
|
|
64
84
|
|
|
65
85
|
---
|
|
@@ -1206,6 +1226,14 @@ permission (pending challenge code for an email, immediately-active for an
|
|
|
1206
1226
|
already-permitted account, or a blank permission for QR-code linking) and
|
|
1207
1227
|
returns server rejections as `{ error, error_status }` data.
|
|
1208
1228
|
|
|
1229
|
+
`linkClient` must NOT mail anything. The core shows the challenge code on
|
|
1230
|
+
screen and offers the email as a separate choice, so a transport that mails
|
|
1231
|
+
here sends a confirmation nobody asked for — and one more on every renewal,
|
|
1232
|
+
since an expiring code re-requests through this same call.
|
|
1233
|
+
`linkClientWithEmail` is the call the operator reaches by choosing the
|
|
1234
|
+
email over the code, and the only one in this seam that mails. A server
|
|
1235
|
+
that mails by default (LoFi does) has to be told not to.
|
|
1236
|
+
|
|
1209
1237
|
The account-management methods are all optional and all follow that same
|
|
1210
1238
|
"a rejection is data, not a throw" convention, because every one of them
|
|
1211
1239
|
reports to an operator in the middle of an action: `setAccountEmail` /
|
|
@@ -1256,7 +1284,7 @@ numeric value patches; local-only controls and animation frames make no bridge
|
|
|
1256
1284
|
calls. Controls with `continuous: true` send `change` events during dragging and a
|
|
1257
1285
|
final `commit` on release; pending movements are coalesced to the newest value.
|
|
1258
1286
|
Numeric text supports `scale`, `truncate`, `modulo`, and `minIntegerDigits`
|
|
1259
|
-
for local numeric formatting.
|
|
1287
|
+
for local numeric formatting. KI2D’s Radio Panel uses these for its Modern
|
|
1260
1288
|
frequency groups; its settings offer Modern/LCD styles and radio selection. Local sliders may use `hover` and `discrete` hourly buckets. Text `samples`
|
|
1261
1289
|
may hold numbers or preformatted strings; control `valueLabels` supplies accessible
|
|
1262
1290
|
value descriptions. Transform/opacity bindings may also supply numeric `samples`,
|
|
@@ -1302,12 +1330,12 @@ Button controls can supply `menu: [{label, event}]` to open a native dropdown.
|
|
|
1302
1330
|
Selecting an item emits its `event` as the action with the original control ID;
|
|
1303
1331
|
dismissing the menu emits nothing.
|
|
1304
1332
|
|
|
1305
|
-
The `
|
|
1333
|
+
The `ki2d-weather-panel`, `ki2d-solar-panel` and `ki2d-radio-panel` reference
|
|
1334
|
+
panels live in
|
|
1306
1335
|
[ham2k/extensions](https://github.com/ham2k/extensions/tree/main/extensions/dashboard).
|
|
1307
1336
|
They use public host APIs and ship as `.h2kext` packages, not app assets.
|
|
1308
|
-
Install the packages, then add their panels through Edit Layout.
|
|
1309
|
-
|
|
1310
|
-
See that repository’s dashboard README for building against the unreleased SDK.
|
|
1337
|
+
Install the packages, then add their panels through Edit Layout. See that
|
|
1338
|
+
repository's dashboard README for building them.
|
|
1311
1339
|
|
|
1312
1340
|
The radio host calls are manifest capabilities, refused unless declared — the
|
|
1313
1341
|
same shape as `requiresLocation`, and shown to the operator at install:
|
|
@@ -1315,8 +1343,16 @@ same shape as `requiresLocation`, and shown to the operator at install:
|
|
|
1315
1343
|
`"requiresRadioWrite": true` allows `host.tuneRadio()` and
|
|
1316
1344
|
`host.setRadioConnection()`, and implies read, since a command answers with the
|
|
1317
1345
|
radio's state. An undeclared call rejects rather than answering null.
|
|
1346
|
+
A capability belongs to the bundle that declared it, and to the sub-extensions
|
|
1347
|
+
that bundle defines under its own key. A separately installed bundle never
|
|
1348
|
+
inherits one through its name: `rigpanel-themes` gets nothing from `rigpanel`.
|
|
1349
|
+
|
|
1350
|
+
An `onEvent` that cannot read its panel's config is refused rather than run
|
|
1351
|
+
with an empty one, since a config is where a panel keeps which radio it
|
|
1352
|
+
commands. The host allows an event up to about ten seconds in all (config, then
|
|
1353
|
+
the hook); the control shows its pending value until the outcome is known.
|
|
1318
1354
|
|
|
1319
|
-
**Radio Panel
|
|
1355
|
+
**KI2D’s Radio Panel** is the CAT reference extension. `host.listRadios()` lists configured
|
|
1320
1356
|
local transceivers. `host.readRadio(id?)` returns
|
|
1321
1357
|
a **local** radio's reported frequency (Hz), mode, connection state,
|
|
1322
1358
|
power, TX state and fresh telemetry, or null on hosts without this API.
|
package/docs/templates.md
CHANGED
|
@@ -227,8 +227,9 @@ will jump rather than count. Show HH:MM.
|
|
|
227
227
|
| CW messages | Radio settings `cwMessage1..8`, keyed on F1-F8 through the radio (docs/design/cat.md § CW keying) — rendered by the `template` hook (hooks.md) | by the operator, in the Station dialog's Messages… dialog |
|
|
228
228
|
|
|
229
229
|
NOTES and COMMENT default to QSO notes and are withheld when private data
|
|
230
|
-
is off. QSLMSG defaults to empty for program exports, and
|
|
231
|
-
|
|
230
|
+
is off. QSLMSG defaults to empty for program exports, and for the whole-log
|
|
231
|
+
ADIF to the operation’s references as `refLabels | sentence` names them —
|
|
232
|
+
“POTA US-0001 & WWFF KFF-0002”. Custom QSL messages may use contact values.
|
|
232
233
|
Templates receive no withheld private or lookup values. File titles obey the
|
|
233
234
|
private-data choice; filename templates are labels for the operator’s files.
|
|
234
235
|
|
package/package.json
CHANGED
|
@@ -19,6 +19,6 @@ node build.mjs
|
|
|
19
19
|
node ../../tools/h2kext-pack.mjs build -o /tmp/k2hrc-svg-scenes.h2kext
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
For the
|
|
23
|
-
|
|
22
|
+
For the contract and migration plan, see `docs/design/svg-scenes.md` in the
|
|
23
|
+
logger repository. This is an API experiment,
|
|
24
24
|
not a replacement for the production weather/solar panels yet.
|