@openbrf/plugin-sdk 0.0.0-stage → 1.2.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/LICENSE +661 -0
- package/LICENSE-EXCEPTION.md +28 -0
- package/README.md +94 -2
- 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 +42 -0
- package/dist/action-schema.d.ts.map +1 -0
- package/dist/action-schema.js +67 -0
- package/dist/action-schema.js.map +1 -0
- package/dist/actions.d.ts +287 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +68 -0
- package/dist/actions.js.map +1 -0
- package/dist/api-version.d.ts +23 -0
- package/dist/api-version.d.ts.map +1 -0
- package/dist/api-version.js +27 -0
- package/dist/api-version.js.map +1 -0
- 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 +707 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +567 -0
- package/dist/catalog.js.map +1 -0
- package/dist/define-plugin.d.ts +14 -0
- package/dist/define-plugin.d.ts.map +1 -0
- package/dist/define-plugin.js +15 -0
- package/dist/define-plugin.js.map +1 -0
- 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 +156 -0
- package/dist/findings.d.ts.map +1 -0
- package/dist/findings.js +146 -0
- package/dist/findings.js.map +1 -0
- package/dist/host.d.ts +827 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +80 -0
- package/dist/host.js.map +1 -0
- 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 +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/integrity.d.ts +38 -0
- package/dist/integrity.d.ts.map +1 -0
- package/dist/integrity.js +105 -0
- package/dist/integrity.js.map +1 -0
- 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 +1122 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +1118 -0
- package/dist/manifest.js.map +1 -0
- package/dist/module.d.ts +35 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +2 -0
- package/dist/module.js.map +1 -0
- package/dist/package-check.d.ts +66 -0
- package/dist/package-check.d.ts.map +1 -0
- package/dist/package-check.js +755 -0
- package/dist/package-check.js.map +1 -0
- package/dist/permissions.d.ts +224 -0
- package/dist/permissions.d.ts.map +1 -0
- package/dist/permissions.js +277 -0
- package/dist/permissions.js.map +1 -0
- 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 +130 -0
- package/dist/settings-schema.d.ts.map +1 -0
- package/dist/settings-schema.js +272 -0
- package/dist/settings-schema.js.map +1 -0
- package/dist/standard-schema.d.ts +43 -0
- package/dist/standard-schema.d.ts.map +1 -0
- package/dist/standard-schema.js +2 -0
- package/dist/standard-schema.js.map +1 -0
- package/package.json +55 -3
- package/src/abort-signal.ts +22 -0
- package/src/action-refusal.ts +178 -0
- package/src/action-schema.ts +89 -0
- package/src/actions.ts +344 -0
- package/src/api-version.ts +28 -0
- package/src/blocks.ts +289 -0
- package/src/catalog.ts +679 -0
- package/src/define-plugin.ts +18 -0
- package/src/entitlements.ts +150 -0
- package/src/extensions.ts +212 -0
- package/src/finances.ts +317 -0
- package/src/findings.ts +163 -0
- package/src/host.ts +894 -0
- package/src/imports.ts +135 -0
- package/src/index.ts +316 -0
- package/src/integrity.ts +125 -0
- package/src/localized-text.ts +19 -0
- package/src/manifest.ts +1412 -0
- package/src/module.ts +38 -0
- package/src/package-check.ts +894 -0
- package/src/permissions.ts +295 -0
- package/src/recipients.ts +294 -0
- package/src/records.ts +172 -0
- package/src/require-capability.ts +106 -0
- package/src/settings-schema.ts +334 -0
- package/src/standard-schema.ts +39 -0
package/dist/host.d.ts
ADDED
|
@@ -0,0 +1,827 @@
|
|
|
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";
|
|
9
|
+
import type { PluginSettingsValues } from "./settings-schema.ts";
|
|
10
|
+
/**
|
|
11
|
+
* The host services a plugin receives.
|
|
12
|
+
*
|
|
13
|
+
* Every service is present on the object whether or not the plugin declared
|
|
14
|
+
* the permission it needs; the ones it did not declare throw
|
|
15
|
+
* PluginPermissionError on use. Handing out nulls instead would push a
|
|
16
|
+
* null-check into every call site of a plugin that did declare the permission,
|
|
17
|
+
* for the sake of a case the plugin author has already ruled out by writing
|
|
18
|
+
* the manifest. `permissions` is on the object for the plugin that genuinely
|
|
19
|
+
* wants to degrade rather than fail.
|
|
20
|
+
*/
|
|
21
|
+
export declare class PluginPermissionError extends Error {
|
|
22
|
+
readonly pluginId: string;
|
|
23
|
+
readonly permission: PluginPermission;
|
|
24
|
+
constructor(pluginId: string, permission: PluginPermission);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Writes to the host's log, tagged with the plugin's id.
|
|
28
|
+
*
|
|
29
|
+
* A plugin must not reach for console: its output would be indistinguishable
|
|
30
|
+
* from the core's, and an operator reading a log needs to know which plugin
|
|
31
|
+
* produced a line before they can decide whether to disable it.
|
|
32
|
+
*/
|
|
33
|
+
export interface PluginLogger {
|
|
34
|
+
debug(message: string): void;
|
|
35
|
+
info(message: string): void;
|
|
36
|
+
warn(message: string): void;
|
|
37
|
+
error(message: string, cause?: unknown): void;
|
|
38
|
+
}
|
|
39
|
+
/** The plugin's own settings, validated against its declared settingsSchema. */
|
|
40
|
+
export interface PluginSettings {
|
|
41
|
+
/**
|
|
42
|
+
* The stored values, with declared defaults applied. Reads the current
|
|
43
|
+
* values on each call rather than caching, so a change made in the admin
|
|
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.
|
|
49
|
+
*/
|
|
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>;
|
|
65
|
+
}
|
|
66
|
+
export interface PluginMailMessage {
|
|
67
|
+
to: string;
|
|
68
|
+
subject: string;
|
|
69
|
+
/**
|
|
70
|
+
* The body, as text.
|
|
71
|
+
*
|
|
72
|
+
* Blank lines separate paragraphs; the host renders them in the house style
|
|
73
|
+
* and escapes them. There is no markup parameter, and that is the point: a
|
|
74
|
+
* message sent here leaves under the cooperative's own address and passes
|
|
75
|
+
* its DKIM signature, so a link, an image or a styled block a plugin put in
|
|
76
|
+
* it would be a link, an image or a styled block the cooperative appears to
|
|
77
|
+
* have written. A plugin that interpolates a resident's own text into a
|
|
78
|
+
* body - the ordinary case, and the one that actually happens - cannot turn
|
|
79
|
+
* it into markup from here.
|
|
80
|
+
*/
|
|
81
|
+
text: string;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Sends mail through the instance's configured SMTP server.
|
|
85
|
+
*
|
|
86
|
+
* The from address is the instance's and is not a parameter: mail from a
|
|
87
|
+
* housing cooperative's system has to be attributable to the cooperative.
|
|
88
|
+
* Requires the mail:send permission.
|
|
89
|
+
*/
|
|
90
|
+
export interface PluginMail {
|
|
91
|
+
send(message: PluginMailMessage): Promise<void>;
|
|
92
|
+
}
|
|
93
|
+
export interface PluginSmsMessage {
|
|
94
|
+
/** The recipient's number in E.164 form. */
|
|
95
|
+
to: string;
|
|
96
|
+
/**
|
|
97
|
+
* The whole message, as text.
|
|
98
|
+
*
|
|
99
|
+
* SMS carries no markup, no subject and no alternative part, so what is
|
|
100
|
+
* written here is literally what the recipient reads. Its length is the
|
|
101
|
+
* plugin's own decision and is not bounded by the host: a text message is
|
|
102
|
+
* billed by length, and what a message may cost the association is the
|
|
103
|
+
* plugin's business to keep in hand rather than something a silent
|
|
104
|
+
* truncation can settle.
|
|
105
|
+
*/
|
|
106
|
+
text: string;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Sends text messages through the instance's configured SMS provider.
|
|
110
|
+
*
|
|
111
|
+
* The sender the message presents is the instance's and is not a parameter,
|
|
112
|
+
* for the reason the mail from address is not one: a text message from a
|
|
113
|
+
* housing cooperative's system has to be attributable to the cooperative.
|
|
114
|
+
*
|
|
115
|
+
* An instance with no provider configured cannot send at all, and the send
|
|
116
|
+
* fails rather than being dropped. Having no provider is the ordinary state of
|
|
117
|
+
* a housing cooperative that only ever mails its members, so a plugin whose
|
|
118
|
+
* work depends on SMS should read `permissions` and degrade, or treat the
|
|
119
|
+
* failure as the answer. Requires the sms:send permission.
|
|
120
|
+
*/
|
|
121
|
+
export interface PluginSms {
|
|
122
|
+
send(message: PluginSmsMessage): Promise<void>;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Background work. Queue names are namespaced with the plugin's id by the
|
|
126
|
+
* host, so two plugins cannot collide on a name and no plugin can subscribe to
|
|
127
|
+
* a core queue. A name is 1-64 letters, digits, `_`, `.` or `-`; any other
|
|
128
|
+
* name is refused with a RangeError. Requires the jobs:schedule permission.
|
|
129
|
+
*/
|
|
130
|
+
export interface PluginJobs {
|
|
131
|
+
work<Data extends object>(name: string, handler: (data: Data) => Promise<void> | void): Promise<void>;
|
|
132
|
+
send<Data extends object>(name: string, data: Data): Promise<void>;
|
|
133
|
+
sendAt<Data extends object>(name: string, data: Data, runAt: Date): Promise<void>;
|
|
134
|
+
schedule<Data extends object>(name: string, cron: string, data: Data): Promise<void>;
|
|
135
|
+
}
|
|
136
|
+
export interface PluginApartment {
|
|
137
|
+
id: string;
|
|
138
|
+
number: string;
|
|
139
|
+
floor: number | null;
|
|
140
|
+
address: {
|
|
141
|
+
id: string;
|
|
142
|
+
street: string;
|
|
143
|
+
number: string;
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
export interface PluginResident {
|
|
147
|
+
personId: string;
|
|
148
|
+
name: string;
|
|
149
|
+
/** MEMBER holds the tenant-ownership; RESIDENT occupies without holding it. */
|
|
150
|
+
role: "MEMBER" | "RESIDENT";
|
|
151
|
+
apartment: PluginApartment | null;
|
|
152
|
+
movedInOn: string | null;
|
|
153
|
+
movedOutOn: string | null;
|
|
154
|
+
/** Present only with the addressBook:readContact permission. */
|
|
155
|
+
email?: string | null;
|
|
156
|
+
/** Present only with the addressBook:readContact permission. */
|
|
157
|
+
phone?: string | null;
|
|
158
|
+
}
|
|
159
|
+
export interface PluginOccupancySummary {
|
|
160
|
+
apartments: number;
|
|
161
|
+
/** Distinct persons with a current residency. */
|
|
162
|
+
residents: number;
|
|
163
|
+
/** Distinct persons holding a current tenant-ownership. */
|
|
164
|
+
members: number;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Reading the register, scoped to what the plugin declared.
|
|
168
|
+
*
|
|
169
|
+
* Three rules hold on every method here regardless of permission, because
|
|
170
|
+
* they are the product's own (plan section 4.4) and a plugin is not a reason
|
|
171
|
+
* to relax them: a person with protected personal data never appears, a
|
|
172
|
+
* personal identity number is never returned, and nothing is writable.
|
|
173
|
+
* Requires addressBook:read; the contact fields additionally require
|
|
174
|
+
* addressBook:readContact.
|
|
175
|
+
*/
|
|
176
|
+
export interface PluginAddressBook {
|
|
177
|
+
apartments(): Promise<PluginApartment[]>;
|
|
178
|
+
/** Current residencies only. Moved-out rows are not plugin business. */
|
|
179
|
+
residents(): Promise<PluginResident[]>;
|
|
180
|
+
summary(): Promise<PluginOccupancySummary>;
|
|
181
|
+
}
|
|
182
|
+
/** What a theme install is told about the package besides its bytes. */
|
|
183
|
+
export interface PluginThemeInstallOptions {
|
|
184
|
+
/**
|
|
185
|
+
* The package's sha512, as whoever published it stated it: `sha512-<base64>`
|
|
186
|
+
* or 128 hex characters, the two spellings a catalog entry may use. The
|
|
187
|
+
* bytes are checked against it before anything is unpacked.
|
|
188
|
+
*/
|
|
189
|
+
sha512: string;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* A finding the install lint reported without refusing the theme: a token or
|
|
193
|
+
* a manifest field this core does not know, which the token contract says to
|
|
194
|
+
* ignore rather than refuse. Rule codes and numbers, never prose.
|
|
195
|
+
*/
|
|
196
|
+
export interface PluginThemeInstallWarning {
|
|
197
|
+
rule: string;
|
|
198
|
+
detail: Readonly<Record<string, string | number | boolean>>;
|
|
199
|
+
}
|
|
200
|
+
export interface PluginThemeInstallResult {
|
|
201
|
+
/** The theme's id, from its manifest. */
|
|
202
|
+
id: string;
|
|
203
|
+
version: string;
|
|
204
|
+
warnings: readonly PluginThemeInstallWarning[];
|
|
205
|
+
}
|
|
206
|
+
/** A theme this plugin installed, as `host.themes.list` returns it. */
|
|
207
|
+
export interface PluginInstalledTheme {
|
|
208
|
+
id: string;
|
|
209
|
+
version: string;
|
|
210
|
+
/** ISO 8601. When the version now installed was installed first. */
|
|
211
|
+
installedAt: string;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Installing themes on the instance (ADR 0046). Requires themes:install.
|
|
215
|
+
*
|
|
216
|
+
* A theme a plugin hands over takes the path a theme from the catalog takes:
|
|
217
|
+
* its sha512 checked before anything is unpacked, the package read and held to
|
|
218
|
+
* the same install lint, the statutory register contrast included, and the
|
|
219
|
+
* files and the row written together under the same lock per theme id. A
|
|
220
|
+
* package the lint refuses is refused here with the same findings, and what
|
|
221
|
+
* the instance already had stays as it was.
|
|
222
|
+
*
|
|
223
|
+
* `install` takes the request the plugin's own route received and installs as
|
|
224
|
+
* the person behind it, who must hold association:manage, the capability the
|
|
225
|
+
* theme screen requires. A request a connected app's token reached is refused,
|
|
226
|
+
* and a background job has no request, so a plugin installs a theme only when
|
|
227
|
+
* an administrator asks it to.
|
|
228
|
+
*
|
|
229
|
+
* A plugin installs over a theme it installed itself and over nothing else:
|
|
230
|
+
* not the catalog's, not one composed on the instance, not another plugin's.
|
|
231
|
+
* It installs and nothing else. Activating and removing stay on the theme
|
|
232
|
+
* screen, and a theme stays installed when the plugin is removed.
|
|
233
|
+
*
|
|
234
|
+
* A refusal is thrown as an error carrying a `reason` code and, for
|
|
235
|
+
* `lint-failed`, the `findings`. Let it propagate from a route and the client
|
|
236
|
+
* is answered with its status, reason and findings, as the theme screen is.
|
|
237
|
+
*/
|
|
238
|
+
export interface PluginThemes {
|
|
239
|
+
install(request: ActionRequest, archive: Uint8Array, options: PluginThemeInstallOptions): Promise<PluginThemeInstallResult>;
|
|
240
|
+
/** The themes this plugin installed, so it can offer an update. */
|
|
241
|
+
list(): Promise<PluginInstalledTheme[]>;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Who a news item or an event is for: the members, or anyone at all.
|
|
245
|
+
*
|
|
246
|
+
* On every item the content services return, because the host cannot know
|
|
247
|
+
* where the plugin puts it. A screen inside the building may show a members'
|
|
248
|
+
* item and a public calendar feed should not; which of the two the plugin is
|
|
249
|
+
* doing is what its consent screen tells the board (ADR 0032).
|
|
250
|
+
*/
|
|
251
|
+
export type PluginContentAudience = "anyone" | "members";
|
|
252
|
+
/** One published news item, as a plugin reads it. */
|
|
253
|
+
export interface PluginNewsItem {
|
|
254
|
+
readonly id: string;
|
|
255
|
+
readonly title: string;
|
|
256
|
+
/** The body's text, one string per paragraph or heading, in order. */
|
|
257
|
+
readonly paragraphs: readonly string[];
|
|
258
|
+
/**
|
|
259
|
+
* The pictures the body shows, in order.
|
|
260
|
+
*
|
|
261
|
+
* Empty while a news body holds prose only, which is all the core's news
|
|
262
|
+
* editor writes and all the website shows of one.
|
|
263
|
+
*/
|
|
264
|
+
readonly pictures: readonly {
|
|
265
|
+
mediaFileId: string;
|
|
266
|
+
alt: string;
|
|
267
|
+
}[];
|
|
268
|
+
readonly audience: PluginContentAudience;
|
|
269
|
+
/** ISO 8601 instant. */
|
|
270
|
+
readonly publishedAt: string;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* The association's published news. Requires the news:read permission.
|
|
274
|
+
*
|
|
275
|
+
* What the website publishes and nothing more: a draft, an item taken down, a
|
|
276
|
+
* deleted one and one the board wrote to Styrelsen or Administratörer in the
|
|
277
|
+
* feed are absent. Never an author, a comment, a like or who has read an item.
|
|
278
|
+
*
|
|
279
|
+
* To a plugin that declares a device route, an item whose title, paragraphs or
|
|
280
|
+
* picture alt texts name somebody the register holds, one of their email
|
|
281
|
+
* addresses or phone numbers, or an apartment number is absent as well, and
|
|
282
|
+
* the read goes on to older items to make up the count, as far back as the
|
|
283
|
+
* newest 500 published items (ADR 0032).
|
|
284
|
+
*/
|
|
285
|
+
export interface PluginNews {
|
|
286
|
+
/**
|
|
287
|
+
* Published items, newest first.
|
|
288
|
+
*
|
|
289
|
+
* `limit` is 1 to 50 and defaults to 50. `since` is an ISO 8601 instant and
|
|
290
|
+
* keeps the items published at or after it. `audience` keeps only the items
|
|
291
|
+
* for that audience; without it both are returned, each saying which it is.
|
|
292
|
+
* A value outside those bounds is refused with a RangeError.
|
|
293
|
+
*/
|
|
294
|
+
published(options?: {
|
|
295
|
+
audience?: PluginContentAudience;
|
|
296
|
+
limit?: number;
|
|
297
|
+
since?: string;
|
|
298
|
+
}): Promise<readonly PluginNewsItem[]>;
|
|
299
|
+
}
|
|
300
|
+
/** One occurrence of a published event. */
|
|
301
|
+
export interface PluginOccurrence {
|
|
302
|
+
readonly eventId: string;
|
|
303
|
+
readonly occurrenceId: string;
|
|
304
|
+
/** The board's own words, as written and never translated. */
|
|
305
|
+
readonly title: string;
|
|
306
|
+
readonly description: string | null;
|
|
307
|
+
readonly category: string | null;
|
|
308
|
+
readonly location: string | null;
|
|
309
|
+
/** ISO 8601 instant. */
|
|
310
|
+
readonly startsAt: string;
|
|
311
|
+
/** ISO 8601 instant. */
|
|
312
|
+
readonly endsAt: string;
|
|
313
|
+
/** Whether the board has called this one occurrence off. */
|
|
314
|
+
readonly calledOff: boolean;
|
|
315
|
+
/**
|
|
316
|
+
* Places left when the event takes sign-ups with a limit, and null when it
|
|
317
|
+
* takes none or has no limit. Never who took them.
|
|
318
|
+
*/
|
|
319
|
+
readonly placesLeft: number | null;
|
|
320
|
+
readonly audience: PluginContentAudience;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* The notice of a general meeting the board has called.
|
|
324
|
+
*
|
|
325
|
+
* What the notice states (EFL 6 kap. 22 §): the time, the place, how to take
|
|
326
|
+
* part digitally and the matters on the agenda. Never who was summoned, who
|
|
327
|
+
* attended, the voting register or a proxy.
|
|
328
|
+
*/
|
|
329
|
+
export interface PluginMeetingNotice {
|
|
330
|
+
readonly meetingId: string;
|
|
331
|
+
readonly kind: "ordinary" | "extraordinary";
|
|
332
|
+
/** ISO 8601 instant. */
|
|
333
|
+
readonly startsAt: string;
|
|
334
|
+
readonly place: string;
|
|
335
|
+
readonly digitalParticipation: string | null;
|
|
336
|
+
readonly agenda: readonly {
|
|
337
|
+
position: number;
|
|
338
|
+
title: string;
|
|
339
|
+
}[];
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* The association's calendar. Requires the calendar:read permission.
|
|
343
|
+
*
|
|
344
|
+
* Published events only: a series that is not published is absent, and an
|
|
345
|
+
* occurrence the board called off is present and says so.
|
|
346
|
+
*
|
|
347
|
+
* To a plugin that declares a device route, an event whose title,
|
|
348
|
+
* description, category or location names somebody the register holds or an
|
|
349
|
+
* apartment number is absent with every occurrence, and a notice whose place,
|
|
350
|
+
* digital participation or any agenda title does is absent whole (ADR 0032).
|
|
351
|
+
*/
|
|
352
|
+
export interface PluginCalendar {
|
|
353
|
+
/**
|
|
354
|
+
* Occurrences starting in [from, to), soonest first.
|
|
355
|
+
*
|
|
356
|
+
* `from` and `to` are ISO 8601 instants at most 92 days apart, and
|
|
357
|
+
* `audience` works as it does for the news. A range that is not one is
|
|
358
|
+
* refused with a RangeError.
|
|
359
|
+
*/
|
|
360
|
+
occurrences(range: {
|
|
361
|
+
from: string;
|
|
362
|
+
to: string;
|
|
363
|
+
audience?: PluginContentAudience;
|
|
364
|
+
}): Promise<readonly PluginOccurrence[]>;
|
|
365
|
+
/**
|
|
366
|
+
* Notices of the general meetings called and not yet held, soonest first.
|
|
367
|
+
*
|
|
368
|
+
* A notice summons the members, so every one of them is for the members.
|
|
369
|
+
*/
|
|
370
|
+
meetingNotices(): Promise<readonly PluginMeetingNotice[]>;
|
|
371
|
+
}
|
|
372
|
+
/** A bookable resource the house offers, and how it is booked. */
|
|
373
|
+
export interface PluginBookableResource {
|
|
374
|
+
readonly id: string;
|
|
375
|
+
/** The board's own name for it, as written. */
|
|
376
|
+
readonly name: string;
|
|
377
|
+
readonly mode: "timeSlots" | "wholeDay" | "dateRange";
|
|
378
|
+
/** The slot length in the time-slot mode, and null otherwise. */
|
|
379
|
+
readonly slotMinutes: number | null;
|
|
380
|
+
/** Minutes after local midnight the resource opens, in the time-slot mode. */
|
|
381
|
+
readonly opensAtMinute: number | null;
|
|
382
|
+
/** Minutes after local midnight the resource closes, in the time-slot mode. */
|
|
383
|
+
readonly closesAtMinute: number | null;
|
|
384
|
+
}
|
|
385
|
+
/** A period a resource is taken. Never by whom. */
|
|
386
|
+
export interface PluginBusyInterval {
|
|
387
|
+
readonly resourceId: string;
|
|
388
|
+
/** ISO 8601 instant. */
|
|
389
|
+
readonly start: string;
|
|
390
|
+
/** ISO 8601 instant. */
|
|
391
|
+
readonly end: string;
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Free and busy for the house's bookable resources. Requires the
|
|
395
|
+
* bookings:readAvailability permission.
|
|
396
|
+
*
|
|
397
|
+
* Less than a resident's own booking screen shows: when a resource is taken,
|
|
398
|
+
* and nothing about who took it - no booker, no apartment and no booking's
|
|
399
|
+
* identifier.
|
|
400
|
+
*
|
|
401
|
+
* To a plugin that declares a device route, a resource whose name names
|
|
402
|
+
* somebody the register holds or an apartment number is absent from both
|
|
403
|
+
* reads, and `busy` starts no earlier than the moment of the call, so no
|
|
404
|
+
* booking that has ended is in it (ADR 0032).
|
|
405
|
+
*/
|
|
406
|
+
export interface PluginBookings {
|
|
407
|
+
/** The resources open for booking, by name. A withdrawn one is absent. */
|
|
408
|
+
resources(): Promise<readonly PluginBookableResource[]>;
|
|
409
|
+
/**
|
|
410
|
+
* When each resource is taken in [from, to), per resource and in order.
|
|
411
|
+
*
|
|
412
|
+
* `from` and `to` are ISO 8601 instants at most 31 days apart, refused with
|
|
413
|
+
* a RangeError otherwise. Bookings that overlap or touch are merged into one
|
|
414
|
+
* interval, so a run of slots cannot be read as one household's habits. A
|
|
415
|
+
* resource id that is not an offered resource's answers nothing.
|
|
416
|
+
*/
|
|
417
|
+
busy(range: {
|
|
418
|
+
from: string;
|
|
419
|
+
to: string;
|
|
420
|
+
resourceIds?: readonly string[];
|
|
421
|
+
}): Promise<readonly PluginBusyInterval[]>;
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* The bytes of a picture, as a web stream of `Uint8Array` chunks.
|
|
425
|
+
*
|
|
426
|
+
* The host hands a real `ReadableStream`. This package compiles against the
|
|
427
|
+
* language alone and cannot name the platform's type, so it is looked up in the
|
|
428
|
+
* plugin's own program, as the block's abort signal is: where that has a
|
|
429
|
+
* `ReadableStream`, from the DOM library or from Node's types, this is it, and
|
|
430
|
+
* the stream can go into a `Response` or `Readable.fromWeb` as it is. Where it
|
|
431
|
+
* has none, this is the part of one a plugin can read without them.
|
|
432
|
+
*/
|
|
433
|
+
export type PluginMediaStream = typeof globalThis extends {
|
|
434
|
+
readonly ReadableStream: {
|
|
435
|
+
readonly prototype: infer Stream;
|
|
436
|
+
};
|
|
437
|
+
} ? Stream : PluginMediaStreamShape;
|
|
438
|
+
/** What every `ReadableStream` has, for a program without the platform's types. */
|
|
439
|
+
interface PluginMediaStreamShape {
|
|
440
|
+
readonly locked: boolean;
|
|
441
|
+
cancel(reason?: unknown): Promise<void>;
|
|
442
|
+
getReader(): {
|
|
443
|
+
read(): Promise<{
|
|
444
|
+
done: false;
|
|
445
|
+
value: Uint8Array;
|
|
446
|
+
} | {
|
|
447
|
+
done: true;
|
|
448
|
+
value?: undefined;
|
|
449
|
+
}>;
|
|
450
|
+
cancel(reason?: unknown): Promise<void>;
|
|
451
|
+
releaseLock(): void;
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* A stored picture the plugin opened.
|
|
456
|
+
*
|
|
457
|
+
* What a reply serving it needs and nothing else: not the name it was uploaded
|
|
458
|
+
* under, which is somebody's own words, and not who uploaded it.
|
|
459
|
+
*/
|
|
460
|
+
export interface PluginMediaFile {
|
|
461
|
+
/** Identified from the bytes when they were uploaded: an image type. */
|
|
462
|
+
readonly contentType: string;
|
|
463
|
+
/** The size of the picture as uploaded, in bytes. */
|
|
464
|
+
readonly byteSize: number;
|
|
465
|
+
/**
|
|
466
|
+
* A keyed hash of the bytes, hex encoded. The same value the core serves the
|
|
467
|
+
* picture's entity tag from, so a plugin may use it as one too.
|
|
468
|
+
*/
|
|
469
|
+
readonly checksum: string;
|
|
470
|
+
/**
|
|
471
|
+
* The picture's bytes. Read it to the end or cancel it: the host holds the
|
|
472
|
+
* stored file open until one or the other.
|
|
473
|
+
*/
|
|
474
|
+
readonly stream: PluginMediaStream;
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* The association's stored pictures. Requires the media:read permission.
|
|
478
|
+
*
|
|
479
|
+
* Only a picture held for anyone or for the members whose upload declared that
|
|
480
|
+
* it shows no identifiable person (ADR 0032). A photograph of people needs a
|
|
481
|
+
* publication consent, and the consent the core records is for the website,
|
|
482
|
+
* not for wherever a plugin puts the picture. Nothing here lists or finds a
|
|
483
|
+
* picture: a plugin opens one whose id it already holds, such as one the board
|
|
484
|
+
* picked in the plugin's own view.
|
|
485
|
+
*/
|
|
486
|
+
export interface PluginMedia {
|
|
487
|
+
/**
|
|
488
|
+
* Opens one picture.
|
|
489
|
+
*
|
|
490
|
+
* Null when the file does not exist and when it is not one a plugin may
|
|
491
|
+
* read, the two alike, so the answer says nothing about a file the plugin
|
|
492
|
+
* may not see. A `mediaFileId` that is not a string is refused with a
|
|
493
|
+
* RangeError.
|
|
494
|
+
*/
|
|
495
|
+
open(mediaFileId: string): Promise<PluginMediaFile | null>;
|
|
496
|
+
}
|
|
497
|
+
/** One of the association's addresses: an entrance, and nobody behind it. */
|
|
498
|
+
export interface PluginAddress {
|
|
499
|
+
readonly id: string;
|
|
500
|
+
readonly street: string;
|
|
501
|
+
/** The street number, as written: "12", "12 B". */
|
|
502
|
+
readonly number: string;
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* The association's addresses. Requires the addresses:read permission.
|
|
506
|
+
*
|
|
507
|
+
* A fact about the building: never an apartment, a resident or a member, which
|
|
508
|
+
* is what addressBook:read is for.
|
|
509
|
+
*/
|
|
510
|
+
export interface PluginAddresses {
|
|
511
|
+
/** Every address, in the order the core's own screens show them. */
|
|
512
|
+
list(): Promise<readonly PluginAddress[]>;
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* What a request to a recipient sends as personal data, and about whom.
|
|
516
|
+
*
|
|
517
|
+
* The host writes one audit entry per subject before anything is sent, and
|
|
518
|
+
* a second after, with the outcome; each reaches that person's data subject
|
|
519
|
+
* access report. A disclosure that names nobody, such as text a board member
|
|
520
|
+
* typed, is recorded once with no person.
|
|
521
|
+
*/
|
|
522
|
+
export interface PluginDisclosure {
|
|
523
|
+
/**
|
|
524
|
+
* The categories the body carries. One or more, each among those the
|
|
525
|
+
* recipient's declaration says it receives, or nothing is sent.
|
|
526
|
+
*/
|
|
527
|
+
personalData: readonly PluginPersonalDataCategory[];
|
|
528
|
+
/**
|
|
529
|
+
* The ids of the persons the body is about, at most 100. Each must be a
|
|
530
|
+
* person the host would hand the plugin: a person with protected personal
|
|
531
|
+
* data, one under a restriction of processing, or an id the register does
|
|
532
|
+
* not hold refuses the request, and the error does not say which.
|
|
533
|
+
*/
|
|
534
|
+
subjects: readonly string[];
|
|
535
|
+
}
|
|
536
|
+
export interface PluginRecipientRequest {
|
|
537
|
+
/** `GET` when left out. */
|
|
538
|
+
method?: "GET" | "HEAD" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
539
|
+
/**
|
|
540
|
+
* Sent as given, apart from the ones the host writes: `host`,
|
|
541
|
+
* `content-length`, `transfer-encoding`, `connection` and the other
|
|
542
|
+
* hop-by-hop headers are refused.
|
|
543
|
+
*/
|
|
544
|
+
headers?: Readonly<Record<string, string>>;
|
|
545
|
+
/** At most 16 MiB. */
|
|
546
|
+
body?: string | Uint8Array;
|
|
547
|
+
/**
|
|
548
|
+
* Required whenever the body carries personal data. A request without it
|
|
549
|
+
* is recorded nowhere, which is right for fetching a list of models and
|
|
550
|
+
* wrong for anything about a person.
|
|
551
|
+
*/
|
|
552
|
+
disclosure?: PluginDisclosure;
|
|
553
|
+
/**
|
|
554
|
+
* The whole exchange, name lookup and redirects included. 60 seconds when
|
|
555
|
+
* left out, at most 300.
|
|
556
|
+
*/
|
|
557
|
+
timeoutMs?: number;
|
|
558
|
+
}
|
|
559
|
+
export interface PluginRecipientResponse {
|
|
560
|
+
/** Whatever the recipient answered, 4xx and 5xx included. */
|
|
561
|
+
status: number;
|
|
562
|
+
/** Lowercased names; a repeated header is joined with ", ". */
|
|
563
|
+
headers: Readonly<Record<string, string>>;
|
|
564
|
+
/** The whole body, at most 16 MiB. */
|
|
565
|
+
body: Uint8Array;
|
|
566
|
+
/** The body as UTF-8. */
|
|
567
|
+
text(): string;
|
|
568
|
+
/** The body parsed as JSON. */
|
|
569
|
+
json(): unknown;
|
|
570
|
+
}
|
|
571
|
+
/** Why `host.recipients.fetch` sent nothing, or got no answer. */
|
|
572
|
+
export declare const PLUGIN_RECIPIENT_ERROR_CODES: readonly [
|
|
573
|
+
/** The manifest declares no recipient by that id. */
|
|
574
|
+
"recipient-not-declared",
|
|
575
|
+
/** The path is not a path on the recipient's origin. */
|
|
576
|
+
"path-refused",
|
|
577
|
+
/** The method, a header, the body or the timeout is not one the host sends. */
|
|
578
|
+
"request-refused",
|
|
579
|
+
/** The disclosure names a category the recipient is not declared to receive. */
|
|
580
|
+
"personal-data-not-declared",
|
|
581
|
+
/** The disclosure names a person the plugin may not send data about. */
|
|
582
|
+
"subject-refused",
|
|
583
|
+
/** The origin's host is not an address this instance may connect to. */
|
|
584
|
+
"address-refused",
|
|
585
|
+
/** The recipient redirected to another origin, or more than five times. */
|
|
586
|
+
"redirect-refused",
|
|
587
|
+
/** No answer: the connection failed or the deadline passed. */
|
|
588
|
+
"unreachable",
|
|
589
|
+
/** The answer's body was longer than 16 MiB. */
|
|
590
|
+
"response-too-large"];
|
|
591
|
+
export type PluginRecipientErrorCode = (typeof PLUGIN_RECIPIENT_ERROR_CODES)[number];
|
|
592
|
+
/**
|
|
593
|
+
* A request to a recipient the host refused or could not complete.
|
|
594
|
+
*
|
|
595
|
+
* The message never repeats the path, a header or the body: a plugin may put
|
|
596
|
+
* a resident's name in any of them, and the error ends up in the log.
|
|
597
|
+
*/
|
|
598
|
+
export declare class PluginRecipientError extends Error {
|
|
599
|
+
readonly pluginId: string;
|
|
600
|
+
readonly recipient: string;
|
|
601
|
+
readonly code: PluginRecipientErrorCode;
|
|
602
|
+
constructor(pluginId: string, recipient: string, code: PluginRecipientErrorCode);
|
|
603
|
+
}
|
|
604
|
+
/**
|
|
605
|
+
* The way out to the places the manifest's `recipients` declares (ADR 0037).
|
|
606
|
+
*
|
|
607
|
+
* `fetch` reaches the declared origin of the recipient named and nothing
|
|
608
|
+
* else, through the instance's outbound address rules, and follows a
|
|
609
|
+
* redirect only within that origin. A request whose body carries personal
|
|
610
|
+
* data says so in `disclosure`, and the host records it per person before
|
|
611
|
+
* and after the send.
|
|
612
|
+
*
|
|
613
|
+
* Needs no permission: the declaration is what the board consented to.
|
|
614
|
+
* Added after this contract version shipped, like `actions`: a plugin built
|
|
615
|
+
* against a newer host than the one it is installed on must feature-detect
|
|
616
|
+
* before using it.
|
|
617
|
+
*/
|
|
618
|
+
export interface PluginRecipients {
|
|
619
|
+
fetch(id: string,
|
|
620
|
+
/** Starts with `/`, and may carry a query: `/v1/messages?beta=true`. */
|
|
621
|
+
path: string, init?: PluginRecipientRequest): Promise<PluginRecipientResponse>;
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* One device token, as the plugin and the board see it. Never the token.
|
|
625
|
+
*/
|
|
626
|
+
export interface DeviceTokenSummary {
|
|
627
|
+
readonly id: string;
|
|
628
|
+
/** The id of the device route it was issued for. */
|
|
629
|
+
readonly route: string;
|
|
630
|
+
/** The plugin's own name for the device, such as its screen id. */
|
|
631
|
+
readonly subject: string;
|
|
632
|
+
/** The board's name for it, such as "Entrance B, ground floor". */
|
|
633
|
+
readonly label: string;
|
|
634
|
+
readonly issuedAt: string;
|
|
635
|
+
/** Updated at most once a minute while the device calls. */
|
|
636
|
+
readonly lastUsedAt: string | null;
|
|
637
|
+
readonly revokedAt: string | null;
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* Device tokens for the plugin's own device routes (ADR 0031).
|
|
641
|
+
*
|
|
642
|
+
* A device token reaches one device route of this plugin, names a device and
|
|
643
|
+
* never a person, and is cut at once when revoked. The plugin issues one only
|
|
644
|
+
* on a board member's request, and the board can revoke any of them from the
|
|
645
|
+
* core's own devices screen, whatever the plugin's screen says.
|
|
646
|
+
*/
|
|
647
|
+
export interface PluginDevices {
|
|
648
|
+
/**
|
|
649
|
+
* Issues a device token, and returns it once. It is stored as a digest and
|
|
650
|
+
* cannot be read again.
|
|
651
|
+
*
|
|
652
|
+
* `request` is the one the plugin's own route received. It has to come from
|
|
653
|
+
* the web interface, not a connected app's token, from a person who holds
|
|
654
|
+
* `site:manage` at that moment; anything else is refused. `route` is the id
|
|
655
|
+
* of one of the plugin's declared device routes. `subject` is the plugin's
|
|
656
|
+
* handle on the device, 1 to 64 letters, digits, `.`, `_`, `:` or `-`, and
|
|
657
|
+
* `label` the board's name for it, at most 80 characters. A plugin holds at
|
|
658
|
+
* most 200 live tokens.
|
|
659
|
+
*/
|
|
660
|
+
issue(request: ActionRequest, options: {
|
|
661
|
+
route: string;
|
|
662
|
+
subject: string;
|
|
663
|
+
label: string;
|
|
664
|
+
}): Promise<{
|
|
665
|
+
token: string;
|
|
666
|
+
device: DeviceTokenSummary;
|
|
667
|
+
}>;
|
|
668
|
+
/** The plugin's own tokens, newest first. Revoked ones included. */
|
|
669
|
+
list(filter?: {
|
|
670
|
+
route?: string;
|
|
671
|
+
subject?: string;
|
|
672
|
+
}): Promise<readonly DeviceTokenSummary[]>;
|
|
673
|
+
/**
|
|
674
|
+
* Revokes one of the plugin's own tokens, at once. True when it was live.
|
|
675
|
+
*
|
|
676
|
+
* Pass the request when a person asked for it, so the audit log names them;
|
|
677
|
+
* without one the revocation is recorded as the plugin's.
|
|
678
|
+
*/
|
|
679
|
+
revoke(tokenId: string, request?: ActionRequest): Promise<boolean>;
|
|
680
|
+
/**
|
|
681
|
+
* Which token a request on one of the plugin's device routes came with.
|
|
682
|
+
* Throws for any other request.
|
|
683
|
+
*/
|
|
684
|
+
current(request: object): DeviceTokenSummary;
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* The host object a plugin's module factory receives.
|
|
688
|
+
*
|
|
689
|
+
* It is late-bound: the services behind it are the application's own, and the
|
|
690
|
+
* application is built after the factory has run. Every member below is
|
|
691
|
+
* therefore usable from a lifecycle hook (`onModuleInit` onwards), a guard or
|
|
692
|
+
* a request handler, and not from a provider's constructor - which is where
|
|
693
|
+
* NestJS asks for work to be done in any case. A call made too early throws
|
|
694
|
+
* rather than reading a half-built application.
|
|
695
|
+
*
|
|
696
|
+
* A plugin the board has switched off keeps its object, and every service on
|
|
697
|
+
* it refuses. Disabling has to bite immediately, and a plugin whose own timer
|
|
698
|
+
* outlived the switch must not still be reading the register through it.
|
|
699
|
+
*/
|
|
700
|
+
export interface PluginHost {
|
|
701
|
+
/** The plugin's own id, as declared in its manifest. */
|
|
702
|
+
id: string;
|
|
703
|
+
/** What the manifest declared and the board consented to. */
|
|
704
|
+
permissions: readonly PluginPermission[];
|
|
705
|
+
logger: PluginLogger;
|
|
706
|
+
settings: PluginSettings;
|
|
707
|
+
mail: PluginMail;
|
|
708
|
+
sms: PluginSms;
|
|
709
|
+
jobs: PluginJobs;
|
|
710
|
+
addressBook: PluginAddressBook;
|
|
711
|
+
/**
|
|
712
|
+
* The actions this plugin declared, and dispatch for every action it may
|
|
713
|
+
* reach.
|
|
714
|
+
*
|
|
715
|
+
* Added after this contract version shipped, so a plugin built against a
|
|
716
|
+
* newer host than the one it is installed on must feature-detect before
|
|
717
|
+
* using it - `isSupportedApiVersion` cannot see a member added to an
|
|
718
|
+
* interface, and the failure would otherwise surface as a load-failed
|
|
719
|
+
* finding with the message deliberately withheld.
|
|
720
|
+
*/
|
|
721
|
+
actions: PluginActions;
|
|
722
|
+
/**
|
|
723
|
+
* The association's fee notices and charges, delivery receipts against them,
|
|
724
|
+
* and the events that say one was issued.
|
|
725
|
+
*
|
|
726
|
+
* Added after this contract version shipped, like `actions`: a plugin must
|
|
727
|
+
* feature-detect it (`host.finances === undefined`) before using it.
|
|
728
|
+
*/
|
|
729
|
+
finances: PluginFinances;
|
|
730
|
+
/**
|
|
731
|
+
* The website blocks this plugin declared, and their render functions.
|
|
732
|
+
*
|
|
733
|
+
* Added after this contract version shipped, like `actions`: a plugin built
|
|
734
|
+
* against a newer host than the one it is installed on must feature-detect
|
|
735
|
+
* before using it.
|
|
736
|
+
*/
|
|
737
|
+
blocks: PluginBlocks;
|
|
738
|
+
/**
|
|
739
|
+
* The extension points this plugin offers or extends (ADR 0030): a host
|
|
740
|
+
* plugin defines its points and calls the addons serving there, and an
|
|
741
|
+
* addon contributes its handler.
|
|
742
|
+
*
|
|
743
|
+
* Added after this contract version shipped, like `actions`: a plugin built
|
|
744
|
+
* against a newer host than the one it is installed on must feature-detect
|
|
745
|
+
* before using it.
|
|
746
|
+
*/
|
|
747
|
+
extensions: PluginExtensions;
|
|
748
|
+
/**
|
|
749
|
+
* The association's published content: its news, its calendar, when its
|
|
750
|
+
* bookable resources are taken, its pictures and its addresses (ADR 0032).
|
|
751
|
+
*
|
|
752
|
+
* Added after this contract version shipped, like `actions`: a plugin built
|
|
753
|
+
* against a newer host than the one it is installed on must feature-detect
|
|
754
|
+
* before using them.
|
|
755
|
+
*/
|
|
756
|
+
news: PluginNews;
|
|
757
|
+
calendar: PluginCalendar;
|
|
758
|
+
bookings: PluginBookings;
|
|
759
|
+
media: PluginMedia;
|
|
760
|
+
addresses: PluginAddresses;
|
|
761
|
+
/**
|
|
762
|
+
* The way out to the recipients this plugin declared.
|
|
763
|
+
*
|
|
764
|
+
* Added after this contract version shipped, like `actions`: a plugin built
|
|
765
|
+
* against a newer host than the one it is installed on must feature-detect
|
|
766
|
+
* before using it.
|
|
767
|
+
*/
|
|
768
|
+
recipients: PluginRecipients;
|
|
769
|
+
/**
|
|
770
|
+
* The plugin's own records: configuration it keeps under a collection and a
|
|
771
|
+
* key, and never anything about a person (ADR 0033).
|
|
772
|
+
*
|
|
773
|
+
* Added after this contract version shipped, like `actions`: a plugin built
|
|
774
|
+
* against a newer host than the one it is installed on must feature-detect
|
|
775
|
+
* before using it.
|
|
776
|
+
*/
|
|
777
|
+
records: PluginRecords;
|
|
778
|
+
/**
|
|
779
|
+
* Device tokens for the plugin's declared device routes.
|
|
780
|
+
*
|
|
781
|
+
* Added after this contract version shipped, like `actions`: a plugin built
|
|
782
|
+
* against a newer host than the one it is installed on must feature-detect
|
|
783
|
+
* before using it.
|
|
784
|
+
*/
|
|
785
|
+
devices: PluginDevices;
|
|
786
|
+
/**
|
|
787
|
+
* Installing themes, and listing the ones this plugin installed.
|
|
788
|
+
*
|
|
789
|
+
* Added after this contract version shipped. An older host refuses a
|
|
790
|
+
* manifest asking for themes:install before it loads the plugin, so a plugin
|
|
791
|
+
* that declares the permission never meets a host without this member.
|
|
792
|
+
*/
|
|
793
|
+
themes: PluginThemes;
|
|
794
|
+
/**
|
|
795
|
+
* Handing a member list to the board for review (ADR 0043).
|
|
796
|
+
*
|
|
797
|
+
* Added after this contract version shipped. An older host refuses a
|
|
798
|
+
* manifest asking for addressBook:proposeImport before it loads the plugin,
|
|
799
|
+
* so a plugin that declares the permission never meets a host without this
|
|
800
|
+
* member; checking for it is a defensive guard only.
|
|
801
|
+
*/
|
|
802
|
+
imports: PluginImports;
|
|
803
|
+
/**
|
|
804
|
+
* The plugin's licence, judged by the host (ADR 0042).
|
|
805
|
+
*
|
|
806
|
+
* Present only on a plugin whose manifest declares a `licence`, and added
|
|
807
|
+
* after this contract version shipped, so a plugin feature-detects it as it
|
|
808
|
+
* does `actions`. A paid plugin on a host without it has no way to tell a
|
|
809
|
+
* licensed instance from an unlicensed one, and should stay dormant.
|
|
810
|
+
*/
|
|
811
|
+
entitlements?: PluginEntitlements;
|
|
812
|
+
}
|
|
813
|
+
/**
|
|
814
|
+
* A host service was used before the application finished starting, or after
|
|
815
|
+
* the plugin stopped serving.
|
|
816
|
+
*
|
|
817
|
+
* Both cases are the plugin reaching for the host at a moment the host cannot
|
|
818
|
+
* answer for: the first is work done in a constructor that belongs in
|
|
819
|
+
* `onModuleInit`, the second is a plugin the board switched off.
|
|
820
|
+
*/
|
|
821
|
+
export declare class PluginHostUnavailableError extends Error {
|
|
822
|
+
readonly pluginId: string;
|
|
823
|
+
readonly detail: string;
|
|
824
|
+
constructor(pluginId: string, detail: string);
|
|
825
|
+
}
|
|
826
|
+
export {};
|
|
827
|
+
//# sourceMappingURL=host.d.ts.map
|