@ham2k/extension-sdk 0.10.0 → 0.10.1
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 +2 -1
- package/docs/distribution.md +69 -12
- package/docs/hooks.md +19 -7
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @ham2k/extension-sdk 0.10.
|
|
1
|
+
// @ham2k/extension-sdk 0.10.1
|
|
2
2
|
/** Experimental v1 panel scene contract. All coordinates are in the scene's viewBox. */
|
|
3
3
|
export interface PanelScene {
|
|
4
4
|
version: 1;
|
|
@@ -661,6 +661,7 @@ export interface AdifFieldsHook {
|
|
|
661
661
|
fieldsForOneQSO(args: {
|
|
662
662
|
qso: Record<string, JSONValue>;
|
|
663
663
|
operation: Record<string, JSONValue>;
|
|
664
|
+
mainHandler?: boolean;
|
|
664
665
|
}, ctx: HookContext): Promise<{
|
|
665
666
|
name: string;
|
|
666
667
|
value: string;
|
package/docs/distribution.md
CHANGED
|
@@ -526,15 +526,72 @@ Beyond what the packer already refused:
|
|
|
526
526
|
|
|
527
527
|
Each has its own message. A bundle that cannot be installed says why.
|
|
528
528
|
|
|
529
|
-
##
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
529
|
+
## Where installed bundles live
|
|
530
|
+
|
|
531
|
+
Everything above is platform-neutral — the zip walk, the manifest rules, the
|
|
532
|
+
consent screen, the hash check. What differs is only where the bytes are kept
|
|
533
|
+
(`BundleStorage`):
|
|
534
|
+
|
|
535
|
+
- **natively**, one directory per key under the app's data directory, one
|
|
536
|
+
file per bundle entry;
|
|
537
|
+
- **on web**, one IndexedDB record per key (database `halo-extensions`),
|
|
538
|
+
holding every entry's bytes under its own name. IndexedDB rather than the
|
|
539
|
+
Origin Private File System, which would mirror the native layout: every
|
|
540
|
+
browser HaLo runs in supports it the same way, while OPFS writes from the
|
|
541
|
+
page are newer and patchier on Safari.
|
|
542
|
+
|
|
543
|
+
So the web build installs from a file, installs and updates from the catalog,
|
|
544
|
+
pre-loads the shipped bundles and takes the upgrade exactly as the native ones
|
|
545
|
+
do.
|
|
546
|
+
|
|
547
|
+
### When the store is lost
|
|
548
|
+
|
|
549
|
+
The store can go while the preferences describing it survive: a browser
|
|
550
|
+
clearing IndexedDB alone, a data directory deleted by hand, a store that
|
|
551
|
+
failed mid-session. (When a browser clears a whole site, preferences go with
|
|
552
|
+
it, and the app starts as a new install.) So what the operator installed is
|
|
553
|
+
kept apart from the store that holds it, and put back from there.
|
|
554
|
+
|
|
555
|
+
`extensionsInstalled` records every extension the operator installed
|
|
556
|
+
(`{key: name}`). Every install writes it; only an uninstall — or Forget, below
|
|
557
|
+
— removes it. An install that predates it is seeded from its store once, and
|
|
558
|
+
after that it never follows the store: a store found short is exactly what it
|
|
559
|
+
must not shrink to. Whatever is recorded there and not in the store is
|
|
560
|
+
**missing**, however it went — judged by the keys the store holds, not by the
|
|
561
|
+
extensions the app offers, since a built-in or a dev server can stand in front
|
|
562
|
+
of an installed bundle. A store that cannot be read at all has lost nothing:
|
|
563
|
+
that launch offers nothing, rather than everything back into a failing store.
|
|
564
|
+
Where each came from is its provenance record's answer, and a key with none
|
|
565
|
+
came from a file.
|
|
566
|
+
|
|
567
|
+
The operator's on/off choice for a missing extension is kept too: the boot
|
|
568
|
+
cleanup that prunes settings for keys the app no longer knows treats every
|
|
569
|
+
recorded key as known.
|
|
570
|
+
|
|
571
|
+
Putting them back, after the app starts:
|
|
572
|
+
|
|
573
|
+
- **Shipped bundles** come back at boot from the app's own assets, unasked and
|
|
574
|
+
offline. The pre-load record says they were already offered, which is true
|
|
575
|
+
and beside the point; they are installed anyway, never as a first install,
|
|
576
|
+
so their settings and on/off choice stand. An install that has not taken the
|
|
577
|
+
upgrade gets back only what it had.
|
|
578
|
+
- **Everything else** is offered in a dialog once the boot has settled:
|
|
579
|
+
- extensions from the catalog in use are listed to install, at the release
|
|
580
|
+
it serves now. **Later** keeps every one for the next launch;
|
|
581
|
+
- extensions from a file are listed to install again from their files, and
|
|
582
|
+
ones from a different catalog as not available here. Neither is fetched —
|
|
583
|
+
the bytes would come from a publisher the operator never agreed to;
|
|
584
|
+
- every row has **Forget**, which drops it with everything it stored — the
|
|
585
|
+
only way out for one the catalog no longer serves, which would otherwise
|
|
586
|
+
be offered, and fail, every launch.
|
|
587
|
+
- **Install** installs each on its own: one that is not listed, will not
|
|
588
|
+
download or fails the check costs only itself. The runtime restarts with
|
|
589
|
+
everything that landed; a bundle it will not evaluate is set aside, as the
|
|
590
|
+
upgrade does, and the runtime restarts without it. The result names what
|
|
591
|
+
could not be installed (offered again next launch) and what installed but
|
|
592
|
+
would not run (kept, marked in the panel, where an update is the way back);
|
|
593
|
+
says so when the runtime would not start at all, rather than calling it a
|
|
594
|
+
success; and says the app is still busy — offering them again next launch
|
|
595
|
+
— when another catalog pass holds the store.
|
|
596
|
+
- The offer waits for the boot's catch-up to finish, or for an upgrade that
|
|
597
|
+
every catch-up stepped aside for to let go.
|
package/docs/hooks.md
CHANGED
|
@@ -741,12 +741,17 @@ knowing them. Called by the `adif` extension **inside the runtime** via
|
|
|
741
741
|
|
|
742
742
|
```ts
|
|
743
743
|
interface AdifFieldsHook {
|
|
744
|
-
fieldsForOneQSO(args: { qso, operation }, ctx): Promise<{name, value}[]>
|
|
744
|
+
fieldsForOneQSO(args: { qso, operation, mainHandler? }, ctx): Promise<{name, value}[]>
|
|
745
745
|
// One field set PER ADIF RECORD this contact should produce.
|
|
746
|
-
fieldCombinationsForOneQSO?(args: { qso, operation }, ctx): Promise<{name, value}[][]>
|
|
746
|
+
fieldCombinationsForOneQSO?(args: { qso, operation, mainHandler? }, ctx): Promise<{name, value}[][]>
|
|
747
747
|
}
|
|
748
748
|
```
|
|
749
749
|
|
|
750
|
+
`mainHandler` is true when the file is this extension's own export — app-polo's
|
|
751
|
+
argument of the same name. It is how a program writes what only its own
|
|
752
|
+
submission asks for: SOTA's files carry both stations' gridsquares, which the
|
|
753
|
+
full export leaves to the contact's own privacy rules.
|
|
754
|
+
|
|
750
755
|
POTA contributes `SIG/SIG_INFO/POTA_REF` (hunted refs on the QSO) and
|
|
751
756
|
`MY_SIG/MY_SIG_INFO/MY_POTA_REF` (activation refs on the operation).
|
|
752
757
|
|
|
@@ -819,11 +824,18 @@ would claim no reference at all.
|
|
|
819
824
|
**A field name is written once per record, and the first to carry a value
|
|
820
825
|
wins.** ADIF gives no meaning to a repeated field, so where two hooks answer
|
|
821
826
|
the same name — the full export asks every program on the contact, and a park
|
|
822
|
-
and a summit both answer `MY_SIG` — the later one is dropped
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
+
and a summit both answer `MY_SIG` — the later one is dropped. Hooks are asked
|
|
828
|
+
main handler first, then each `includeFieldsFrom` key in the order given, so
|
|
829
|
+
that order decides — whichever of the two methods each hook answered. The
|
|
830
|
+
contact's own fields come after every hook's: a program knows what its file
|
|
831
|
+
needs in a field better than the contact's generic answer does (the section a
|
|
832
|
+
Field Day station sent, a satellite's downlink band). The exception is what
|
|
833
|
+
identifies the contact — `CALL`, `QSO_DATE`, `TIME_ON`, `QSO_DATE_OFF`,
|
|
834
|
+
`TIME_OFF`, `BAND`, `FREQ`, `MODE`, `SUBMODE`, `STATION_CALLSIGN`,
|
|
835
|
+
`OPERATOR`: a hook answering one of those is dropped, since it would rewrite
|
|
836
|
+
every record it is asked about, the whole-log backup included. This is a
|
|
837
|
+
deliberate divergence from app-polo, whose contact fields come first and whose
|
|
838
|
+
main handler's are appended unchecked, so a name both answer is written twice. The **full export**, which asks every
|
|
827
839
|
program on the contact, has no such order: hooks answering `fieldCombinationsForOneQSO` are asked as one
|
|
828
840
|
group and hooks answering `fieldsForOneQSO` as another, so which of two programs
|
|
829
841
|
keeps a shared `MY_SIG` there is not something either of them chose.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ham2k/extension-sdk",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"description": "Write extensions for the Ham2K Logger: typed hook contracts and the host API",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ham2k",
|
|
@@ -71,12 +71,12 @@
|
|
|
71
71
|
"build": "node build.mjs"
|
|
72
72
|
},
|
|
73
73
|
"//peerDependencies": [
|
|
74
|
-
"The libraries the extension host
|
|
74
|
+
"The libraries the extension host provides. An extension does NOT need these",
|
|
75
75
|
"installed: the build preset rewrites each one the manifest declares into a",
|
|
76
76
|
"lookup on the host's single instance, before esbuild ever resolves it, and",
|
|
77
|
-
"the published .d.ts
|
|
77
|
+
"the published .d.ts has their types rolled in. They are here, optional,",
|
|
78
78
|
"for the one case that does reach the filesystem \u2014 `inline: [...]`, which",
|
|
79
|
-
"ships your own copy because you need a version the host does not
|
|
79
|
+
"ships your own copy because you need a version the host does not provide."
|
|
80
80
|
],
|
|
81
81
|
"peerDependencies": {
|
|
82
82
|
"@ham2k/lib-callsigns": "*",
|