@adukilabs/sdk 0.0.0-stage → 0.1.2
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 +201 -0
- package/README.md +184 -2
- package/dist/api/api.d.ts +226 -0
- package/dist/api/api.js +365 -0
- package/dist/api/id.d.ts +75 -0
- package/dist/api/id.js +184 -0
- package/dist/api/index.d.ts +23 -0
- package/dist/api/index.js +19 -0
- package/dist/api/key.d.ts +16 -0
- package/dist/api/key.js +16 -0
- package/dist/api/model.d.ts +476 -0
- package/dist/api/space.d.ts +147 -0
- package/dist/api/space.js +218 -0
- package/dist/api/store.d.ts +181 -0
- package/dist/api/store.js +352 -0
- package/dist/api/tenant.d.ts +319 -0
- package/dist/api/tenant.js +429 -0
- package/dist/base64.d.ts +11 -0
- package/dist/base64.js +40 -0
- package/dist/client.d.ts +29 -0
- package/dist/client.js +22 -0
- package/dist/dpop.d.ts +82 -0
- package/dist/dpop.js +156 -0
- package/dist/envelope.d.ts +59 -0
- package/dist/envelope.js +114 -0
- package/dist/errors.d.ts +165 -0
- package/dist/errors.js +206 -0
- package/dist/http.d.ts +11 -0
- package/dist/http.js +22 -0
- package/dist/jmap.d.ts +100 -0
- package/dist/jmap.js +180 -0
- package/dist/space/model.d.ts +147 -0
- package/dist/store/blake3.d.ts +4 -0
- package/dist/store/blake3.js +130 -0
- package/dist/store/cdc.d.ts +12 -0
- package/dist/store/cdc.js +127 -0
- package/dist/store/chunks.d.ts +23 -0
- package/dist/store/chunks.js +63 -0
- package/dist/store/model.d.ts +202 -0
- package/dist/store/model.js +38 -0
- package/package.json +45 -4
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** A new key: the raw value to keep secret, and what the server stores. */
|
|
2
|
+
export interface NewKey {
|
|
3
|
+
/** the raw key, sent as `Authorization: Key <key>`; shown once, never sent to the server when created */
|
|
4
|
+
key: string;
|
|
5
|
+
/** SHA-256 of the key as lowercase hex (what the server stores) */
|
|
6
|
+
hash: string;
|
|
7
|
+
/** the first 16 characters of the key (the server's lookup index, not a secret by itself) */
|
|
8
|
+
prefix: string;
|
|
9
|
+
}
|
|
10
|
+
/** SHA-256 of `key` (its UTF-8 bytes) as lowercase hex, as the server hashes it. */
|
|
11
|
+
export declare function hashKey(key: string): Promise<string>;
|
|
12
|
+
/**
|
|
13
|
+
* A fresh random key (`adk_` and 32 random bytes as hex) with its hash and
|
|
14
|
+
* prefix. `random` fills the bytes (default `crypto.getRandomValues`).
|
|
15
|
+
*/
|
|
16
|
+
export declare function createKey(random?: (bytes: Uint8Array<ArrayBuffer>) => Uint8Array): Promise<NewKey>;
|
package/dist/api/key.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Making an API key on the client (Aduki Mail keeps only its SHA-256): the
|
|
2
|
+
// raw key is random bytes, shown once; the server gets the hash and a short
|
|
3
|
+
// prefix to find it by. Web platform APIs only (WebCrypto).
|
|
4
|
+
const hex = (bytes) => Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');
|
|
5
|
+
/** SHA-256 of `key` (its UTF-8 bytes) as lowercase hex, as the server hashes it. */
|
|
6
|
+
export async function hashKey(key) {
|
|
7
|
+
return hex(new Uint8Array(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(key))));
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* A fresh random key (`adk_` and 32 random bytes as hex) with its hash and
|
|
11
|
+
* prefix. `random` fills the bytes (default `crypto.getRandomValues`).
|
|
12
|
+
*/
|
|
13
|
+
export async function createKey(random = (b) => crypto.getRandomValues(b)) {
|
|
14
|
+
const key = `adk_${hex(random(new Uint8Array(32)))}`;
|
|
15
|
+
return { key, hash: await hashKey(key), prefix: key.slice(0, 16) };
|
|
16
|
+
}
|
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
/** A list: page mode (`page`, `pages`) or cursor mode (`next`, when more follow). */
|
|
2
|
+
export interface Page<T> {
|
|
3
|
+
items: T[];
|
|
4
|
+
total: number;
|
|
5
|
+
/** page mode: this page (from 1) */
|
|
6
|
+
page?: number;
|
|
7
|
+
/** page mode: the number of pages */
|
|
8
|
+
pages?: number;
|
|
9
|
+
/** cursor mode: pass as `after` for the next page; absent on the last one */
|
|
10
|
+
next?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Which part of a list: `{page, limit}` (pages from 1) or `{after, limit}`
|
|
14
|
+
* (a cursor, the `next` of the page before). `limit` is 1 to 200 (default 50).
|
|
15
|
+
*/
|
|
16
|
+
export interface PageQuery {
|
|
17
|
+
page?: number;
|
|
18
|
+
after?: string;
|
|
19
|
+
limit?: number;
|
|
20
|
+
}
|
|
21
|
+
/** A message row of the mail lists. */
|
|
22
|
+
export interface MessageRow {
|
|
23
|
+
hex: string;
|
|
24
|
+
uid: number;
|
|
25
|
+
subject?: string | null;
|
|
26
|
+
sender?: string | null;
|
|
27
|
+
size: number;
|
|
28
|
+
flags: (string | null)[];
|
|
29
|
+
thread?: string | null;
|
|
30
|
+
spam?: number | null;
|
|
31
|
+
internaldate: string;
|
|
32
|
+
preview?: string | null;
|
|
33
|
+
from?: unknown;
|
|
34
|
+
to: unknown;
|
|
35
|
+
cc: unknown;
|
|
36
|
+
bcc: unknown;
|
|
37
|
+
reply_to: unknown;
|
|
38
|
+
message_id?: string | null;
|
|
39
|
+
has_attachment: boolean;
|
|
40
|
+
mailbox: unknown;
|
|
41
|
+
[field: string]: unknown;
|
|
42
|
+
}
|
|
43
|
+
/** A thread row (`GET /v1/user/mail/threads`). */
|
|
44
|
+
export interface ThreadRow {
|
|
45
|
+
thread: string;
|
|
46
|
+
subject?: string | null;
|
|
47
|
+
count: number;
|
|
48
|
+
unread: number;
|
|
49
|
+
latest: string;
|
|
50
|
+
mailbox: unknown;
|
|
51
|
+
[field: string]: unknown;
|
|
52
|
+
}
|
|
53
|
+
/** A mailbox row. */
|
|
54
|
+
export interface MailboxRow {
|
|
55
|
+
hex: string;
|
|
56
|
+
name: string;
|
|
57
|
+
delimiter: string;
|
|
58
|
+
flags: unknown;
|
|
59
|
+
uidvalidity: number;
|
|
60
|
+
uidnext: number;
|
|
61
|
+
role?: string | null;
|
|
62
|
+
messages: number;
|
|
63
|
+
unread: number;
|
|
64
|
+
created: string;
|
|
65
|
+
[field: string]: unknown;
|
|
66
|
+
}
|
|
67
|
+
/** What changed in one mailbox since a modseq (`GET /v1/user/mail/changes`). */
|
|
68
|
+
export interface MailChanges {
|
|
69
|
+
mailbox: string;
|
|
70
|
+
uidvalidity: number;
|
|
71
|
+
modseq: number;
|
|
72
|
+
/** the `uidvalidity` given is stale: sync the mailbox again from 0 */
|
|
73
|
+
reset: boolean;
|
|
74
|
+
/** more changes follow: ask again from `modseq` */
|
|
75
|
+
more: boolean;
|
|
76
|
+
created: MessageRow[];
|
|
77
|
+
updated: MessageRow[];
|
|
78
|
+
/** uids removed */
|
|
79
|
+
vanished: number[];
|
|
80
|
+
[field: string]: unknown;
|
|
81
|
+
}
|
|
82
|
+
/** A contact card. */
|
|
83
|
+
export interface Card {
|
|
84
|
+
hex: string;
|
|
85
|
+
uid: string;
|
|
86
|
+
href: string;
|
|
87
|
+
etag: string;
|
|
88
|
+
/** the vCard text */
|
|
89
|
+
vcard: string;
|
|
90
|
+
name?: string | null;
|
|
91
|
+
emails: unknown[];
|
|
92
|
+
phones: unknown[];
|
|
93
|
+
groups: unknown[];
|
|
94
|
+
meta: unknown;
|
|
95
|
+
version: number;
|
|
96
|
+
size: number;
|
|
97
|
+
created: string;
|
|
98
|
+
updated: string;
|
|
99
|
+
photo: unknown;
|
|
100
|
+
[field: string]: unknown;
|
|
101
|
+
}
|
|
102
|
+
/** One page of the address book's change feed (`GET /v1/user/contacts/sync`). */
|
|
103
|
+
export interface ContactChanges {
|
|
104
|
+
items: Card[];
|
|
105
|
+
/** hexes removed */
|
|
106
|
+
removed: unknown[];
|
|
107
|
+
/** pass as `since` next time */
|
|
108
|
+
token: string;
|
|
109
|
+
more: boolean;
|
|
110
|
+
/** the answer is the whole book, not changes */
|
|
111
|
+
full: boolean;
|
|
112
|
+
total?: number;
|
|
113
|
+
[field: string]: unknown;
|
|
114
|
+
}
|
|
115
|
+
/** A calendar. */
|
|
116
|
+
export interface CalendarRow {
|
|
117
|
+
hex: string;
|
|
118
|
+
kind: string;
|
|
119
|
+
href: string;
|
|
120
|
+
name: string;
|
|
121
|
+
description?: string | null;
|
|
122
|
+
color?: string | null;
|
|
123
|
+
timezone: string;
|
|
124
|
+
components: string[];
|
|
125
|
+
transp: string;
|
|
126
|
+
created: string;
|
|
127
|
+
updated: string;
|
|
128
|
+
[field: string]: unknown;
|
|
129
|
+
}
|
|
130
|
+
/** An event (occurrences are expanded in a range). */
|
|
131
|
+
export interface EventRow {
|
|
132
|
+
hex: string;
|
|
133
|
+
uid: string;
|
|
134
|
+
href: string;
|
|
135
|
+
etag: string;
|
|
136
|
+
/** the iCalendar object */
|
|
137
|
+
ical: string;
|
|
138
|
+
kind: string;
|
|
139
|
+
start?: string | null;
|
|
140
|
+
end?: string | null;
|
|
141
|
+
summary?: string | null;
|
|
142
|
+
description?: string | null;
|
|
143
|
+
location?: string | null;
|
|
144
|
+
attendees: unknown[];
|
|
145
|
+
organizer?: unknown;
|
|
146
|
+
status?: string | null;
|
|
147
|
+
sequence: number;
|
|
148
|
+
categories: string[];
|
|
149
|
+
rrule?: string | null;
|
|
150
|
+
recurring: boolean;
|
|
151
|
+
/** the calendar's hex */
|
|
152
|
+
calendar: string;
|
|
153
|
+
created: string;
|
|
154
|
+
updated: string;
|
|
155
|
+
[field: string]: unknown;
|
|
156
|
+
}
|
|
157
|
+
/** An API key as listed (never the key itself, nor its hash). */
|
|
158
|
+
export interface KeyRow {
|
|
159
|
+
hex: string;
|
|
160
|
+
name: string;
|
|
161
|
+
prefix: string;
|
|
162
|
+
active: boolean;
|
|
163
|
+
expires?: string | null;
|
|
164
|
+
last?: string | null;
|
|
165
|
+
created: string;
|
|
166
|
+
tenant: unknown;
|
|
167
|
+
user?: unknown;
|
|
168
|
+
[field: string]: unknown;
|
|
169
|
+
}
|
|
170
|
+
/** An API key in full (`GET /v1/tenant/keys/{hex}`). */
|
|
171
|
+
export interface KeyDetail {
|
|
172
|
+
hex: string;
|
|
173
|
+
name: string;
|
|
174
|
+
prefix: string;
|
|
175
|
+
scopes: (string | null)[] | null;
|
|
176
|
+
meta: unknown;
|
|
177
|
+
last?: string | null;
|
|
178
|
+
expires?: string | null;
|
|
179
|
+
revoked?: string | null;
|
|
180
|
+
created: string;
|
|
181
|
+
updated: string;
|
|
182
|
+
[field: string]: unknown;
|
|
183
|
+
}
|
|
184
|
+
/** The account a key acts as (`GET /v1/user`). */
|
|
185
|
+
export interface Account {
|
|
186
|
+
hex: string;
|
|
187
|
+
email: string;
|
|
188
|
+
name: string;
|
|
189
|
+
tenant: unknown;
|
|
190
|
+
owner: boolean;
|
|
191
|
+
state: string;
|
|
192
|
+
timezone: string;
|
|
193
|
+
locale: string;
|
|
194
|
+
created: string;
|
|
195
|
+
[field: string]: unknown;
|
|
196
|
+
}
|
|
197
|
+
/** The account's profile (`GET /v1/user/profile`). */
|
|
198
|
+
export interface Profile {
|
|
199
|
+
hex: string;
|
|
200
|
+
name: string;
|
|
201
|
+
email: string;
|
|
202
|
+
avatar?: {
|
|
203
|
+
hex: string;
|
|
204
|
+
updated: string;
|
|
205
|
+
} | null;
|
|
206
|
+
kind: string;
|
|
207
|
+
tenant?: {
|
|
208
|
+
hex: string;
|
|
209
|
+
name: string;
|
|
210
|
+
slug: string;
|
|
211
|
+
} | null;
|
|
212
|
+
role: {
|
|
213
|
+
label: string;
|
|
214
|
+
owner: boolean;
|
|
215
|
+
};
|
|
216
|
+
plan?: {
|
|
217
|
+
code: string;
|
|
218
|
+
state: string;
|
|
219
|
+
} | null;
|
|
220
|
+
storage: {
|
|
221
|
+
used: number;
|
|
222
|
+
limit?: number | null;
|
|
223
|
+
};
|
|
224
|
+
editable: boolean;
|
|
225
|
+
[field: string]: unknown;
|
|
226
|
+
}
|
|
227
|
+
/** The workspace's profile (`GET /v1/tenant`). */
|
|
228
|
+
export interface TenantProfile {
|
|
229
|
+
hex: string;
|
|
230
|
+
name?: string;
|
|
231
|
+
slug?: string;
|
|
232
|
+
[field: string]: unknown;
|
|
233
|
+
}
|
|
234
|
+
/** A member row (`GET /v1/tenant/members`). */
|
|
235
|
+
export interface MemberRow {
|
|
236
|
+
hex: string;
|
|
237
|
+
email: string;
|
|
238
|
+
name: string;
|
|
239
|
+
avatar?: string | null;
|
|
240
|
+
owner: boolean;
|
|
241
|
+
state: string;
|
|
242
|
+
last?: string | null;
|
|
243
|
+
created: string;
|
|
244
|
+
tenant: unknown;
|
|
245
|
+
role: unknown;
|
|
246
|
+
[field: string]: unknown;
|
|
247
|
+
}
|
|
248
|
+
/** An audit row. */
|
|
249
|
+
export interface AuditRow {
|
|
250
|
+
hex: string;
|
|
251
|
+
action: string;
|
|
252
|
+
success: boolean;
|
|
253
|
+
reason?: string | null;
|
|
254
|
+
ip?: string | null;
|
|
255
|
+
agent?: string | null;
|
|
256
|
+
device?: unknown;
|
|
257
|
+
created: string;
|
|
258
|
+
actor?: unknown;
|
|
259
|
+
[field: string]: unknown;
|
|
260
|
+
}
|
|
261
|
+
/** An audit record with its `meta` (`GET /v1/tenant/view/audit/{hex}`). */
|
|
262
|
+
export interface AuditDetail extends AuditRow {
|
|
263
|
+
meta?: unknown;
|
|
264
|
+
}
|
|
265
|
+
/** A usage row: `value` of `metric` in the billing `window`. */
|
|
266
|
+
export interface UsageRow {
|
|
267
|
+
tenant: string;
|
|
268
|
+
metric: string;
|
|
269
|
+
window: string;
|
|
270
|
+
value: number;
|
|
271
|
+
ceiling: number;
|
|
272
|
+
[field: string]: unknown;
|
|
273
|
+
}
|
|
274
|
+
/** A quota in full. */
|
|
275
|
+
export interface Quota {
|
|
276
|
+
tenant: string;
|
|
277
|
+
metric: string;
|
|
278
|
+
ceiling: number;
|
|
279
|
+
reason?: string | null;
|
|
280
|
+
granted?: string | null;
|
|
281
|
+
expires?: string | null;
|
|
282
|
+
created: string;
|
|
283
|
+
updated: string;
|
|
284
|
+
[field: string]: unknown;
|
|
285
|
+
}
|
|
286
|
+
/** A quota as listed. */
|
|
287
|
+
export interface QuotaRow {
|
|
288
|
+
tenant: string;
|
|
289
|
+
metric: string;
|
|
290
|
+
ceiling: number;
|
|
291
|
+
expires?: string | null;
|
|
292
|
+
created: string;
|
|
293
|
+
[field: string]: unknown;
|
|
294
|
+
}
|
|
295
|
+
/** A domain to register. */
|
|
296
|
+
export interface DomainCreate {
|
|
297
|
+
name: string;
|
|
298
|
+
/** `primary`, `sending`, `receiving` or `alias` */
|
|
299
|
+
kind?: string;
|
|
300
|
+
/** the DKIM selector */
|
|
301
|
+
selector?: string;
|
|
302
|
+
meta?: Record<string, unknown>;
|
|
303
|
+
}
|
|
304
|
+
/** A DNS record of a DKIM key: publish `value` as TXT at `name`. */
|
|
305
|
+
export interface DkimRecord {
|
|
306
|
+
selector?: string;
|
|
307
|
+
name: string;
|
|
308
|
+
value: string;
|
|
309
|
+
[field: string]: unknown;
|
|
310
|
+
}
|
|
311
|
+
/** A domain in full: its status and the DNS records and snapshots. */
|
|
312
|
+
export interface Domain {
|
|
313
|
+
hex: string;
|
|
314
|
+
tenant: string;
|
|
315
|
+
name: string;
|
|
316
|
+
kind: string;
|
|
317
|
+
/** `pending`, `verified`, `active`, `suspended` or `failed` */
|
|
318
|
+
status: string;
|
|
319
|
+
selector: string;
|
|
320
|
+
/** the active key's record (never the private key) */
|
|
321
|
+
dkim?: DkimRecord | null;
|
|
322
|
+
dkim_twin?: DkimRecord | null;
|
|
323
|
+
dkim_rotation?: {
|
|
324
|
+
pending?: DkimRecord | null;
|
|
325
|
+
retired?: unknown;
|
|
326
|
+
} | null;
|
|
327
|
+
spf: unknown;
|
|
328
|
+
dmarc: unknown;
|
|
329
|
+
mta_sts: unknown;
|
|
330
|
+
bimi: unknown;
|
|
331
|
+
meta: unknown;
|
|
332
|
+
verified?: string | null;
|
|
333
|
+
created: string;
|
|
334
|
+
updated: string;
|
|
335
|
+
[field: string]: unknown;
|
|
336
|
+
}
|
|
337
|
+
/** A domain as listed. */
|
|
338
|
+
export interface DomainRow {
|
|
339
|
+
hex: string;
|
|
340
|
+
name: string;
|
|
341
|
+
kind: string;
|
|
342
|
+
status: string;
|
|
343
|
+
verified?: string | null;
|
|
344
|
+
created: string;
|
|
345
|
+
tenant: unknown;
|
|
346
|
+
[field: string]: unknown;
|
|
347
|
+
}
|
|
348
|
+
/** The state of a DKIM rotation. */
|
|
349
|
+
export interface DkimRotation {
|
|
350
|
+
active?: DkimRecord | null;
|
|
351
|
+
/** the staged key: publish it, then confirm */
|
|
352
|
+
pending?: DkimRecord | null;
|
|
353
|
+
/** the previous record, safe to remove after `remove_after` */
|
|
354
|
+
retired?: {
|
|
355
|
+
selector: string;
|
|
356
|
+
name: string;
|
|
357
|
+
remove_after: string;
|
|
358
|
+
} | null;
|
|
359
|
+
[field: string]: unknown;
|
|
360
|
+
}
|
|
361
|
+
/** An alias of a member's mailbox. */
|
|
362
|
+
export interface Alias {
|
|
363
|
+
address: string;
|
|
364
|
+
user: string;
|
|
365
|
+
created?: string;
|
|
366
|
+
[field: string]: unknown;
|
|
367
|
+
}
|
|
368
|
+
/** A spam rule to create. */
|
|
369
|
+
export interface RuleCreate {
|
|
370
|
+
name: string;
|
|
371
|
+
/** `header.from`, `header.to`, `header.subject`, `header.received`, `envelope.from`, `envelope.to`, `body.text`, `body.html`, `body.url`, `attachment.name`, `attachment.mime` */
|
|
372
|
+
target: string;
|
|
373
|
+
pattern: string;
|
|
374
|
+
regex?: boolean;
|
|
375
|
+
/** -100 to 100: positive towards spam, negative towards ham */
|
|
376
|
+
score: number;
|
|
377
|
+
active?: boolean;
|
|
378
|
+
meta?: Record<string, unknown>;
|
|
379
|
+
}
|
|
380
|
+
/** A spam rule. */
|
|
381
|
+
export interface Rule {
|
|
382
|
+
hex: string;
|
|
383
|
+
tenant?: unknown;
|
|
384
|
+
name: string;
|
|
385
|
+
target: string;
|
|
386
|
+
pattern: string;
|
|
387
|
+
regex: boolean;
|
|
388
|
+
score: number;
|
|
389
|
+
active: boolean;
|
|
390
|
+
meta?: unknown;
|
|
391
|
+
created: string;
|
|
392
|
+
updated?: string;
|
|
393
|
+
[field: string]: unknown;
|
|
394
|
+
}
|
|
395
|
+
/** A spam rule as listed. */
|
|
396
|
+
export type RuleRow = Omit<Rule, 'meta' | 'updated'>;
|
|
397
|
+
/** A webhook to create. */
|
|
398
|
+
export interface WebhookCreate {
|
|
399
|
+
/** `https`, a public host, at most 500 characters */
|
|
400
|
+
url: string;
|
|
401
|
+
/** 16 to 128 characters; omitted, the server makes one */
|
|
402
|
+
secret?: string;
|
|
403
|
+
/** `mail.delivered`, `mail.bounced`, `mail.deferred`, `mail.complained` */
|
|
404
|
+
events?: string[];
|
|
405
|
+
domains?: string[];
|
|
406
|
+
active?: boolean;
|
|
407
|
+
meta?: Record<string, unknown>;
|
|
408
|
+
}
|
|
409
|
+
/** A webhook as listed. */
|
|
410
|
+
export interface WebhookRow {
|
|
411
|
+
hex: string;
|
|
412
|
+
url: string;
|
|
413
|
+
active: boolean;
|
|
414
|
+
created: string;
|
|
415
|
+
tenant: unknown;
|
|
416
|
+
[field: string]: unknown;
|
|
417
|
+
}
|
|
418
|
+
/** A webhook (never its secret). */
|
|
419
|
+
export interface Webhook extends WebhookRow {
|
|
420
|
+
events: unknown;
|
|
421
|
+
domains?: unknown;
|
|
422
|
+
meta?: unknown;
|
|
423
|
+
updated?: string;
|
|
424
|
+
}
|
|
425
|
+
/** `GET /v1/tenant/security`. */
|
|
426
|
+
export interface SecurityStatus {
|
|
427
|
+
mtasts: unknown[];
|
|
428
|
+
tlsa: unknown[];
|
|
429
|
+
bimi: unknown[];
|
|
430
|
+
reports: unknown[];
|
|
431
|
+
[field: string]: unknown;
|
|
432
|
+
}
|
|
433
|
+
/** A mail service and whether this workspace may use it. */
|
|
434
|
+
export interface MailService {
|
|
435
|
+
id: string;
|
|
436
|
+
name: string;
|
|
437
|
+
status: string;
|
|
438
|
+
description: string;
|
|
439
|
+
requirements: string[];
|
|
440
|
+
limits: string;
|
|
441
|
+
entitled: boolean;
|
|
442
|
+
reason?: string | null;
|
|
443
|
+
[field: string]: unknown;
|
|
444
|
+
}
|
|
445
|
+
/** An effective holiday of the workspace. */
|
|
446
|
+
export interface Holiday {
|
|
447
|
+
date: string;
|
|
448
|
+
name: string;
|
|
449
|
+
kind: string;
|
|
450
|
+
source: string;
|
|
451
|
+
region?: string | null;
|
|
452
|
+
hex?: string;
|
|
453
|
+
verified?: string | null;
|
|
454
|
+
[field: string]: unknown;
|
|
455
|
+
}
|
|
456
|
+
/** A schedule template. */
|
|
457
|
+
export interface ScheduleTemplate {
|
|
458
|
+
hex: string;
|
|
459
|
+
name: string;
|
|
460
|
+
zone: string;
|
|
461
|
+
rules: unknown[];
|
|
462
|
+
followers: number;
|
|
463
|
+
[field: string]: unknown;
|
|
464
|
+
}
|
|
465
|
+
/** A room or piece of equipment. */
|
|
466
|
+
export interface ScheduleResource {
|
|
467
|
+
hex: string;
|
|
468
|
+
name: string;
|
|
469
|
+
kind: string;
|
|
470
|
+
capacity?: number | null;
|
|
471
|
+
schedule?: string | null;
|
|
472
|
+
retired: boolean | string | null;
|
|
473
|
+
created: string;
|
|
474
|
+
updated: string;
|
|
475
|
+
[field: string]: unknown;
|
|
476
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import type { Activity, Checkin, Found, Member, Message, Page, Reply, Settings, SupportTicket, Task, Team } from '../space/model.js';
|
|
2
|
+
import type { AudienceFetch } from './store.js';
|
|
3
|
+
/** The Space REST root. */
|
|
4
|
+
export declare const SPACE = "https://space.aduki.pro/v1";
|
|
5
|
+
export interface SpaceApiOptions {
|
|
6
|
+
/** the REST root with `/v1` (default `https://space.aduki.pro/v1`) */
|
|
7
|
+
root?: string | undefined;
|
|
8
|
+
}
|
|
9
|
+
/** A query: undefined, null and false values are left out. */
|
|
10
|
+
export type SpaceQuery = Record<string, string | number | boolean | null | undefined>;
|
|
11
|
+
/** One page: `limit` 1 to 100, `after` the `next` of the previous page. */
|
|
12
|
+
export interface SpacePage {
|
|
13
|
+
limit?: number;
|
|
14
|
+
after?: string;
|
|
15
|
+
}
|
|
16
|
+
/** A request of `call`. */
|
|
17
|
+
export interface SpaceCall {
|
|
18
|
+
query?: SpaceQuery;
|
|
19
|
+
body?: unknown;
|
|
20
|
+
/** `Idempotency-Key` (a UUID) */
|
|
21
|
+
key?: string;
|
|
22
|
+
/** `If-Match`: the `etag` of the read the change is based on (stale: 409 `entity.conflict`) */
|
|
23
|
+
version?: string;
|
|
24
|
+
signal?: AbortSignal;
|
|
25
|
+
}
|
|
26
|
+
/** The filters of `tasks`. */
|
|
27
|
+
export interface SpaceTaskFilters extends SpacePage {
|
|
28
|
+
status?: string;
|
|
29
|
+
client?: string;
|
|
30
|
+
team?: string;
|
|
31
|
+
orphaned?: boolean;
|
|
32
|
+
unbilled?: boolean;
|
|
33
|
+
q?: string;
|
|
34
|
+
archived?: boolean;
|
|
35
|
+
}
|
|
36
|
+
/** The fields of a new task (`title` required). */
|
|
37
|
+
export interface SpaceTaskInput {
|
|
38
|
+
title: string;
|
|
39
|
+
description?: string;
|
|
40
|
+
priority?: string;
|
|
41
|
+
status?: string;
|
|
42
|
+
due?: string;
|
|
43
|
+
client?: string;
|
|
44
|
+
service?: string;
|
|
45
|
+
team?: string;
|
|
46
|
+
[field: string]: unknown;
|
|
47
|
+
}
|
|
48
|
+
/** The filters of `tickets`. */
|
|
49
|
+
export interface SpaceTicketFilters extends SpacePage {
|
|
50
|
+
status?: string;
|
|
51
|
+
client?: string;
|
|
52
|
+
assignee?: string;
|
|
53
|
+
unassigned?: boolean;
|
|
54
|
+
breached?: boolean;
|
|
55
|
+
q?: string;
|
|
56
|
+
}
|
|
57
|
+
/** The fields of a new ticket (`client` and `title` required). */
|
|
58
|
+
export interface SpaceTicketInput {
|
|
59
|
+
client: string;
|
|
60
|
+
title: string;
|
|
61
|
+
contact?: string;
|
|
62
|
+
body?: string;
|
|
63
|
+
priority?: string;
|
|
64
|
+
assignee?: string;
|
|
65
|
+
service?: string;
|
|
66
|
+
node?: string;
|
|
67
|
+
[field: string]: unknown;
|
|
68
|
+
}
|
|
69
|
+
/** The filters of `activity`. */
|
|
70
|
+
export interface SpaceActivityFilters extends SpacePage {
|
|
71
|
+
entity?: string;
|
|
72
|
+
action?: string;
|
|
73
|
+
task?: string;
|
|
74
|
+
}
|
|
75
|
+
/** Aduki Space for a program (see the module notes for what it may not do). */
|
|
76
|
+
export declare class SpaceApi {
|
|
77
|
+
#private;
|
|
78
|
+
readonly root: string;
|
|
79
|
+
constructor(session: AudienceFetch, options?: SpaceApiOptions);
|
|
80
|
+
/**
|
|
81
|
+
* One request to `path` (under `/v1`, segments already encoded): the
|
|
82
|
+
* envelope's `data`, the status and the `ETag`. A refusal throws the typed
|
|
83
|
+
* error of `errors.refusal`: `ClientRefusedError` on a strict or money
|
|
84
|
+
* route, `NetworkError 403 access.denied` for a bit the client lacks,
|
|
85
|
+
* `403 app.disabled` for a read-only workspace, `404` for a row it may not
|
|
86
|
+
* see, `RateLimitedError` with `retryAfter`.
|
|
87
|
+
*/
|
|
88
|
+
call<T = any>(method: string, path: string, options?: SpaceCall): Promise<Reply<T>>;
|
|
89
|
+
/** One page of a list route (`items`, `next`). */
|
|
90
|
+
list<T = Record<string, unknown>>(path: string, query?: SpaceQuery, page?: SpacePage): Promise<Page<T>>;
|
|
91
|
+
/** Every item of a list route, page by page (`size` per page). */
|
|
92
|
+
all<T = Record<string, unknown>>(path: string, query?: SpaceQuery, size?: number): AsyncGenerator<T>;
|
|
93
|
+
/** The workspace settings, read only (`GET /v1/settings`); changing them is strict and refused to programs. */
|
|
94
|
+
settings(): Promise<Reply<Settings>>;
|
|
95
|
+
/** The workspace's teams (`GET /v1/teams`). */
|
|
96
|
+
teams(page?: SpacePage): Promise<Page<Team>>;
|
|
97
|
+
/** The members of the workspace: name, handle and teams (`GET /v1/staff/directory`). */
|
|
98
|
+
directory(page?: SpacePage): Promise<Page<Member>>;
|
|
99
|
+
/** The activity feed (`GET /v1/activity`); entries a program made carry `kind: "client"`. */
|
|
100
|
+
activity(filters?: SpaceActivityFilters): Promise<Page<Activity>>;
|
|
101
|
+
/** Tasks the client may see (`GET /v1/tasks`), filtered. */
|
|
102
|
+
tasks(filters?: SpaceTaskFilters): Promise<Page<Task>>;
|
|
103
|
+
/** A task and its version (`GET /v1/tasks/{id}`). */
|
|
104
|
+
task(task: string): Promise<Reply<Task>>;
|
|
105
|
+
/** Creates a task (`POST /v1/tasks`, `tasks.write`); a new Idempotency-Key unless `key` is given. */
|
|
106
|
+
createTask(input: SpaceTaskInput, options?: {
|
|
107
|
+
key?: string;
|
|
108
|
+
}): Promise<Reply<Task>>;
|
|
109
|
+
/** Changes a task (`PATCH /v1/tasks/{id}`); `version` guards against a lost update. */
|
|
110
|
+
updateTask(task: string, changes: Record<string, unknown>, options?: {
|
|
111
|
+
version?: string;
|
|
112
|
+
}): Promise<Reply<Task>>;
|
|
113
|
+
/** The check-ins of a task (`GET /v1/tasks/{id}/checkins`). */
|
|
114
|
+
checkins(task: string, page?: SpacePage): Promise<Page<Checkin>>;
|
|
115
|
+
/** Reports work on a task (`POST /v1/tasks/{id}/checkins`, `tasks.work`): `minutes` and an optional `proof` link. */
|
|
116
|
+
checkin(task: string, input: {
|
|
117
|
+
body: string;
|
|
118
|
+
minutes?: number;
|
|
119
|
+
proof?: string;
|
|
120
|
+
}, options?: {
|
|
121
|
+
key?: string;
|
|
122
|
+
}): Promise<Reply<Checkin>>;
|
|
123
|
+
/** Tickets the client may see (`GET /v1/tickets`, `tickets.read`), filtered. */
|
|
124
|
+
tickets(filters?: SpaceTicketFilters): Promise<Page<SupportTicket>>;
|
|
125
|
+
/** A ticket and its version (`GET /v1/tickets/{id}`). */
|
|
126
|
+
ticket(ticket: string): Promise<Reply<SupportTicket>>;
|
|
127
|
+
/** Opens a ticket (`POST /v1/tickets`, `tickets.write`). */
|
|
128
|
+
createTicket(input: SpaceTicketInput, options?: {
|
|
129
|
+
key?: string;
|
|
130
|
+
}): Promise<Reply<SupportTicket>>;
|
|
131
|
+
/** Changes a ticket (`PATCH /v1/tickets/{id}`): title, priority, status, assignee, service, node. */
|
|
132
|
+
updateTicket(ticket: string, changes: Record<string, unknown>, options?: {
|
|
133
|
+
version?: string;
|
|
134
|
+
}): Promise<Reply<SupportTicket>>;
|
|
135
|
+
/** The thread of a ticket, oldest first (`GET /v1/tickets/{id}/messages`). */
|
|
136
|
+
messages(ticket: string, page?: SpacePage): Promise<Page<Message>>;
|
|
137
|
+
/** Replies on a ticket (`POST /v1/tickets/{id}/messages`); `internal` makes it a staff note the client never sees. */
|
|
138
|
+
reply(ticket: string, body: string, options?: {
|
|
139
|
+
internal?: boolean;
|
|
140
|
+
key?: string;
|
|
141
|
+
}): Promise<Reply<Message>>;
|
|
142
|
+
/** Ids by query (`GET /v1/search`): `q` 1 to 200 characters, `entity` one collection, `limit` 1 to 50. */
|
|
143
|
+
search(q: string, options?: {
|
|
144
|
+
entity?: string;
|
|
145
|
+
limit?: number;
|
|
146
|
+
}): Promise<Found>;
|
|
147
|
+
}
|