@openbrf/plugin-sdk 1.0.0 → 1.4.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 +95 -0
- package/dist/abort-signal.d.ts +23 -0
- package/dist/abort-signal.d.ts.map +1 -0
- package/dist/abort-signal.js +2 -0
- package/dist/abort-signal.js.map +1 -0
- package/dist/action-refusal.d.ts +101 -0
- package/dist/action-refusal.d.ts.map +1 -0
- package/dist/action-refusal.js +96 -0
- package/dist/action-refusal.js.map +1 -0
- package/dist/action-schema.d.ts.map +1 -1
- package/dist/action-schema.js +4 -1
- package/dist/action-schema.js.map +1 -1
- package/dist/actions.d.ts +94 -6
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js.map +1 -1
- package/dist/blocks.d.ts +310 -0
- package/dist/blocks.d.ts.map +1 -0
- package/dist/blocks.js +185 -0
- package/dist/blocks.js.map +1 -0
- package/dist/catalog.d.ts +1092 -41
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +472 -15
- package/dist/catalog.js.map +1 -1
- package/dist/entitlements.d.ts +117 -0
- package/dist/entitlements.d.ts.map +1 -0
- package/dist/entitlements.js +62 -0
- package/dist/entitlements.js.map +1 -0
- package/dist/extensions.d.ts +183 -0
- package/dist/extensions.d.ts.map +1 -0
- package/dist/extensions.js +67 -0
- package/dist/extensions.js.map +1 -0
- package/dist/finances.d.ts +294 -0
- package/dist/finances.d.ts.map +1 -0
- package/dist/finances.js +56 -0
- package/dist/finances.js.map +1 -0
- package/dist/findings.d.ts +92 -1
- package/dist/findings.d.ts.map +1 -1
- package/dist/findings.js +91 -0
- package/dist/findings.js.map +1 -1
- package/dist/host.d.ts +729 -4
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +54 -0
- package/dist/host.js.map +1 -1
- package/dist/imports.d.ts +104 -0
- package/dist/imports.d.ts.map +1 -0
- package/dist/imports.js +70 -0
- package/dist/imports.js.map +1 -0
- package/dist/index.d.ts +17 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -6
- package/dist/index.js.map +1 -1
- package/dist/localized-text.d.ts +18 -0
- package/dist/localized-text.d.ts.map +1 -0
- package/dist/localized-text.js +17 -0
- package/dist/localized-text.js.map +1 -0
- package/dist/manifest.d.ts +859 -0
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +957 -12
- package/dist/manifest.js.map +1 -1
- package/dist/package-check.d.ts.map +1 -1
- package/dist/package-check.js +9 -1
- package/dist/package-check.js.map +1 -1
- package/dist/permissions.d.ts +170 -11
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +210 -2
- package/dist/permissions.js.map +1 -1
- package/dist/recipients.d.ts +139 -0
- package/dist/recipients.d.ts.map +1 -0
- package/dist/recipients.js +223 -0
- package/dist/recipients.js.map +1 -0
- package/dist/records.d.ts +130 -0
- package/dist/records.d.ts.map +1 -0
- package/dist/records.js +85 -0
- package/dist/records.js.map +1 -0
- package/dist/require-capability.d.ts +37 -0
- package/dist/require-capability.d.ts.map +1 -0
- package/dist/require-capability.js +88 -0
- package/dist/require-capability.js.map +1 -0
- package/dist/settings-schema.d.ts +35 -0
- package/dist/settings-schema.d.ts.map +1 -1
- package/dist/settings-schema.js +55 -2
- package/dist/settings-schema.js.map +1 -1
- package/package.json +4 -4
- package/src/abort-signal.ts +22 -0
- package/src/action-refusal.ts +178 -0
- package/src/action-schema.ts +4 -1
- package/src/actions.ts +103 -6
- package/src/blocks.ts +289 -0
- package/src/catalog.ts +630 -72
- package/src/entitlements.ts +150 -0
- package/src/extensions.ts +212 -0
- package/src/finances.ts +317 -0
- package/src/findings.ts +94 -0
- package/src/host.ts +768 -4
- package/src/imports.ts +135 -0
- package/src/index.ts +209 -0
- package/src/localized-text.ts +19 -0
- package/src/manifest.ts +1231 -12
- package/src/package-check.ts +15 -0
- package/src/permissions.ts +223 -3
- package/src/recipients.ts +294 -0
- package/src/records.ts +172 -0
- package/src/require-capability.ts +106 -0
- package/src/settings-schema.ts +64 -2
package/dist/host.d.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
import type { PluginActions } from "./actions.ts";
|
|
2
|
-
import type {
|
|
1
|
+
import type { ActionRequest, PluginActions } from "./actions.ts";
|
|
2
|
+
import type { PluginBlocks } from "./blocks.ts";
|
|
3
|
+
import type { PluginExtensions } from "./extensions.ts";
|
|
4
|
+
import type { PluginEntitlements } from "./entitlements.ts";
|
|
5
|
+
import type { PluginFinances } from "./finances.ts";
|
|
6
|
+
import type { PluginImports } from "./imports.ts";
|
|
7
|
+
import type { PluginPermission, PluginPersonalDataCategory } from "./permissions.ts";
|
|
8
|
+
import type { PluginRecords } from "./records.ts";
|
|
3
9
|
import type { PluginSettingsValues } from "./settings-schema.ts";
|
|
4
10
|
/**
|
|
5
11
|
* The host services a plugin receives.
|
|
@@ -36,8 +42,26 @@ export interface PluginSettings {
|
|
|
36
42
|
* The stored values, with declared defaults applied. Reads the current
|
|
37
43
|
* values on each call rather than caching, so a change made in the admin
|
|
38
44
|
* interface reaches a long-running job without a restart.
|
|
45
|
+
*
|
|
46
|
+
* A secret field is in it in clear, which is the one place its value
|
|
47
|
+
* leaves the host: never write it to the log, a job's payload or anything
|
|
48
|
+
* a route returns.
|
|
39
49
|
*/
|
|
40
50
|
read(): Promise<PluginSettingsValues>;
|
|
51
|
+
/**
|
|
52
|
+
* Replaces or clears one of the plugin's own secret fields: `null` clears
|
|
53
|
+
* it.
|
|
54
|
+
*
|
|
55
|
+
* For a credential the far end replaces, such as an OAuth refresh token
|
|
56
|
+
* that is new after every use. Only a field the manifest declares as
|
|
57
|
+
* `secret`, checked against its declared bounds; the change is written to
|
|
58
|
+
* the audit log under the field's key, never with its value.
|
|
59
|
+
*
|
|
60
|
+
* Added after this contract version shipped, like `actions`: a plugin built
|
|
61
|
+
* against a newer host than the one it is installed on must feature-detect
|
|
62
|
+
* before using it.
|
|
63
|
+
*/
|
|
64
|
+
writeSecret(key: string, value: string | null): Promise<void>;
|
|
41
65
|
}
|
|
42
66
|
export interface PluginMailMessage {
|
|
43
67
|
to: string;
|
|
@@ -122,6 +146,12 @@ export interface PluginApartment {
|
|
|
122
146
|
export interface PluginResident {
|
|
123
147
|
personId: string;
|
|
124
148
|
name: string;
|
|
149
|
+
/**
|
|
150
|
+
* The family name alone, for a reader that shows no first names: a household
|
|
151
|
+
* as the name on the door shows it, without the first names that say who
|
|
152
|
+
* lives alone and name the children.
|
|
153
|
+
*/
|
|
154
|
+
lastName: string;
|
|
125
155
|
/** MEMBER holds the tenant-ownership; RESIDENT occupies without holding it. */
|
|
126
156
|
role: "MEMBER" | "RESIDENT";
|
|
127
157
|
apartment: PluginApartment | null;
|
|
@@ -131,6 +161,21 @@ export interface PluginResident {
|
|
|
131
161
|
email?: string | null;
|
|
132
162
|
/** Present only with the addressBook:readContact permission. */
|
|
133
163
|
phone?: string | null;
|
|
164
|
+
/**
|
|
165
|
+
* Whether a publication consent to the person's name on screens inside the
|
|
166
|
+
* building stands (the `NAME_IN_BUILDING` scope), recorded by the board on
|
|
167
|
+
* the person's panel like every other scope. A different consent from a name
|
|
168
|
+
* on the website, because the two are different things to agree to.
|
|
169
|
+
*/
|
|
170
|
+
nameInBuilding: boolean;
|
|
171
|
+
}
|
|
172
|
+
/** Narrows a read of the residents. */
|
|
173
|
+
export interface PluginResidentFilter {
|
|
174
|
+
/**
|
|
175
|
+
* Only the residents of this entrance, so a plugin that shows one entrance
|
|
176
|
+
* never loads the others. An id no address has returns nobody.
|
|
177
|
+
*/
|
|
178
|
+
addressId?: string;
|
|
134
179
|
}
|
|
135
180
|
export interface PluginOccupancySummary {
|
|
136
181
|
apartments: number;
|
|
@@ -148,13 +193,594 @@ export interface PluginOccupancySummary {
|
|
|
148
193
|
* personal identity number is never returned, and nothing is writable.
|
|
149
194
|
* Requires addressBook:read; the contact fields additionally require
|
|
150
195
|
* addressBook:readContact.
|
|
196
|
+
*
|
|
197
|
+
* A person who has objected to this plugin's processing, and whose objection
|
|
198
|
+
* the board granted, is absent as well (ADR 0035) - absent, not flagged, so a
|
|
199
|
+
* plugin cannot list who objected. Closing the objection brings the person
|
|
200
|
+
* back on the next read.
|
|
151
201
|
*/
|
|
152
202
|
export interface PluginAddressBook {
|
|
153
203
|
apartments(): Promise<PluginApartment[]>;
|
|
154
|
-
/**
|
|
155
|
-
|
|
204
|
+
/**
|
|
205
|
+
* Current residencies only. Moved-out rows are not plugin business.
|
|
206
|
+
*
|
|
207
|
+
* The filter was added after this contract version shipped; an older host
|
|
208
|
+
* ignores it and returns every entrance, so a plugin that must not load the
|
|
209
|
+
* others filters the result by `apartment.address.id` as well.
|
|
210
|
+
*/
|
|
211
|
+
residents(filter?: PluginResidentFilter): Promise<PluginResident[]>;
|
|
156
212
|
summary(): Promise<PluginOccupancySummary>;
|
|
157
213
|
}
|
|
214
|
+
/** The bounds `host.audit.record` holds an entry to. */
|
|
215
|
+
export declare const PLUGIN_AUDIT_LIMITS: {
|
|
216
|
+
/** Characters in `event`, which is also part of a text key. */
|
|
217
|
+
readonly event: 64;
|
|
218
|
+
/** Characters in `targetKind`. */
|
|
219
|
+
readonly targetKind: 64;
|
|
220
|
+
/** Characters in `targetId`. */
|
|
221
|
+
readonly targetId: 200;
|
|
222
|
+
/** Values in `detail`. */
|
|
223
|
+
readonly detailValues: 8;
|
|
224
|
+
/** Characters in a key of `detail`, letters and digits. */
|
|
225
|
+
readonly detailKey: 64;
|
|
226
|
+
/** Characters in a string value of `detail`. */
|
|
227
|
+
readonly detailValue: 200;
|
|
228
|
+
};
|
|
229
|
+
/** One entry a plugin writes to the instance's audit log. */
|
|
230
|
+
export interface PluginAuditEntry {
|
|
231
|
+
/**
|
|
232
|
+
* What happened, as lowercase letters, digits, dots and hyphens, starting
|
|
233
|
+
* with a letter: `screen.residents-enabled`. The audit log shows it through
|
|
234
|
+
* the plugin's own text key `audit.<event>`.
|
|
235
|
+
*/
|
|
236
|
+
event: string;
|
|
237
|
+
/** What the act was done to, in the plugin's own words: `screen`. */
|
|
238
|
+
targetKind?: string;
|
|
239
|
+
/** Which one: the screen's id. */
|
|
240
|
+
targetId?: string;
|
|
241
|
+
/**
|
|
242
|
+
* At most eight values about the act, never a copy of what the plugin read.
|
|
243
|
+
* A key is letters and digits, starting with a letter: `screenCount`. A
|
|
244
|
+
* person is named as the actor, never here, and a key or value holding a
|
|
245
|
+
* personal identity number is refused.
|
|
246
|
+
*/
|
|
247
|
+
detail?: Record<string, string | number | boolean>;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Writing to the instance's audit log (ADR 0035).
|
|
251
|
+
*
|
|
252
|
+
* The entry is written as `PLUGIN_RECORDED`, with the plugin's id and the
|
|
253
|
+
* event, on the plugin channel. With a request, the actor is the person the
|
|
254
|
+
* host marked on it, as for `actions`; with `null`, the entry has no actor - a
|
|
255
|
+
* plugin's own job, say. An entry that breaks a bound is refused with a
|
|
256
|
+
* RangeError and nothing is written. Needs no permission: an entry is about
|
|
257
|
+
* what the plugin did, which the association is entitled to a record of.
|
|
258
|
+
*/
|
|
259
|
+
export interface PluginAudit {
|
|
260
|
+
record(request: ActionRequest | null, entry: PluginAuditEntry): Promise<void>;
|
|
261
|
+
}
|
|
262
|
+
/** What a theme install is told about the package besides its bytes. */
|
|
263
|
+
export interface PluginThemeInstallOptions {
|
|
264
|
+
/**
|
|
265
|
+
* The package's sha512, as whoever published it stated it: `sha512-<base64>`
|
|
266
|
+
* or 128 hex characters, the two spellings a catalog entry may use. The
|
|
267
|
+
* bytes are checked against it before anything is unpacked.
|
|
268
|
+
*/
|
|
269
|
+
sha512: string;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* A finding the install lint reported without refusing the theme: a token or
|
|
273
|
+
* a manifest field this core does not know, which the token contract says to
|
|
274
|
+
* ignore rather than refuse. Rule codes and numbers, never prose.
|
|
275
|
+
*/
|
|
276
|
+
export interface PluginThemeInstallWarning {
|
|
277
|
+
rule: string;
|
|
278
|
+
detail: Readonly<Record<string, string | number | boolean>>;
|
|
279
|
+
}
|
|
280
|
+
export interface PluginThemeInstallResult {
|
|
281
|
+
/** The theme's id, from its manifest. */
|
|
282
|
+
id: string;
|
|
283
|
+
version: string;
|
|
284
|
+
warnings: readonly PluginThemeInstallWarning[];
|
|
285
|
+
}
|
|
286
|
+
/** A theme this plugin installed, as `host.themes.list` returns it. */
|
|
287
|
+
export interface PluginInstalledTheme {
|
|
288
|
+
id: string;
|
|
289
|
+
version: string;
|
|
290
|
+
/** ISO 8601. When the version now installed was installed first. */
|
|
291
|
+
installedAt: string;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Installing themes on the instance (ADR 0046). Requires themes:install.
|
|
295
|
+
*
|
|
296
|
+
* A theme a plugin hands over takes the path a theme from the catalog takes:
|
|
297
|
+
* its sha512 checked before anything is unpacked, the package read and held to
|
|
298
|
+
* the same install lint, the statutory register contrast included, and the
|
|
299
|
+
* files and the row written together under the same lock per theme id. A
|
|
300
|
+
* package the lint refuses is refused here with the same findings, and what
|
|
301
|
+
* the instance already had stays as it was.
|
|
302
|
+
*
|
|
303
|
+
* `install` takes the request the plugin's own route received and installs as
|
|
304
|
+
* the person behind it, who must hold association:manage, the capability the
|
|
305
|
+
* theme screen requires. A request a connected app's token reached is refused,
|
|
306
|
+
* and a background job has no request, so a plugin installs a theme only when
|
|
307
|
+
* an administrator asks it to.
|
|
308
|
+
*
|
|
309
|
+
* A plugin installs over a theme it installed itself and over nothing else:
|
|
310
|
+
* not the catalog's, not one composed on the instance, not another plugin's.
|
|
311
|
+
* It installs and nothing else. Activating and removing stay on the theme
|
|
312
|
+
* screen, and a theme stays installed when the plugin is removed.
|
|
313
|
+
*
|
|
314
|
+
* A refusal is thrown as an error carrying a `reason` code and, for
|
|
315
|
+
* `lint-failed`, the `findings`. Let it propagate from a route and the client
|
|
316
|
+
* is answered with its status, reason and findings, as the theme screen is.
|
|
317
|
+
*/
|
|
318
|
+
export interface PluginThemes {
|
|
319
|
+
install(request: ActionRequest, archive: Uint8Array, options: PluginThemeInstallOptions): Promise<PluginThemeInstallResult>;
|
|
320
|
+
/** The themes this plugin installed, so it can offer an update. */
|
|
321
|
+
list(): Promise<PluginInstalledTheme[]>;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Who a news item or an event is for: the members, or anyone at all.
|
|
325
|
+
*
|
|
326
|
+
* On every item the content services return, because the host cannot know
|
|
327
|
+
* where the plugin puts it. A screen inside the building may show a members'
|
|
328
|
+
* item and a public calendar feed should not; which of the two the plugin is
|
|
329
|
+
* doing is what its consent screen tells the board (ADR 0032).
|
|
330
|
+
*/
|
|
331
|
+
export type PluginContentAudience = "anyone" | "members";
|
|
332
|
+
/** One published news item, as a plugin reads it. */
|
|
333
|
+
export interface PluginNewsItem {
|
|
334
|
+
readonly id: string;
|
|
335
|
+
readonly title: string;
|
|
336
|
+
/** The body's text, one string per paragraph or heading, in order. */
|
|
337
|
+
readonly paragraphs: readonly string[];
|
|
338
|
+
/**
|
|
339
|
+
* The pictures the body shows, in order.
|
|
340
|
+
*
|
|
341
|
+
* Empty while a news body holds prose only, which is all the core's news
|
|
342
|
+
* editor writes and all the website shows of one.
|
|
343
|
+
*/
|
|
344
|
+
readonly pictures: readonly {
|
|
345
|
+
mediaFileId: string;
|
|
346
|
+
alt: string;
|
|
347
|
+
}[];
|
|
348
|
+
readonly audience: PluginContentAudience;
|
|
349
|
+
/** ISO 8601 instant. */
|
|
350
|
+
readonly publishedAt: string;
|
|
351
|
+
/**
|
|
352
|
+
* Whether the board marked the item "show on screens": that it may be shown
|
|
353
|
+
* on a screen in the building (ADR 0050). Off until the board sets it. A
|
|
354
|
+
* plugin that puts items where anybody passing can read them shows only the
|
|
355
|
+
* marked ones.
|
|
356
|
+
*/
|
|
357
|
+
readonly onScreens: boolean;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* The association's published news. Requires the news:read permission.
|
|
361
|
+
*
|
|
362
|
+
* What the website publishes and nothing more: a draft, an item taken down, a
|
|
363
|
+
* deleted one and one the board wrote to Styrelsen or Administratörer in the
|
|
364
|
+
* feed are absent. Never an author, a comment, a like or who has read an item.
|
|
365
|
+
*
|
|
366
|
+
* To a plugin that declares a device route, an item whose title, paragraphs or
|
|
367
|
+
* picture alt texts name somebody the register holds, one of their email
|
|
368
|
+
* addresses or phone numbers, or an apartment number is absent as well, and
|
|
369
|
+
* the read goes on to older items to make up the count, as far back as the
|
|
370
|
+
* newest 500 published items (ADR 0032).
|
|
371
|
+
*/
|
|
372
|
+
export interface PluginNews {
|
|
373
|
+
/**
|
|
374
|
+
* Published items, newest first.
|
|
375
|
+
*
|
|
376
|
+
* `limit` is 1 to 50 and defaults to 50. `since` is an ISO 8601 instant and
|
|
377
|
+
* keeps the items published at or after it. `audience` keeps only the items
|
|
378
|
+
* for that audience; without it both are returned, each saying which it is.
|
|
379
|
+
* A value outside those bounds is refused with a RangeError.
|
|
380
|
+
*/
|
|
381
|
+
published(options?: {
|
|
382
|
+
audience?: PluginContentAudience;
|
|
383
|
+
limit?: number;
|
|
384
|
+
since?: string;
|
|
385
|
+
}): Promise<readonly PluginNewsItem[]>;
|
|
386
|
+
}
|
|
387
|
+
/** One occurrence of a published event. */
|
|
388
|
+
export interface PluginOccurrence {
|
|
389
|
+
readonly eventId: string;
|
|
390
|
+
readonly occurrenceId: string;
|
|
391
|
+
/** The board's own words, as written and never translated. */
|
|
392
|
+
readonly title: string;
|
|
393
|
+
readonly description: string | null;
|
|
394
|
+
readonly category: string | null;
|
|
395
|
+
readonly location: string | null;
|
|
396
|
+
/** ISO 8601 instant. */
|
|
397
|
+
readonly startsAt: string;
|
|
398
|
+
/** ISO 8601 instant. */
|
|
399
|
+
readonly endsAt: string;
|
|
400
|
+
/** Whether the board has called this one occurrence off. */
|
|
401
|
+
readonly calledOff: boolean;
|
|
402
|
+
/**
|
|
403
|
+
* Places left when the event takes sign-ups with a limit, and null when it
|
|
404
|
+
* takes none or has no limit. Never who took them.
|
|
405
|
+
*/
|
|
406
|
+
readonly placesLeft: number | null;
|
|
407
|
+
readonly audience: PluginContentAudience;
|
|
408
|
+
/**
|
|
409
|
+
* Whether the board marked the event, with all its occurrences, "show on
|
|
410
|
+
* screens" (ADR 0050), as a news item's mark.
|
|
411
|
+
*/
|
|
412
|
+
readonly onScreens: boolean;
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* The notice of a general meeting the board has called.
|
|
416
|
+
*
|
|
417
|
+
* What the notice states (EFL 6 kap. 22 §): the time, the place, how to take
|
|
418
|
+
* part digitally and the matters on the agenda. Never who was summoned, who
|
|
419
|
+
* attended, the voting register or a proxy.
|
|
420
|
+
*/
|
|
421
|
+
export interface PluginMeetingNotice {
|
|
422
|
+
readonly meetingId: string;
|
|
423
|
+
readonly kind: "ordinary" | "extraordinary";
|
|
424
|
+
/** ISO 8601 instant. */
|
|
425
|
+
readonly startsAt: string;
|
|
426
|
+
readonly place: string;
|
|
427
|
+
readonly digitalParticipation: string | null;
|
|
428
|
+
readonly agenda: readonly {
|
|
429
|
+
position: number;
|
|
430
|
+
title: string;
|
|
431
|
+
}[];
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* The association's calendar. Requires the calendar:read permission.
|
|
435
|
+
*
|
|
436
|
+
* Published events only: a series that is not published is absent, and an
|
|
437
|
+
* occurrence the board called off is present and says so.
|
|
438
|
+
*
|
|
439
|
+
* To a plugin that declares a device route, an event whose title,
|
|
440
|
+
* description, category or location names somebody the register holds or an
|
|
441
|
+
* apartment number is absent with every occurrence, and a notice whose place,
|
|
442
|
+
* digital participation or any agenda title does is absent whole (ADR 0032).
|
|
443
|
+
*/
|
|
444
|
+
export interface PluginCalendar {
|
|
445
|
+
/**
|
|
446
|
+
* Occurrences starting in [from, to), soonest first.
|
|
447
|
+
*
|
|
448
|
+
* `from` and `to` are ISO 8601 instants at most 92 days apart, and
|
|
449
|
+
* `audience` works as it does for the news. A range that is not one is
|
|
450
|
+
* refused with a RangeError.
|
|
451
|
+
*/
|
|
452
|
+
occurrences(range: {
|
|
453
|
+
from: string;
|
|
454
|
+
to: string;
|
|
455
|
+
audience?: PluginContentAudience;
|
|
456
|
+
}): Promise<readonly PluginOccurrence[]>;
|
|
457
|
+
/**
|
|
458
|
+
* Notices of the general meetings called and not yet held, soonest first.
|
|
459
|
+
*
|
|
460
|
+
* A notice summons the members, so every one of them is for the members.
|
|
461
|
+
*/
|
|
462
|
+
meetingNotices(): Promise<readonly PluginMeetingNotice[]>;
|
|
463
|
+
}
|
|
464
|
+
/** A bookable resource the house offers, and how it is booked. */
|
|
465
|
+
export interface PluginBookableResource {
|
|
466
|
+
readonly id: string;
|
|
467
|
+
/** The board's own name for it, as written. */
|
|
468
|
+
readonly name: string;
|
|
469
|
+
readonly mode: "timeSlots" | "wholeDay" | "dateRange";
|
|
470
|
+
/** The slot length in the time-slot mode, and null otherwise. */
|
|
471
|
+
readonly slotMinutes: number | null;
|
|
472
|
+
/** Minutes after local midnight the resource opens, in the time-slot mode. */
|
|
473
|
+
readonly opensAtMinute: number | null;
|
|
474
|
+
/** Minutes after local midnight the resource closes, in the time-slot mode. */
|
|
475
|
+
readonly closesAtMinute: number | null;
|
|
476
|
+
}
|
|
477
|
+
/** A period a resource is taken. Never by whom. */
|
|
478
|
+
export interface PluginBusyInterval {
|
|
479
|
+
readonly resourceId: string;
|
|
480
|
+
/** ISO 8601 instant. */
|
|
481
|
+
readonly start: string;
|
|
482
|
+
/** ISO 8601 instant. */
|
|
483
|
+
readonly end: string;
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Free and busy for the house's bookable resources. Requires the
|
|
487
|
+
* bookings:readAvailability permission.
|
|
488
|
+
*
|
|
489
|
+
* Less than a resident's own booking screen shows: when a resource is taken,
|
|
490
|
+
* and nothing about who took it - no booker, no apartment and no booking's
|
|
491
|
+
* identifier.
|
|
492
|
+
*
|
|
493
|
+
* To a plugin that declares a device route, a resource whose name names
|
|
494
|
+
* somebody the register holds or an apartment number is absent from both
|
|
495
|
+
* reads, and `busy` starts no earlier than the moment of the call, so no
|
|
496
|
+
* booking that has ended is in it (ADR 0032).
|
|
497
|
+
*/
|
|
498
|
+
export interface PluginBookings {
|
|
499
|
+
/** The resources open for booking, by name. A withdrawn one is absent. */
|
|
500
|
+
resources(): Promise<readonly PluginBookableResource[]>;
|
|
501
|
+
/**
|
|
502
|
+
* When each resource is taken in [from, to), per resource and in order.
|
|
503
|
+
*
|
|
504
|
+
* `from` and `to` are ISO 8601 instants at most 31 days apart, refused with
|
|
505
|
+
* a RangeError otherwise. Bookings that overlap or touch are merged into one
|
|
506
|
+
* interval, so a run of slots cannot be read as one household's habits. A
|
|
507
|
+
* resource id that is not an offered resource's answers nothing.
|
|
508
|
+
*/
|
|
509
|
+
busy(range: {
|
|
510
|
+
from: string;
|
|
511
|
+
to: string;
|
|
512
|
+
resourceIds?: readonly string[];
|
|
513
|
+
}): Promise<readonly PluginBusyInterval[]>;
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* The bytes of a picture, as a web stream of `Uint8Array` chunks.
|
|
517
|
+
*
|
|
518
|
+
* The host hands a real `ReadableStream`. This package compiles against the
|
|
519
|
+
* language alone and cannot name the platform's type, so it is looked up in the
|
|
520
|
+
* plugin's own program, as the block's abort signal is: where that has a
|
|
521
|
+
* `ReadableStream`, from the DOM library or from Node's types, this is it, and
|
|
522
|
+
* the stream can go into a `Response` or `Readable.fromWeb` as it is. Where it
|
|
523
|
+
* has none, this is the part of one a plugin can read without them.
|
|
524
|
+
*/
|
|
525
|
+
export type PluginMediaStream = typeof globalThis extends {
|
|
526
|
+
readonly ReadableStream: {
|
|
527
|
+
readonly prototype: infer Stream;
|
|
528
|
+
};
|
|
529
|
+
} ? Stream : PluginMediaStreamShape;
|
|
530
|
+
/** What every `ReadableStream` has, for a program without the platform's types. */
|
|
531
|
+
interface PluginMediaStreamShape {
|
|
532
|
+
readonly locked: boolean;
|
|
533
|
+
cancel(reason?: unknown): Promise<void>;
|
|
534
|
+
getReader(): {
|
|
535
|
+
read(): Promise<{
|
|
536
|
+
done: false;
|
|
537
|
+
value: Uint8Array;
|
|
538
|
+
} | {
|
|
539
|
+
done: true;
|
|
540
|
+
value?: undefined;
|
|
541
|
+
}>;
|
|
542
|
+
cancel(reason?: unknown): Promise<void>;
|
|
543
|
+
releaseLock(): void;
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* A stored picture the plugin opened.
|
|
548
|
+
*
|
|
549
|
+
* What a reply serving it needs and nothing else: not the name it was uploaded
|
|
550
|
+
* under, which is somebody's own words, and not who uploaded it.
|
|
551
|
+
*/
|
|
552
|
+
export interface PluginMediaFile {
|
|
553
|
+
/** Identified from the bytes when they were uploaded: an image type. */
|
|
554
|
+
readonly contentType: string;
|
|
555
|
+
/** The size of the picture as uploaded, in bytes. */
|
|
556
|
+
readonly byteSize: number;
|
|
557
|
+
/**
|
|
558
|
+
* A keyed hash of the bytes, hex encoded. The same value the core serves the
|
|
559
|
+
* picture's entity tag from, so a plugin may use it as one too.
|
|
560
|
+
*/
|
|
561
|
+
readonly checksum: string;
|
|
562
|
+
/**
|
|
563
|
+
* Who the picture is for: `anyone`, or the `members`, as the board held it.
|
|
564
|
+
* The host does not filter for you, because it cannot know where you put it;
|
|
565
|
+
* see {@link PluginContentAudience}.
|
|
566
|
+
*/
|
|
567
|
+
readonly audience: PluginContentAudience;
|
|
568
|
+
/**
|
|
569
|
+
* The picture's bytes. Read it to the end or cancel it: the host holds the
|
|
570
|
+
* stored file open until one or the other.
|
|
571
|
+
*/
|
|
572
|
+
readonly stream: PluginMediaStream;
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* The association's stored pictures. Requires the media:read permission.
|
|
576
|
+
*
|
|
577
|
+
* Only a picture held for anyone or for the members whose upload declared that
|
|
578
|
+
* it shows no identifiable person (ADR 0032). A photograph of people needs a
|
|
579
|
+
* publication consent, and the consent the core records is for the website,
|
|
580
|
+
* not for wherever a plugin puts the picture. Nothing here lists or finds a
|
|
581
|
+
* picture: a plugin opens one whose id it already holds, such as one the board
|
|
582
|
+
* picked in the plugin's own view.
|
|
583
|
+
*/
|
|
584
|
+
export interface PluginMedia {
|
|
585
|
+
/**
|
|
586
|
+
* Opens one picture.
|
|
587
|
+
*
|
|
588
|
+
* Null when the file does not exist and when it is not one a plugin may
|
|
589
|
+
* read, the two alike, so the answer says nothing about a file the plugin
|
|
590
|
+
* may not see. A `mediaFileId` that is not a string is refused with a
|
|
591
|
+
* RangeError.
|
|
592
|
+
*/
|
|
593
|
+
open(mediaFileId: string): Promise<PluginMediaFile | null>;
|
|
594
|
+
}
|
|
595
|
+
/** One of the association's addresses: an entrance, and nobody behind it. */
|
|
596
|
+
export interface PluginAddress {
|
|
597
|
+
readonly id: string;
|
|
598
|
+
readonly street: string;
|
|
599
|
+
/** The street number, as written: "12", "12 B". */
|
|
600
|
+
readonly number: string;
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* The association's addresses. Requires the addresses:read permission.
|
|
604
|
+
*
|
|
605
|
+
* A fact about the building: never an apartment, a resident or a member, which
|
|
606
|
+
* is what addressBook:read is for.
|
|
607
|
+
*/
|
|
608
|
+
export interface PluginAddresses {
|
|
609
|
+
/** Every address, in the order the core's own screens show them. */
|
|
610
|
+
list(): Promise<readonly PluginAddress[]>;
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* What a request to a recipient sends as personal data, and about whom.
|
|
614
|
+
*
|
|
615
|
+
* The host writes one audit entry per subject before anything is sent, and
|
|
616
|
+
* a second after, with the outcome; each reaches that person's data subject
|
|
617
|
+
* access report. A disclosure that names nobody, such as text a board member
|
|
618
|
+
* typed, is recorded once with no person.
|
|
619
|
+
*/
|
|
620
|
+
export interface PluginDisclosure {
|
|
621
|
+
/**
|
|
622
|
+
* The categories the body carries. One or more, each among those the
|
|
623
|
+
* recipient's declaration says it receives, or nothing is sent.
|
|
624
|
+
*/
|
|
625
|
+
personalData: readonly PluginPersonalDataCategory[];
|
|
626
|
+
/**
|
|
627
|
+
* The ids of the persons the body is about, at most 100. Each must be a
|
|
628
|
+
* person the host would hand the plugin: a person with protected personal
|
|
629
|
+
* data, one under a restriction of processing, or an id the register does
|
|
630
|
+
* not hold refuses the request, and the error does not say which.
|
|
631
|
+
*/
|
|
632
|
+
subjects: readonly string[];
|
|
633
|
+
}
|
|
634
|
+
export interface PluginRecipientRequest {
|
|
635
|
+
/** `GET` when left out. */
|
|
636
|
+
method?: "GET" | "HEAD" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
637
|
+
/**
|
|
638
|
+
* Sent as given, apart from the ones the host writes: `host`,
|
|
639
|
+
* `content-length`, `transfer-encoding`, `connection` and the other
|
|
640
|
+
* hop-by-hop headers are refused.
|
|
641
|
+
*/
|
|
642
|
+
headers?: Readonly<Record<string, string>>;
|
|
643
|
+
/** At most 16 MiB. */
|
|
644
|
+
body?: string | Uint8Array;
|
|
645
|
+
/**
|
|
646
|
+
* Required whenever the body carries personal data. A request without it
|
|
647
|
+
* is recorded nowhere, which is right for fetching a list of models and
|
|
648
|
+
* wrong for anything about a person.
|
|
649
|
+
*/
|
|
650
|
+
disclosure?: PluginDisclosure;
|
|
651
|
+
/**
|
|
652
|
+
* The whole exchange, name lookup and redirects included. 60 seconds when
|
|
653
|
+
* left out, at most 300.
|
|
654
|
+
*/
|
|
655
|
+
timeoutMs?: number;
|
|
656
|
+
}
|
|
657
|
+
export interface PluginRecipientResponse {
|
|
658
|
+
/** Whatever the recipient answered, 4xx and 5xx included. */
|
|
659
|
+
status: number;
|
|
660
|
+
/** Lowercased names; a repeated header is joined with ", ". */
|
|
661
|
+
headers: Readonly<Record<string, string>>;
|
|
662
|
+
/** The whole body, at most 16 MiB. */
|
|
663
|
+
body: Uint8Array;
|
|
664
|
+
/** The body as UTF-8. */
|
|
665
|
+
text(): string;
|
|
666
|
+
/** The body parsed as JSON. */
|
|
667
|
+
json(): unknown;
|
|
668
|
+
}
|
|
669
|
+
/** Why `host.recipients.fetch` sent nothing, or got no answer. */
|
|
670
|
+
export declare const PLUGIN_RECIPIENT_ERROR_CODES: readonly [
|
|
671
|
+
/** The manifest declares no recipient by that id. */
|
|
672
|
+
"recipient-not-declared",
|
|
673
|
+
/** The path is not a path on the recipient's origin. */
|
|
674
|
+
"path-refused",
|
|
675
|
+
/** The method, a header, the body or the timeout is not one the host sends. */
|
|
676
|
+
"request-refused",
|
|
677
|
+
/** The disclosure names a category the recipient is not declared to receive. */
|
|
678
|
+
"personal-data-not-declared",
|
|
679
|
+
/** The disclosure names a person the plugin may not send data about. */
|
|
680
|
+
"subject-refused",
|
|
681
|
+
/** The origin's host is not an address this instance may connect to. */
|
|
682
|
+
"address-refused",
|
|
683
|
+
/** The recipient redirected to another origin, or more than five times. */
|
|
684
|
+
"redirect-refused",
|
|
685
|
+
/** No answer: the connection failed or the deadline passed. */
|
|
686
|
+
"unreachable",
|
|
687
|
+
/** The answer's body was longer than 16 MiB. */
|
|
688
|
+
"response-too-large"];
|
|
689
|
+
export type PluginRecipientErrorCode = (typeof PLUGIN_RECIPIENT_ERROR_CODES)[number];
|
|
690
|
+
/**
|
|
691
|
+
* A request to a recipient the host refused or could not complete.
|
|
692
|
+
*
|
|
693
|
+
* The message never repeats the path, a header or the body: a plugin may put
|
|
694
|
+
* a resident's name in any of them, and the error ends up in the log.
|
|
695
|
+
*/
|
|
696
|
+
export declare class PluginRecipientError extends Error {
|
|
697
|
+
readonly pluginId: string;
|
|
698
|
+
readonly recipient: string;
|
|
699
|
+
readonly code: PluginRecipientErrorCode;
|
|
700
|
+
constructor(pluginId: string, recipient: string, code: PluginRecipientErrorCode);
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* The way out to the places the manifest's `recipients` declares (ADR 0037).
|
|
704
|
+
*
|
|
705
|
+
* `fetch` reaches the declared origin of the recipient named and nothing
|
|
706
|
+
* else, through the instance's outbound address rules, and follows a
|
|
707
|
+
* redirect only within that origin. A request whose body carries personal
|
|
708
|
+
* data says so in `disclosure`, and the host records it per person before
|
|
709
|
+
* and after the send.
|
|
710
|
+
*
|
|
711
|
+
* Needs no permission: the declaration is what the board consented to.
|
|
712
|
+
* Added after this contract version shipped, like `actions`: a plugin built
|
|
713
|
+
* against a newer host than the one it is installed on must feature-detect
|
|
714
|
+
* before using it.
|
|
715
|
+
*/
|
|
716
|
+
export interface PluginRecipients {
|
|
717
|
+
fetch(id: string,
|
|
718
|
+
/** Starts with `/`, and may carry a query: `/v1/messages?beta=true`. */
|
|
719
|
+
path: string, init?: PluginRecipientRequest): Promise<PluginRecipientResponse>;
|
|
720
|
+
}
|
|
721
|
+
/**
|
|
722
|
+
* One device token, as the plugin and the board see it. Never the token.
|
|
723
|
+
*/
|
|
724
|
+
export interface DeviceTokenSummary {
|
|
725
|
+
readonly id: string;
|
|
726
|
+
/** The id of the device route it was issued for. */
|
|
727
|
+
readonly route: string;
|
|
728
|
+
/** The plugin's own name for the device, such as its screen id. */
|
|
729
|
+
readonly subject: string;
|
|
730
|
+
/** The board's name for it, such as "Entrance B, ground floor". */
|
|
731
|
+
readonly label: string;
|
|
732
|
+
readonly issuedAt: string;
|
|
733
|
+
/** Updated at most once a minute while the device calls. */
|
|
734
|
+
readonly lastUsedAt: string | null;
|
|
735
|
+
readonly revokedAt: string | null;
|
|
736
|
+
}
|
|
737
|
+
/**
|
|
738
|
+
* Device tokens for the plugin's own device routes (ADR 0031).
|
|
739
|
+
*
|
|
740
|
+
* A device token reaches one device route of this plugin, names a device and
|
|
741
|
+
* never a person, and is cut at once when revoked. The plugin issues one only
|
|
742
|
+
* on a board member's request, and the board can revoke any of them from the
|
|
743
|
+
* core's own devices screen, whatever the plugin's screen says.
|
|
744
|
+
*/
|
|
745
|
+
export interface PluginDevices {
|
|
746
|
+
/**
|
|
747
|
+
* Issues a device token, and returns it once. It is stored as a digest and
|
|
748
|
+
* cannot be read again.
|
|
749
|
+
*
|
|
750
|
+
* `request` is the one the plugin's own route received. It has to come from
|
|
751
|
+
* the web interface, not a connected app's token, from a person who holds
|
|
752
|
+
* `site:manage` at that moment; anything else is refused. `route` is the id
|
|
753
|
+
* of one of the plugin's declared device routes. `subject` is the plugin's
|
|
754
|
+
* handle on the device, 1 to 64 letters, digits, `.`, `_`, `:` or `-`, and
|
|
755
|
+
* `label` the board's name for it, at most 80 characters. A plugin holds at
|
|
756
|
+
* most 200 live tokens.
|
|
757
|
+
*/
|
|
758
|
+
issue(request: ActionRequest, options: {
|
|
759
|
+
route: string;
|
|
760
|
+
subject: string;
|
|
761
|
+
label: string;
|
|
762
|
+
}): Promise<{
|
|
763
|
+
token: string;
|
|
764
|
+
device: DeviceTokenSummary;
|
|
765
|
+
}>;
|
|
766
|
+
/** The plugin's own tokens, newest first. Revoked ones included. */
|
|
767
|
+
list(filter?: {
|
|
768
|
+
route?: string;
|
|
769
|
+
subject?: string;
|
|
770
|
+
}): Promise<readonly DeviceTokenSummary[]>;
|
|
771
|
+
/**
|
|
772
|
+
* Revokes one of the plugin's own tokens, at once. True when it was live.
|
|
773
|
+
*
|
|
774
|
+
* Pass the request when a person asked for it, so the audit log names them;
|
|
775
|
+
* without one the revocation is recorded as the plugin's.
|
|
776
|
+
*/
|
|
777
|
+
revoke(tokenId: string, request?: ActionRequest): Promise<boolean>;
|
|
778
|
+
/**
|
|
779
|
+
* Which token a request on one of the plugin's device routes came with.
|
|
780
|
+
* Throws for any other request.
|
|
781
|
+
*/
|
|
782
|
+
current(request: object): DeviceTokenSummary;
|
|
783
|
+
}
|
|
158
784
|
/**
|
|
159
785
|
* The host object a plugin's module factory receives.
|
|
160
786
|
*
|
|
@@ -191,6 +817,104 @@ export interface PluginHost {
|
|
|
191
817
|
* finding with the message deliberately withheld.
|
|
192
818
|
*/
|
|
193
819
|
actions: PluginActions;
|
|
820
|
+
/**
|
|
821
|
+
* The association's fee notices and charges, delivery receipts against them,
|
|
822
|
+
* and the events that say one was issued.
|
|
823
|
+
*
|
|
824
|
+
* Added after this contract version shipped, like `actions`: a plugin must
|
|
825
|
+
* feature-detect it (`host.finances === undefined`) before using it.
|
|
826
|
+
*/
|
|
827
|
+
finances: PluginFinances;
|
|
828
|
+
/**
|
|
829
|
+
* The website blocks this plugin declared, and their render functions.
|
|
830
|
+
*
|
|
831
|
+
* Added after this contract version shipped, like `actions`: a plugin built
|
|
832
|
+
* against a newer host than the one it is installed on must feature-detect
|
|
833
|
+
* before using it.
|
|
834
|
+
*/
|
|
835
|
+
blocks: PluginBlocks;
|
|
836
|
+
/**
|
|
837
|
+
* The instance's audit log, for what this plugin did.
|
|
838
|
+
*
|
|
839
|
+
* Added after this contract version shipped, like `actions`: a plugin built
|
|
840
|
+
* against a newer host than the one it is installed on must feature-detect
|
|
841
|
+
* before using it.
|
|
842
|
+
*/
|
|
843
|
+
audit: PluginAudit;
|
|
844
|
+
/**
|
|
845
|
+
* The extension points this plugin offers or extends (ADR 0030): a host
|
|
846
|
+
* plugin defines its points and calls the addons serving there, and an
|
|
847
|
+
* addon contributes its handler.
|
|
848
|
+
*
|
|
849
|
+
* Added after this contract version shipped, like `actions`: a plugin built
|
|
850
|
+
* against a newer host than the one it is installed on must feature-detect
|
|
851
|
+
* before using it.
|
|
852
|
+
*/
|
|
853
|
+
extensions: PluginExtensions;
|
|
854
|
+
/**
|
|
855
|
+
* The association's published content: its news, its calendar, when its
|
|
856
|
+
* bookable resources are taken, its pictures and its addresses (ADR 0032).
|
|
857
|
+
*
|
|
858
|
+
* Added after this contract version shipped, like `actions`: a plugin built
|
|
859
|
+
* against a newer host than the one it is installed on must feature-detect
|
|
860
|
+
* before using them.
|
|
861
|
+
*/
|
|
862
|
+
news: PluginNews;
|
|
863
|
+
calendar: PluginCalendar;
|
|
864
|
+
bookings: PluginBookings;
|
|
865
|
+
media: PluginMedia;
|
|
866
|
+
addresses: PluginAddresses;
|
|
867
|
+
/**
|
|
868
|
+
* The way out to the recipients this plugin declared.
|
|
869
|
+
*
|
|
870
|
+
* Added after this contract version shipped, like `actions`: a plugin built
|
|
871
|
+
* against a newer host than the one it is installed on must feature-detect
|
|
872
|
+
* before using it.
|
|
873
|
+
*/
|
|
874
|
+
recipients: PluginRecipients;
|
|
875
|
+
/**
|
|
876
|
+
* The plugin's own records: configuration it keeps under a collection and a
|
|
877
|
+
* key, and never anything about a person (ADR 0033).
|
|
878
|
+
*
|
|
879
|
+
* Added after this contract version shipped, like `actions`: a plugin built
|
|
880
|
+
* against a newer host than the one it is installed on must feature-detect
|
|
881
|
+
* before using it.
|
|
882
|
+
*/
|
|
883
|
+
records: PluginRecords;
|
|
884
|
+
/**
|
|
885
|
+
* Device tokens for the plugin's declared device routes.
|
|
886
|
+
*
|
|
887
|
+
* Added after this contract version shipped, like `actions`: a plugin built
|
|
888
|
+
* against a newer host than the one it is installed on must feature-detect
|
|
889
|
+
* before using it.
|
|
890
|
+
*/
|
|
891
|
+
devices: PluginDevices;
|
|
892
|
+
/**
|
|
893
|
+
* Installing themes, and listing the ones this plugin installed.
|
|
894
|
+
*
|
|
895
|
+
* Added after this contract version shipped. An older host refuses a
|
|
896
|
+
* manifest asking for themes:install before it loads the plugin, so a plugin
|
|
897
|
+
* that declares the permission never meets a host without this member.
|
|
898
|
+
*/
|
|
899
|
+
themes: PluginThemes;
|
|
900
|
+
/**
|
|
901
|
+
* Handing a member list to the board for review (ADR 0043).
|
|
902
|
+
*
|
|
903
|
+
* Added after this contract version shipped. An older host refuses a
|
|
904
|
+
* manifest asking for addressBook:proposeImport before it loads the plugin,
|
|
905
|
+
* so a plugin that declares the permission never meets a host without this
|
|
906
|
+
* member; checking for it is a defensive guard only.
|
|
907
|
+
*/
|
|
908
|
+
imports: PluginImports;
|
|
909
|
+
/**
|
|
910
|
+
* The plugin's licence, judged by the host (ADR 0042).
|
|
911
|
+
*
|
|
912
|
+
* Present only on a plugin whose manifest declares a `licence`, and added
|
|
913
|
+
* after this contract version shipped, so a plugin feature-detects it as it
|
|
914
|
+
* does `actions`. A paid plugin on a host without it has no way to tell a
|
|
915
|
+
* licensed instance from an unlicensed one, and should stay dormant.
|
|
916
|
+
*/
|
|
917
|
+
entitlements?: PluginEntitlements;
|
|
194
918
|
}
|
|
195
919
|
/**
|
|
196
920
|
* A host service was used before the application finished starting, or after
|
|
@@ -205,4 +929,5 @@ export declare class PluginHostUnavailableError extends Error {
|
|
|
205
929
|
readonly detail: string;
|
|
206
930
|
constructor(pluginId: string, detail: string);
|
|
207
931
|
}
|
|
932
|
+
export {};
|
|
208
933
|
//# sourceMappingURL=host.d.ts.map
|