@tx5dr/plugin-api 1.0.0 → 1.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/dist/context.d.ts +27 -3
- package/dist/context.d.ts.map +1 -1
- package/dist/definition.d.ts +35 -3
- package/dist/definition.d.ts.map +1 -1
- package/dist/helpers.d.ts +177 -2
- package/dist/helpers.d.ts.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/sync.d.ts +161 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +9 -0
- package/dist/sync.js.map +1 -0
- package/dist/testing/index.d.ts +2 -1
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +45 -0
- package/dist/testing/index.js.map +1 -1
- package/package.json +1 -1
package/dist/context.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { KVStore, PluginLogger, PluginTimers, OperatorControl, RadioControl, LogbookAccess, BandAccess, UIBridge } from './helpers.js';
|
|
1
|
+
import type { KVStore, PluginLogger, PluginTimers, OperatorControl, RadioControl, LogbookAccess, BandAccess, UIBridge, PluginFileStore } from './helpers.js';
|
|
2
|
+
import type { LogbookSyncRegistrar } from './sync.js';
|
|
2
3
|
/**
|
|
3
4
|
* Runtime services exposed to a plugin instance.
|
|
4
5
|
*
|
|
@@ -60,7 +61,13 @@ export interface PluginContext {
|
|
|
60
61
|
*/
|
|
61
62
|
readonly radio: RadioControl;
|
|
62
63
|
/**
|
|
63
|
-
*
|
|
64
|
+
* Full logbook access — read-only queries, record writes and UI notifications.
|
|
65
|
+
*
|
|
66
|
+
* Provides the original read-only helpers (`hasWorked`, `hasWorkedDXCC`,
|
|
67
|
+
* `hasWorkedGrid`) plus advanced query (`queryQSOs`, `countQSOs`), write
|
|
68
|
+
* (`addQSO`, `updateQSO`) and notification (`notifyUpdated`) capabilities.
|
|
69
|
+
* Sync providers and other data-oriented plugins use the write methods to
|
|
70
|
+
* self-orchestrate their flow without host-side special handling.
|
|
64
71
|
*/
|
|
65
72
|
readonly logbook: LogbookAccess;
|
|
66
73
|
/**
|
|
@@ -68,9 +75,26 @@ export interface PluginContext {
|
|
|
68
75
|
*/
|
|
69
76
|
readonly band: BandAccess;
|
|
70
77
|
/**
|
|
71
|
-
* Bridge for pushing structured data into declarative plugin panels
|
|
78
|
+
* Bridge for pushing structured data into declarative plugin panels and
|
|
79
|
+
* for communicating with custom iframe UI pages.
|
|
72
80
|
*/
|
|
73
81
|
readonly ui: UIBridge;
|
|
82
|
+
/**
|
|
83
|
+
* Persistent binary file storage sandboxed to the plugin.
|
|
84
|
+
*
|
|
85
|
+
* Files are stored in the plugin data directory under a host-managed sandbox.
|
|
86
|
+
* Use this for binary assets such as certificates, images or cached data.
|
|
87
|
+
* For structured JSON data, prefer {@link PluginContext.store} instead.
|
|
88
|
+
*/
|
|
89
|
+
readonly files: PluginFileStore;
|
|
90
|
+
/**
|
|
91
|
+
* Logbook sync registration entry point.
|
|
92
|
+
*
|
|
93
|
+
* Utility plugins that implement logbook synchronization call
|
|
94
|
+
* `ctx.logbookSync.register(provider)` during `onLoad` to register their
|
|
95
|
+
* sync provider. The host manages the provider lifecycle and UI integration.
|
|
96
|
+
*/
|
|
97
|
+
readonly logbookSync: LogbookSyncRegistrar;
|
|
74
98
|
/**
|
|
75
99
|
* Permission-gated HTTP client.
|
|
76
100
|
*
|
package/dist/context.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,aAAa,EACb,UAAU,EACV,QAAQ,
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,aAAa,EACb,UAAU,EACV,QAAQ,EACR,eAAe,EAChB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEtD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAEnD;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE;QACd;;WAEG;QACH,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;QAEzB;;WAEG;QACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;KAC5B,CAAC;IAEF;;;;;OAKG;IACH,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC;IAE3B;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAE9B;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IAEnC;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAE7B;;;;;;;;OAQG;IACH,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAEhC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAE1B;;;OAGG;IACH,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC;IAEtB;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAEhC;;;;;;OAMG;IACH,QAAQ,CAAC,WAAW,EAAE,oBAAoB,CAAC;IAE3C;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;CACzE"}
|
package/dist/definition.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PluginSettingDescriptor, PluginQuickAction, PluginQuickSetting, PluginPanelDescriptor, PluginPermission, PluginType } from '@tx5dr/contracts';
|
|
1
|
+
import type { PluginSettingDescriptor, PluginQuickAction, PluginQuickSetting, PluginPanelDescriptor, PluginPermission, PluginType, PluginInstanceScope, PluginUIPageDescriptor } from '@tx5dr/contracts';
|
|
2
2
|
import type { PluginContext } from './context.js';
|
|
3
3
|
import type { PluginHooks } from './hooks.js';
|
|
4
4
|
import type { StrategyRuntime } from './runtime.js';
|
|
@@ -91,6 +91,13 @@ export interface PluginDefinition {
|
|
|
91
91
|
* do not own the core automation state machine.
|
|
92
92
|
*/
|
|
93
93
|
type: PluginType;
|
|
94
|
+
/**
|
|
95
|
+
* Controls whether the host creates one instance per operator or a single
|
|
96
|
+
* shared instance for the whole station.
|
|
97
|
+
*
|
|
98
|
+
* Defaults to `operator` when omitted.
|
|
99
|
+
*/
|
|
100
|
+
instanceScope?: PluginInstanceScope;
|
|
94
101
|
/**
|
|
95
102
|
* Human-readable summary shown in plugin management UIs.
|
|
96
103
|
*
|
|
@@ -132,8 +139,14 @@ export interface PluginDefinition {
|
|
|
132
139
|
/**
|
|
133
140
|
* Panel descriptors used to render plugin-owned UI sections.
|
|
134
141
|
*
|
|
135
|
-
*
|
|
136
|
-
* {@link PluginContext.ui}
|
|
142
|
+
* Structured panels (`key-value`, `table`, `log`, `chart`) receive live data
|
|
143
|
+
* through {@link PluginContext.ui.send}. Iframe panels (`component: 'iframe'`)
|
|
144
|
+
* render a custom HTML page and communicate via `invoke` / `onPush`.
|
|
145
|
+
*
|
|
146
|
+
* Each panel has a `slot` that controls where it renders: `'operator'` (the
|
|
147
|
+
* default, shown in the operator card) or `'automation'` (shown in the
|
|
148
|
+
* top-right automation popover). Panels may also declare a preferred
|
|
149
|
+
* `width`, such as `'full'`, so hosts can promote more important live panels.
|
|
137
150
|
*/
|
|
138
151
|
panels?: PluginPanelDescriptor[];
|
|
139
152
|
/**
|
|
@@ -146,6 +159,25 @@ export interface PluginDefinition {
|
|
|
146
159
|
storage?: {
|
|
147
160
|
scopes: ('global' | 'operator')[];
|
|
148
161
|
};
|
|
162
|
+
/**
|
|
163
|
+
* Declares custom UI pages served from the plugin's static file directory.
|
|
164
|
+
*
|
|
165
|
+
* Pages are rendered inside an iframe by the host's `PluginIframeHost`
|
|
166
|
+
* component. The host automatically injects CSS design tokens and a
|
|
167
|
+
* communication bridge SDK. Plugins can use any web technology inside the
|
|
168
|
+
* iframe.
|
|
169
|
+
*
|
|
170
|
+
* Pages are declarative — they only define _what_ exists, not _where_ it is
|
|
171
|
+
* rendered. The rendering location is decided by consumers (e.g. a logbook
|
|
172
|
+
* sync host renders the page in a settings modal tab, while a future
|
|
173
|
+
* dashboard host may render it in a side panel).
|
|
174
|
+
*/
|
|
175
|
+
ui?: {
|
|
176
|
+
/** Static file directory relative to the plugin root (default: 'ui'). */
|
|
177
|
+
dir?: string;
|
|
178
|
+
/** Registered custom UI pages. */
|
|
179
|
+
pages?: PluginUIPageDescriptor[];
|
|
180
|
+
};
|
|
149
181
|
/**
|
|
150
182
|
* Creates the strategy runtime for a `strategy` plugin.
|
|
151
183
|
*
|
package/dist/definition.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../src/definition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,uBAAuB,EACvB,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,gBAAgB,EAChB,UAAU,
|
|
1
|
+
{"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../src/definition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,uBAAuB,EACvB,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,gBAAgB,EAChB,UAAU,EACV,mBAAmB,EACnB,sBAAsB,EACvB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;;;;OAMG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;;;;;OAOG;IACH,IAAI,EAAE,UAAU,CAAC;IAEjB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,mBAAmB,CAAC;IAEpC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAEjC;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC;IAEnD;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAEnC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAErC;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,EAAE,qBAAqB,EAAE,CAAC;IAEjC;;;;;;OAMG;IACH,OAAO,CAAC,EAAE;QAAE,MAAM,EAAE,CAAC,QAAQ,GAAG,UAAU,CAAC,EAAE,CAAA;KAAE,CAAC;IAEhD;;;;;;;;;;;;OAYG;IACH,EAAE,CAAC,EAAE;QACH,yEAAyE;QACzE,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,kCAAkC;QAClC,KAAK,CAAC,EAAE,sBAAsB,EAAE,CAAC;KAClC,CAAC;IAEF;;;;;;OAMG;IACH,qBAAqB,CAAC,CAAC,GAAG,EAAE,aAAa,GAAG,eAAe,CAAC;IAE5D;;;;;;OAMG;IACH,MAAM,CAAC,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElD;;;;;;OAMG;IACH,QAAQ,CAAC,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpD;;;;;OAKG;IACH,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB"}
|
package/dist/helpers.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ParsedFT8Message, SlotInfo, SlotPack, QSORecord, FrameMessage, OperatorSlots, ModeDescriptor } from '@tx5dr/contracts';
|
|
1
|
+
import type { ParsedFT8Message, SlotInfo, SlotPack, QSORecord, FrameMessage, OperatorSlots, ModeDescriptor, PermissionGrant } from '@tx5dr/contracts';
|
|
2
2
|
import type { StrategyRuntimeSnapshot } from './runtime.js';
|
|
3
3
|
/**
|
|
4
4
|
* Simple persistent key-value store exposed to plugins.
|
|
@@ -141,7 +141,71 @@ export interface RadioControl {
|
|
|
141
141
|
setFrequency(freq: number): Promise<void>;
|
|
142
142
|
}
|
|
143
143
|
/**
|
|
144
|
-
*
|
|
144
|
+
* Filter criteria for querying QSO records from the logbook.
|
|
145
|
+
*
|
|
146
|
+
* This type is defined in the plugin-api layer so plugins have no compile-time
|
|
147
|
+
* dependency on core internals. The host translates it to the storage layer's
|
|
148
|
+
* native query format.
|
|
149
|
+
*/
|
|
150
|
+
export interface QSOQueryFilter {
|
|
151
|
+
/** Match a specific callsign (exact match). */
|
|
152
|
+
callsign?: string;
|
|
153
|
+
/** Restrict to a time window (epoch ms). */
|
|
154
|
+
timeRange?: {
|
|
155
|
+
start: number;
|
|
156
|
+
end: number;
|
|
157
|
+
};
|
|
158
|
+
/** Restrict to a frequency window (Hz). */
|
|
159
|
+
frequencyRange?: {
|
|
160
|
+
min: number;
|
|
161
|
+
max: number;
|
|
162
|
+
};
|
|
163
|
+
/** Mode filter (e.g. 'FT8'). */
|
|
164
|
+
mode?: string;
|
|
165
|
+
/**
|
|
166
|
+
* QSL confirmation status filter.
|
|
167
|
+
* - `'confirmed'`: at least one platform confirmed
|
|
168
|
+
* - `'uploaded'`: at least one platform uploaded but not confirmed
|
|
169
|
+
* - `'none'`: not uploaded to any platform
|
|
170
|
+
*/
|
|
171
|
+
qslStatus?: 'confirmed' | 'uploaded' | 'none';
|
|
172
|
+
/** Maximum number of records to return. */
|
|
173
|
+
limit?: number;
|
|
174
|
+
/** Number of records to skip (for pagination). */
|
|
175
|
+
offset?: number;
|
|
176
|
+
/** Sort direction. Defaults to descending (newest first). */
|
|
177
|
+
orderDirection?: 'asc' | 'desc';
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Callsign-bound view over a single logbook.
|
|
181
|
+
*
|
|
182
|
+
* The host resolves the concrete logbook lazily on each operation, which keeps
|
|
183
|
+
* the handle valid even if the underlying logbook is created or reloaded later.
|
|
184
|
+
*/
|
|
185
|
+
export interface CallsignLogbookAccess {
|
|
186
|
+
/** Normalized callsign that scopes this accessor. */
|
|
187
|
+
readonly callsign: string;
|
|
188
|
+
/** Returns the resolved logbook id, or null when no logbook exists yet. */
|
|
189
|
+
getLogBookId(): Promise<string | null>;
|
|
190
|
+
/** Queries QSO records matching the given filter. */
|
|
191
|
+
queryQSOs(filter: QSOQueryFilter): Promise<import('@tx5dr/contracts').QSORecord[]>;
|
|
192
|
+
/** Counts QSO records matching the given filter. */
|
|
193
|
+
countQSOs(filter?: QSOQueryFilter): Promise<number>;
|
|
194
|
+
/** Adds a new QSO record to this callsign's logbook. */
|
|
195
|
+
addQSO(record: import('@tx5dr/contracts').QSORecord): Promise<void>;
|
|
196
|
+
/** Updates partial fields of an existing QSO record. */
|
|
197
|
+
updateQSO(qsoId: string, updates: Partial<import('@tx5dr/contracts').QSORecord>): Promise<void>;
|
|
198
|
+
/** Returns current statistics for this callsign's logbook. */
|
|
199
|
+
getStatistics(): Promise<import('@tx5dr/contracts').LogBookStatistics | null>;
|
|
200
|
+
/** Notifies the frontend that this callsign's logbook changed. */
|
|
201
|
+
notifyUpdated(operatorId?: string): Promise<void>;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Full logbook access for plugins.
|
|
205
|
+
*
|
|
206
|
+
* Extends the original read-only helpers with query, write and notification
|
|
207
|
+
* capabilities so that sync providers can self-orchestrate their entire flow
|
|
208
|
+
* without host-side special handling.
|
|
145
209
|
*/
|
|
146
210
|
export interface LogbookAccess {
|
|
147
211
|
/** Checks whether the callsign has already been worked. */
|
|
@@ -150,6 +214,18 @@ export interface LogbookAccess {
|
|
|
150
214
|
hasWorkedDXCC(dxccEntity: string): Promise<boolean>;
|
|
151
215
|
/** Checks whether the Maidenhead grid has already been worked. */
|
|
152
216
|
hasWorkedGrid(grid: string): Promise<boolean>;
|
|
217
|
+
/** Queries QSO records matching the given filter. */
|
|
218
|
+
queryQSOs(filter: QSOQueryFilter): Promise<import('@tx5dr/contracts').QSORecord[]>;
|
|
219
|
+
/** Counts QSO records matching the given filter. */
|
|
220
|
+
countQSOs(filter?: QSOQueryFilter): Promise<number>;
|
|
221
|
+
/** Returns a callsign-bound accessor suitable for global plugin instances. */
|
|
222
|
+
forCallsign(callsign: string): CallsignLogbookAccess;
|
|
223
|
+
/** Adds a new QSO record. Deduplication is the caller's responsibility. */
|
|
224
|
+
addQSO(record: import('@tx5dr/contracts').QSORecord): Promise<void>;
|
|
225
|
+
/** Updates partial fields of an existing QSO record (e.g. QSL status). */
|
|
226
|
+
updateQSO(qsoId: string, updates: Partial<import('@tx5dr/contracts').QSORecord>): Promise<void>;
|
|
227
|
+
/** Notifies the frontend to refresh logbook data (call after batch writes). */
|
|
228
|
+
notifyUpdated(): Promise<void>;
|
|
153
229
|
}
|
|
154
230
|
/**
|
|
155
231
|
* Optional constraints used when asking the host for a quieter transmit offset.
|
|
@@ -219,5 +295,104 @@ export interface UIBridge {
|
|
|
219
295
|
* Publishes new panel data for the given declarative panel id.
|
|
220
296
|
*/
|
|
221
297
|
send(panelId: string, data: unknown): void;
|
|
298
|
+
/**
|
|
299
|
+
* Registers a handler for custom messages sent from iframe UI pages via the
|
|
300
|
+
* `bridge.invoke()` SDK method. The host routes incoming invoke requests to
|
|
301
|
+
* the handler and sends the return value back to the iframe.
|
|
302
|
+
*
|
|
303
|
+
* Only one handler can be registered per plugin instance. Calling this method
|
|
304
|
+
* again replaces the previous handler.
|
|
305
|
+
*/
|
|
306
|
+
registerPageHandler(handler: PluginUIHandler): void;
|
|
307
|
+
/**
|
|
308
|
+
* Pushes a custom message to the specific page session.
|
|
309
|
+
*
|
|
310
|
+
* Prefer this API whenever the plugin already knows the target session id
|
|
311
|
+
* (for example from {@link PluginUIRequestContext.pageSessionId} or
|
|
312
|
+
* `requestContext.page.sessionId`).
|
|
313
|
+
*/
|
|
314
|
+
pushToSession(pageSessionId: string, action: string, data?: unknown): void;
|
|
315
|
+
/**
|
|
316
|
+
* Lists active page sessions for the current plugin instance and page id.
|
|
317
|
+
*
|
|
318
|
+
* This is useful for background timers or sync completions that need to
|
|
319
|
+
* notify every open page tied to the same runtime instance.
|
|
320
|
+
*/
|
|
321
|
+
listActivePageSessions(pageId: string): PluginUIPageSessionInfo[];
|
|
322
|
+
/**
|
|
323
|
+
* Pushes a custom message to an iframe UI page by page id.
|
|
324
|
+
*
|
|
325
|
+
* This compatibility helper only succeeds when exactly one active session of
|
|
326
|
+
* the current plugin instance matches the page id. If multiple sessions are
|
|
327
|
+
* open, the host throws `explicit_page_session_required`.
|
|
328
|
+
*/
|
|
329
|
+
pushToPage(pageId: string, action: string, data?: unknown): void;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Handler for custom messages sent from iframe UI pages.
|
|
333
|
+
*
|
|
334
|
+
* Plugins register a handler via `ctx.ui.registerPageHandler()` to receive
|
|
335
|
+
* arbitrary invoke requests from their iframe-based UIs. The host acts as a
|
|
336
|
+
* transparent router — it does not inspect or interpret the action or data.
|
|
337
|
+
*/
|
|
338
|
+
export interface PluginUIHandler {
|
|
339
|
+
/**
|
|
340
|
+
* Called when the iframe sends an invoke request via `bridge.invoke(action, data)`.
|
|
341
|
+
*
|
|
342
|
+
* @param pageId - The page that sent the message.
|
|
343
|
+
* @param action - Developer-defined action identifier.
|
|
344
|
+
* @param data - Arbitrary payload from the iframe.
|
|
345
|
+
* @param requestContext - Host-authenticated page context, including any
|
|
346
|
+
* bound resource for this page session.
|
|
347
|
+
* @returns The response value sent back to the iframe.
|
|
348
|
+
*/
|
|
349
|
+
onMessage(pageId: string, action: string, data: unknown, requestContext: PluginUIRequestContext): Promise<unknown>;
|
|
350
|
+
}
|
|
351
|
+
export interface PluginUIRequestUser {
|
|
352
|
+
readonly tokenId: string;
|
|
353
|
+
readonly role: 'viewer' | 'operator' | 'admin';
|
|
354
|
+
readonly operatorIds: string[];
|
|
355
|
+
readonly permissionGrants?: PermissionGrant[];
|
|
356
|
+
}
|
|
357
|
+
export interface PluginUIBoundResource {
|
|
358
|
+
readonly kind: 'callsign' | 'operator';
|
|
359
|
+
readonly value: string;
|
|
360
|
+
}
|
|
361
|
+
export type PluginUIInstanceTarget = {
|
|
362
|
+
readonly kind: 'global';
|
|
363
|
+
} | {
|
|
364
|
+
readonly kind: 'operator';
|
|
365
|
+
readonly operatorId: string;
|
|
366
|
+
};
|
|
367
|
+
export interface PluginUIPageSessionInfo {
|
|
368
|
+
readonly sessionId: string;
|
|
369
|
+
readonly pageId: string;
|
|
370
|
+
readonly resource?: PluginUIBoundResource;
|
|
371
|
+
}
|
|
372
|
+
export interface PluginUIPageContext extends PluginUIPageSessionInfo {
|
|
373
|
+
push(action: string, data?: unknown): void;
|
|
374
|
+
}
|
|
375
|
+
export interface PluginUIRequestContext {
|
|
376
|
+
readonly pageSessionId: string;
|
|
377
|
+
readonly user: PluginUIRequestUser;
|
|
378
|
+
readonly resource?: PluginUIBoundResource;
|
|
379
|
+
readonly instanceTarget: PluginUIInstanceTarget;
|
|
380
|
+
readonly page: PluginUIPageContext;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Persistent binary file storage for plugins.
|
|
384
|
+
*
|
|
385
|
+
* Files are stored in a sandboxed directory under the plugin's data path. Path
|
|
386
|
+
* traversal outside the sandbox is rejected by the host.
|
|
387
|
+
*/
|
|
388
|
+
export interface PluginFileStore {
|
|
389
|
+
/** Writes (or overwrites) a file at the given path. */
|
|
390
|
+
write(path: string, data: Buffer): Promise<void>;
|
|
391
|
+
/** Reads a file. Returns `null` when the path does not exist. */
|
|
392
|
+
read(path: string): Promise<Buffer | null>;
|
|
393
|
+
/** Deletes a file. Returns `true` if the file existed and was removed. */
|
|
394
|
+
delete(path: string): Promise<boolean>;
|
|
395
|
+
/** Lists file paths under the given prefix (or all files when omitted). */
|
|
396
|
+
list(prefix?: string): Promise<string[]>;
|
|
222
397
|
}
|
|
223
398
|
//# sourceMappingURL=helpers.d.ts.map
|
package/dist/helpers.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,aAAa,EACb,cAAc,
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -25,9 +25,11 @@ export type { PluginContext } from './context.js';
|
|
|
25
25
|
export type { PluginHooks, AutoCallProposal, AutoCallExecutionRequest, AutoCallExecutionPlan, ScoredCandidate, StrategyDecision, StrategyDecisionMeta, LastMessageInfo, } from './hooks.js';
|
|
26
26
|
export type { StrategyRuntime, StrategyRuntimeContext, StrategyRuntimeSnapshot, StrategyRuntimeSlot, StrategyRuntimeSlotContentUpdate, } from './runtime.js';
|
|
27
27
|
/** Host-provided helper interfaces available through {@link PluginContext}. */
|
|
28
|
-
export type { KVStore, PluginLogger, PluginTimers, OperatorControl, RadioControl, LogbookAccess, BandAccess, IdleTransmitFrequencyOptions, AutoTargetEligibilityReason, AutoTargetEligibilityDecision, UIBridge, } from './helpers.js';
|
|
28
|
+
export type { KVStore, PluginLogger, PluginTimers, OperatorControl, RadioControl, LogbookAccess, CallsignLogbookAccess, QSOQueryFilter, BandAccess, IdleTransmitFrequencyOptions, AutoTargetEligibilityReason, AutoTargetEligibilityDecision, UIBridge, PluginUIHandler, PluginUIRequestContext, PluginUIRequestUser, PluginUIBoundResource, PluginUIInstanceTarget, PluginUIPageSessionInfo, PluginUIPageContext, PluginFileStore, } from './helpers.js';
|
|
29
29
|
/** Common radio/message/settings types re-exported for plugin author convenience. */
|
|
30
|
-
export type { FT8Message, FT8MessageBase, FT8MessageCQ, FT8MessageCall, FT8MessageSignalReport, FT8MessageRogerReport, FT8MessageRRR, FT8MessageSeventyThree, FT8MessageFoxRR73, FT8MessageCustom, FT8MessageUnknown, ParsedFT8Message, LogbookAnalysis, SlotInfo, SlotPack, QSORecord, FrameMessage, ModeDescriptor, OperatorSlots, DxccStatus, TargetSelectionPriorityMode, PluginType, PluginPermission, PluginSettingType, PluginSettingDescriptor, PluginSettingScope, PluginQuickAction, PluginQuickSetting, PluginCapability, PluginPanelDescriptor, PluginPanelComponent, PluginSettingOption, PluginStorageScope, PluginStorageConfig, PluginManifest, PluginStatus, } from '@tx5dr/contracts';
|
|
30
|
+
export type { FT8Message, FT8MessageBase, FT8MessageCQ, FT8MessageCall, FT8MessageSignalReport, FT8MessageRogerReport, FT8MessageRRR, FT8MessageSeventyThree, FT8MessageFoxRR73, FT8MessageCustom, FT8MessageUnknown, ParsedFT8Message, LogbookAnalysis, SlotInfo, SlotPack, QSORecord, FrameMessage, ModeDescriptor, OperatorSlots, DxccStatus, TargetSelectionPriorityMode, PluginType, PluginInstanceScope, PluginPermission, PluginSettingType, PluginSettingDescriptor, PluginSettingScope, PluginQuickAction, PluginQuickSetting, PluginCapability, PluginPanelDescriptor, PluginPanelComponent, PluginPanelWidth, PluginSettingOption, PluginStorageScope, PluginStorageConfig, PluginManifest, PluginStatus, PluginUIPageDescriptor, PluginUIConfig, } from '@tx5dr/contracts';
|
|
31
|
+
/** Logbook sync provider interfaces. */
|
|
32
|
+
export type { LogbookSyncProvider, LogbookSyncRegistrar, SyncAction, SyncTestResult, SyncUploadResult, SyncPreflightIssue, SyncUploadPreflightResult, SyncDownloadResult, SyncDownloadOptions, } from './sync.js';
|
|
31
33
|
/** Stable runtime enum values commonly referenced by plugin implementations. */
|
|
32
34
|
export { FT8MessageType } from './ft8-message-type.js';
|
|
33
35
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,uDAAuD;AACvD,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,YAAY,EACV,WAAW,EACX,gBAAgB,EAChB,wBAAwB,EACxB,qBAAqB,EACrB,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,eAAe,EACf,sBAAsB,EACtB,uBAAuB,EACvB,mBAAmB,EACnB,gCAAgC,GACjC,MAAM,cAAc,CAAC;AAEtB,+EAA+E;AAC/E,YAAY,EACV,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,aAAa,EACb,UAAU,EACV,4BAA4B,EAC5B,2BAA2B,EAC3B,6BAA6B,EAC7B,QAAQ,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,uDAAuD;AACvD,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,YAAY,EACV,WAAW,EACX,gBAAgB,EAChB,wBAAwB,EACxB,qBAAqB,EACrB,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,eAAe,EACf,sBAAsB,EACtB,uBAAuB,EACvB,mBAAmB,EACnB,gCAAgC,GACjC,MAAM,cAAc,CAAC;AAEtB,+EAA+E;AAC/E,YAAY,EACV,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,aAAa,EACb,qBAAqB,EACrB,cAAc,EACd,UAAU,EACV,4BAA4B,EAC5B,2BAA2B,EAC3B,6BAA6B,EAC7B,QAAQ,EACR,eAAe,EACf,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,EACvB,mBAAmB,EACnB,eAAe,GAChB,MAAM,cAAc,CAAC;AAEtB,qFAAqF;AACrF,YAAY,EACV,UAAU,EACV,cAAc,EACd,YAAY,EACZ,cAAc,EACd,sBAAsB,EACtB,qBAAqB,EACrB,aAAa,EACb,sBAAsB,EACtB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,cAAc,EACd,aAAa,EACb,UAAU,EACV,2BAA2B,EAC3B,UAAU,EACV,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,uBAAuB,EACvB,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,YAAY,EACZ,sBAAsB,EACtB,cAAc,GACf,MAAM,kBAAkB,CAAC;AAE1B,wCAAwC;AACxC,YAAY,EACV,mBAAmB,EACnB,oBAAoB,EACpB,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,yBAAyB,EACzB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,WAAW,CAAC;AAEnB,gFAAgF;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAyGH,gFAAgF;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC"}
|
package/dist/sync.d.ts
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logbook sync provider interfaces.
|
|
3
|
+
*
|
|
4
|
+
* A utility plugin registers a sync provider via `ctx.logbookSync.register()`
|
|
5
|
+
* during `onLoad`. The host manages per-callsign lifecycle, auto-upload on QSO
|
|
6
|
+
* completion, and renders the provider's settings page in the sync modal.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* A logbook sync provider implements the communication logic with a single
|
|
10
|
+
* external log service (e.g. LoTW, QRZ.com, WaveLog).
|
|
11
|
+
*
|
|
12
|
+
* All methods receive a `callsign` parameter because sync configuration and
|
|
13
|
+
* data are organized per-callsign. The provider is responsible for managing
|
|
14
|
+
* its own per-callsign state (typically via `ctx.store.global` keyed by
|
|
15
|
+
* callsign).
|
|
16
|
+
*
|
|
17
|
+
* The provider has full access to the logbook via `ctx.logbook` and is
|
|
18
|
+
* responsible for querying, writing and deduplicating QSO records internally.
|
|
19
|
+
* The host only routes user actions to provider methods — it does not read or
|
|
20
|
+
* write QSOs on the provider's behalf.
|
|
21
|
+
*/
|
|
22
|
+
export interface LogbookSyncProvider {
|
|
23
|
+
/** Stable service identifier (e.g. 'lotw', 'qrz', 'wavelog'). */
|
|
24
|
+
readonly id: string;
|
|
25
|
+
/** Display name (i18n key or literal text). */
|
|
26
|
+
readonly displayName: string;
|
|
27
|
+
/** Optional icon identifier (FontAwesome icon name or URL). */
|
|
28
|
+
readonly icon?: string;
|
|
29
|
+
/** Optional button color hint for the frontend (HeroUI color name). */
|
|
30
|
+
readonly color?: 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'danger';
|
|
31
|
+
/** Which audience may access this provider through host runtime routes. */
|
|
32
|
+
readonly accessScope?: 'admin' | 'operator';
|
|
33
|
+
/**
|
|
34
|
+
* ID of the settings page declared in `PluginDefinition.ui.pages`.
|
|
35
|
+
* The host renders this page inside `<PluginIframeHost>` in the sync
|
|
36
|
+
* settings modal, passing `{ callsign }` as params.
|
|
37
|
+
*/
|
|
38
|
+
readonly settingsPageId: string;
|
|
39
|
+
/**
|
|
40
|
+
* Custom sync action menu items. When declared, these replace the default
|
|
41
|
+
* three-item dropdown (download / upload / full_sync).
|
|
42
|
+
*
|
|
43
|
+
* Each action either performs an operation directly (`operation`) or opens
|
|
44
|
+
* an iframe page for user input before proceeding (`pageId`).
|
|
45
|
+
*/
|
|
46
|
+
readonly actions?: SyncAction[];
|
|
47
|
+
/** Tests whether the external service connection is healthy. */
|
|
48
|
+
testConnection(callsign: string): Promise<SyncTestResult>;
|
|
49
|
+
/**
|
|
50
|
+
* Uploads QSO records to the external service.
|
|
51
|
+
*
|
|
52
|
+
* The provider queries the logbook via `ctx.logbook.queryQSOs()` internally
|
|
53
|
+
* to determine which records to upload. It is also responsible for updating
|
|
54
|
+
* QSL status fields (e.g. `lotwQslSent`) via `ctx.logbook.updateQSO()`.
|
|
55
|
+
*/
|
|
56
|
+
upload(callsign: string): Promise<SyncUploadResult>;
|
|
57
|
+
/**
|
|
58
|
+
* Optional host-visible upload readiness check.
|
|
59
|
+
*
|
|
60
|
+
* When implemented, the host may call this before upload/full-sync actions
|
|
61
|
+
* to surface blocked QSOs or missing configuration without starting upload.
|
|
62
|
+
*/
|
|
63
|
+
getUploadPreflight?(callsign: string): Promise<SyncUploadPreflightResult>;
|
|
64
|
+
/**
|
|
65
|
+
* Downloads QSO confirmations/records from the external service.
|
|
66
|
+
*
|
|
67
|
+
* The provider writes downloaded records or QSL updates directly into the
|
|
68
|
+
* logbook via `ctx.logbook.addQSO()` / `ctx.logbook.updateQSO()`. It
|
|
69
|
+
* should call `ctx.logbook.notifyUpdated()` when done.
|
|
70
|
+
*/
|
|
71
|
+
download(callsign: string, options?: SyncDownloadOptions): Promise<SyncDownloadResult>;
|
|
72
|
+
/** Returns `true` when the provider is fully configured for this callsign. */
|
|
73
|
+
isConfigured(callsign: string): boolean;
|
|
74
|
+
/** Returns `true` when auto-upload is enabled for this callsign. */
|
|
75
|
+
isAutoUploadEnabled(callsign: string): boolean;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Describes a single sync action menu item displayed in the frontend dropdown.
|
|
79
|
+
*
|
|
80
|
+
* Either `operation` or `pageId` must be set (not both):
|
|
81
|
+
* - `operation`: the host directly calls the corresponding provider method
|
|
82
|
+
* - `pageId`: the host opens an iframe page where the user provides input;
|
|
83
|
+
* the page then triggers the operation via `bridge.invoke()`.
|
|
84
|
+
*/
|
|
85
|
+
export interface SyncAction {
|
|
86
|
+
/** Unique action identifier within this provider. */
|
|
87
|
+
id: string;
|
|
88
|
+
/** Display label for the menu item. */
|
|
89
|
+
label: string;
|
|
90
|
+
/** Optional description text shown below the label. */
|
|
91
|
+
description?: string;
|
|
92
|
+
/** Icon hint: download / upload / sync. */
|
|
93
|
+
icon?: 'download' | 'upload' | 'sync';
|
|
94
|
+
/**
|
|
95
|
+
* When set, clicking this action opens the iframe page (registered in
|
|
96
|
+
* `PluginDefinition.ui.pages`) instead of directly executing an operation.
|
|
97
|
+
* The page is responsible for collecting user input and calling
|
|
98
|
+
* `bridge.invoke()` to trigger the actual sync.
|
|
99
|
+
*/
|
|
100
|
+
pageId?: string;
|
|
101
|
+
/**
|
|
102
|
+
* When set (and `pageId` is not), clicking this action directly triggers
|
|
103
|
+
* the corresponding provider method.
|
|
104
|
+
*/
|
|
105
|
+
operation?: 'upload' | 'download' | 'full_sync';
|
|
106
|
+
}
|
|
107
|
+
export interface SyncTestResult {
|
|
108
|
+
success: boolean;
|
|
109
|
+
/** Human-readable result description. */
|
|
110
|
+
message?: string;
|
|
111
|
+
/** Additional service-specific details (e.g. account info, logbook count). */
|
|
112
|
+
details?: unknown;
|
|
113
|
+
}
|
|
114
|
+
export interface SyncUploadResult {
|
|
115
|
+
uploaded: number;
|
|
116
|
+
skipped: number;
|
|
117
|
+
failed: number;
|
|
118
|
+
errors?: string[];
|
|
119
|
+
}
|
|
120
|
+
export interface SyncPreflightIssue {
|
|
121
|
+
code: string;
|
|
122
|
+
severity: 'info' | 'warning' | 'error';
|
|
123
|
+
message: string;
|
|
124
|
+
}
|
|
125
|
+
export interface SyncUploadPreflightResult {
|
|
126
|
+
ready: boolean;
|
|
127
|
+
pendingCount: number;
|
|
128
|
+
uploadableCount: number;
|
|
129
|
+
blockedCount: number;
|
|
130
|
+
issues?: SyncPreflightIssue[];
|
|
131
|
+
guidance?: string[];
|
|
132
|
+
}
|
|
133
|
+
export interface SyncDownloadResult {
|
|
134
|
+
/** Number of records downloaded from the external service. */
|
|
135
|
+
downloaded: number;
|
|
136
|
+
/** Number of records matched to existing local QSOs. */
|
|
137
|
+
matched: number;
|
|
138
|
+
/** Number of local QSOs whose QSL status was updated. */
|
|
139
|
+
updated: number;
|
|
140
|
+
errors?: string[];
|
|
141
|
+
}
|
|
142
|
+
export interface SyncDownloadOptions {
|
|
143
|
+
/** Download records since this timestamp (epoch ms). */
|
|
144
|
+
since?: number;
|
|
145
|
+
/** Download records until this timestamp (epoch ms). */
|
|
146
|
+
until?: number;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Registration entry point exposed via `ctx.logbookSync`.
|
|
150
|
+
*/
|
|
151
|
+
export interface LogbookSyncRegistrar {
|
|
152
|
+
/**
|
|
153
|
+
* Registers a logbook sync provider. The host stores the reference and
|
|
154
|
+
* exposes it through the sync settings UI and auto-upload pipeline.
|
|
155
|
+
*
|
|
156
|
+
* A single plugin may register multiple providers (e.g. one plugin
|
|
157
|
+
* supporting both upload and download for different services).
|
|
158
|
+
*/
|
|
159
|
+
register(provider: LogbookSyncProvider): void;
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"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"}
|
package/dist/sync.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logbook sync provider interfaces.
|
|
3
|
+
*
|
|
4
|
+
* A utility plugin registers a sync provider via `ctx.logbookSync.register()`
|
|
5
|
+
* during `onLoad`. The host manages per-callsign lifecycle, auto-upload on QSO
|
|
6
|
+
* completion, and renders the provider's settings page in the sync modal.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=sync.js.map
|
package/dist/sync.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* import { createMockContext, createMockSlotInfo } from '@tx5dr/plugin-api/testing';
|
|
10
10
|
* ```
|
|
11
11
|
*/
|
|
12
|
-
import type { KVStore, PluginLogger, PluginTimers, OperatorControl, RadioControl, LogbookAccess, BandAccess, UIBridge } from '../helpers.js';
|
|
12
|
+
import type { KVStore, PluginLogger, PluginTimers, OperatorControl, RadioControl, LogbookAccess, BandAccess, UIBridge, PluginFileStore } from '../helpers.js';
|
|
13
13
|
import type { PluginContext } from '../context.js';
|
|
14
14
|
import type { SlotInfo, ParsedFT8Message, ModeDescriptor } from '@tx5dr/contracts';
|
|
15
15
|
/** KVStore backed by an in-memory Map. Inspect `_data` in assertions. */
|
|
@@ -50,6 +50,7 @@ export declare function createMockRadioControl(overrides?: Partial<RadioControl>
|
|
|
50
50
|
export declare function createMockLogbookAccess(overrides?: Partial<LogbookAccess>): LogbookAccess;
|
|
51
51
|
export declare function createMockBandAccess(overrides?: Partial<BandAccess>): BandAccess;
|
|
52
52
|
export declare function createMockUIBridge(): MockUIBridge;
|
|
53
|
+
export declare function createMockFileStore(): PluginFileStore;
|
|
53
54
|
export interface MockPluginContextOptions {
|
|
54
55
|
/** Initial config values (default: empty). */
|
|
55
56
|
config?: Record<string, unknown>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EACV,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,aAAa,EACb,UAAU,EACV,QAAQ,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"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"}
|
package/dist/testing/index.js
CHANGED
|
@@ -96,10 +96,26 @@ export function createMockRadioControl(overrides) {
|
|
|
96
96
|
}
|
|
97
97
|
// ===== Factory: LogbookAccess =====
|
|
98
98
|
export function createMockLogbookAccess(overrides) {
|
|
99
|
+
const callsignAccess = {
|
|
100
|
+
callsign: 'N0CALL',
|
|
101
|
+
getLogBookId: async () => 'logbook-N0CALL',
|
|
102
|
+
queryQSOs: async () => [],
|
|
103
|
+
countQSOs: async () => 0,
|
|
104
|
+
addQSO: async () => { },
|
|
105
|
+
updateQSO: async () => { },
|
|
106
|
+
getStatistics: async () => null,
|
|
107
|
+
notifyUpdated: async () => { },
|
|
108
|
+
};
|
|
99
109
|
return {
|
|
100
110
|
hasWorked: async () => false,
|
|
101
111
|
hasWorkedDXCC: async () => false,
|
|
102
112
|
hasWorkedGrid: async () => false,
|
|
113
|
+
queryQSOs: async () => [],
|
|
114
|
+
countQSOs: async () => 0,
|
|
115
|
+
forCallsign: () => callsignAccess,
|
|
116
|
+
addQSO: async () => { },
|
|
117
|
+
updateQSO: async () => { },
|
|
118
|
+
notifyUpdated: async () => { },
|
|
103
119
|
...overrides,
|
|
104
120
|
};
|
|
105
121
|
}
|
|
@@ -123,6 +139,31 @@ export function createMockUIBridge() {
|
|
|
123
139
|
existing.push(data);
|
|
124
140
|
sentData.set(panelId, existing);
|
|
125
141
|
},
|
|
142
|
+
registerPageHandler(_handler) {
|
|
143
|
+
// no-op in mock
|
|
144
|
+
},
|
|
145
|
+
pushToSession(_pageSessionId, _action, _data) {
|
|
146
|
+
// no-op in mock
|
|
147
|
+
},
|
|
148
|
+
listActivePageSessions(_pageId) {
|
|
149
|
+
return [];
|
|
150
|
+
},
|
|
151
|
+
pushToPage(_pageId, _action, _data) {
|
|
152
|
+
// no-op in mock
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
// ===== Factory: PluginFileStore =====
|
|
157
|
+
export function createMockFileStore() {
|
|
158
|
+
const storage = new Map();
|
|
159
|
+
return {
|
|
160
|
+
async write(p, data) { storage.set(p, data); },
|
|
161
|
+
async read(p) { return storage.get(p) ?? null; },
|
|
162
|
+
async delete(p) { return storage.delete(p); },
|
|
163
|
+
async list(prefix) {
|
|
164
|
+
const keys = Array.from(storage.keys());
|
|
165
|
+
return prefix ? keys.filter(k => k.startsWith(prefix)) : keys;
|
|
166
|
+
},
|
|
126
167
|
};
|
|
127
168
|
}
|
|
128
169
|
export function createMockContext(options) {
|
|
@@ -146,6 +187,8 @@ export function createMockContext(options) {
|
|
|
146
187
|
const radio = createMockRadioControl(opts.radio);
|
|
147
188
|
const logbook = createMockLogbookAccess(opts.logbook);
|
|
148
189
|
const band = createMockBandAccess(opts.band);
|
|
190
|
+
const files = createMockFileStore();
|
|
191
|
+
const logbookSync = { register() { } };
|
|
149
192
|
return {
|
|
150
193
|
config: opts.config ?? {},
|
|
151
194
|
store: { global: globalStore, operator: operatorStore },
|
|
@@ -156,6 +199,8 @@ export function createMockContext(options) {
|
|
|
156
199
|
logbook,
|
|
157
200
|
band,
|
|
158
201
|
ui,
|
|
202
|
+
files,
|
|
203
|
+
logbookSync,
|
|
159
204
|
};
|
|
160
205
|
}
|
|
161
206
|
// ===== Data factories =====
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"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"}
|