@ham2k/extension-sdk 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 +58 -0
- package/dist/activityAdifImport.js +45 -0
- package/dist/activityExports.js +157 -0
- package/dist/activityScoring.js +227 -0
- package/dist/appClock.js +42 -0
- package/dist/dxcc.js +25 -0
- package/dist/exportNames.js +57 -0
- package/dist/i18n/activityExports.en.json +4 -0
- package/dist/i18n/activityExports.es.json +4 -0
- package/dist/i18n/activityScoring.en.json +11 -0
- package/dist/i18n/activityScoring.es.json +11 -0
- package/dist/i18n.js +43 -0
- package/dist/index.d.ts +1361 -0
- package/dist/index.js +231 -0
- package/dist/location.js +19 -0
- package/dist/modes.js +28 -0
- package/dist/number-format.js +68 -0
- package/dist/referenceActivity.js +226 -0
- package/dist/scoring.js +163 -0
- package/dist/settingsPanels.js +59 -0
- package/dist/templateContext.js +113 -0
- package/dist/templates.js +76 -0
- package/dist/testOperation.js +6 -0
- package/dist/types.js +0 -0
- package/package.json +110 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1361 @@
|
|
|
1
|
+
// @ham2k/extension-sdk 0.1.0
|
|
2
|
+
export type CallInfo = {
|
|
3
|
+
call: string;
|
|
4
|
+
baseCall?: string;
|
|
5
|
+
prefix?: string;
|
|
6
|
+
prefixOverride?: string;
|
|
7
|
+
ituPrefix?: string;
|
|
8
|
+
digit?: string;
|
|
9
|
+
preindicator?: string;
|
|
10
|
+
postindicators?: string[];
|
|
11
|
+
indicators?: string[];
|
|
12
|
+
entityPrefix?: string;
|
|
13
|
+
entityName?: string;
|
|
14
|
+
dxccCode?: number;
|
|
15
|
+
continent?: string;
|
|
16
|
+
cqZone?: number;
|
|
17
|
+
ituZone?: number;
|
|
18
|
+
regionCode?: string;
|
|
19
|
+
tz?: string;
|
|
20
|
+
matchSource?: string;
|
|
21
|
+
matchNote?: string;
|
|
22
|
+
location?: String;
|
|
23
|
+
lat?: number;
|
|
24
|
+
lon?: number;
|
|
25
|
+
grid?: string;
|
|
26
|
+
locSource?: string;
|
|
27
|
+
locationScope?: "qth" | "prefixed" | "portable";
|
|
28
|
+
name?: string;
|
|
29
|
+
city?: string;
|
|
30
|
+
state?: string;
|
|
31
|
+
county?: string;
|
|
32
|
+
country?: string;
|
|
33
|
+
exchange?: string;
|
|
34
|
+
sent?: string;
|
|
35
|
+
};
|
|
36
|
+
export type CallInfoLookup = CallInfo & {
|
|
37
|
+
source?: String;
|
|
38
|
+
scope?: "general" | "operation" | "qso";
|
|
39
|
+
notes?: String[];
|
|
40
|
+
history?: QSON[];
|
|
41
|
+
};
|
|
42
|
+
export type AnnotatedCallInfo = CallInfo & {
|
|
43
|
+
guess?: CallInfo;
|
|
44
|
+
lookups?: CallInfoLookup[];
|
|
45
|
+
};
|
|
46
|
+
export type RefInfo = {
|
|
47
|
+
type: string;
|
|
48
|
+
ref?: string;
|
|
49
|
+
label?: string;
|
|
50
|
+
};
|
|
51
|
+
export type QSLInfo = {
|
|
52
|
+
type: string;
|
|
53
|
+
ref?: string;
|
|
54
|
+
label?: string;
|
|
55
|
+
received?: boolean;
|
|
56
|
+
};
|
|
57
|
+
export type EventInfo = {
|
|
58
|
+
event: string;
|
|
59
|
+
operation?: Operation;
|
|
60
|
+
};
|
|
61
|
+
export type QSON = {
|
|
62
|
+
uuid?: string;
|
|
63
|
+
event?: EventInfo;
|
|
64
|
+
our: AnnotatedCallInfo;
|
|
65
|
+
their: AnnotatedCallInfo;
|
|
66
|
+
freq: number;
|
|
67
|
+
band: string;
|
|
68
|
+
mode: string;
|
|
69
|
+
startAt?: string;
|
|
70
|
+
startAtMillis?: number;
|
|
71
|
+
endAt?: string;
|
|
72
|
+
endAtMillis?: number;
|
|
73
|
+
number?: number;
|
|
74
|
+
line?: number;
|
|
75
|
+
deleted?: boolean;
|
|
76
|
+
refs?: RefInfo[];
|
|
77
|
+
qsl?: QSLInfo[];
|
|
78
|
+
};
|
|
79
|
+
export type Operation = {
|
|
80
|
+
uuid?: string;
|
|
81
|
+
deleted?: boolean;
|
|
82
|
+
stationCall?: string;
|
|
83
|
+
stationCallPlus?: string;
|
|
84
|
+
operatorCall?: string;
|
|
85
|
+
grid?: string;
|
|
86
|
+
qsoCount?: number;
|
|
87
|
+
title?: string;
|
|
88
|
+
qsos?: QSON[];
|
|
89
|
+
refs?: RefInfo[];
|
|
90
|
+
};
|
|
91
|
+
export type JSONValue = string | number | boolean | null | JSONValue[] | {
|
|
92
|
+
[key: string]: JSONValue;
|
|
93
|
+
};
|
|
94
|
+
export interface HookContext {
|
|
95
|
+
online: boolean;
|
|
96
|
+
account?: {
|
|
97
|
+
credentials?: Record<string, string>;
|
|
98
|
+
session?: Record<string, string>;
|
|
99
|
+
};
|
|
100
|
+
developerMode?: boolean;
|
|
101
|
+
locale?: string;
|
|
102
|
+
appName?: string;
|
|
103
|
+
distanceUnits?: string;
|
|
104
|
+
decimalSeparator?: string;
|
|
105
|
+
groupingSeparator?: string;
|
|
106
|
+
edition?: string;
|
|
107
|
+
enabledExperiments?: string[];
|
|
108
|
+
getOperation?(uuid: string): Promise<Record<string, JSONValue> | null>;
|
|
109
|
+
getQsos?(operationUuid: string): Promise<Record<string, JSONValue>[] | null>;
|
|
110
|
+
getSpotsForCall?(call: string, maxAgeMinutes?: number): Promise<Spot[]>;
|
|
111
|
+
getHistoryForCall?(call: string): Promise<Record<string, JSONValue>[]>;
|
|
112
|
+
}
|
|
113
|
+
export type LookupResult = (CallInfoLookup & {
|
|
114
|
+
locAccuracy?: number;
|
|
115
|
+
refs?: RefInfo[];
|
|
116
|
+
online?: boolean;
|
|
117
|
+
})[];
|
|
118
|
+
export interface LookupHook {
|
|
119
|
+
lookupCall(args: {
|
|
120
|
+
callInfo: AnnotatedCallInfo;
|
|
121
|
+
qso: Record<string, JSONValue>;
|
|
122
|
+
operation: Record<string, JSONValue>;
|
|
123
|
+
}, ctx: HookContext): Promise<LookupResult>;
|
|
124
|
+
}
|
|
125
|
+
export type RecentContextLookupHook = LookupHook;
|
|
126
|
+
export interface LookupServiceRequest {
|
|
127
|
+
callInfo: CallInfo;
|
|
128
|
+
qso: Record<string, JSONValue>;
|
|
129
|
+
operation: Record<string, JSONValue>;
|
|
130
|
+
recentContext?: boolean;
|
|
131
|
+
}
|
|
132
|
+
export interface LookupServiceResult {
|
|
133
|
+
lookups: CallInfoLookup[];
|
|
134
|
+
guess: CallInfo;
|
|
135
|
+
}
|
|
136
|
+
export interface LookupServiceHook {
|
|
137
|
+
lookupCallInfo(args: LookupServiceRequest, ctx: HookContext): Promise<LookupServiceResult>;
|
|
138
|
+
}
|
|
139
|
+
export interface SpotRef {
|
|
140
|
+
type: string;
|
|
141
|
+
ref: string;
|
|
142
|
+
}
|
|
143
|
+
export interface Spot {
|
|
144
|
+
their: {
|
|
145
|
+
call: string;
|
|
146
|
+
};
|
|
147
|
+
freq?: number;
|
|
148
|
+
band?: string;
|
|
149
|
+
mode?: string;
|
|
150
|
+
refs?: SpotRef[];
|
|
151
|
+
icon?: string;
|
|
152
|
+
spot: {
|
|
153
|
+
timeInMillis: number;
|
|
154
|
+
source: string;
|
|
155
|
+
label?: string;
|
|
156
|
+
sourceInfo?: Record<string, JSONValue>;
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
export interface SpotEligibility {
|
|
160
|
+
enabled: boolean;
|
|
161
|
+
icon?: string;
|
|
162
|
+
}
|
|
163
|
+
export interface PostResult {
|
|
164
|
+
ok: boolean;
|
|
165
|
+
message?: string;
|
|
166
|
+
userMessage?: ResultMessage;
|
|
167
|
+
}
|
|
168
|
+
export interface ResultMessage {
|
|
169
|
+
presentation: "status" | "dialog";
|
|
170
|
+
title?: string;
|
|
171
|
+
text: string;
|
|
172
|
+
icon?: string;
|
|
173
|
+
actions?: NoticeAction[];
|
|
174
|
+
}
|
|
175
|
+
export interface PostSelfSpotRequest {
|
|
176
|
+
operation: Record<string, JSONValue>;
|
|
177
|
+
freq: number;
|
|
178
|
+
mode?: string;
|
|
179
|
+
comment?: string;
|
|
180
|
+
}
|
|
181
|
+
export interface PostOtherSpotRequest {
|
|
182
|
+
qso: Record<string, JSONValue>;
|
|
183
|
+
comment?: string;
|
|
184
|
+
spotterCall?: string;
|
|
185
|
+
}
|
|
186
|
+
export interface SpotsHook {
|
|
187
|
+
sourceName: string;
|
|
188
|
+
fetchSpots(args: Record<string, never>, ctx: HookContext): Promise<Spot[]>;
|
|
189
|
+
isSelfSpotEnabled?(args: {
|
|
190
|
+
operation: Record<string, JSONValue>;
|
|
191
|
+
}, ctx: HookContext): Promise<SpotEligibility>;
|
|
192
|
+
isOtherSpotEnabled?(args: {
|
|
193
|
+
qso: Record<string, JSONValue>;
|
|
194
|
+
}, ctx: HookContext): Promise<SpotEligibility>;
|
|
195
|
+
postSelfSpot?(args: PostSelfSpotRequest, ctx: HookContext): Promise<PostResult>;
|
|
196
|
+
postOtherSpot?(args: PostOtherSpotRequest, ctx: HookContext): Promise<PostResult>;
|
|
197
|
+
}
|
|
198
|
+
export interface Ref {
|
|
199
|
+
type: string;
|
|
200
|
+
ref?: string;
|
|
201
|
+
name?: string;
|
|
202
|
+
label?: string;
|
|
203
|
+
shortLabel?: string;
|
|
204
|
+
grid?: string;
|
|
205
|
+
lat?: number;
|
|
206
|
+
lon?: number;
|
|
207
|
+
location?: string;
|
|
208
|
+
program?: string;
|
|
209
|
+
retired?: boolean;
|
|
210
|
+
for?: "operation" | "qso";
|
|
211
|
+
[key: string]: JSONValue | undefined;
|
|
212
|
+
}
|
|
213
|
+
export interface TitleSuggestion {
|
|
214
|
+
title?: string;
|
|
215
|
+
for?: string;
|
|
216
|
+
at?: string;
|
|
217
|
+
subtitle?: string;
|
|
218
|
+
priority?: number;
|
|
219
|
+
}
|
|
220
|
+
export interface RefLink {
|
|
221
|
+
url: string;
|
|
222
|
+
label?: string;
|
|
223
|
+
}
|
|
224
|
+
export interface RefHandlerHook {
|
|
225
|
+
validateRef?(args: {
|
|
226
|
+
ref: Ref;
|
|
227
|
+
}, ctx: HookContext): Promise<{
|
|
228
|
+
valid: boolean;
|
|
229
|
+
normalized?: string;
|
|
230
|
+
}>;
|
|
231
|
+
decorateRef?(args: {
|
|
232
|
+
ref: Ref;
|
|
233
|
+
}, ctx: HookContext): Promise<Ref>;
|
|
234
|
+
suggestOperationTitle?(args: {
|
|
235
|
+
ref: Ref;
|
|
236
|
+
operation: Record<string, JSONValue>;
|
|
237
|
+
}, ctx: HookContext): Promise<TitleSuggestion | null>;
|
|
238
|
+
linkForRef?(args: {
|
|
239
|
+
ref: Ref;
|
|
240
|
+
}, ctx: HookContext): Promise<RefLink | null>;
|
|
241
|
+
geojsonUrlForRef?(args: {
|
|
242
|
+
ref: Ref;
|
|
243
|
+
}, ctx: HookContext): Promise<RefGeojson | null>;
|
|
244
|
+
}
|
|
245
|
+
export interface RefGeojson {
|
|
246
|
+
url: string;
|
|
247
|
+
maxAgeInDays?: number;
|
|
248
|
+
missMaxAgeInDays?: number;
|
|
249
|
+
}
|
|
250
|
+
export interface LoggingControlDescriptor {
|
|
251
|
+
key: string;
|
|
252
|
+
label: string;
|
|
253
|
+
icon?: string;
|
|
254
|
+
color?: string;
|
|
255
|
+
order?: number;
|
|
256
|
+
optionType?: "optional" | "mandatory";
|
|
257
|
+
editable?: boolean;
|
|
258
|
+
allowsMultiple?: boolean;
|
|
259
|
+
input: InputDescriptor;
|
|
260
|
+
}
|
|
261
|
+
export type InputDescriptor = RefListInputDescriptor | TextInputDescriptor | OptionsInputDescriptor | SerialInputDescriptor | FormInputDescriptor;
|
|
262
|
+
export interface SequenceBinding {
|
|
263
|
+
key: string;
|
|
264
|
+
scope?: ("band" | "mode")[];
|
|
265
|
+
start?: number;
|
|
266
|
+
padTo?: number;
|
|
267
|
+
}
|
|
268
|
+
export interface SerialInputDescriptor {
|
|
269
|
+
kind: "serial";
|
|
270
|
+
refType: string;
|
|
271
|
+
field: string;
|
|
272
|
+
sequence: SequenceBinding;
|
|
273
|
+
editable?: boolean;
|
|
274
|
+
}
|
|
275
|
+
export interface FormInputDescriptor {
|
|
276
|
+
kind: "form";
|
|
277
|
+
refType: string;
|
|
278
|
+
form: FormDefinition;
|
|
279
|
+
}
|
|
280
|
+
export interface TextInputDescriptor {
|
|
281
|
+
kind: "text";
|
|
282
|
+
refType: string;
|
|
283
|
+
field: string;
|
|
284
|
+
placeholder?: string;
|
|
285
|
+
pattern?: string;
|
|
286
|
+
transforms?: {
|
|
287
|
+
pattern: string;
|
|
288
|
+
replacement: string;
|
|
289
|
+
flags?: string;
|
|
290
|
+
}[];
|
|
291
|
+
numeric?: boolean;
|
|
292
|
+
uppercase?: boolean;
|
|
293
|
+
maxLength?: number;
|
|
294
|
+
suggestedValue?: string;
|
|
295
|
+
}
|
|
296
|
+
export interface OptionsInputDescriptor {
|
|
297
|
+
kind: "options";
|
|
298
|
+
refType: string;
|
|
299
|
+
field: string;
|
|
300
|
+
options: {
|
|
301
|
+
code: string;
|
|
302
|
+
name?: string;
|
|
303
|
+
}[];
|
|
304
|
+
matchOn?: ("code" | "name")[];
|
|
305
|
+
allowFreeform?: boolean;
|
|
306
|
+
preferredCodes?: string[];
|
|
307
|
+
minCharsForSuggestions?: number;
|
|
308
|
+
placeholder?: string;
|
|
309
|
+
uppercase?: boolean;
|
|
310
|
+
maxLength?: number;
|
|
311
|
+
suggestedValue?: string;
|
|
312
|
+
pattern?: string;
|
|
313
|
+
transforms?: {
|
|
314
|
+
pattern: string;
|
|
315
|
+
replacement: string;
|
|
316
|
+
flags?: string;
|
|
317
|
+
}[];
|
|
318
|
+
numeric?: boolean;
|
|
319
|
+
}
|
|
320
|
+
export interface RefListInputDescriptor {
|
|
321
|
+
kind: "refList";
|
|
322
|
+
refType: string;
|
|
323
|
+
placeholder?: string;
|
|
324
|
+
pattern?: string;
|
|
325
|
+
transforms?: {
|
|
326
|
+
pattern: string;
|
|
327
|
+
replacement: string;
|
|
328
|
+
flags?: string;
|
|
329
|
+
}[];
|
|
330
|
+
}
|
|
331
|
+
export interface ActivitySuggestion extends Ref {
|
|
332
|
+
distance?: number;
|
|
333
|
+
relevance?: number;
|
|
334
|
+
allowsMultiple?: boolean;
|
|
335
|
+
}
|
|
336
|
+
export interface SuggestArgs {
|
|
337
|
+
operation: Record<string, JSONValue>;
|
|
338
|
+
location?: {
|
|
339
|
+
lat: number;
|
|
340
|
+
lon: number;
|
|
341
|
+
};
|
|
342
|
+
callsign?: string;
|
|
343
|
+
searchTerm?: string;
|
|
344
|
+
scoped?: boolean;
|
|
345
|
+
}
|
|
346
|
+
export interface ActivityHook {
|
|
347
|
+
loggingControls?(args: {
|
|
348
|
+
operation: Record<string, JSONValue>;
|
|
349
|
+
qso?: Record<string, JSONValue>;
|
|
350
|
+
}, ctx: HookContext): Promise<LoggingControlDescriptor[]>;
|
|
351
|
+
operationControls?(args: {
|
|
352
|
+
operation: Record<string, JSONValue>;
|
|
353
|
+
qso?: Record<string, JSONValue>;
|
|
354
|
+
}, ctx: HookContext): Promise<LoggingControlDescriptor[]>;
|
|
355
|
+
suggest?(args: SuggestArgs, ctx: HookContext): Promise<ActivitySuggestion[]>;
|
|
356
|
+
processQsoBeforeSave?(args: {
|
|
357
|
+
qso: Record<string, JSONValue>;
|
|
358
|
+
operation: Record<string, JSONValue>;
|
|
359
|
+
}, ctx: HookContext): Promise<Record<string, JSONValue> | null>;
|
|
360
|
+
}
|
|
361
|
+
export interface AdifFieldsHook {
|
|
362
|
+
fieldsForOneQSO(args: {
|
|
363
|
+
qso: Record<string, JSONValue>;
|
|
364
|
+
operation: Record<string, JSONValue>;
|
|
365
|
+
}, ctx: HookContext): Promise<{
|
|
366
|
+
name: string;
|
|
367
|
+
value: string;
|
|
368
|
+
}[]>;
|
|
369
|
+
}
|
|
370
|
+
export interface AdifImportResult {
|
|
371
|
+
refs?: Ref[];
|
|
372
|
+
}
|
|
373
|
+
export interface AdifImportHook {
|
|
374
|
+
refsForRecords(args: {
|
|
375
|
+
records: {
|
|
376
|
+
fields: Record<string, string>;
|
|
377
|
+
}[];
|
|
378
|
+
}, ctx: HookContext): Promise<(AdifImportResult | null)[]>;
|
|
379
|
+
}
|
|
380
|
+
export interface ExportRequest {
|
|
381
|
+
operation: Record<string, JSONValue>;
|
|
382
|
+
qsos: Record<string, JSONValue>[];
|
|
383
|
+
exportType?: string;
|
|
384
|
+
compactFilenames?: boolean;
|
|
385
|
+
includePrivateData?: boolean;
|
|
386
|
+
mainHandler?: string;
|
|
387
|
+
includeFieldsFrom?: string[];
|
|
388
|
+
}
|
|
389
|
+
export interface ExportResult {
|
|
390
|
+
filename: string;
|
|
391
|
+
mimeType: string;
|
|
392
|
+
content: string;
|
|
393
|
+
}
|
|
394
|
+
export interface ExportOptionsRequest {
|
|
395
|
+
operation: Record<string, JSONValue>;
|
|
396
|
+
qsos: Record<string, JSONValue>[];
|
|
397
|
+
compactFilenames?: boolean;
|
|
398
|
+
}
|
|
399
|
+
export interface ExportOption {
|
|
400
|
+
exportType: string;
|
|
401
|
+
format: string;
|
|
402
|
+
label: string;
|
|
403
|
+
filename?: string;
|
|
404
|
+
icon?: string;
|
|
405
|
+
color?: string;
|
|
406
|
+
alwaysIncludePrivateData?: boolean;
|
|
407
|
+
priority?: number;
|
|
408
|
+
selectedByDefault?: boolean;
|
|
409
|
+
refType?: string;
|
|
410
|
+
}
|
|
411
|
+
export interface ExportHook {
|
|
412
|
+
suggestExportOptions?(args: ExportOptionsRequest, ctx: HookContext): Promise<ExportOption[]>;
|
|
413
|
+
generateExport(args: ExportRequest, ctx: HookContext): Promise<ExportResult>;
|
|
414
|
+
}
|
|
415
|
+
export interface QsoScoreVerdict {
|
|
416
|
+
value: number;
|
|
417
|
+
dupe?: boolean;
|
|
418
|
+
notices?: string[];
|
|
419
|
+
alerts?: string[];
|
|
420
|
+
[extra: string]: JSONValue | undefined;
|
|
421
|
+
}
|
|
422
|
+
export type QsoScoreEntry = Record<string, QsoScoreVerdict>;
|
|
423
|
+
export interface ScoreTally {
|
|
424
|
+
key: string;
|
|
425
|
+
for: "day" | "operation";
|
|
426
|
+
icon?: string;
|
|
427
|
+
label?: string;
|
|
428
|
+
summary?: string;
|
|
429
|
+
longSummary?: string;
|
|
430
|
+
grid?: boolean;
|
|
431
|
+
total: number;
|
|
432
|
+
[extra: string]: JSONValue | undefined;
|
|
433
|
+
}
|
|
434
|
+
export interface DayScoreSummary {
|
|
435
|
+
day: number;
|
|
436
|
+
count: number;
|
|
437
|
+
scores: Record<string, ScoreTally>;
|
|
438
|
+
}
|
|
439
|
+
export interface OperationSegmentPayload {
|
|
440
|
+
fromMillis: number;
|
|
441
|
+
operation: Record<string, JSONValue>;
|
|
442
|
+
}
|
|
443
|
+
export interface ScoreQsosRequest {
|
|
444
|
+
operation: Record<string, JSONValue>;
|
|
445
|
+
qsos: Record<string, JSONValue>[];
|
|
446
|
+
segments?: OperationSegmentPayload[];
|
|
447
|
+
ref?: Record<string, JSONValue>;
|
|
448
|
+
resumeFrom?: JSONValue;
|
|
449
|
+
}
|
|
450
|
+
export interface ScoreQsosResult {
|
|
451
|
+
qsoScores: Record<string, QsoScoreVerdict>;
|
|
452
|
+
daySections: DayScoreSummary[];
|
|
453
|
+
operationSummary: Record<string, ScoreTally>;
|
|
454
|
+
scoresheet?: JSONValue;
|
|
455
|
+
}
|
|
456
|
+
export interface ScoreQsoRequest {
|
|
457
|
+
operation: Record<string, JSONValue>;
|
|
458
|
+
qso: Record<string, JSONValue>;
|
|
459
|
+
excludeUuid?: string;
|
|
460
|
+
ref?: Record<string, JSONValue>;
|
|
461
|
+
segments?: OperationSegmentPayload[];
|
|
462
|
+
resumeFrom?: JSONValue;
|
|
463
|
+
}
|
|
464
|
+
export interface QsoScoreNotices {
|
|
465
|
+
notices: string[];
|
|
466
|
+
alerts: string[];
|
|
467
|
+
}
|
|
468
|
+
export interface ScoreCandidatesRequest {
|
|
469
|
+
operation: Record<string, JSONValue>;
|
|
470
|
+
candidates: {
|
|
471
|
+
key: string;
|
|
472
|
+
qso: Record<string, JSONValue>;
|
|
473
|
+
}[];
|
|
474
|
+
ref?: Record<string, JSONValue>;
|
|
475
|
+
segments?: OperationSegmentPayload[];
|
|
476
|
+
resumeFrom?: JSONValue;
|
|
477
|
+
}
|
|
478
|
+
export type ScoreCandidatesResult = Record<string, QsoScoreNotices>;
|
|
479
|
+
export interface ScoringHook {
|
|
480
|
+
scoreQsos(args: ScoreQsosRequest, ctx: HookContext): Promise<ScoreQsosResult>;
|
|
481
|
+
scoreQso?(args: ScoreQsoRequest, ctx: HookContext): Promise<QsoScoreNotices>;
|
|
482
|
+
scoreCandidates?(args: ScoreCandidatesRequest, ctx: HookContext): Promise<ScoreCandidatesResult>;
|
|
483
|
+
}
|
|
484
|
+
export type ScoringScope = "always" | {
|
|
485
|
+
refTypes: string[];
|
|
486
|
+
huntingRefTypes?: string[];
|
|
487
|
+
};
|
|
488
|
+
export type Scoresheet = JSONValue;
|
|
489
|
+
export interface ContestScorer<S extends Scoresheet = Scoresheet> {
|
|
490
|
+
startScoresheet(args: {
|
|
491
|
+
operation: Record<string, JSONValue>;
|
|
492
|
+
ref?: Record<string, JSONValue>;
|
|
493
|
+
}, ctx: HookContext): S;
|
|
494
|
+
scoreQso(args: {
|
|
495
|
+
scoresheet: S;
|
|
496
|
+
qso: Record<string, JSONValue>;
|
|
497
|
+
operation: Record<string, JSONValue>;
|
|
498
|
+
ref?: Record<string, JSONValue>;
|
|
499
|
+
isNewDay: boolean;
|
|
500
|
+
}, ctx: HookContext): {
|
|
501
|
+
scoresheet: S;
|
|
502
|
+
score: QsoScoreVerdict;
|
|
503
|
+
};
|
|
504
|
+
summarizeScore(args: {
|
|
505
|
+
scoresheet: S;
|
|
506
|
+
operation: Record<string, JSONValue>;
|
|
507
|
+
ref?: Record<string, JSONValue>;
|
|
508
|
+
scope: "day" | "operation";
|
|
509
|
+
}, ctx: HookContext): Record<string, ScoreTally>;
|
|
510
|
+
}
|
|
511
|
+
export interface CommandAction {
|
|
512
|
+
setVfo?: {
|
|
513
|
+
freq?: number;
|
|
514
|
+
band?: string;
|
|
515
|
+
mode?: string;
|
|
516
|
+
};
|
|
517
|
+
setPower?: {
|
|
518
|
+
watts: number;
|
|
519
|
+
};
|
|
520
|
+
updateQso?: Record<string, JSONValue>;
|
|
521
|
+
addQso?: Record<string, JSONValue>;
|
|
522
|
+
sendSpots?: {
|
|
523
|
+
comment?: string;
|
|
524
|
+
target?: "self" | "last";
|
|
525
|
+
};
|
|
526
|
+
syncAll?: Record<string, never>;
|
|
527
|
+
purgeTests?: Record<string, never>;
|
|
528
|
+
updateSettings?: {
|
|
529
|
+
developerMode?: boolean;
|
|
530
|
+
};
|
|
531
|
+
updateSetting?: {
|
|
532
|
+
key: string;
|
|
533
|
+
value: JSONValue;
|
|
534
|
+
};
|
|
535
|
+
openSettings?: {
|
|
536
|
+
keys: string[];
|
|
537
|
+
title?: string;
|
|
538
|
+
};
|
|
539
|
+
updateOperation?: {
|
|
540
|
+
operatorCall?: string;
|
|
541
|
+
multiIdentifier?: string;
|
|
542
|
+
};
|
|
543
|
+
setCallField?: {
|
|
544
|
+
text: string;
|
|
545
|
+
};
|
|
546
|
+
reloadDataFiles?: {
|
|
547
|
+
target: string;
|
|
548
|
+
};
|
|
549
|
+
devNotice?: {
|
|
550
|
+
key?: string;
|
|
551
|
+
icon?: string;
|
|
552
|
+
title?: string;
|
|
553
|
+
text: string;
|
|
554
|
+
};
|
|
555
|
+
devStatus?: {
|
|
556
|
+
key?: string;
|
|
557
|
+
icon?: string;
|
|
558
|
+
title?: string;
|
|
559
|
+
text?: string;
|
|
560
|
+
};
|
|
561
|
+
devProgress?: {
|
|
562
|
+
icon?: string;
|
|
563
|
+
title?: string;
|
|
564
|
+
percent?: number;
|
|
565
|
+
};
|
|
566
|
+
devHammer?: {
|
|
567
|
+
seconds?: number;
|
|
568
|
+
};
|
|
569
|
+
devSplash?: Record<string, never>;
|
|
570
|
+
devOnboard?: Record<string, never>;
|
|
571
|
+
devTester?: Record<string, never>;
|
|
572
|
+
devPopup?: Record<string, never>;
|
|
573
|
+
devTimeTravel?: {
|
|
574
|
+
reset?: boolean;
|
|
575
|
+
deltaMillis?: number;
|
|
576
|
+
speed?: number;
|
|
577
|
+
};
|
|
578
|
+
toggleExperiment?: {
|
|
579
|
+
token: string;
|
|
580
|
+
};
|
|
581
|
+
[actionName: string]: unknown;
|
|
582
|
+
}
|
|
583
|
+
export interface CommandInterpretation {
|
|
584
|
+
expectsParams?: boolean;
|
|
585
|
+
error?: string;
|
|
586
|
+
mixedCase?: boolean;
|
|
587
|
+
describe?: string;
|
|
588
|
+
confirm?: string;
|
|
589
|
+
commands?: CommandAction[];
|
|
590
|
+
skipOnlineLookup?: boolean;
|
|
591
|
+
}
|
|
592
|
+
export interface SearchSettingsParams {
|
|
593
|
+
args: string;
|
|
594
|
+
kind?: "set" | "show" | "hide";
|
|
595
|
+
}
|
|
596
|
+
export interface SettingsSearchCandidate {
|
|
597
|
+
key: string;
|
|
598
|
+
label: string;
|
|
599
|
+
section: string;
|
|
600
|
+
}
|
|
601
|
+
export interface SettingsSearchResult {
|
|
602
|
+
found: boolean;
|
|
603
|
+
query?: string;
|
|
604
|
+
key?: string;
|
|
605
|
+
label?: string;
|
|
606
|
+
section?: string;
|
|
607
|
+
fieldType?: string;
|
|
608
|
+
valueLabel?: string;
|
|
609
|
+
value?: boolean;
|
|
610
|
+
simple?: boolean;
|
|
611
|
+
ambiguous?: boolean;
|
|
612
|
+
candidates?: SettingsSearchCandidate[];
|
|
613
|
+
newValue?: JSONValue;
|
|
614
|
+
newValueLabel?: string;
|
|
615
|
+
unchanged?: boolean;
|
|
616
|
+
expects?: string;
|
|
617
|
+
}
|
|
618
|
+
export interface CommandCatalogEntry {
|
|
619
|
+
command: string;
|
|
620
|
+
describe: string;
|
|
621
|
+
params?: string;
|
|
622
|
+
category?: string;
|
|
623
|
+
needsOperation?: boolean;
|
|
624
|
+
expectsParams?: boolean;
|
|
625
|
+
suggest?: boolean;
|
|
626
|
+
}
|
|
627
|
+
export interface CommandHook {
|
|
628
|
+
interpret(args: {
|
|
629
|
+
input: string;
|
|
630
|
+
operation?: Record<string, JSONValue>;
|
|
631
|
+
qso?: Record<string, JSONValue>;
|
|
632
|
+
execute?: boolean;
|
|
633
|
+
}, ctx: HookContext): Promise<CommandInterpretation | null>;
|
|
634
|
+
catalog?(ctx: HookContext): Promise<CommandCatalogEntry[]>;
|
|
635
|
+
}
|
|
636
|
+
export interface SyncPayload {
|
|
637
|
+
operations?: Record<string, JSONValue>[];
|
|
638
|
+
qsos?: Record<string, JSONValue>[];
|
|
639
|
+
meta?: Record<string, JSONValue>;
|
|
640
|
+
}
|
|
641
|
+
export interface SyncResponse {
|
|
642
|
+
operations?: Record<string, JSONValue>[];
|
|
643
|
+
qsos?: Record<string, JSONValue>[];
|
|
644
|
+
meta?: Record<string, JSONValue>;
|
|
645
|
+
account?: Record<string, JSONValue>;
|
|
646
|
+
success?: boolean;
|
|
647
|
+
error?: string;
|
|
648
|
+
error_status?: number;
|
|
649
|
+
}
|
|
650
|
+
export interface SyncTransportHook {
|
|
651
|
+
sync(payload: SyncPayload, ctx: HookContext): Promise<SyncResponse>;
|
|
652
|
+
getAccountData(args: Record<string, never>, ctx: HookContext): Promise<Record<string, JSONValue>>;
|
|
653
|
+
linkClient?(args: {
|
|
654
|
+
email?: string;
|
|
655
|
+
}, ctx: HookContext): Promise<Record<string, JSONValue>>;
|
|
656
|
+
linkClientWithEmail(args: {
|
|
657
|
+
email: string;
|
|
658
|
+
}, ctx: HookContext): Promise<Record<string, JSONValue>>;
|
|
659
|
+
setAccountEmail?(args: {
|
|
660
|
+
email: string;
|
|
661
|
+
}, ctx: HookContext): Promise<Record<string, JSONValue>>;
|
|
662
|
+
resendAccountEmail?(args: Record<string, never>, ctx: HookContext): Promise<Record<string, JSONValue>>;
|
|
663
|
+
findLinkRequest?(args: {
|
|
664
|
+
challenge_token: string;
|
|
665
|
+
}, ctx: HookContext): Promise<Record<string, JSONValue>>;
|
|
666
|
+
findLinkRequestByClient?(args: {
|
|
667
|
+
client: string;
|
|
668
|
+
challenge_token: string;
|
|
669
|
+
}, ctx: HookContext): Promise<Record<string, JSONValue>>;
|
|
670
|
+
approveLinkRequest?(args: {
|
|
671
|
+
client: string;
|
|
672
|
+
challenge_token?: string;
|
|
673
|
+
}, ctx: HookContext): Promise<Record<string, JSONValue>>;
|
|
674
|
+
ensureClientRegistered?(args: {
|
|
675
|
+
refreshWebhookToken?: boolean;
|
|
676
|
+
}, ctx: HookContext): Promise<{
|
|
677
|
+
push_channel_name: string;
|
|
678
|
+
webhook_client_token: string;
|
|
679
|
+
}>;
|
|
680
|
+
fetchWebhookEvents?(args: Record<string, never>, ctx: HookContext): Promise<{
|
|
681
|
+
webhook_events: Record<string, JSONValue>[];
|
|
682
|
+
}>;
|
|
683
|
+
submitReport?(args: {
|
|
684
|
+
title: string;
|
|
685
|
+
body: string;
|
|
686
|
+
kind: "idea" | "task" | "bug";
|
|
687
|
+
}, ctx: HookContext): Promise<{
|
|
688
|
+
ref?: string | null;
|
|
689
|
+
error?: string;
|
|
690
|
+
}>;
|
|
691
|
+
}
|
|
692
|
+
export interface AccountField {
|
|
693
|
+
key: string;
|
|
694
|
+
label: string;
|
|
695
|
+
type: "text" | "email" | "secret";
|
|
696
|
+
preface?: string;
|
|
697
|
+
postface?: string;
|
|
698
|
+
}
|
|
699
|
+
export interface OAuth2Config {
|
|
700
|
+
issuer: string;
|
|
701
|
+
clientId: string;
|
|
702
|
+
redirectUrl: string;
|
|
703
|
+
webhookRedirectUrl?: string;
|
|
704
|
+
scopes: string[];
|
|
705
|
+
}
|
|
706
|
+
export type Localizable<T> = T | ((args: Record<string, never>, ctx: HookContext) => T | Promise<T>);
|
|
707
|
+
export interface AccountHook {
|
|
708
|
+
label: Localizable<string>;
|
|
709
|
+
description?: Localizable<string>;
|
|
710
|
+
kvKey?: string;
|
|
711
|
+
fields?: Localizable<AccountField[]>;
|
|
712
|
+
oauth2?: OAuth2Config | ((args: Record<string, never>, ctx: HookContext) => OAuth2Config | Promise<OAuth2Config>);
|
|
713
|
+
synchronizable?: boolean;
|
|
714
|
+
testCredentials(credentials: Record<string, string>, ctx: HookContext): Promise<string>;
|
|
715
|
+
}
|
|
716
|
+
export type Hook = LookupHook | LookupServiceHook | SpotsHook | ExportHook | ScoringHook | RefHandlerHook | ActivityHook | AdifFieldsHook | AdifImportHook | CommandHook | SyncTransportHook | AccountHook | DataFileDefinition | FormHook | SettingsPanelHook | PanelHook | Record<string, unknown>;
|
|
717
|
+
export interface RegisterHookParams {
|
|
718
|
+
hook: Hook;
|
|
719
|
+
key?: string;
|
|
720
|
+
priority?: number;
|
|
721
|
+
}
|
|
722
|
+
export interface ActivationApi {
|
|
723
|
+
registerHook(category: string, params: RegisterHookParams): void;
|
|
724
|
+
hostCall(method: string, params: Record<string, unknown>): Promise<unknown>;
|
|
725
|
+
}
|
|
726
|
+
export interface ExtensionManifest {
|
|
727
|
+
key: string;
|
|
728
|
+
name: string;
|
|
729
|
+
shortName?: string;
|
|
730
|
+
version: string;
|
|
731
|
+
description?: string;
|
|
732
|
+
icon?: string;
|
|
733
|
+
accentColor?: string;
|
|
734
|
+
keywords?: string[];
|
|
735
|
+
category?: string;
|
|
736
|
+
enabledByDefault?: boolean;
|
|
737
|
+
hooks?: string[];
|
|
738
|
+
domains?: string[];
|
|
739
|
+
allowUserAgentOverride?: boolean;
|
|
740
|
+
requiresLocation?: boolean;
|
|
741
|
+
experiments?: string[];
|
|
742
|
+
translations?: Record<string, {
|
|
743
|
+
name?: string;
|
|
744
|
+
description?: string;
|
|
745
|
+
keywords?: string[];
|
|
746
|
+
}>;
|
|
747
|
+
}
|
|
748
|
+
export interface ExtensionDefinition extends ExtensionManifest {
|
|
749
|
+
onActivation(api: ActivationApi): void;
|
|
750
|
+
}
|
|
751
|
+
export interface FetchOptions {
|
|
752
|
+
method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
753
|
+
/**
|
|
754
|
+
* Extra request headers. Note: the host stamps HaLo's canonical
|
|
755
|
+
* `User-Agent` on every request and it overrides any you set here, so
|
|
756
|
+
* don't provide your own — unless your extension declares
|
|
757
|
+
* `allowUserAgentOverride` in build.mjs (see docs/design/network.md).
|
|
758
|
+
*/
|
|
759
|
+
headers?: Record<string, string>;
|
|
760
|
+
body?: string;
|
|
761
|
+
/**
|
|
762
|
+
* Give up on this request after `timeout` milliseconds, instead of the
|
|
763
|
+
* host's default allowance. Clamped DOWNWARD only — asking for longer than
|
|
764
|
+
* the default changes nothing — and it bounds the whole request, headers
|
|
765
|
+
* and body alike.
|
|
766
|
+
*
|
|
767
|
+
* For a request whose answer is optional: a cache-validation probe, an
|
|
768
|
+
* enrichment worth having but not worth waiting for. It matters because a
|
|
769
|
+
* hook fan-out shares ONE budget across every extension in the category,
|
|
770
|
+
* so a request that stalls costs the other extensions their results too
|
|
771
|
+
* (see `invokeHookAll`'s `partialOnTimeout`). This is how a hook says
|
|
772
|
+
* "not worth waiting the default for" rather than spending everyone's time.
|
|
773
|
+
*/
|
|
774
|
+
timeout?: number;
|
|
775
|
+
}
|
|
776
|
+
export interface FetchResponse {
|
|
777
|
+
status: number;
|
|
778
|
+
body: string;
|
|
779
|
+
}
|
|
780
|
+
export interface DeviceLocation {
|
|
781
|
+
latitude: number;
|
|
782
|
+
longitude: number;
|
|
783
|
+
}
|
|
784
|
+
export interface VersionInfo {
|
|
785
|
+
platform: string;
|
|
786
|
+
edition: string;
|
|
787
|
+
version: string;
|
|
788
|
+
versionName: string;
|
|
789
|
+
buildNumber: number | null;
|
|
790
|
+
gitSha: string;
|
|
791
|
+
}
|
|
792
|
+
export interface LookupRow {
|
|
793
|
+
category: string;
|
|
794
|
+
subCategory?: string;
|
|
795
|
+
key: string;
|
|
796
|
+
name?: string;
|
|
797
|
+
data?: any;
|
|
798
|
+
lat?: number;
|
|
799
|
+
lon?: number;
|
|
800
|
+
flags?: number;
|
|
801
|
+
}
|
|
802
|
+
export interface LookupEntry {
|
|
803
|
+
subCategory?: string;
|
|
804
|
+
key: string;
|
|
805
|
+
name?: string;
|
|
806
|
+
lat?: number;
|
|
807
|
+
lon?: number;
|
|
808
|
+
flags?: number;
|
|
809
|
+
data?: Record<string, unknown>;
|
|
810
|
+
}
|
|
811
|
+
export interface CsvOptions {
|
|
812
|
+
hasHeaders?: boolean;
|
|
813
|
+
skipRows?: number;
|
|
814
|
+
delimiter?: string;
|
|
815
|
+
}
|
|
816
|
+
export interface JsonOptions {
|
|
817
|
+
rootPath?: string;
|
|
818
|
+
}
|
|
819
|
+
export type FetchType = "csv" | "json" | "raw";
|
|
820
|
+
export interface DataFileDefinition {
|
|
821
|
+
key: string;
|
|
822
|
+
name: Localizable<string>;
|
|
823
|
+
description: Localizable<string>;
|
|
824
|
+
url: Localizable<string>;
|
|
825
|
+
maxAgeInDays: number;
|
|
826
|
+
fetchType: FetchType;
|
|
827
|
+
encoding?: string;
|
|
828
|
+
category?: string;
|
|
829
|
+
csvOptions?: CsvOptions;
|
|
830
|
+
csvToLookupEntry?: (row: string[] | Record<string, string>) => LookupEntry | null;
|
|
831
|
+
jsonOptions?: JsonOptions;
|
|
832
|
+
jsonToLookupEntry?: (entry: Record<string, any>) => LookupEntry | null;
|
|
833
|
+
rawToJSONData?: (args: {
|
|
834
|
+
body: string;
|
|
835
|
+
url: string;
|
|
836
|
+
options: Record<string, any>;
|
|
837
|
+
}) => Promise<any>;
|
|
838
|
+
onLoadRawData?: (data: any) => void;
|
|
839
|
+
onRemoveRawData?: () => Promise<void>;
|
|
840
|
+
}
|
|
841
|
+
export type FormFieldType = "text" | "multiline" | "email" | "callsign" | "number" | "select" | "radio" | "checkbox" | "secret" | "list" | "multiselect" | "account";
|
|
842
|
+
export interface FormFieldOption {
|
|
843
|
+
label: string;
|
|
844
|
+
value: any;
|
|
845
|
+
common?: boolean;
|
|
846
|
+
uncommon?: boolean;
|
|
847
|
+
}
|
|
848
|
+
export interface FormField {
|
|
849
|
+
type: "field";
|
|
850
|
+
fieldType: FormFieldType;
|
|
851
|
+
key: string;
|
|
852
|
+
label: string;
|
|
853
|
+
value?: any;
|
|
854
|
+
placeholder?: string;
|
|
855
|
+
uppercase?: boolean;
|
|
856
|
+
options?: FormFieldOption[] | string;
|
|
857
|
+
validate?: (value: any, state: Record<string, any>) => string | null | undefined | Promise<string | null | undefined>;
|
|
858
|
+
transform?: (value: any, state: Record<string, any>) => any | Promise<any>;
|
|
859
|
+
itemFields?: FormField[];
|
|
860
|
+
itemTitle?: string;
|
|
861
|
+
orderable?: boolean;
|
|
862
|
+
inline?: boolean;
|
|
863
|
+
itemLabel?: string;
|
|
864
|
+
defaultValue?: any[];
|
|
865
|
+
account?: {
|
|
866
|
+
key: string;
|
|
867
|
+
subkey?: string;
|
|
868
|
+
};
|
|
869
|
+
devMode?: boolean;
|
|
870
|
+
icon?: string;
|
|
871
|
+
description?: string;
|
|
872
|
+
visibleWhen?: {
|
|
873
|
+
field: string;
|
|
874
|
+
equals: any;
|
|
875
|
+
};
|
|
876
|
+
common?: boolean;
|
|
877
|
+
environment?: string | string[];
|
|
878
|
+
target?: string | string[];
|
|
879
|
+
restartOnChange?: boolean;
|
|
880
|
+
}
|
|
881
|
+
export interface FormHeader {
|
|
882
|
+
type: "header";
|
|
883
|
+
title: string;
|
|
884
|
+
subtitle?: string;
|
|
885
|
+
devMode?: boolean;
|
|
886
|
+
style?: "default" | "section";
|
|
887
|
+
environment?: string | string[];
|
|
888
|
+
}
|
|
889
|
+
export interface FormSectionDivider {
|
|
890
|
+
type: "divider";
|
|
891
|
+
title?: string;
|
|
892
|
+
devMode?: boolean;
|
|
893
|
+
environment?: string | string[];
|
|
894
|
+
}
|
|
895
|
+
export interface FormMarkdownBlock {
|
|
896
|
+
type: "markdown";
|
|
897
|
+
text: string;
|
|
898
|
+
devMode?: boolean;
|
|
899
|
+
environment?: string | string[];
|
|
900
|
+
collapsible?: boolean;
|
|
901
|
+
title?: string;
|
|
902
|
+
}
|
|
903
|
+
export interface FormActionElement {
|
|
904
|
+
type: "action";
|
|
905
|
+
key: string;
|
|
906
|
+
label: string;
|
|
907
|
+
method: string;
|
|
908
|
+
devMode?: boolean;
|
|
909
|
+
common?: boolean;
|
|
910
|
+
environment?: string | string[];
|
|
911
|
+
target?: string | string[];
|
|
912
|
+
}
|
|
913
|
+
export interface FormLinkElement {
|
|
914
|
+
type: "link";
|
|
915
|
+
key?: string;
|
|
916
|
+
label: string;
|
|
917
|
+
url: string;
|
|
918
|
+
icon?: string;
|
|
919
|
+
description?: string;
|
|
920
|
+
devMode?: boolean;
|
|
921
|
+
common?: boolean;
|
|
922
|
+
environment?: string | string[];
|
|
923
|
+
}
|
|
924
|
+
export type FormElement = FormField | FormHeader | FormSectionDivider | FormMarkdownBlock | FormActionElement | FormLinkElement;
|
|
925
|
+
export interface FormDefinition {
|
|
926
|
+
title?: string;
|
|
927
|
+
subtitle?: string;
|
|
928
|
+
elements: FormElement[];
|
|
929
|
+
onChange?: (fieldKey: string, value: any, state: Record<string, any>) => Promise<Record<string, any> | void> | Record<string, any> | void;
|
|
930
|
+
}
|
|
931
|
+
export interface FormHook {
|
|
932
|
+
getDefinition(args: {
|
|
933
|
+
formId?: string;
|
|
934
|
+
}, ctx: HookContext): Promise<FormDefinition>;
|
|
935
|
+
validateField?(args: {
|
|
936
|
+
formId?: string;
|
|
937
|
+
fieldKey: string;
|
|
938
|
+
value: any;
|
|
939
|
+
state: Record<string, any>;
|
|
940
|
+
}, ctx: HookContext): Promise<string | null>;
|
|
941
|
+
transformField?(args: {
|
|
942
|
+
formId?: string;
|
|
943
|
+
fieldKey: string;
|
|
944
|
+
value: any;
|
|
945
|
+
state: Record<string, any>;
|
|
946
|
+
}, ctx: HookContext): Promise<any>;
|
|
947
|
+
onChangeField?(args: {
|
|
948
|
+
formId?: string;
|
|
949
|
+
fieldKey: string;
|
|
950
|
+
value: any;
|
|
951
|
+
state: Record<string, any>;
|
|
952
|
+
}, ctx: HookContext): Promise<Record<string, any> | null | void>;
|
|
953
|
+
}
|
|
954
|
+
export interface SettingsPanelDescriptor {
|
|
955
|
+
key: string;
|
|
956
|
+
title: string;
|
|
957
|
+
icon?: string;
|
|
958
|
+
order?: number;
|
|
959
|
+
sidebar?: boolean;
|
|
960
|
+
dataFilesSection?: boolean;
|
|
961
|
+
}
|
|
962
|
+
export interface SettingsField extends Omit<FormField, "validate" | "transform" | "itemFields"> {
|
|
963
|
+
pattern?: string;
|
|
964
|
+
patternError?: string;
|
|
965
|
+
itemFields?: SettingsField[];
|
|
966
|
+
aliases?: string | string[];
|
|
967
|
+
}
|
|
968
|
+
export interface SimpleSettingsPanel {
|
|
969
|
+
kind: "simple";
|
|
970
|
+
key?: string;
|
|
971
|
+
title: string;
|
|
972
|
+
icon?: string;
|
|
973
|
+
order?: number;
|
|
974
|
+
sidebar?: boolean;
|
|
975
|
+
dataFilesSection?: boolean;
|
|
976
|
+
fields: (SettingsField | FormActionElement)[];
|
|
977
|
+
}
|
|
978
|
+
export interface DynamicSettingsPanel {
|
|
979
|
+
kind: "dynamic";
|
|
980
|
+
key?: string;
|
|
981
|
+
getPanels?(args: Record<string, never>, ctx: HookContext): Promise<SettingsPanelDescriptor[]>;
|
|
982
|
+
getDefinition(args: {
|
|
983
|
+
panelKey: string;
|
|
984
|
+
}, ctx: HookContext): Promise<FormDefinition>;
|
|
985
|
+
validateField?(args: {
|
|
986
|
+
panelKey: string;
|
|
987
|
+
fieldKey: string;
|
|
988
|
+
value: any;
|
|
989
|
+
state: Record<string, any>;
|
|
990
|
+
}, ctx: HookContext): Promise<string | null>;
|
|
991
|
+
transformField?(args: {
|
|
992
|
+
panelKey: string;
|
|
993
|
+
fieldKey: string;
|
|
994
|
+
value: any;
|
|
995
|
+
state: Record<string, any>;
|
|
996
|
+
}, ctx: HookContext): Promise<any>;
|
|
997
|
+
onChangeField(args: {
|
|
998
|
+
panelKey: string;
|
|
999
|
+
fieldKey: string;
|
|
1000
|
+
value: any;
|
|
1001
|
+
state: Record<string, any>;
|
|
1002
|
+
}, ctx: HookContext): Promise<void>;
|
|
1003
|
+
}
|
|
1004
|
+
export type SettingsPanelHook = SimpleSettingsPanel | DynamicSettingsPanel;
|
|
1005
|
+
export type NoticeAction = {
|
|
1006
|
+
label: string;
|
|
1007
|
+
type: "link";
|
|
1008
|
+
url: string;
|
|
1009
|
+
} | {
|
|
1010
|
+
label: string;
|
|
1011
|
+
type: "dialog";
|
|
1012
|
+
title?: string;
|
|
1013
|
+
text: string;
|
|
1014
|
+
} | {
|
|
1015
|
+
label: string;
|
|
1016
|
+
type: "account";
|
|
1017
|
+
key: string;
|
|
1018
|
+
subkey?: string;
|
|
1019
|
+
};
|
|
1020
|
+
export interface StatusBarMessageParams {
|
|
1021
|
+
key: string;
|
|
1022
|
+
icon?: string;
|
|
1023
|
+
title?: string;
|
|
1024
|
+
text?: string;
|
|
1025
|
+
}
|
|
1026
|
+
export interface StatusBarProgressParams {
|
|
1027
|
+
key: string;
|
|
1028
|
+
icon?: string;
|
|
1029
|
+
title?: string;
|
|
1030
|
+
text?: string;
|
|
1031
|
+
value?: number;
|
|
1032
|
+
}
|
|
1033
|
+
export interface StatusBarNoticeParams {
|
|
1034
|
+
key: string;
|
|
1035
|
+
icon?: string;
|
|
1036
|
+
title?: string;
|
|
1037
|
+
text: string;
|
|
1038
|
+
actions?: NoticeAction[];
|
|
1039
|
+
}
|
|
1040
|
+
export type PanelTrigger = "operation" | "qso" | "qsoLogged" | "lookup" | "spots" | `tick:${number}`;
|
|
1041
|
+
export interface PanelDescriptor {
|
|
1042
|
+
key: string;
|
|
1043
|
+
title: string;
|
|
1044
|
+
description?: string;
|
|
1045
|
+
icon?: string;
|
|
1046
|
+
preview?: string;
|
|
1047
|
+
on?: PanelTrigger[];
|
|
1048
|
+
multiple?: boolean;
|
|
1049
|
+
form?: SettingsField[];
|
|
1050
|
+
}
|
|
1051
|
+
export interface PanelRenderArgs {
|
|
1052
|
+
panelKey: string;
|
|
1053
|
+
operation: Record<string, JSONValue>;
|
|
1054
|
+
qso?: Record<string, JSONValue>;
|
|
1055
|
+
qsoCount: number;
|
|
1056
|
+
config: Record<string, JSONValue>;
|
|
1057
|
+
reason: string;
|
|
1058
|
+
}
|
|
1059
|
+
export type PanelContent = {
|
|
1060
|
+
kind: "markdown";
|
|
1061
|
+
content: string;
|
|
1062
|
+
title?: string;
|
|
1063
|
+
triggers?: string[];
|
|
1064
|
+
} | {
|
|
1065
|
+
kind: "svg";
|
|
1066
|
+
content: string;
|
|
1067
|
+
title?: string;
|
|
1068
|
+
triggers?: string[];
|
|
1069
|
+
} | {
|
|
1070
|
+
kind: "html";
|
|
1071
|
+
content: string;
|
|
1072
|
+
title?: string;
|
|
1073
|
+
triggers?: string[];
|
|
1074
|
+
};
|
|
1075
|
+
export interface PanelHook {
|
|
1076
|
+
getPanels(args: Record<string, never>, ctx: HookContext): Promise<PanelDescriptor[]>;
|
|
1077
|
+
render(args: PanelRenderArgs, ctx: HookContext): Promise<PanelContent>;
|
|
1078
|
+
}
|
|
1079
|
+
/**
|
|
1080
|
+
* The standard per-extension translator: takes the extension's i18next
|
|
1081
|
+
* resources once and returns a `tFor(ctx)` that hooks call with their
|
|
1082
|
+
* HookContext. The underlying i18next instance is rebuilt only when
|
|
1083
|
+
* `ctx.locale` changes (it only does when the app's locale setting does).
|
|
1084
|
+
* Typical use, with per-locale JSON catalogs:
|
|
1085
|
+
*
|
|
1086
|
+
* import en from "./i18n/en.json" with { type: "json" }
|
|
1087
|
+
* import es from "./i18n/es.json" with { type: "json" }
|
|
1088
|
+
* export const tFor = createCachedTranslator({ en: { translation: en }, es: { translation: es } })
|
|
1089
|
+
*/
|
|
1090
|
+
export declare function createCachedTranslator(resources: Record<string, any>): (ctx: {
|
|
1091
|
+
locale?: string;
|
|
1092
|
+
}) => ReturnType<typeof createTranslator>;
|
|
1093
|
+
/**
|
|
1094
|
+
* Creates a lightweight translator function using an i18next instance
|
|
1095
|
+
* initialized with the given resources and active locale.
|
|
1096
|
+
*/
|
|
1097
|
+
export declare function createTranslator(resources: Record<string, any>, currentLocale: string): (key: string, options?: any) => string;
|
|
1098
|
+
export interface ParsedCallsign {
|
|
1099
|
+
call: string;
|
|
1100
|
+
baseCall?: string;
|
|
1101
|
+
prefix?: string;
|
|
1102
|
+
extendedPrefix?: string;
|
|
1103
|
+
ituPrefix?: string;
|
|
1104
|
+
digit?: string;
|
|
1105
|
+
preindicator?: string;
|
|
1106
|
+
postindicators?: string[];
|
|
1107
|
+
prefixOverride?: string;
|
|
1108
|
+
indicators?: string[];
|
|
1109
|
+
ssid?: string;
|
|
1110
|
+
}
|
|
1111
|
+
export type CombinedCallInfo = ParsedCallsign & {
|
|
1112
|
+
isoPrefix?: string;
|
|
1113
|
+
dxccCode?: number;
|
|
1114
|
+
regionCode?: string;
|
|
1115
|
+
state?: string;
|
|
1116
|
+
entityPrefix?: string;
|
|
1117
|
+
entityName?: string;
|
|
1118
|
+
continent?: string;
|
|
1119
|
+
cqZone?: number;
|
|
1120
|
+
ituZone?: number;
|
|
1121
|
+
lat?: number;
|
|
1122
|
+
lon?: number;
|
|
1123
|
+
tz?: string;
|
|
1124
|
+
matchSource?: string;
|
|
1125
|
+
matchNote?: string;
|
|
1126
|
+
locSource?: string;
|
|
1127
|
+
};
|
|
1128
|
+
type AnnotatedCallInfo$1 = CombinedCallInfo & {
|
|
1129
|
+
originalValues?: AnnotatedCallInfo$1;
|
|
1130
|
+
cfValues?: AnnotatedCallInfo$1;
|
|
1131
|
+
};
|
|
1132
|
+
export declare function annotateCallAgainstCountryFile(call: string): AnnotatedCallInfo$1;
|
|
1133
|
+
export declare function entityPrefixForCall(call: string | undefined): string | undefined;
|
|
1134
|
+
export declare function flagForDxccCode(dxccCode: number | undefined): string | undefined;
|
|
1135
|
+
export declare function regionAndCountryForDxccCode(dxccCode: number | undefined): {
|
|
1136
|
+
ituRegion?: number;
|
|
1137
|
+
countryCode?: string;
|
|
1138
|
+
};
|
|
1139
|
+
export declare const LOCATION_ACCURACY: {
|
|
1140
|
+
readonly EXACT: 0;
|
|
1141
|
+
readonly ACCURATE: 2;
|
|
1142
|
+
readonly REASONABLE: 10;
|
|
1143
|
+
readonly VAGUE: 100;
|
|
1144
|
+
readonly NO_LOCATION: 1000;
|
|
1145
|
+
};
|
|
1146
|
+
export declare function applyLatLonFromApiFields(target: {
|
|
1147
|
+
lat?: number;
|
|
1148
|
+
lon?: number;
|
|
1149
|
+
}, raw: Record<string, unknown>): void;
|
|
1150
|
+
export declare function canonicalMode(mode: string): string;
|
|
1151
|
+
export declare function modesMatchForDupe(worked: string, candidate: string): boolean;
|
|
1152
|
+
export interface ContestScorerOptions {
|
|
1153
|
+
scope?: ScoringScope;
|
|
1154
|
+
}
|
|
1155
|
+
export declare function contestScorer<S extends Scoresheet = Scoresheet>(scorer: ContestScorer<S>, options?: ContestScorerOptions): ScoringHook & {
|
|
1156
|
+
scope: ScoringScope;
|
|
1157
|
+
};
|
|
1158
|
+
export declare function tally(key: string, forScope: "day" | "operation", total: number, extra?: Partial<ScoreTally>): ScoreTally;
|
|
1159
|
+
export type UniqueAxis = "day" | "band" | "mode" | "ref";
|
|
1160
|
+
export interface ActivityScoringRules {
|
|
1161
|
+
label: string;
|
|
1162
|
+
icon?: string;
|
|
1163
|
+
activationType: string;
|
|
1164
|
+
huntingType?: string;
|
|
1165
|
+
qsosToActivate?: number | ((activatedRefs: string[]) => number);
|
|
1166
|
+
tracksActivation?: boolean;
|
|
1167
|
+
freshRefRescuesActivation?: boolean;
|
|
1168
|
+
allowsMultipleReferences?: boolean;
|
|
1169
|
+
uniquePer?: readonly UniqueAxis[];
|
|
1170
|
+
activates?: "daily" | "once";
|
|
1171
|
+
refNoun?: string | ((ctx: HookContext) => string);
|
|
1172
|
+
refNounPlural?: string | ((ctx: HookContext) => string);
|
|
1173
|
+
p2pLabel?: string | ((ctx: HookContext) => string);
|
|
1174
|
+
}
|
|
1175
|
+
export type ActivityScoresheet = {
|
|
1176
|
+
workedByCall: Record<string, string[]>;
|
|
1177
|
+
activatedRefs: Record<string, number>;
|
|
1178
|
+
huntedRefs: Record<string, number>;
|
|
1179
|
+
activatedQsos: number;
|
|
1180
|
+
huntedQsos: number;
|
|
1181
|
+
duplicates: number;
|
|
1182
|
+
dayActivatedRefs: Record<string, number>;
|
|
1183
|
+
dayHuntedRefs: Record<string, number>;
|
|
1184
|
+
dayActivatedQsos: number;
|
|
1185
|
+
dayHuntedQsos: number;
|
|
1186
|
+
dayDuplicates: number;
|
|
1187
|
+
};
|
|
1188
|
+
export declare function activityScorer(rules: ActivityScoringRules): ContestScorer<ActivityScoresheet>;
|
|
1189
|
+
export interface ActivityExportRules {
|
|
1190
|
+
key: string;
|
|
1191
|
+
label: string;
|
|
1192
|
+
activationType: string;
|
|
1193
|
+
icon?: string;
|
|
1194
|
+
includeFieldsFrom?: string[];
|
|
1195
|
+
}
|
|
1196
|
+
export declare function activityExportHook(rules: ActivityExportRules): {
|
|
1197
|
+
suggestExportOptions({ operation, qsos, compactFilenames }: ExportOptionsRequest, ctx: HookContext): Promise<ExportOption[]>;
|
|
1198
|
+
generateExport(args: ExportRequest, ctx: HookContext): Promise<ExportResult>;
|
|
1199
|
+
};
|
|
1200
|
+
export interface HuntingExportRules {
|
|
1201
|
+
key: string;
|
|
1202
|
+
label: string;
|
|
1203
|
+
huntingType: string;
|
|
1204
|
+
activationType: string;
|
|
1205
|
+
icon?: string;
|
|
1206
|
+
color?: string;
|
|
1207
|
+
includeFieldsFrom?: string[];
|
|
1208
|
+
}
|
|
1209
|
+
export declare function huntingExportHook(rules: HuntingExportRules): {
|
|
1210
|
+
suggestExportOptions({ operation, qsos, compactFilenames }: ExportOptionsRequest, ctx: HookContext): Promise<ExportOption[]>;
|
|
1211
|
+
generateExport(args: ExportRequest, ctx: HookContext): Promise<ExportResult>;
|
|
1212
|
+
};
|
|
1213
|
+
export declare function adifForExport({ operation, qsos, includePrivateData, mainHandler, includeFieldsFrom }: {
|
|
1214
|
+
operation: Record<string, JSONValue>;
|
|
1215
|
+
qsos: Record<string, JSONValue>[];
|
|
1216
|
+
includePrivateData?: boolean;
|
|
1217
|
+
mainHandler: string;
|
|
1218
|
+
includeFieldsFrom?: string[];
|
|
1219
|
+
}): Promise<string>;
|
|
1220
|
+
export interface ActivityAdifImportRules {
|
|
1221
|
+
sig: string;
|
|
1222
|
+
huntingType?: string;
|
|
1223
|
+
activationType: string;
|
|
1224
|
+
refField?: string;
|
|
1225
|
+
normalize?: (ref: string) => string;
|
|
1226
|
+
}
|
|
1227
|
+
export declare function activityAdifImport(rules: ActivityAdifImportRules): AdifImportHook;
|
|
1228
|
+
export interface ExportNameParts {
|
|
1229
|
+
stationCall?: JSONValue;
|
|
1230
|
+
ref?: string;
|
|
1231
|
+
activity?: string;
|
|
1232
|
+
modifier?: string;
|
|
1233
|
+
startAtMillis?: number;
|
|
1234
|
+
extension: string;
|
|
1235
|
+
compact?: boolean;
|
|
1236
|
+
}
|
|
1237
|
+
export declare function exportFilename(parts: ExportNameParts): string;
|
|
1238
|
+
export declare function startMillisOf(operation: Record<string, JSONValue>, qsos?: Record<string, JSONValue>[]): number | undefined;
|
|
1239
|
+
export interface ReferenceActivityConfig {
|
|
1240
|
+
key: string;
|
|
1241
|
+
label: string;
|
|
1242
|
+
activationType: string;
|
|
1243
|
+
huntingType?: string;
|
|
1244
|
+
splitRecordsPerHuntedRef?: boolean;
|
|
1245
|
+
referenceRegex: RegExp;
|
|
1246
|
+
icon?: string;
|
|
1247
|
+
color?: string;
|
|
1248
|
+
placeholder?: string;
|
|
1249
|
+
category?: string;
|
|
1250
|
+
tFor: (ctx: {
|
|
1251
|
+
locale?: string;
|
|
1252
|
+
}) => (key: string) => string;
|
|
1253
|
+
adifProgram?: string;
|
|
1254
|
+
adifRefField?: string;
|
|
1255
|
+
allowsMultiple?: boolean;
|
|
1256
|
+
linkUrl?: (reference: string) => string;
|
|
1257
|
+
}
|
|
1258
|
+
export interface ReferenceActivityHooks {
|
|
1259
|
+
refHandler: Record<string, unknown>;
|
|
1260
|
+
activityHook: Record<string, unknown>;
|
|
1261
|
+
adifFieldsHook: Record<string, unknown>;
|
|
1262
|
+
adifImportHook: AdifImportHook;
|
|
1263
|
+
}
|
|
1264
|
+
export declare function referenceActivity(config: ReferenceActivityConfig): ReferenceActivityHooks;
|
|
1265
|
+
export declare class TemplateError extends Error {
|
|
1266
|
+
readonly cause?: unknown;
|
|
1267
|
+
constructor(message: string, options?: {
|
|
1268
|
+
cause?: unknown;
|
|
1269
|
+
});
|
|
1270
|
+
}
|
|
1271
|
+
export declare function renderTemplate(template: string, context: Record<string, unknown>, label?: string): string;
|
|
1272
|
+
export declare function oneLine(text: string): string;
|
|
1273
|
+
export declare function triggersForTemplate(template: string): string[];
|
|
1274
|
+
export declare function utcDate(millis: number): string;
|
|
1275
|
+
export declare function utcDateCompact(millis: number): string;
|
|
1276
|
+
export declare function utcTime(millis: number): string;
|
|
1277
|
+
export declare function utcIso(millis: number): string;
|
|
1278
|
+
export declare function dateValues(millis: number): Record<string, JSONValue>;
|
|
1279
|
+
export declare function opValues(operation: Record<string, JSONValue>, extra?: {
|
|
1280
|
+
qsoCount?: number;
|
|
1281
|
+
atMillis?: number;
|
|
1282
|
+
}): Record<string, JSONValue>;
|
|
1283
|
+
export declare function qsoValues(qso: Record<string, JSONValue>): Record<string, JSONValue>;
|
|
1284
|
+
export interface LogValues {
|
|
1285
|
+
station?: string;
|
|
1286
|
+
ref?: string;
|
|
1287
|
+
refName?: string;
|
|
1288
|
+
refShortName?: string;
|
|
1289
|
+
activity?: string;
|
|
1290
|
+
handlerName?: string;
|
|
1291
|
+
handlerShortName?: string;
|
|
1292
|
+
format?: string;
|
|
1293
|
+
exportType?: string;
|
|
1294
|
+
modifier?: string;
|
|
1295
|
+
extension?: string;
|
|
1296
|
+
compact?: boolean;
|
|
1297
|
+
}
|
|
1298
|
+
export declare function logValues(values: LogValues): Record<string, JSONValue>;
|
|
1299
|
+
export interface TemplateContextArgs {
|
|
1300
|
+
operation?: Record<string, JSONValue>;
|
|
1301
|
+
qso?: Record<string, JSONValue>;
|
|
1302
|
+
qsoCount?: number;
|
|
1303
|
+
config?: Record<string, JSONValue>;
|
|
1304
|
+
log?: LogValues;
|
|
1305
|
+
appName?: string;
|
|
1306
|
+
atMillis?: number;
|
|
1307
|
+
nowMillis?: number;
|
|
1308
|
+
}
|
|
1309
|
+
export declare function templateContext(args: TemplateContextArgs): Record<string, unknown>;
|
|
1310
|
+
export declare function isTestOperation(stationCall: JSONValue | undefined): boolean;
|
|
1311
|
+
export declare function defineExtension(def: ExtensionDefinition): void;
|
|
1312
|
+
export declare const hooks: {
|
|
1313
|
+
invokeAll(category: string, method: string, args: unknown, online?: boolean): Promise<{
|
|
1314
|
+
key: string;
|
|
1315
|
+
ok: boolean;
|
|
1316
|
+
value?: unknown;
|
|
1317
|
+
error?: string;
|
|
1318
|
+
}[]>;
|
|
1319
|
+
invokeOne(category: string, key: string, method: string, args: unknown, online?: boolean): Promise<{
|
|
1320
|
+
key: string;
|
|
1321
|
+
ok: boolean;
|
|
1322
|
+
value?: unknown;
|
|
1323
|
+
error?: string;
|
|
1324
|
+
}[]>;
|
|
1325
|
+
invokeAllSequential(category: string, method: string, initialArgs: unknown, fold: (args: unknown, hookResult: unknown, hookKey: string) => unknown, online?: boolean): Promise<{
|
|
1326
|
+
key: string;
|
|
1327
|
+
ok: boolean;
|
|
1328
|
+
value?: unknown;
|
|
1329
|
+
error?: string;
|
|
1330
|
+
}[]>;
|
|
1331
|
+
};
|
|
1332
|
+
export declare const host: {
|
|
1333
|
+
fetch(url: string, options?: FetchOptions): Promise<FetchResponse>;
|
|
1334
|
+
kvGet(key: string): Promise<JSONValue | null>;
|
|
1335
|
+
getLocation(): Promise<DeviceLocation | null>;
|
|
1336
|
+
getVersionInfo(): Promise<VersionInfo>;
|
|
1337
|
+
getSettings(): Promise<Record<string, JSONValue>>;
|
|
1338
|
+
setSettings(values: Record<string, JSONValue>): Promise<void>;
|
|
1339
|
+
searchSettings(params: SearchSettingsParams): Promise<SettingsSearchResult>;
|
|
1340
|
+
kvSet(key: string, value: JSONValue): Promise<void>;
|
|
1341
|
+
setAccountSession(session: Record<string, string>): Promise<void>;
|
|
1342
|
+
showMessage(message: ResultMessage): Promise<void>;
|
|
1343
|
+
translate(key: string): Promise<string | null>;
|
|
1344
|
+
translateAll(keys: string[]): Promise<Record<string, string | null>>;
|
|
1345
|
+
secret(name: string): Promise<string | null>;
|
|
1346
|
+
dbLookupSelectOne(category: string, key: string): Promise<LookupRow | null>;
|
|
1347
|
+
dbLookupSelectAll(category: string, query: string, subCategory?: string, activeOnly?: boolean): Promise<LookupRow[]>;
|
|
1348
|
+
dbLookupSelectByLocation(category: string, lat: number, lon: number, delta: number, activeOnly?: boolean): Promise<LookupRow[]>;
|
|
1349
|
+
showForm(form: FormDefinition, state?: Record<string, any>): Promise<Record<string, any> | null>;
|
|
1350
|
+
statusBar: {
|
|
1351
|
+
setMessage(params: StatusBarMessageParams): Promise<void>;
|
|
1352
|
+
setProgress(params: StatusBarProgressParams): Promise<void>;
|
|
1353
|
+
clear(key: string): Promise<void>;
|
|
1354
|
+
showNotice(params: StatusBarNoticeParams): Promise<void>;
|
|
1355
|
+
dismissNotice(key: string): Promise<void>;
|
|
1356
|
+
};
|
|
1357
|
+
log(message: string): void;
|
|
1358
|
+
updateInterpretation(input: string, interpretation: Record<string, unknown>): void;
|
|
1359
|
+
};
|
|
1360
|
+
|
|
1361
|
+
export {};
|