@larc-iu/plaid-client 0.2.0-alpha.2 → 0.2.0-alpha.20
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/index.d.ts +1638 -156
- package/package.json +1 -1
- package/src/batchRef.js +128 -0
- package/src/constraints.js +84 -0
- package/src/created.js +29 -0
- package/src/documentLock.js +342 -0
- package/src/events.js +266 -0
- package/src/http.js +719 -90
- package/src/ids.js +54 -0
- package/src/index.js +2781 -645
- package/src/metadataOps.js +117 -0
- package/src/pagination.js +19 -35
- package/src/provenance.js +268 -27
- package/src/replayed.js +27 -0
- package/src/requester.js +56 -0
- package/src/roles.js +26 -0
- package/src/serviceSchema.js +87 -33
- package/src/services.js +550 -54
- package/src/sse.js +60 -3
- package/src/textEdits.js +191 -0
- package/src/transforms.js +11 -1
package/index.d.ts
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A config write's compare-and-set. With `expected` present (null or
|
|
3
|
+
* undefined for a key that was absent) the write is refused with a 409 when
|
|
4
|
+
* the stored value is no longer `expected`.
|
|
5
|
+
*/
|
|
6
|
+
interface ConfigWriteOptions {
|
|
7
|
+
expected?: any;
|
|
8
|
+
}
|
|
9
|
+
|
|
1
10
|
/** A single page of a cursor-paginated collection. */
|
|
2
11
|
interface Page<T = any> {
|
|
3
12
|
entries: T[];
|
|
@@ -15,7 +24,7 @@ interface ServiceParam {
|
|
|
15
24
|
/** Key the value is sent under in the request payload. */
|
|
16
25
|
key: string;
|
|
17
26
|
label: string;
|
|
18
|
-
type:
|
|
27
|
+
type: "string" | "number" | "boolean" | "enum" | "multiselect" | "field";
|
|
19
28
|
description?: string;
|
|
20
29
|
default?: any;
|
|
21
30
|
required?: boolean;
|
|
@@ -25,9 +34,16 @@ interface ServiceParam {
|
|
|
25
34
|
min?: number;
|
|
26
35
|
max?: number;
|
|
27
36
|
step?: number;
|
|
37
|
+
/** `number` only: render as a slider to drag rather than a box to type in. */
|
|
38
|
+
slider?: boolean;
|
|
28
39
|
/** `string` only. */
|
|
29
40
|
placeholder?: string;
|
|
30
41
|
multiline?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* `field` only: the scope of the project's annotation fields the value names
|
|
44
|
+
* one of. A `field` value is a string everywhere else.
|
|
45
|
+
*/
|
|
46
|
+
scope?: "Sentence" | "Word" | "Morpheme";
|
|
31
47
|
}
|
|
32
48
|
|
|
33
49
|
/** A service's standardized self-description (lives in `extras`). */
|
|
@@ -62,108 +78,340 @@ interface DiscoveredService {
|
|
|
62
78
|
|
|
63
79
|
interface ServiceRegistration {
|
|
64
80
|
stop(): void;
|
|
81
|
+
/** Still serving, including while retrying a channel through a server restart. */
|
|
65
82
|
isRunning(): boolean;
|
|
83
|
+
/** Channel open right now, i.e. the server currently sees this service as online. */
|
|
84
|
+
isConnected(): boolean;
|
|
66
85
|
serviceInfo: ServiceInfo & { extras: any };
|
|
67
86
|
}
|
|
68
87
|
|
|
88
|
+
/** Connection-state transitions reported by a service registration. */
|
|
89
|
+
/** "stopped": the server refused the channel for a reason retrying cannot fix (a revoked token, no write access, no such project), which ends the registration. */
|
|
90
|
+
type ServiceStatusEvent = "registered" | "reconnected" | "disconnected" | "stopped";
|
|
91
|
+
|
|
69
92
|
interface ResponseHelper {
|
|
70
|
-
|
|
93
|
+
requestId: string;
|
|
94
|
+
requesterId: string | null;
|
|
95
|
+
/** True once the requester has asked this request to stop. */
|
|
96
|
+
readonly cancelled: boolean;
|
|
97
|
+
/**
|
|
98
|
+
* Report progress — and a cancellation CHECKPOINT: throws
|
|
99
|
+
* `ServiceCancelled` once a stop has been asked for, which is what makes a
|
|
100
|
+
* service that already reports progress cancellable for free.
|
|
101
|
+
*/
|
|
102
|
+
progress(percent: number, message: string, extra?: Record<string, any>): void;
|
|
103
|
+
/** Stop here if the requester has asked the request to stop. */
|
|
104
|
+
raiseIfCancelled(): void;
|
|
105
|
+
/** Run `fn` as a stretch that must finish once begun, usually the writes. */
|
|
106
|
+
critical<T>(fn: () => T | Promise<T>): Promise<T>;
|
|
71
107
|
complete(data: any): void;
|
|
108
|
+
/** End the request because it was asked to stop; result carries `stopped: true`. */
|
|
109
|
+
stopped(data?: any): void;
|
|
72
110
|
error(error: string | Error): void;
|
|
73
111
|
}
|
|
74
112
|
|
|
113
|
+
/** Thrown inside a handler when the requester has asked it to stop. */
|
|
114
|
+
export class ServiceCancelled extends Error {
|
|
115
|
+
constructor(message?: string);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** The key a run's stored record names its requester under. */
|
|
119
|
+
export const REQUESTED_BY: "requestedBy";
|
|
120
|
+
|
|
121
|
+
/** The person who asked for one service run. Both fields are null when nobody asked. */
|
|
122
|
+
export interface Requester {
|
|
123
|
+
id: string | null;
|
|
124
|
+
name: string | null;
|
|
125
|
+
/** `"<text>, requested by <name>"`, or `text` when nobody asked. */
|
|
126
|
+
label(text: string): string;
|
|
127
|
+
/** `{ id, name }` for a stored report, or null when nobody asked. */
|
|
128
|
+
record(): { id: string; name: string | null } | null;
|
|
129
|
+
/** A machine stamp's `provDetail` with `requestedBy: <id>` added. */
|
|
130
|
+
detail(detail?: Record<string, any>): Record<string, any>;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function makeRequester(id?: string | null, name?: string | null): Requester;
|
|
134
|
+
|
|
135
|
+
/** The requester of one request, from the `requesterId` in a `serve` handler's data, named by display name. */
|
|
136
|
+
export function requesterOf(client: { users: { get(id: string): Promise<any> } }, data: any): Promise<Requester>;
|
|
137
|
+
|
|
138
|
+
/** The cancellation half of a responseHelper, on its own. */
|
|
139
|
+
export function createCancelScope(isCancelled: () => boolean): {
|
|
140
|
+
readonly cancelled: boolean;
|
|
141
|
+
raiseIfCancelled(): void;
|
|
142
|
+
critical<T>(fn: () => T | Promise<T>): Promise<T>;
|
|
143
|
+
};
|
|
144
|
+
|
|
75
145
|
interface SSEConnection {
|
|
76
146
|
close(): void;
|
|
77
147
|
getStats(): any;
|
|
78
148
|
readyState: number;
|
|
149
|
+
/**
|
|
150
|
+
* Once CLOSED, why: null when this side closed it. A refused stream's error
|
|
151
|
+
* carries the HTTP `status`, and one the server ended is named "StreamClosed".
|
|
152
|
+
*/
|
|
153
|
+
error: (Error & { status?: number }) | null;
|
|
79
154
|
}
|
|
80
155
|
|
|
81
156
|
interface VocabLinksBundle {
|
|
82
|
-
create(
|
|
157
|
+
create(
|
|
158
|
+
vocabItem: string,
|
|
159
|
+
tokens: any[],
|
|
160
|
+
metadata?: any,
|
|
161
|
+
auditMessage?: string,
|
|
162
|
+
opts?: { id?: string },
|
|
163
|
+
): Promise<any>;
|
|
83
164
|
bulkCreate(body: any[], auditMessage?: string): Promise<{ ids: string[] }>;
|
|
84
165
|
bulkDelete(body: any[], auditMessage?: string): Promise<void>;
|
|
85
166
|
setMetadata(id: string, body: any, auditMessage?: string): Promise<any>;
|
|
86
167
|
deleteMetadata(id: string, auditMessage?: string): Promise<any>;
|
|
87
|
-
patchMetadata(id: string, body:
|
|
88
|
-
get(id: string
|
|
168
|
+
patchMetadata(id: string, body: MetadataOp[], auditMessage?: string): Promise<any>;
|
|
169
|
+
get(id: string): Promise<any>;
|
|
89
170
|
delete(id: string, auditMessage?: string): Promise<any>;
|
|
90
171
|
}
|
|
91
172
|
|
|
173
|
+
/** What `vocabLayers.restoreItem` did, or with `dryRun` would do. */
|
|
174
|
+
interface VocabItemRestoreSummary {
|
|
175
|
+
/** The entry was gone and came back under its old id. */
|
|
176
|
+
inserted: boolean;
|
|
177
|
+
/** A living entry's form was set back. */
|
|
178
|
+
form: boolean;
|
|
179
|
+
/** A living entry's fields were set back. */
|
|
180
|
+
metadata: boolean;
|
|
181
|
+
/** 0 when nothing changes. */
|
|
182
|
+
total: number;
|
|
183
|
+
}
|
|
184
|
+
|
|
92
185
|
interface VocabLayersBundle {
|
|
186
|
+
/** `asOf` reads the vocabulary as it was at that instant. */
|
|
93
187
|
get(id: string, includeItems?: boolean, asOf?: string): Promise<any>;
|
|
188
|
+
/** One entry as it was at `asOf`, also when it has been deleted since. */
|
|
189
|
+
getItemAt(id: string, itemId: string, asOf: string): Promise<any>;
|
|
190
|
+
/** `itemId` keeps only the changes that wrote that one entry. */
|
|
191
|
+
audit(
|
|
192
|
+
id: string,
|
|
193
|
+
startTime?: string,
|
|
194
|
+
endTime?: string,
|
|
195
|
+
opTypes?: string[] | string,
|
|
196
|
+
itemId?: string,
|
|
197
|
+
kinds?: OperationKind[] | string,
|
|
198
|
+
): Promise<any[]>;
|
|
199
|
+
auditPage(id: string, opts?: AuditPageOptions & { itemId?: string }): Promise<Page>;
|
|
200
|
+
/** Put one entry back as it was at `asOf`. Maintainers of the vocabulary only. */
|
|
201
|
+
restoreItem(
|
|
202
|
+
id: string,
|
|
203
|
+
itemId: string,
|
|
204
|
+
asOf: string,
|
|
205
|
+
options?: { dryRun?: boolean },
|
|
206
|
+
auditMessage?: string,
|
|
207
|
+
): Promise<VocabItemRestoreSummary>;
|
|
94
208
|
delete(id: string, auditMessage?: string): Promise<any>;
|
|
95
209
|
update(id: string, name: string, auditMessage?: string): Promise<any>;
|
|
96
|
-
setConfig(
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
210
|
+
setConfig(
|
|
211
|
+
id: string,
|
|
212
|
+
namespace: string,
|
|
213
|
+
configKey: string,
|
|
214
|
+
configValue: any,
|
|
215
|
+
auditMessage?: string,
|
|
216
|
+
options?: ConfigWriteOptions,
|
|
217
|
+
): Promise<any>;
|
|
218
|
+
deleteConfig(
|
|
219
|
+
id: string,
|
|
220
|
+
namespace: string,
|
|
221
|
+
configKey: string,
|
|
222
|
+
auditMessage?: string,
|
|
223
|
+
options?: ConfigWriteOptions,
|
|
224
|
+
): Promise<any>;
|
|
225
|
+
list(): Promise<any[]>;
|
|
226
|
+
listPage(opts?: { limit?: number; cursor?: string }): Promise<Page>;
|
|
227
|
+
iterPages(opts?: { pageSize?: number }): AsyncGenerator<any[]>;
|
|
228
|
+
create(name: string, auditMessage?: string, opts?: { id?: string }): Promise<any>;
|
|
229
|
+
addMaintainer(
|
|
230
|
+
id: string,
|
|
231
|
+
userId: string,
|
|
232
|
+
auditMessage?: string,
|
|
233
|
+
): Promise<any>;
|
|
234
|
+
removeMaintainer(
|
|
235
|
+
id: string,
|
|
236
|
+
userId: string,
|
|
237
|
+
auditMessage?: string,
|
|
238
|
+
): Promise<any>;
|
|
104
239
|
}
|
|
105
240
|
|
|
106
241
|
interface RelationsBundle {
|
|
107
|
-
setMetadata(
|
|
242
|
+
setMetadata(
|
|
243
|
+
relationId: string,
|
|
244
|
+
body: any,
|
|
245
|
+
auditMessage?: string,
|
|
246
|
+
): Promise<any>;
|
|
108
247
|
deleteMetadata(relationId: string, auditMessage?: string): Promise<any>;
|
|
109
|
-
patchMetadata(
|
|
110
|
-
|
|
111
|
-
|
|
248
|
+
patchMetadata(
|
|
249
|
+
relationId: string,
|
|
250
|
+
body: MetadataOp[],
|
|
251
|
+
auditMessage?: string,
|
|
252
|
+
): Promise<any>;
|
|
253
|
+
setTarget(
|
|
254
|
+
relationId: string,
|
|
255
|
+
spanId: string,
|
|
256
|
+
auditMessage?: string,
|
|
257
|
+
): Promise<any>;
|
|
258
|
+
get(relationId: string): Promise<any>;
|
|
112
259
|
delete(relationId: string, auditMessage?: string): Promise<any>;
|
|
113
260
|
update(relationId: string, value: any, auditMessage?: string): Promise<any>;
|
|
114
|
-
setSource(
|
|
115
|
-
|
|
261
|
+
setSource(
|
|
262
|
+
relationId: string,
|
|
263
|
+
spanId: string,
|
|
264
|
+
auditMessage?: string,
|
|
265
|
+
): Promise<any>;
|
|
266
|
+
create(
|
|
267
|
+
layerId: string,
|
|
268
|
+
sourceId: string,
|
|
269
|
+
targetId: string,
|
|
270
|
+
value: any,
|
|
271
|
+
metadata?: any,
|
|
272
|
+
auditMessage?: string,
|
|
273
|
+
opts?: { id?: string },
|
|
274
|
+
): Promise<any>;
|
|
116
275
|
bulkCreate(body: any[], auditMessage?: string): Promise<{ ids: string[] }>;
|
|
117
276
|
bulkDelete(body: any[], auditMessage?: string): Promise<void>;
|
|
277
|
+
bulkUpdate(body: any[], auditMessage?: string): Promise<{ count: number }>;
|
|
118
278
|
}
|
|
119
279
|
|
|
120
280
|
interface SpanLayersBundle {
|
|
121
|
-
setConfig(
|
|
122
|
-
|
|
123
|
-
|
|
281
|
+
setConfig(
|
|
282
|
+
spanLayerId: string,
|
|
283
|
+
namespace: string,
|
|
284
|
+
configKey: string,
|
|
285
|
+
configValue: any,
|
|
286
|
+
auditMessage?: string,
|
|
287
|
+
options?: ConfigWriteOptions,
|
|
288
|
+
): Promise<any>;
|
|
289
|
+
deleteConfig(
|
|
290
|
+
spanLayerId: string,
|
|
291
|
+
namespace: string,
|
|
292
|
+
configKey: string,
|
|
293
|
+
auditMessage?: string,
|
|
294
|
+
options?: ConfigWriteOptions,
|
|
295
|
+
): Promise<any>;
|
|
296
|
+
get(spanLayerId: string): Promise<any>;
|
|
124
297
|
delete(spanLayerId: string, auditMessage?: string): Promise<any>;
|
|
125
|
-
update(
|
|
126
|
-
|
|
127
|
-
|
|
298
|
+
update(
|
|
299
|
+
spanLayerId: string,
|
|
300
|
+
name: string,
|
|
301
|
+
auditMessage?: string,
|
|
302
|
+
): Promise<any>;
|
|
303
|
+
create(
|
|
304
|
+
tokenLayerId: string,
|
|
305
|
+
name: string,
|
|
306
|
+
auditMessage?: string,
|
|
307
|
+
opts?: { id?: string },
|
|
308
|
+
): Promise<any>;
|
|
309
|
+
shift(
|
|
310
|
+
spanLayerId: string,
|
|
311
|
+
direction: string,
|
|
312
|
+
auditMessage?: string,
|
|
313
|
+
): Promise<any>;
|
|
314
|
+
setConstraints(
|
|
315
|
+
layerId: string,
|
|
316
|
+
namespace: string,
|
|
317
|
+
constraints: LayerConstraint[],
|
|
318
|
+
auditMessage?: string,
|
|
319
|
+
options?: ConstraintWriteOptions,
|
|
320
|
+
): Promise<{ constraints: Record<string, LayerConstraint[]> }>;
|
|
321
|
+
deleteConstraints(
|
|
322
|
+
layerId: string,
|
|
323
|
+
namespace: string,
|
|
324
|
+
auditMessage?: string,
|
|
325
|
+
options?: ConstraintWriteOptions,
|
|
326
|
+
): Promise<any>;
|
|
327
|
+
checkConstraints(
|
|
328
|
+
layerId: string,
|
|
329
|
+
constraints: LayerConstraint[],
|
|
330
|
+
): Promise<{ violations: ConstraintViolation[]; violationCount: number }>;
|
|
331
|
+
repairConstraints(
|
|
332
|
+
layerId: string,
|
|
333
|
+
constraints: LayerConstraint[],
|
|
334
|
+
auditMessage?: string,
|
|
335
|
+
options?: { document?: string },
|
|
336
|
+
): Promise<{
|
|
337
|
+
repaired: { document: string; constraint: string; deleted: number; joined: number }[];
|
|
338
|
+
locked: { document: string; lockedBy: string }[];
|
|
339
|
+
violations: ConstraintViolation[];
|
|
340
|
+
violationCount: number;
|
|
341
|
+
}>;
|
|
128
342
|
}
|
|
129
343
|
|
|
130
344
|
interface SpansBundle {
|
|
131
345
|
setTokens(spanId: string, tokens: any[], auditMessage?: string): Promise<any>;
|
|
132
|
-
create(
|
|
133
|
-
|
|
346
|
+
create(
|
|
347
|
+
spanLayerId: string,
|
|
348
|
+
tokens: any[],
|
|
349
|
+
value: any,
|
|
350
|
+
metadata?: any,
|
|
351
|
+
auditMessage?: string,
|
|
352
|
+
opts?: { id?: string },
|
|
353
|
+
): Promise<any>;
|
|
354
|
+
get(spanId: string): Promise<any>;
|
|
134
355
|
delete(spanId: string, auditMessage?: string): Promise<any>;
|
|
135
356
|
update(spanId: string, value: any, auditMessage?: string): Promise<any>;
|
|
136
357
|
bulkCreate(body: any[], auditMessage?: string): Promise<{ ids: string[] }>;
|
|
137
358
|
bulkDelete(body: any[], auditMessage?: string): Promise<void>;
|
|
359
|
+
bulkUpdate(body: any[], auditMessage?: string): Promise<{ count: number }>;
|
|
138
360
|
setMetadata(spanId: string, body: any, auditMessage?: string): Promise<any>;
|
|
139
361
|
deleteMetadata(spanId: string, auditMessage?: string): Promise<any>;
|
|
140
|
-
patchMetadata(spanId: string, body:
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
interface BatchBundle {
|
|
144
|
-
submit(body: any[], auditMessage?: string): Promise<any>;
|
|
362
|
+
patchMetadata(spanId: string, body: MetadataOp[], auditMessage?: string): Promise<any>;
|
|
145
363
|
}
|
|
146
364
|
|
|
147
365
|
interface TextsBundle {
|
|
148
366
|
setMetadata(textId: string, body: any, auditMessage?: string): Promise<any>;
|
|
149
367
|
deleteMetadata(textId: string, auditMessage?: string): Promise<any>;
|
|
150
|
-
patchMetadata(textId: string, body:
|
|
151
|
-
create(
|
|
152
|
-
|
|
368
|
+
patchMetadata(textId: string, body: MetadataOp[], auditMessage?: string): Promise<any>;
|
|
369
|
+
create(
|
|
370
|
+
textLayerId: string,
|
|
371
|
+
documentId: string,
|
|
372
|
+
body: string,
|
|
373
|
+
metadata?: any,
|
|
374
|
+
auditMessage?: string,
|
|
375
|
+
opts?: { id?: string },
|
|
376
|
+
): Promise<any>;
|
|
377
|
+
get(textId: string): Promise<any>;
|
|
153
378
|
delete(textId: string, auditMessage?: string): Promise<any>;
|
|
154
|
-
|
|
379
|
+
/** With `base` (a text's `digest`) the update applies only to that body. */
|
|
380
|
+
update(textId: string, body: any, auditMessage?: string, opts?: { base?: string; versioned?: boolean }): Promise<any>;
|
|
381
|
+
/** Edits made at the caret; with `base` they apply only to that body. Answers the text with `digest` and `reshape`. */
|
|
382
|
+
edit(textId: string, edits: TextEditOp[], auditMessage?: string, opts?: { base?: string; versioned?: boolean }): Promise<any>;
|
|
155
383
|
}
|
|
156
384
|
|
|
157
385
|
interface UsersBundle {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
386
|
+
/** `q` narrows to users whose id or display name contains it (admin or maintainer). */
|
|
387
|
+
list(opts?: { q?: string }): Promise<any[]>;
|
|
388
|
+
listPage(opts?: { q?: string; limit?: number; cursor?: string }): Promise<Page>;
|
|
389
|
+
iterPages(opts?: { q?: string; pageSize?: number }): AsyncGenerator<any[]>;
|
|
390
|
+
create(
|
|
391
|
+
email: string,
|
|
392
|
+
password: string,
|
|
393
|
+
isAdmin: boolean,
|
|
394
|
+
displayName?: string,
|
|
395
|
+
auditMessage?: string,
|
|
396
|
+
): Promise<any>;
|
|
397
|
+
audit(
|
|
398
|
+
userId: string,
|
|
399
|
+
startTime?: string,
|
|
400
|
+
endTime?: string,
|
|
401
|
+
opTypes?: string[] | string,
|
|
402
|
+
kinds?: OperationKind[] | string,
|
|
403
|
+
): Promise<any[]>;
|
|
404
|
+
auditPage(userId: string, opts?: AuditPageOptions): Promise<Page>;
|
|
405
|
+
get(id: string): Promise<any>;
|
|
164
406
|
delete(id: string, auditMessage?: string): Promise<any>;
|
|
165
407
|
activate(id: string, auditMessage?: string): Promise<any>;
|
|
166
|
-
update(
|
|
408
|
+
update(
|
|
409
|
+
id: string,
|
|
410
|
+
password?: string,
|
|
411
|
+
displayName?: string,
|
|
412
|
+
isAdmin?: boolean,
|
|
413
|
+
auditMessage?: string,
|
|
414
|
+
): Promise<any>;
|
|
167
415
|
/** URL for a user's profile picture, usable as an <img> src. Null when avatarHash is explicitly null. */
|
|
168
416
|
avatarUrl(id: string, avatarHash?: string | null): string | null;
|
|
169
417
|
getAvatar(id: string): Promise<any>;
|
|
@@ -171,11 +419,247 @@ interface UsersBundle {
|
|
|
171
419
|
deleteAvatar(id: string, auditMessage?: string): Promise<any>;
|
|
172
420
|
}
|
|
173
421
|
|
|
422
|
+
interface UserDataEntry {
|
|
423
|
+
key: string;
|
|
424
|
+
updatedAt: string;
|
|
425
|
+
value?: any;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
interface UserDataOptions {
|
|
429
|
+
prefix?: string;
|
|
430
|
+
pattern?: string;
|
|
431
|
+
includeValues?: boolean;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/** Private per-user key/value storage (owner or admin only; not audited). */
|
|
435
|
+
interface UserDataBundle {
|
|
436
|
+
list(
|
|
437
|
+
userId: string,
|
|
438
|
+
opts?: UserDataOptions & { pageSize?: number },
|
|
439
|
+
): Promise<UserDataEntry[]>;
|
|
440
|
+
listPage(
|
|
441
|
+
userId: string,
|
|
442
|
+
opts?: UserDataOptions & { limit?: number; cursor?: string },
|
|
443
|
+
): Promise<Page<UserDataEntry>>;
|
|
444
|
+
iterPages(
|
|
445
|
+
userId: string,
|
|
446
|
+
opts?: UserDataOptions & { pageSize?: number },
|
|
447
|
+
): AsyncGenerator<UserDataEntry[]>;
|
|
448
|
+
get(userId: string, key: string): Promise<UserDataEntry & { value: any }>;
|
|
449
|
+
put(
|
|
450
|
+
userId: string,
|
|
451
|
+
key: string,
|
|
452
|
+
value: any,
|
|
453
|
+
): Promise<{ key: string; updatedAt: string }>;
|
|
454
|
+
delete(userId: string, key: string): Promise<any>;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
interface CommentFilters {
|
|
458
|
+
documentId?: string;
|
|
459
|
+
entityType?: CommentableType;
|
|
460
|
+
entityId?: string;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/** Entities that can carry a comment. */
|
|
464
|
+
type CommentableType =
|
|
465
|
+
"document" | "text" | "token" | "span" | "relation" | "vocab-item";
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* One entry in a project's annotation manual: a short Markdown document
|
|
469
|
+
* stating a convention the project follows. Read by the people on the
|
|
470
|
+
* project, and by the assistant before it proposes anything.
|
|
471
|
+
*/
|
|
472
|
+
interface Guideline {
|
|
473
|
+
id: string;
|
|
474
|
+
projectId: string;
|
|
475
|
+
/** The handle the assistant asks for a guideline by. Not required to be unique. */
|
|
476
|
+
title: string;
|
|
477
|
+
/** The Markdown text. Present on a single read and on a list made with `includeBodies`. */
|
|
478
|
+
body?: string;
|
|
479
|
+
/** The body's length in characters. Present on a list made WITHOUT `includeBodies`. */
|
|
480
|
+
bodyChars?: number;
|
|
481
|
+
/** Whether the assistant is given this one in full on every turn. */
|
|
482
|
+
pinned: boolean;
|
|
483
|
+
createdAt: string;
|
|
484
|
+
updatedAt: string;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
interface GuidelinesBundle {
|
|
488
|
+
create(
|
|
489
|
+
projectId: string,
|
|
490
|
+
title: string,
|
|
491
|
+
opts?: { body?: string; pinned?: boolean; id?: string },
|
|
492
|
+
auditMessage?: string,
|
|
493
|
+
): Promise<{ id: string }>;
|
|
494
|
+
get(id: string): Promise<Guideline>;
|
|
495
|
+
update(
|
|
496
|
+
id: string,
|
|
497
|
+
changes?: {
|
|
498
|
+
title?: string;
|
|
499
|
+
body?: string;
|
|
500
|
+
pinned?: boolean;
|
|
501
|
+
/** Write only if this is still the stored updatedAt; 409 otherwise. */
|
|
502
|
+
expectedUpdatedAt?: string;
|
|
503
|
+
},
|
|
504
|
+
auditMessage?: string,
|
|
505
|
+
): Promise<Guideline>;
|
|
506
|
+
delete(id: string, auditMessage?: string): Promise<any>;
|
|
507
|
+
list(
|
|
508
|
+
projectId: string,
|
|
509
|
+
opts?: { includeBodies?: boolean },
|
|
510
|
+
): Promise<Guideline[]>;
|
|
511
|
+
listPage(
|
|
512
|
+
projectId: string,
|
|
513
|
+
opts?: { includeBodies?: boolean; limit?: number; cursor?: string },
|
|
514
|
+
): Promise<Page<Guideline>>;
|
|
515
|
+
iterPages(
|
|
516
|
+
projectId: string,
|
|
517
|
+
opts?: { includeBodies?: boolean; pageSize?: number },
|
|
518
|
+
): AsyncGenerator<Guideline[]>;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
interface Comment {
|
|
522
|
+
id: string;
|
|
523
|
+
/** The owning project, or null for a comment on a vocabulary entry. */
|
|
524
|
+
projectId: string | null;
|
|
525
|
+
/** The owning document, or null for a comment on a vocabulary entry. */
|
|
526
|
+
documentId: string | null;
|
|
527
|
+
/** The owning vocab layer, set only for a comment on a vocabulary entry. */
|
|
528
|
+
vocabLayerId: string | null;
|
|
529
|
+
entityType: CommentableType;
|
|
530
|
+
entityId: string;
|
|
531
|
+
/**
|
|
532
|
+
* What the comment is about, in words, captured when it was posted. A
|
|
533
|
+
* comment outlives its anchor, and this is what is left to show once the
|
|
534
|
+
* anchor has been deleted.
|
|
535
|
+
*/
|
|
536
|
+
anchorLabel: string | null;
|
|
537
|
+
authorId: string;
|
|
538
|
+
body: string;
|
|
539
|
+
createdAt: string;
|
|
540
|
+
updatedAt: string;
|
|
541
|
+
/** True once the body has been rewritten since it was posted. */
|
|
542
|
+
edited: boolean;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
/** A research-telemetry event type (core manual, "Research telemetry"). */
|
|
546
|
+
type ClientEventType =
|
|
547
|
+
| "suggestion.shown"
|
|
548
|
+
| "suggestion.adopted"
|
|
549
|
+
| "suggestion.dismissed"
|
|
550
|
+
| "plan.opened";
|
|
551
|
+
|
|
552
|
+
interface ClientEventFields {
|
|
553
|
+
projectId: string;
|
|
554
|
+
documentId?: string;
|
|
555
|
+
targetId?: string;
|
|
556
|
+
/** Keyed by single lowercase words: value, source, field, written, conversation. */
|
|
557
|
+
data?: Record<string, any>;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
interface ClientEvent {
|
|
561
|
+
id: number;
|
|
562
|
+
projectId: string;
|
|
563
|
+
documentId: string | null;
|
|
564
|
+
userId: string;
|
|
565
|
+
type: ClientEventType;
|
|
566
|
+
targetId: string | null;
|
|
567
|
+
data: Record<string, any> | null;
|
|
568
|
+
clientTs: string | null;
|
|
569
|
+
ts: string;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
interface ClientEventFilters {
|
|
573
|
+
types?: ClientEventType | ClientEventType[] | string;
|
|
574
|
+
startTime?: string;
|
|
575
|
+
endTime?: string;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
interface EventsBundle {
|
|
579
|
+
/** Buffer one event; never throws. False when not recorded (switch off, a repeat shown). */
|
|
580
|
+
record(type: ClientEventType, fields: ClientEventFields): boolean;
|
|
581
|
+
flush(): void;
|
|
582
|
+
setEnabled(projectId: string, on: boolean): void;
|
|
583
|
+
create(
|
|
584
|
+
projectId: string,
|
|
585
|
+
events: Array<{
|
|
586
|
+
type: ClientEventType;
|
|
587
|
+
documentId?: string;
|
|
588
|
+
targetId?: string;
|
|
589
|
+
data?: Record<string, any>;
|
|
590
|
+
clientTs?: string;
|
|
591
|
+
}>,
|
|
592
|
+
): Promise<{ count: number }>;
|
|
593
|
+
list(projectId: string, filters?: ClientEventFilters): Promise<ClientEvent[]>;
|
|
594
|
+
listPage(
|
|
595
|
+
projectId: string,
|
|
596
|
+
opts?: ClientEventFilters & { limit?: number; cursor?: string },
|
|
597
|
+
): Promise<Page<ClientEvent>>;
|
|
598
|
+
iterPages(
|
|
599
|
+
projectId: string,
|
|
600
|
+
opts?: ClientEventFilters & { pageSize?: number },
|
|
601
|
+
): AsyncGenerator<ClientEvent[]>;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
interface CommentsBundle {
|
|
605
|
+
create(
|
|
606
|
+
entityType: CommentableType,
|
|
607
|
+
entityId: string,
|
|
608
|
+
body: string,
|
|
609
|
+
opts?: { anchorLabel?: string; id?: string },
|
|
610
|
+
): Promise<Comment>;
|
|
611
|
+
get(id: string): Promise<Comment>;
|
|
612
|
+
update(id: string, body: string): Promise<Comment>;
|
|
613
|
+
delete(id: string): Promise<any>;
|
|
614
|
+
list(projectId: string, filters?: CommentFilters): Promise<Comment[]>;
|
|
615
|
+
listPage(
|
|
616
|
+
projectId: string,
|
|
617
|
+
opts?: CommentFilters & { limit?: number; cursor?: string },
|
|
618
|
+
): Promise<Page<Comment>>;
|
|
619
|
+
iterPages(
|
|
620
|
+
projectId: string,
|
|
621
|
+
opts?: CommentFilters & { pageSize?: number },
|
|
622
|
+
): AsyncGenerator<Comment[]>;
|
|
623
|
+
/** `{entityId: count}`; keys are raw entity ids, never key-transformed. */
|
|
624
|
+
counts(
|
|
625
|
+
projectId: string,
|
|
626
|
+
filters?: CommentFilters,
|
|
627
|
+
): Promise<Record<string, number>>;
|
|
628
|
+
/** Comments on a vocabulary's entries, oldest first. */
|
|
629
|
+
listInVocab(
|
|
630
|
+
vocabId: string,
|
|
631
|
+
filters?: { entityId?: string },
|
|
632
|
+
): Promise<Comment[]>;
|
|
633
|
+
listInVocabPage(
|
|
634
|
+
vocabId: string,
|
|
635
|
+
opts?: { entityId?: string; limit?: number; cursor?: string },
|
|
636
|
+
): Promise<Page<Comment>>;
|
|
637
|
+
iterInVocabPages(
|
|
638
|
+
vocabId: string,
|
|
639
|
+
opts?: { entityId?: string; pageSize?: number },
|
|
640
|
+
): AsyncGenerator<Comment[]>;
|
|
641
|
+
/** `{entryId: count}` over a vocabulary; keys are raw entry ids. */
|
|
642
|
+
countsInVocab(
|
|
643
|
+
vocabId: string,
|
|
644
|
+
filters?: { entityId?: string },
|
|
645
|
+
): Promise<Record<string, number>>;
|
|
646
|
+
}
|
|
647
|
+
|
|
174
648
|
interface ApiTokensBundle {
|
|
175
649
|
list(userId: string): Promise<any[]>;
|
|
176
|
-
listPage(
|
|
177
|
-
|
|
178
|
-
|
|
650
|
+
listPage(
|
|
651
|
+
userId: string,
|
|
652
|
+
opts?: { limit?: number; cursor?: string },
|
|
653
|
+
): Promise<Page>;
|
|
654
|
+
iterPages(
|
|
655
|
+
userId: string,
|
|
656
|
+
opts?: { pageSize?: number },
|
|
657
|
+
): AsyncGenerator<any[]>;
|
|
658
|
+
create(
|
|
659
|
+
userId: string,
|
|
660
|
+
name: string,
|
|
661
|
+
auditMessage?: string,
|
|
662
|
+
): Promise<{ id: string; name: string; token: string }>;
|
|
179
663
|
revoke(userId: string, tokenId: string, auditMessage?: string): Promise<any>;
|
|
180
664
|
}
|
|
181
665
|
|
|
@@ -207,8 +691,8 @@ interface InvitePreview {
|
|
|
207
691
|
grantAdmin: boolean;
|
|
208
692
|
projectName?: string;
|
|
209
693
|
projectRole?: string;
|
|
210
|
-
/** Present only for a password reset:
|
|
211
|
-
|
|
694
|
+
/** Present only for a password reset: the email of the account it belongs to. */
|
|
695
|
+
email?: string;
|
|
212
696
|
}
|
|
213
697
|
|
|
214
698
|
interface CreateInviteOptions {
|
|
@@ -223,52 +707,536 @@ interface CreateInviteOptions {
|
|
|
223
707
|
note?: string;
|
|
224
708
|
}
|
|
225
709
|
|
|
710
|
+
/** Server limits, as reported by /api/v1/info. An unset limit is absent. */
|
|
711
|
+
interface ServerLimits {
|
|
712
|
+
mediaFileBytes?: number;
|
|
713
|
+
jsonBodyBytes?: number;
|
|
714
|
+
batchOperations?: number;
|
|
715
|
+
metadataDepth?: number;
|
|
716
|
+
metadataKeyCount?: number;
|
|
717
|
+
metadataStringLength?: number;
|
|
718
|
+
metadataTotalBytes?: number;
|
|
719
|
+
userDataValueBytes?: number;
|
|
720
|
+
guidelineTitleLength?: number;
|
|
721
|
+
guidelineBodyLength?: number;
|
|
722
|
+
/** The shortest password the server accepts on any path. */
|
|
723
|
+
passwordMinLength?: number;
|
|
724
|
+
/** How long a document lock is held before it lapses. */
|
|
725
|
+
lockExpirationMs?: number;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
interface ServerHealth {
|
|
729
|
+
ok: boolean;
|
|
730
|
+
version: string;
|
|
731
|
+
uptimeMs: number;
|
|
732
|
+
audit: { dbSizeMb?: number; auditRows?: number; error?: string };
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
/** A document lock as the admin lock listing reports it. */
|
|
736
|
+
interface DocumentLockInfo {
|
|
737
|
+
documentId: string;
|
|
738
|
+
userId: string;
|
|
739
|
+
expiresAt: number;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
interface RateLimitBucket {
|
|
743
|
+
ip: string;
|
|
744
|
+
userId?: string;
|
|
745
|
+
failures: number;
|
|
746
|
+
limit: number;
|
|
747
|
+
blocked: boolean;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
interface RateLimitSnapshot {
|
|
751
|
+
windowMs: number;
|
|
752
|
+
logins: RateLimitBucket[];
|
|
753
|
+
ips: RateLimitBucket[];
|
|
754
|
+
invites: RateLimitBucket[];
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
interface BackupStatus {
|
|
758
|
+
enabled: boolean;
|
|
759
|
+
directory: string;
|
|
760
|
+
retention: number;
|
|
761
|
+
time: string;
|
|
762
|
+
backups: Array<{ name: string; bytes: number; modified: string }>;
|
|
763
|
+
ok?: boolean;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
interface ServerReport {
|
|
767
|
+
version: string;
|
|
768
|
+
jvm: {
|
|
769
|
+
uptimeMs: number;
|
|
770
|
+
startedAt: string;
|
|
771
|
+
java: string;
|
|
772
|
+
heapUsed: number;
|
|
773
|
+
heapMax: number;
|
|
774
|
+
};
|
|
775
|
+
database: {
|
|
776
|
+
path: string | null;
|
|
777
|
+
bytes: number | null;
|
|
778
|
+
walBytes: number | null;
|
|
779
|
+
slowQueryThresholdMs?: number;
|
|
780
|
+
journalMode?: string;
|
|
781
|
+
maxPoolSize?: number;
|
|
782
|
+
tables: Record<string, number | null>;
|
|
783
|
+
};
|
|
784
|
+
media: {
|
|
785
|
+
directory: string;
|
|
786
|
+
files: number;
|
|
787
|
+
bytes: number;
|
|
788
|
+
orphans: number;
|
|
789
|
+
orphanBytes: number;
|
|
790
|
+
};
|
|
791
|
+
backup: BackupStatus;
|
|
792
|
+
settings: Record<string, any>;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
/** The signed-in user's sign-ins. Signing in is `PlaidClient.login`. */
|
|
796
|
+
interface AuthBundle {
|
|
797
|
+
/**
|
|
798
|
+
* End every sign-in of this user on every device, this client's included.
|
|
799
|
+
* Named API tokens are not affected. Goes out at once even on a batch.
|
|
800
|
+
*/
|
|
801
|
+
logoutEverywhere(): Promise<void>;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
/** Server-level facts. `info` is fetched at most once per client. */
|
|
805
|
+
interface ServerBundle {
|
|
806
|
+
info(): Promise<{ limits: ServerLimits }>;
|
|
807
|
+
limits(): Promise<ServerLimits>;
|
|
808
|
+
health(): Promise<ServerHealth>;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
/** Instance-wide operations. Every method requires a global admin. */
|
|
812
|
+
interface AdminBundle {
|
|
813
|
+
server(): Promise<ServerReport>;
|
|
814
|
+
backup(): Promise<BackupStatus>;
|
|
815
|
+
locks(): Promise<{ entries: DocumentLockInfo[] }>;
|
|
816
|
+
releaseLock(documentId: string): Promise<{ result: string }>;
|
|
817
|
+
rateLimits(): Promise<RateLimitSnapshot>;
|
|
818
|
+
clearRateLimits(opts?: {
|
|
819
|
+
ip?: string;
|
|
820
|
+
userId?: string;
|
|
821
|
+
}): Promise<{ result: string }>;
|
|
822
|
+
logs(opts?: {
|
|
823
|
+
limit?: number;
|
|
824
|
+
q?: string;
|
|
825
|
+
level?: string;
|
|
826
|
+
status?: string;
|
|
827
|
+
user?: string;
|
|
828
|
+
method?: string;
|
|
829
|
+
}): Promise<LiveLog>;
|
|
830
|
+
logFile(opts?: {
|
|
831
|
+
lines?: number;
|
|
832
|
+
}): Promise<{ file: string | null; lines: string[]; error?: string }>;
|
|
833
|
+
userData(opts?: AdminUserDataOptions): Promise<AdminUserDataEntry[]>;
|
|
834
|
+
userDataPage(
|
|
835
|
+
opts?: AdminUserDataOptions & { limit?: number; cursor?: string },
|
|
836
|
+
): Promise<Page<AdminUserDataEntry>>;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
/** One HTTP request as the log buffer holds it. */
|
|
840
|
+
interface LoggedRequest {
|
|
841
|
+
/** Epoch milliseconds. */
|
|
842
|
+
ts: number;
|
|
843
|
+
method: string;
|
|
844
|
+
path: string;
|
|
845
|
+
/** Query string with sensitive values replaced, or null. */
|
|
846
|
+
query: string | null;
|
|
847
|
+
/** Null when the handler threw before producing one. */
|
|
848
|
+
status: number | null;
|
|
849
|
+
ms: number;
|
|
850
|
+
/** Null for a request nobody was authenticated for. */
|
|
851
|
+
user: string | null;
|
|
852
|
+
ip: string | null;
|
|
853
|
+
/** Set when a named API token signed the request. */
|
|
854
|
+
token: string | null;
|
|
855
|
+
/** Exception class, when the handler threw. */
|
|
856
|
+
error: string | null;
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
/** One log event that was not a request. */
|
|
860
|
+
interface LoggedEvent {
|
|
861
|
+
ts: number;
|
|
862
|
+
level: string;
|
|
863
|
+
ns: string;
|
|
864
|
+
message: string;
|
|
865
|
+
trace?: string;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
/**
|
|
869
|
+
* The live log. Requests and events are buffered separately, so a burst of
|
|
870
|
+
* requests cannot evict an error.
|
|
871
|
+
*/
|
|
872
|
+
interface LiveLog {
|
|
873
|
+
requests: {
|
|
874
|
+
entries: LoggedRequest[];
|
|
875
|
+
/** How many passed the filters, which may exceed what `entries` holds. */
|
|
876
|
+
matched: number;
|
|
877
|
+
/** How many are buffered in total. */
|
|
878
|
+
held: number;
|
|
879
|
+
capacity: number;
|
|
880
|
+
stats: {
|
|
881
|
+
count: number;
|
|
882
|
+
failures: number;
|
|
883
|
+
serverErrors: number;
|
|
884
|
+
p50: number | null;
|
|
885
|
+
p95: number | null;
|
|
886
|
+
max: number | null;
|
|
887
|
+
perMinute: number | null;
|
|
888
|
+
oldest: number | null;
|
|
889
|
+
newest: number | null;
|
|
890
|
+
};
|
|
891
|
+
};
|
|
892
|
+
events: {
|
|
893
|
+
entries: LoggedEvent[];
|
|
894
|
+
matched: number;
|
|
895
|
+
held: number;
|
|
896
|
+
capacity: number;
|
|
897
|
+
/** Counts per level of what the search matched, before the level filter. */
|
|
898
|
+
byLevel: Record<string, number>;
|
|
899
|
+
};
|
|
900
|
+
/** Absolute path of the configured log file, or null when logging to stdout. */
|
|
901
|
+
file: string | null;
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
/** Narrowings for the cross-account private-data listing. */
|
|
905
|
+
interface AdminUserDataOptions {
|
|
906
|
+
/** Only keys starting with this literal head. */
|
|
907
|
+
prefix?: string;
|
|
908
|
+
/** Only keys matching this GLOB (`*` any run, `?` one character). */
|
|
909
|
+
pattern?: string;
|
|
910
|
+
includeValues?: boolean;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
type AdminUserDataEntry = UserDataEntry & { userId: string };
|
|
914
|
+
|
|
915
|
+
/** Options for a single page of any audit log. */
|
|
916
|
+
interface AuditPageOptions {
|
|
917
|
+
startTime?: string;
|
|
918
|
+
endTime?: string;
|
|
919
|
+
opTypes?: string[] | string;
|
|
920
|
+
/** Only the entries of operations of these kinds, each whole. */
|
|
921
|
+
kinds?: OperationKind[] | string;
|
|
922
|
+
/** "desc" pages newest-first; a cursor belongs to the direction that made it. */
|
|
923
|
+
order?: "asc" | "desc";
|
|
924
|
+
limit?: number;
|
|
925
|
+
cursor?: string;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
/** One user's activity over a scope and window. */
|
|
929
|
+
interface ActivityTallyRow {
|
|
930
|
+
user: { id: string; displayName?: string };
|
|
931
|
+
operations: number;
|
|
932
|
+
changes: number;
|
|
933
|
+
documents: number;
|
|
934
|
+
firstTs: string;
|
|
935
|
+
lastTs: string;
|
|
936
|
+
byDay?: Array<{ date: string; changes: number }>;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
/** Instance-wide audit reads and the per-user aggregate. */
|
|
940
|
+
interface AuditBundle {
|
|
941
|
+
/** Admin only. */
|
|
942
|
+
list(opts?: {
|
|
943
|
+
startTime?: string;
|
|
944
|
+
endTime?: string;
|
|
945
|
+
opTypes?: string[] | string;
|
|
946
|
+
kinds?: OperationKind[] | string;
|
|
947
|
+
}): Promise<any[]>;
|
|
948
|
+
/** Admin only. */
|
|
949
|
+
listPage(opts?: AuditPageOptions): Promise<Page>;
|
|
950
|
+
/** Admin only. */
|
|
951
|
+
iterPages(opts?: {
|
|
952
|
+
startTime?: string;
|
|
953
|
+
endTime?: string;
|
|
954
|
+
opTypes?: string[] | string;
|
|
955
|
+
kinds?: OperationKind[] | string;
|
|
956
|
+
pageSize?: number;
|
|
957
|
+
}): AsyncGenerator<any[]>;
|
|
958
|
+
/** With projectId, open to that project's maintainers; without one, admin only. */
|
|
959
|
+
tally(opts?: {
|
|
960
|
+
projectId?: string;
|
|
961
|
+
startTime?: string;
|
|
962
|
+
endTime?: string;
|
|
963
|
+
daily?: boolean;
|
|
964
|
+
}): Promise<ActivityTallyRow[]>;
|
|
965
|
+
}
|
|
966
|
+
|
|
226
967
|
interface InvitesBundle {
|
|
227
|
-
list(opts?: { projectId?: string }): Promise<Invite[]>;
|
|
228
|
-
listPage(opts?: {
|
|
229
|
-
|
|
968
|
+
list(opts?: { projectId?: string; all?: boolean }): Promise<Invite[]>;
|
|
969
|
+
listPage(opts?: {
|
|
970
|
+
projectId?: string;
|
|
971
|
+
all?: boolean;
|
|
972
|
+
limit?: number;
|
|
973
|
+
cursor?: string;
|
|
974
|
+
}): Promise<Page>;
|
|
975
|
+
iterPages(opts?: {
|
|
976
|
+
projectId?: string;
|
|
977
|
+
all?: boolean;
|
|
978
|
+
pageSize?: number;
|
|
979
|
+
}): AsyncGenerator<Invite[]>;
|
|
230
980
|
/** The `code` is returned ONCE and is not recoverable afterward. */
|
|
231
|
-
create(
|
|
981
|
+
create(
|
|
982
|
+
opts?: CreateInviteOptions,
|
|
983
|
+
auditMessage?: string,
|
|
984
|
+
): Promise<Invite & { code: string }>;
|
|
232
985
|
revoke(id: string, auditMessage?: string): Promise<any>;
|
|
233
986
|
}
|
|
234
987
|
|
|
235
988
|
interface TokenLayersBundle {
|
|
236
|
-
shift(
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
989
|
+
shift(
|
|
990
|
+
tokenLayerId: string,
|
|
991
|
+
direction: string,
|
|
992
|
+
auditMessage?: string,
|
|
993
|
+
): Promise<any>;
|
|
994
|
+
create(
|
|
995
|
+
textLayerId: string,
|
|
996
|
+
name: string,
|
|
997
|
+
overlapMode?: string,
|
|
998
|
+
parentTokenLayerId?: string,
|
|
999
|
+
auditMessage?: string,
|
|
1000
|
+
opts?: { id?: string },
|
|
1001
|
+
): Promise<any>;
|
|
1002
|
+
setConfig(
|
|
1003
|
+
tokenLayerId: string,
|
|
1004
|
+
namespace: string,
|
|
1005
|
+
configKey: string,
|
|
1006
|
+
configValue: any,
|
|
1007
|
+
auditMessage?: string,
|
|
1008
|
+
options?: ConfigWriteOptions,
|
|
1009
|
+
): Promise<any>;
|
|
1010
|
+
deleteConfig(
|
|
1011
|
+
tokenLayerId: string,
|
|
1012
|
+
namespace: string,
|
|
1013
|
+
configKey: string,
|
|
1014
|
+
auditMessage?: string,
|
|
1015
|
+
options?: ConfigWriteOptions,
|
|
1016
|
+
): Promise<any>;
|
|
1017
|
+
get(tokenLayerId: string): Promise<any>;
|
|
241
1018
|
delete(tokenLayerId: string, auditMessage?: string): Promise<any>;
|
|
242
|
-
update(
|
|
1019
|
+
update(
|
|
1020
|
+
tokenLayerId: string,
|
|
1021
|
+
name: string,
|
|
1022
|
+
auditMessage?: string,
|
|
1023
|
+
): Promise<any>;
|
|
1024
|
+
setConstraints(
|
|
1025
|
+
layerId: string,
|
|
1026
|
+
namespace: string,
|
|
1027
|
+
constraints: LayerConstraint[],
|
|
1028
|
+
auditMessage?: string,
|
|
1029
|
+
options?: ConstraintWriteOptions,
|
|
1030
|
+
): Promise<{ constraints: Record<string, LayerConstraint[]> }>;
|
|
1031
|
+
deleteConstraints(
|
|
1032
|
+
layerId: string,
|
|
1033
|
+
namespace: string,
|
|
1034
|
+
auditMessage?: string,
|
|
1035
|
+
options?: ConstraintWriteOptions,
|
|
1036
|
+
): Promise<any>;
|
|
1037
|
+
checkConstraints(
|
|
1038
|
+
layerId: string,
|
|
1039
|
+
constraints: LayerConstraint[],
|
|
1040
|
+
): Promise<{ violations: ConstraintViolation[]; violationCount: number }>;
|
|
1041
|
+
repairConstraints(
|
|
1042
|
+
layerId: string,
|
|
1043
|
+
constraints: LayerConstraint[],
|
|
1044
|
+
auditMessage?: string,
|
|
1045
|
+
options?: { document?: string },
|
|
1046
|
+
): Promise<{
|
|
1047
|
+
repaired: { document: string; constraint: string; deleted: number; joined: number }[];
|
|
1048
|
+
locked: { document: string; lockedBy: string }[];
|
|
1049
|
+
violations: ConstraintViolation[];
|
|
1050
|
+
violationCount: number;
|
|
1051
|
+
}>;
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
/** Handle passed to a `documents.locked()` block. */
|
|
1055
|
+
export declare class DocumentLock {
|
|
1056
|
+
readonly documentId: string;
|
|
1057
|
+
/** The holder id the acquire answered with. */
|
|
1058
|
+
readonly lockId: string | null;
|
|
1059
|
+
/** The DocumentLockLost if the lock lapsed, else null. */
|
|
1060
|
+
readonly lost: DocumentLockLost | null;
|
|
1061
|
+
/** Throw if the lock lapsed; call it between steps that have not written. */
|
|
1062
|
+
raiseIfLost(): void;
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
/** The lock a `documents.locked()` block was holding is no longer held. */
|
|
1066
|
+
export declare class DocumentLockLost extends Error {
|
|
1067
|
+
readonly name: "DocumentLockLost";
|
|
1068
|
+
readonly documentId: string;
|
|
1069
|
+
readonly cause?: unknown;
|
|
243
1070
|
}
|
|
244
1071
|
|
|
1072
|
+
/** The server's default document-lock window, in ms. */
|
|
1073
|
+
export const DOCUMENT_LOCK_TTL_MS: 60000;
|
|
1074
|
+
|
|
245
1075
|
interface DocumentsBundle {
|
|
246
|
-
checkLock(documentId: string
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
1076
|
+
checkLock(documentId: string): Promise<any>;
|
|
1077
|
+
/**
|
|
1078
|
+
* Take the lock as a new holder. The answer's `lockId` names it:
|
|
1079
|
+
* `newLockId` when the client minted one, which makes a retried acquire
|
|
1080
|
+
* idempotent and a lost answer releasable.
|
|
1081
|
+
*/
|
|
1082
|
+
acquireLock(
|
|
1083
|
+
documentId: string,
|
|
1084
|
+
auditMessage?: string,
|
|
1085
|
+
newLockId?: string,
|
|
1086
|
+
): Promise<any>;
|
|
1087
|
+
/** Renew `lockId`'s lock while it is live. 423 once it has lapsed. */
|
|
1088
|
+
renewLock(
|
|
1089
|
+
documentId: string,
|
|
1090
|
+
lockId: string,
|
|
1091
|
+
auditMessage?: string,
|
|
1092
|
+
): Promise<any>;
|
|
1093
|
+
releaseLock(
|
|
1094
|
+
documentId: string,
|
|
1095
|
+
lockId: string,
|
|
1096
|
+
auditMessage?: string,
|
|
1097
|
+
): Promise<any>;
|
|
1098
|
+
/**
|
|
1099
|
+
* Hold the document's lock for the length of `fn`, renewing it while `fn`
|
|
1100
|
+
* runs and releasing it on the way out. Rejects with a 423 if it is already
|
|
1101
|
+
* held, and with DocumentLockLost if a renewal fails.
|
|
1102
|
+
*/
|
|
1103
|
+
locked<T>(
|
|
1104
|
+
documentId: string,
|
|
1105
|
+
fn: (lock: DocumentLock) => T | Promise<T>,
|
|
1106
|
+
options?: { keepAlive?: boolean },
|
|
1107
|
+
): Promise<T>;
|
|
1108
|
+
getMedia(documentId: string): Promise<ArrayBuffer>;
|
|
1109
|
+
uploadMedia(
|
|
1110
|
+
documentId: string,
|
|
1111
|
+
file: File,
|
|
1112
|
+
auditMessage?: string,
|
|
1113
|
+
options?: {
|
|
1114
|
+
/** Called with the bytes sent so far as the file goes up (`total` is null when unknown). */
|
|
1115
|
+
onProgress?: (progress: { loaded: number; total: number | null }) => void;
|
|
1116
|
+
},
|
|
1117
|
+
): Promise<any>;
|
|
251
1118
|
deleteMedia(documentId: string, auditMessage?: string): Promise<any>;
|
|
252
|
-
setMetadata(
|
|
1119
|
+
setMetadata(
|
|
1120
|
+
documentId: string,
|
|
1121
|
+
body: any,
|
|
1122
|
+
auditMessage?: string,
|
|
1123
|
+
): Promise<any>;
|
|
253
1124
|
deleteMetadata(documentId: string, auditMessage?: string): Promise<any>;
|
|
254
|
-
patchMetadata(
|
|
255
|
-
|
|
256
|
-
|
|
1125
|
+
patchMetadata(
|
|
1126
|
+
documentId: string,
|
|
1127
|
+
body: MetadataOp[],
|
|
1128
|
+
auditMessage?: string,
|
|
1129
|
+
): Promise<any>;
|
|
1130
|
+
audit(
|
|
1131
|
+
documentId: string,
|
|
1132
|
+
startTime?: string,
|
|
1133
|
+
endTime?: string,
|
|
1134
|
+
opTypes?: string[] | string,
|
|
1135
|
+
kinds?: OperationKind[] | string,
|
|
1136
|
+
): Promise<any[]>;
|
|
1137
|
+
auditPage(documentId: string, opts?: AuditPageOptions): Promise<Page>;
|
|
1138
|
+
/**
|
|
1139
|
+
* `asOf` reads the document as it was at that instant. `layers` narrows a
|
|
1140
|
+
* body read to the named layers (ids of any kind), and needs `includeBody`.
|
|
1141
|
+
*/
|
|
1142
|
+
get(
|
|
1143
|
+
documentId: string,
|
|
1144
|
+
includeBody?: boolean,
|
|
1145
|
+
asOf?: string,
|
|
1146
|
+
layers?: string[] | string,
|
|
1147
|
+
): Promise<any>;
|
|
257
1148
|
delete(documentId: string, auditMessage?: string): Promise<any>;
|
|
258
1149
|
update(documentId: string, name: string, auditMessage?: string): Promise<any>;
|
|
259
|
-
create(
|
|
1150
|
+
create(
|
|
1151
|
+
projectId: string,
|
|
1152
|
+
name: string,
|
|
1153
|
+
metadata?: any,
|
|
1154
|
+
auditMessage?: string,
|
|
1155
|
+
opts?: { id?: string },
|
|
1156
|
+
): Promise<any>;
|
|
1157
|
+
/** Copy a document and everything in it into a new document of the same project. */
|
|
1158
|
+
copy(
|
|
1159
|
+
documentId: string,
|
|
1160
|
+
name: string,
|
|
1161
|
+
options?: { includeMedia?: boolean; id?: string },
|
|
1162
|
+
auditMessage?: string,
|
|
1163
|
+
): Promise<{ id: string; mediaError?: string }>;
|
|
1164
|
+
restore(
|
|
1165
|
+
documentId: string,
|
|
1166
|
+
asOf: string,
|
|
1167
|
+
options?: { dryRun?: boolean },
|
|
1168
|
+
auditMessage?: string,
|
|
1169
|
+
): Promise<any>;
|
|
260
1170
|
}
|
|
261
1171
|
|
|
262
1172
|
interface MessagesBundle {
|
|
263
|
-
|
|
264
|
-
|
|
1173
|
+
/** Broadcast to the project's listeners. Never saved and never part of an operation. */
|
|
1174
|
+
sendMessage(projectId: string, data: any): Promise<any>;
|
|
1175
|
+
listen(
|
|
1176
|
+
projectId: string,
|
|
1177
|
+
onEvent: (eventType: string, data: any) => void | boolean,
|
|
1178
|
+
path?: string,
|
|
1179
|
+
): SSEConnection;
|
|
265
1180
|
/** Discover the services seen on a project: online ones plus previously-seen offline ones (check `online`). */
|
|
266
1181
|
discoverServices(projectId: string): Promise<DiscoveredService[]>;
|
|
267
1182
|
/** Forget a previously-seen (offline) service. Maintainer-only; 409 if currently connected. */
|
|
268
1183
|
discardService(projectId: string, serviceId: string): Promise<void>;
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
1184
|
+
/**
|
|
1185
|
+
* Register as a service and handle work requests. The registration reopens
|
|
1186
|
+
* its channel whenever it drops, so a server restart needs no service restart.
|
|
1187
|
+
*/
|
|
1188
|
+
serve(
|
|
1189
|
+
projectId: string,
|
|
1190
|
+
serviceInfo: ServiceInfo,
|
|
1191
|
+
onServiceRequest: (data: any, responseHelper: ResponseHelper) => void,
|
|
1192
|
+
extras?: any,
|
|
1193
|
+
onStatus?: (
|
|
1194
|
+
event: ServiceStatusEvent,
|
|
1195
|
+
projectId: string,
|
|
1196
|
+
detail?: string,
|
|
1197
|
+
) => void,
|
|
1198
|
+
): ServiceRegistration;
|
|
1199
|
+
/**
|
|
1200
|
+
* Submit work to a service; streams progress to `onProgress`, resolves with
|
|
1201
|
+
* the result. Aborting `signal` stops waiting and rejects with an AbortError;
|
|
1202
|
+
* the service is not told and finishes its work regardless.
|
|
1203
|
+
*/
|
|
1204
|
+
requestService(
|
|
1205
|
+
projectId: string,
|
|
1206
|
+
serviceId: string,
|
|
1207
|
+
data: any,
|
|
1208
|
+
timeout?: number,
|
|
1209
|
+
onProgress?: (progress: any) => void,
|
|
1210
|
+
signal?: AbortSignal,
|
|
1211
|
+
opts?: {
|
|
1212
|
+
/** A request id you mint, so you know it before submitting; resubmitting one rejoins that request. */
|
|
1213
|
+
requestId?: string;
|
|
1214
|
+
/** Called with the request id as soon as the server has taken the request. */
|
|
1215
|
+
onAccepted?: (requestId: string) => void;
|
|
1216
|
+
/** Other projects the request is about. A delegating service's token reaches `projectId` and those of these the requester can read, nothing else. */
|
|
1217
|
+
projectIds?: string[];
|
|
1218
|
+
/** Carry no open operation: the service's writes are a group of their own, not part of whatever operation this client has open. */
|
|
1219
|
+
noOperation?: boolean;
|
|
1220
|
+
},
|
|
1221
|
+
): Promise<any>;
|
|
1222
|
+
/**
|
|
1223
|
+
* Rejoin a request made earlier: the latest progress is replayed, then the
|
|
1224
|
+
* result, or at once if it already finished. Only its submitter (or an
|
|
1225
|
+
* admin). Rejects with a 404 when the request is unknown or expired.
|
|
1226
|
+
*/
|
|
1227
|
+
attachServiceRequest(
|
|
1228
|
+
projectId: string,
|
|
1229
|
+
requestId: string,
|
|
1230
|
+
timeout?: number,
|
|
1231
|
+
onProgress?: (progress: any) => void,
|
|
1232
|
+
signal?: AbortSignal,
|
|
1233
|
+
): Promise<any>;
|
|
1234
|
+
/**
|
|
1235
|
+
* Ask the service to stop a request made earlier. The request still ends
|
|
1236
|
+
* with whatever the service then reports. 404 if unknown or expired, 409
|
|
1237
|
+
* once finished.
|
|
1238
|
+
*/
|
|
1239
|
+
cancelServiceRequest(projectId: string, requestId: string): Promise<void>;
|
|
272
1240
|
}
|
|
273
1241
|
|
|
274
1242
|
interface ProjectsBundle {
|
|
@@ -276,75 +1244,257 @@ interface ProjectsBundle {
|
|
|
276
1244
|
removeWriter(id: string, userId: string, auditMessage?: string): Promise<any>;
|
|
277
1245
|
addReader(id: string, userId: string, auditMessage?: string): Promise<any>;
|
|
278
1246
|
removeReader(id: string, userId: string, auditMessage?: string): Promise<any>;
|
|
279
|
-
setConfig(
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
1247
|
+
setConfig(
|
|
1248
|
+
id: string,
|
|
1249
|
+
namespace: string,
|
|
1250
|
+
configKey: string,
|
|
1251
|
+
configValue: any,
|
|
1252
|
+
auditMessage?: string,
|
|
1253
|
+
options?: ConfigWriteOptions,
|
|
1254
|
+
): Promise<any>;
|
|
1255
|
+
deleteConfig(
|
|
1256
|
+
id: string,
|
|
1257
|
+
namespace: string,
|
|
1258
|
+
configKey: string,
|
|
1259
|
+
auditMessage?: string,
|
|
1260
|
+
options?: ConfigWriteOptions,
|
|
1261
|
+
): Promise<any>;
|
|
1262
|
+
addMaintainer(
|
|
1263
|
+
id: string,
|
|
1264
|
+
userId: string,
|
|
1265
|
+
auditMessage?: string,
|
|
1266
|
+
): Promise<any>;
|
|
1267
|
+
removeMaintainer(
|
|
1268
|
+
id: string,
|
|
1269
|
+
userId: string,
|
|
1270
|
+
auditMessage?: string,
|
|
1271
|
+
): Promise<any>;
|
|
1272
|
+
audit(
|
|
1273
|
+
projectId: string,
|
|
1274
|
+
startTime?: string,
|
|
1275
|
+
endTime?: string,
|
|
1276
|
+
opTypes?: string[] | string,
|
|
1277
|
+
kinds?: OperationKind[] | string,
|
|
1278
|
+
): Promise<any[]>;
|
|
1279
|
+
auditPage(projectId: string, opts?: AuditPageOptions): Promise<Page>;
|
|
1280
|
+
/**
|
|
1281
|
+
* When the calling user last wrote to each document of the project, as a
|
|
1282
|
+
* `{documentId: timestamp}` map; documents they never wrote to are absent.
|
|
1283
|
+
* The keys are document ids, so the response is not key-transformed.
|
|
1284
|
+
*/
|
|
1285
|
+
myLastEdits(projectId: string): Promise<Record<string, string>>;
|
|
284
1286
|
linkVocab(id: string, vocabId: string, auditMessage?: string): Promise<any>;
|
|
285
1287
|
unlinkVocab(id: string, vocabId: string, auditMessage?: string): Promise<any>;
|
|
286
|
-
get(id: string
|
|
1288
|
+
get(id: string): Promise<any>;
|
|
287
1289
|
listDocuments(id: string): Promise<any[]>;
|
|
288
|
-
listDocumentsPage(
|
|
289
|
-
|
|
290
|
-
|
|
1290
|
+
listDocumentsPage(
|
|
1291
|
+
id: string,
|
|
1292
|
+
opts?: { limit?: number; cursor?: string },
|
|
1293
|
+
): Promise<Page>;
|
|
1294
|
+
iterDocuments(
|
|
1295
|
+
id: string,
|
|
1296
|
+
opts?: { pageSize?: number },
|
|
1297
|
+
): AsyncGenerator<any[]>;
|
|
291
1298
|
update(id: string, name: string, auditMessage?: string): Promise<any>;
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
1299
|
+
/** The project is gone when this returns, and what it holds is removed on the server afterwards. The timeout defaults to the client's. */
|
|
1300
|
+
delete(
|
|
1301
|
+
id: string,
|
|
1302
|
+
auditMessage?: string,
|
|
1303
|
+
options?: { timeout?: number | null },
|
|
1304
|
+
): Promise<any>;
|
|
1305
|
+
list(): Promise<any[]>;
|
|
1306
|
+
listPage(opts?: { limit?: number; cursor?: string }): Promise<Page>;
|
|
1307
|
+
iterPages(opts?: { pageSize?: number }): AsyncGenerator<any[]>;
|
|
1308
|
+
create(name: string, auditMessage?: string, opts?: { id?: string }): Promise<any>;
|
|
296
1309
|
}
|
|
297
1310
|
|
|
298
1311
|
interface TextLayersBundle {
|
|
299
|
-
setConfig(
|
|
300
|
-
|
|
301
|
-
|
|
1312
|
+
setConfig(
|
|
1313
|
+
textLayerId: string,
|
|
1314
|
+
namespace: string,
|
|
1315
|
+
configKey: string,
|
|
1316
|
+
configValue: any,
|
|
1317
|
+
auditMessage?: string,
|
|
1318
|
+
options?: ConfigWriteOptions,
|
|
1319
|
+
): Promise<any>;
|
|
1320
|
+
deleteConfig(
|
|
1321
|
+
textLayerId: string,
|
|
1322
|
+
namespace: string,
|
|
1323
|
+
configKey: string,
|
|
1324
|
+
auditMessage?: string,
|
|
1325
|
+
options?: ConfigWriteOptions,
|
|
1326
|
+
): Promise<any>;
|
|
1327
|
+
get(textLayerId: string): Promise<any>;
|
|
302
1328
|
delete(textLayerId: string, auditMessage?: string): Promise<any>;
|
|
303
|
-
update(
|
|
304
|
-
|
|
305
|
-
|
|
1329
|
+
update(
|
|
1330
|
+
textLayerId: string,
|
|
1331
|
+
name: string,
|
|
1332
|
+
auditMessage?: string,
|
|
1333
|
+
): Promise<any>;
|
|
1334
|
+
shift(
|
|
1335
|
+
textLayerId: string,
|
|
1336
|
+
direction: string,
|
|
1337
|
+
auditMessage?: string,
|
|
1338
|
+
): Promise<any>;
|
|
1339
|
+
create(projectId: string, name: string, auditMessage?: string, opts?: { id?: string }): Promise<any>;
|
|
306
1340
|
}
|
|
307
1341
|
|
|
308
1342
|
interface VocabItemsBundle {
|
|
309
1343
|
setMetadata(id: string, body: any, auditMessage?: string): Promise<any>;
|
|
310
1344
|
deleteMetadata(id: string, auditMessage?: string): Promise<any>;
|
|
311
|
-
patchMetadata(id: string, body:
|
|
312
|
-
create(
|
|
1345
|
+
patchMetadata(id: string, body: MetadataOp[], auditMessage?: string): Promise<any>;
|
|
1346
|
+
create(
|
|
1347
|
+
vocabLayerId: string,
|
|
1348
|
+
form: string,
|
|
1349
|
+
metadata?: any,
|
|
1350
|
+
auditMessage?: string,
|
|
1351
|
+
opts?: { id?: string },
|
|
1352
|
+
): Promise<any>;
|
|
313
1353
|
bulkCreate(body: any[], auditMessage?: string): Promise<{ ids: string[] }>;
|
|
314
1354
|
bulkDelete(body: any[], auditMessage?: string): Promise<void>;
|
|
315
|
-
|
|
316
|
-
|
|
1355
|
+
bulkUpdate(body: any[], auditMessage?: string): Promise<{ count: number }>;
|
|
1356
|
+
get(id: string): Promise<any>;
|
|
1357
|
+
delete(
|
|
1358
|
+
id: string,
|
|
1359
|
+
auditMessage?: string,
|
|
1360
|
+
options?: { expectedLinkCount?: number },
|
|
1361
|
+
): Promise<any>;
|
|
1362
|
+
merge(
|
|
1363
|
+
survivorId: string,
|
|
1364
|
+
loserIds: string[],
|
|
1365
|
+
auditMessage?: string,
|
|
1366
|
+
): Promise<{ moved: number; duplicates: number; removed: string[] }>;
|
|
317
1367
|
update(id: string, form: string, auditMessage?: string): Promise<any>;
|
|
318
1368
|
}
|
|
319
1369
|
|
|
320
1370
|
interface RelationLayersBundle {
|
|
321
|
-
shift(
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
1371
|
+
shift(
|
|
1372
|
+
relationLayerId: string,
|
|
1373
|
+
direction: string,
|
|
1374
|
+
auditMessage?: string,
|
|
1375
|
+
): Promise<any>;
|
|
1376
|
+
create(
|
|
1377
|
+
spanLayerId: string,
|
|
1378
|
+
name: string,
|
|
1379
|
+
auditMessage?: string,
|
|
1380
|
+
opts?: { id?: string },
|
|
1381
|
+
): Promise<any>;
|
|
1382
|
+
setConfig(
|
|
1383
|
+
relationLayerId: string,
|
|
1384
|
+
namespace: string,
|
|
1385
|
+
configKey: string,
|
|
1386
|
+
configValue: any,
|
|
1387
|
+
auditMessage?: string,
|
|
1388
|
+
options?: ConfigWriteOptions,
|
|
1389
|
+
): Promise<any>;
|
|
1390
|
+
deleteConfig(
|
|
1391
|
+
relationLayerId: string,
|
|
1392
|
+
namespace: string,
|
|
1393
|
+
configKey: string,
|
|
1394
|
+
auditMessage?: string,
|
|
1395
|
+
options?: ConfigWriteOptions,
|
|
1396
|
+
): Promise<any>;
|
|
1397
|
+
get(relationLayerId: string): Promise<any>;
|
|
326
1398
|
delete(relationLayerId: string, auditMessage?: string): Promise<any>;
|
|
327
|
-
update(
|
|
1399
|
+
update(
|
|
1400
|
+
relationLayerId: string,
|
|
1401
|
+
name: string,
|
|
1402
|
+
auditMessage?: string,
|
|
1403
|
+
): Promise<any>;
|
|
1404
|
+
setConstraints(
|
|
1405
|
+
layerId: string,
|
|
1406
|
+
namespace: string,
|
|
1407
|
+
constraints: LayerConstraint[],
|
|
1408
|
+
auditMessage?: string,
|
|
1409
|
+
options?: ConstraintWriteOptions,
|
|
1410
|
+
): Promise<{ constraints: Record<string, LayerConstraint[]> }>;
|
|
1411
|
+
deleteConstraints(
|
|
1412
|
+
layerId: string,
|
|
1413
|
+
namespace: string,
|
|
1414
|
+
auditMessage?: string,
|
|
1415
|
+
options?: ConstraintWriteOptions,
|
|
1416
|
+
): Promise<any>;
|
|
1417
|
+
checkConstraints(
|
|
1418
|
+
layerId: string,
|
|
1419
|
+
constraints: LayerConstraint[],
|
|
1420
|
+
): Promise<{ violations: ConstraintViolation[]; violationCount: number }>;
|
|
1421
|
+
repairConstraints(
|
|
1422
|
+
layerId: string,
|
|
1423
|
+
constraints: LayerConstraint[],
|
|
1424
|
+
auditMessage?: string,
|
|
1425
|
+
options?: { document?: string },
|
|
1426
|
+
): Promise<{
|
|
1427
|
+
repaired: { document: string; constraint: string; deleted: number; joined: number }[];
|
|
1428
|
+
locked: { document: string; lockedBy: string }[];
|
|
1429
|
+
violations: ConstraintViolation[];
|
|
1430
|
+
violationCount: number;
|
|
1431
|
+
}>;
|
|
328
1432
|
}
|
|
329
1433
|
|
|
330
1434
|
interface TokensBundle {
|
|
331
|
-
create(
|
|
332
|
-
|
|
1435
|
+
create(
|
|
1436
|
+
tokenLayerId: string,
|
|
1437
|
+
text: string,
|
|
1438
|
+
begin: number,
|
|
1439
|
+
end: number,
|
|
1440
|
+
precedence?: number | null,
|
|
1441
|
+
metadata?: any,
|
|
1442
|
+
auditMessage?: string,
|
|
1443
|
+
opts?: { id?: string },
|
|
1444
|
+
): Promise<any>;
|
|
1445
|
+
get(tokenId: string): Promise<any>;
|
|
333
1446
|
delete(tokenId: string, auditMessage?: string): Promise<any>;
|
|
334
|
-
update(
|
|
1447
|
+
update(
|
|
1448
|
+
tokenId: string,
|
|
1449
|
+
begin?: number,
|
|
1450
|
+
end?: number,
|
|
1451
|
+
precedence?: number | null,
|
|
1452
|
+
auditMessage?: string,
|
|
1453
|
+
): Promise<any>;
|
|
335
1454
|
bulkCreate(body: any[], auditMessage?: string): Promise<{ ids: string[] }>;
|
|
336
1455
|
bulkDelete(body: any[], auditMessage?: string): Promise<void>;
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
1456
|
+
bulkUpdate(body: any[], auditMessage?: string): Promise<{ count: number }>;
|
|
1457
|
+
split(
|
|
1458
|
+
tokenId: string,
|
|
1459
|
+
position: number,
|
|
1460
|
+
auditMessage?: string,
|
|
1461
|
+
options?: { id?: string },
|
|
1462
|
+
): Promise<any>;
|
|
1463
|
+
merge(
|
|
1464
|
+
tokenId: string,
|
|
1465
|
+
otherTokenId: string,
|
|
1466
|
+
auditMessage?: string,
|
|
1467
|
+
): Promise<any>;
|
|
1468
|
+
shift(
|
|
1469
|
+
tokenId: string,
|
|
1470
|
+
begin?: number,
|
|
1471
|
+
end?: number,
|
|
1472
|
+
auditMessage?: string,
|
|
1473
|
+
): Promise<any>;
|
|
340
1474
|
setMetadata(tokenId: string, body: any, auditMessage?: string): Promise<any>;
|
|
341
1475
|
deleteMetadata(tokenId: string, auditMessage?: string): Promise<any>;
|
|
342
|
-
patchMetadata(
|
|
1476
|
+
patchMetadata(
|
|
1477
|
+
tokenId: string,
|
|
1478
|
+
body: MetadataOp[],
|
|
1479
|
+
auditMessage?: string,
|
|
1480
|
+
): Promise<any>;
|
|
343
1481
|
}
|
|
344
1482
|
|
|
345
1483
|
interface PlaidClientOptions {
|
|
346
1484
|
/** Per-request timeout in ms (default 30000; 0 or null disables it). */
|
|
347
1485
|
timeout?: number | null;
|
|
1486
|
+
/**
|
|
1487
|
+
* Timeout for batch submissions in ms (default 180000; 0 or null disables it).
|
|
1488
|
+
* Batches get their own, longer budget: aborting one does NOT stop the
|
|
1489
|
+
* server, which keeps running the transaction and holding the single SQLite
|
|
1490
|
+
* write lock. Defaults to `timeout` when that is given and this is not.
|
|
1491
|
+
*/
|
|
1492
|
+
batchTimeout?: number | null;
|
|
1493
|
+
/**
|
|
1494
|
+
* Delays in ms before sending a keyed write again when its answer was lost
|
|
1495
|
+
* (no response, 502 or 504). Default [1000, 3000, 9000].
|
|
1496
|
+
*/
|
|
1497
|
+
retryDelaysMs?: number[];
|
|
348
1498
|
/**
|
|
349
1499
|
* Fired once when a request returns HTTP 401 (missing/expired/invalid token).
|
|
350
1500
|
* Use it to discard the stored token and route back to login. 403 (forbidden)
|
|
@@ -353,36 +1503,133 @@ interface PlaidClientOptions {
|
|
|
353
1503
|
onAuthError?: ((error: Error) => void) | null;
|
|
354
1504
|
}
|
|
355
1505
|
|
|
1506
|
+
/** What kind of operation a logical-operation group is (`?group-kind=`). */
|
|
1507
|
+
export type OperationKind =
|
|
1508
|
+
| 'assistant-plan'
|
|
1509
|
+
| 'service-run'
|
|
1510
|
+
| 'import'
|
|
1511
|
+
| 'bulk-edit'
|
|
1512
|
+
| 'guess-adoption'
|
|
1513
|
+
| 'repair'
|
|
1514
|
+
| 'review';
|
|
1515
|
+
|
|
356
1516
|
export interface OperationGroupsBundle {
|
|
357
1517
|
get(id: string): Promise<any>;
|
|
358
1518
|
update(id: string, message: string | null): Promise<any>;
|
|
359
1519
|
}
|
|
360
1520
|
|
|
1521
|
+
/**
|
|
1522
|
+
* A batch: the client's bundles, on which every write of project data queues
|
|
1523
|
+
* until `submit()`. See `PlaidClient.batch()`.
|
|
1524
|
+
*/
|
|
1525
|
+
export interface PlaidBatch extends PlaidClient {
|
|
1526
|
+
/** The client this batch was opened on. */
|
|
1527
|
+
readonly client: PlaidClient;
|
|
1528
|
+
/** The queued operations, in order. */
|
|
1529
|
+
readonly operations: Array<{ path: string; method: string; body?: any }>;
|
|
1530
|
+
/**
|
|
1531
|
+
* Send the queued operations and resolve to one result per operation, in
|
|
1532
|
+
* order. Up to MAX_BATCH_OPS operations go as one atomic request. A larger
|
|
1533
|
+
* batch goes as consecutive requests, each atomic on its own, so a failure
|
|
1534
|
+
* in a later one leaves the earlier ones committed. The error then carries
|
|
1535
|
+
* `committed`, how many operations were saved (0 when none were), and
|
|
1536
|
+
* `committedResults`, their results in queue order.
|
|
1537
|
+
*/
|
|
1538
|
+
submit(): Promise<any[]>;
|
|
1539
|
+
/** Drop the queued operations without sending them. */
|
|
1540
|
+
abort(): void;
|
|
1541
|
+
/**
|
|
1542
|
+
* A stand-in for the id a queued operation will create, to put in a later
|
|
1543
|
+
* operation's body on this batch, so a create and the write that uses it go
|
|
1544
|
+
* in one transaction: op n's `id`, or with `index` the k-th of the `ids` a
|
|
1545
|
+
* bulk create answers. `opIndex` counts from 0, or from the end when
|
|
1546
|
+
* negative (-1, the default, is the op queued last). It goes only in the
|
|
1547
|
+
* body of a later write on this batch, at any depth. Anywhere else (a path,
|
|
1548
|
+
* another batch, a call made on the client) the client refuses it.
|
|
1549
|
+
*/
|
|
1550
|
+
ref(opIndex?: number, index?: number): BatchRef;
|
|
1551
|
+
}
|
|
1552
|
+
|
|
1553
|
+
/**
|
|
1554
|
+
* See `PlaidBatch.ref`. A marker object, not data: the client takes it out of
|
|
1555
|
+
* the body when its write is queued and sends where it was beside the body.
|
|
1556
|
+
*/
|
|
1557
|
+
export interface BatchRef {
|
|
1558
|
+
/** The op, counted from 0 in the batch, whose id this stands for. */
|
|
1559
|
+
readonly $ref: number;
|
|
1560
|
+
/** For a bulk create, which of its ids. */
|
|
1561
|
+
readonly index?: number;
|
|
1562
|
+
}
|
|
1563
|
+
|
|
361
1564
|
export declare class PlaidClient {
|
|
362
1565
|
constructor(baseUrl: string, token: string, options?: PlaidClientOptions);
|
|
363
|
-
|
|
1566
|
+
/** Liveness, version and database size, with no authentication. */
|
|
1567
|
+
static health(
|
|
1568
|
+
baseUrl: string,
|
|
1569
|
+
options?: { timeout?: number | null },
|
|
1570
|
+
): Promise<ServerHealth>;
|
|
1571
|
+
/** The limits this server enforces, with no authentication. */
|
|
1572
|
+
static info(
|
|
1573
|
+
baseUrl: string,
|
|
1574
|
+
options?: { timeout?: number | null },
|
|
1575
|
+
): Promise<{ limits: ServerLimits }>;
|
|
1576
|
+
static login(
|
|
1577
|
+
baseUrl: string,
|
|
1578
|
+
userId: string,
|
|
1579
|
+
password: string,
|
|
1580
|
+
options?: PlaidClientOptions,
|
|
1581
|
+
): Promise<PlaidClient>;
|
|
364
1582
|
/** Build the link to hand someone for an invite code. */
|
|
365
1583
|
static inviteUrl(appUrl: string, code: string): string;
|
|
366
1584
|
/** Describe an invite code with no authentication (for a signup page). */
|
|
367
|
-
static lookupInvite(
|
|
1585
|
+
static lookupInvite(
|
|
1586
|
+
baseUrl: string,
|
|
1587
|
+
code: string,
|
|
1588
|
+
options?: PlaidClientOptions,
|
|
1589
|
+
): Promise<InvitePreview>;
|
|
368
1590
|
/** Redeem an invite code with no authentication; resolves to a logged-in client. */
|
|
369
1591
|
static redeemInvite(
|
|
370
1592
|
baseUrl: string,
|
|
371
1593
|
code: string,
|
|
372
|
-
credentials: {
|
|
1594
|
+
credentials: { email?: string; password: string; displayName?: string },
|
|
373
1595
|
options?: PlaidClientOptions,
|
|
374
1596
|
): Promise<{ client: PlaidClient; userId: string; kind: string }>;
|
|
1597
|
+
/** The server's base URL, without a trailing slash. */
|
|
1598
|
+
readonly baseUrl: string;
|
|
1599
|
+
/** The bearer token every request carries. */
|
|
1600
|
+
token: string;
|
|
375
1601
|
timeout: number | null;
|
|
1602
|
+
batchTimeout: number | null;
|
|
1603
|
+
retryDelaysMs: number[] | undefined;
|
|
1604
|
+
/** The document strict mode is entered for, or null. */
|
|
1605
|
+
readonly strictModeDocumentId: string | null;
|
|
1606
|
+
/** The DocumentLockLost of the open `locked()` block whose lock lapsed, or null. Cleared when that block exits. */
|
|
1607
|
+
documentLockLost: DocumentLockLost | null;
|
|
376
1608
|
/** Fired once on HTTP 401 (see PlaidClientOptions.onAuthError). */
|
|
377
1609
|
onAuthError: ((error: Error) => void) | null;
|
|
1610
|
+
/** The latest version seen for each document written through this client, keyed by document id. */
|
|
1611
|
+
documentVersions: Record<string, number>;
|
|
1612
|
+
/** True once a response left its version list out (X-Document-Versions-Omitted, past fifty documents). Every version held was then forgotten, and the strict-mode document's is read again before the next write. */
|
|
1613
|
+
documentVersionsOmitted?: boolean;
|
|
1614
|
+
/** The server's clock minus this machine's, in ms, from the last response with a Date header, or null before one. */
|
|
1615
|
+
serverClockOffsetMs: number | null;
|
|
1616
|
+
/** The server's time now, from its last response's Date header (to the second), else this machine's. Judge a time the server stamped, such as an audit entry's `ts`, against this rather than `Date.now()`. */
|
|
1617
|
+
serverNow(): Date;
|
|
378
1618
|
|
|
379
|
-
//
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
1619
|
+
// Batches.
|
|
1620
|
+
//
|
|
1621
|
+
// A batch is a view of the client with the same bundles. A write of project
|
|
1622
|
+
// data made on the batch queues; a call made on the client itself always
|
|
1623
|
+
// goes over the wire, whatever batches are open, so a write by code that
|
|
1624
|
+
// knows nothing about a batch can never land inside it. A read, or a signal
|
|
1625
|
+
// that carries no project data (stopping a service request, a service
|
|
1626
|
+
// reporting its progress, taking and dropping a document lock, the admin
|
|
1627
|
+
// actions on the server itself), goes over the wire even when made on the
|
|
1628
|
+
// batch.
|
|
1629
|
+
/** Open a batch. Queue writes on it, then `submit()` them (one atomic request up to MAX_BATCH_OPS operations), or `abort()`. Not nestable. */
|
|
1630
|
+
batch(): PlaidBatch;
|
|
1631
|
+
/** Run `fn` with a batch, then submit it as `submit()` does (or abort if `fn` throws). Resolves to the results array, one entry per queued write. */
|
|
1632
|
+
batched(fn: (batch: PlaidBatch) => void | Promise<void>): Promise<any[]>;
|
|
386
1633
|
|
|
387
1634
|
// Strict mode methods
|
|
388
1635
|
enterStrictMode(documentId: string): void;
|
|
@@ -391,25 +1638,48 @@ export declare class PlaidClient {
|
|
|
391
1638
|
// Logical operations (audit-log grouping). While one is open every write is
|
|
392
1639
|
// stamped with its group id so the audit log folds them into one entry.
|
|
393
1640
|
// Not atomic; nesting flattens into the outer operation.
|
|
394
|
-
|
|
395
|
-
|
|
1641
|
+
// `kind` is one of OperationKind (the server refuses any other) and `ref`
|
|
1642
|
+
// names what the operation came from; nesting keeps the outer ones.
|
|
1643
|
+
operationGroup: {
|
|
1644
|
+
id: string;
|
|
1645
|
+
message: string | null;
|
|
1646
|
+
kind: OperationKind | null;
|
|
1647
|
+
ref: string | null;
|
|
1648
|
+
} | null;
|
|
1649
|
+
beginOperation(
|
|
1650
|
+
message: string,
|
|
1651
|
+
opts?: { id?: string; kind?: OperationKind; ref?: string; keys?: KeySeed; minted?: Set<string> },
|
|
1652
|
+
): string;
|
|
1653
|
+
/** A seed for the Idempotency-Keys of an operation that may be run again (see beginOperation's `keys`). */
|
|
1654
|
+
keySeed(): KeySeed;
|
|
396
1655
|
endOperation(message?: string): Promise<void>;
|
|
397
|
-
withOperation<T>(
|
|
1656
|
+
withOperation<T>(
|
|
1657
|
+
message: string,
|
|
1658
|
+
fn: (setMessage: (msg: string) => void) => Promise<T> | T,
|
|
1659
|
+
opts?: { kind?: OperationKind; ref?: string; id?: string; keys?: KeySeed; minted?: Set<string> },
|
|
1660
|
+
): Promise<T>;
|
|
398
1661
|
operationGroups: OperationGroupsBundle;
|
|
399
1662
|
|
|
400
1663
|
// Query
|
|
401
|
-
query(body: any
|
|
1664
|
+
query(body: any): Promise<any>;
|
|
402
1665
|
|
|
403
1666
|
vocabLinks: VocabLinksBundle;
|
|
404
1667
|
vocabLayers: VocabLayersBundle;
|
|
405
1668
|
relations: RelationsBundle;
|
|
406
1669
|
spanLayers: SpanLayersBundle;
|
|
407
1670
|
spans: SpansBundle;
|
|
408
|
-
batch: BatchBundle;
|
|
409
1671
|
texts: TextsBundle;
|
|
410
1672
|
users: UsersBundle;
|
|
411
1673
|
apiTokens: ApiTokensBundle;
|
|
1674
|
+
userData: UserDataBundle;
|
|
412
1675
|
invites: InvitesBundle;
|
|
1676
|
+
server: ServerBundle;
|
|
1677
|
+
auth: AuthBundle;
|
|
1678
|
+
admin: AdminBundle;
|
|
1679
|
+
audit: AuditBundle;
|
|
1680
|
+
comments: CommentsBundle;
|
|
1681
|
+
events: EventsBundle;
|
|
1682
|
+
guidelines: GuidelinesBundle;
|
|
413
1683
|
tokenLayers: TokenLayersBundle;
|
|
414
1684
|
documents: DocumentsBundle;
|
|
415
1685
|
messages: MessagesBundle;
|
|
@@ -437,26 +1707,57 @@ export function cpToUtf16(s: string, cp: number): number;
|
|
|
437
1707
|
/** Like indexOf, but the result and `fromCp` are code-point indices; -1 if absent. */
|
|
438
1708
|
export function cpIndexOf(s: string, sub: string, fromCp?: number): number;
|
|
439
1709
|
|
|
1710
|
+
// --- Text edit operations (code points, running coordinates) ---------------
|
|
1711
|
+
/** One op as `PATCH /texts/:id` takes it; each index is in the body the ops before it left. */
|
|
1712
|
+
export type TextEditOp =
|
|
1713
|
+
| { type: "insert"; index: number; value: string }
|
|
1714
|
+
| { type: "delete"; index: number; value: number }
|
|
1715
|
+
| { type: "replace"; index: number; length: number; value: string };
|
|
1716
|
+
/** Old-body code points [start, end) give way to `value`. */
|
|
1717
|
+
export interface TextGap {
|
|
1718
|
+
start: number;
|
|
1719
|
+
end: number;
|
|
1720
|
+
value: string;
|
|
1721
|
+
}
|
|
1722
|
+
/** The net change of `ops` on `body` as gaps: sorted, never touching, no-op gaps dropped. Throws on a bad op. */
|
|
1723
|
+
export function composeTextEdits(body: string, ops: TextEditOp[]): TextGap[];
|
|
1724
|
+
/** Gaps as running ops: insert, delete or replace. */
|
|
1725
|
+
export function gapsToOps(gaps: TextGap[]): TextEditOp[];
|
|
1726
|
+
/** `body` with `ops` applied in turn. Throws on a bad op. */
|
|
1727
|
+
export function applyTextOps(body: string, ops: TextEditOp[]): string;
|
|
1728
|
+
|
|
440
1729
|
// --- Shared layer-role vocabulary (cross-app interoperability) --------------
|
|
441
1730
|
// Substrate layers are tagged with a role at `config.plaid.role` (a scalar) so
|
|
442
1731
|
// that different apps can share a project. See the manual, "Layer Interoperability".
|
|
443
1732
|
/** The reserved config namespace for cross-app conventions. */
|
|
444
|
-
export const PLAID_NAMESPACE:
|
|
1733
|
+
export const PLAID_NAMESPACE: "plaid";
|
|
445
1734
|
/** The config key, under `plaid`, holding a layer's role. */
|
|
446
|
-
export const ROLE_KEY:
|
|
1735
|
+
export const ROLE_KEY: "role";
|
|
1736
|
+
/** Layer config key naming the metadata keys a token born of a SPLIT inherits. */
|
|
1737
|
+
export const PRESERVE_ON_SPLIT_KEY: "preserveOnSplit";
|
|
1738
|
+
/** Layer config key asking Plaid to take a text edit plainly on the layer (see the manual's "Changing a text's body"). */
|
|
1739
|
+
export const PLAIN_EDITS_KEY: "plainEdits";
|
|
1740
|
+
/** Layer config key: a space typed inside a word of the text splits it (beside plainEdits). */
|
|
1741
|
+
export const SPLIT_ON_SPACE_KEY: "splitOnSpace";
|
|
1742
|
+
|
|
1743
|
+
/** The server's cap on operations per batch request; a larger batch goes as consecutive requests. */
|
|
1744
|
+
export const MAX_BATCH_OPS: 1000;
|
|
447
1745
|
/** The fixed role inventory; only these values are interoperable across apps. */
|
|
448
1746
|
export const ROLES: {
|
|
449
|
-
readonly BASELINE:
|
|
450
|
-
readonly SENTENCE:
|
|
451
|
-
readonly WORD:
|
|
452
|
-
readonly SYNTACTIC_WORD:
|
|
453
|
-
readonly MORPHEME:
|
|
454
|
-
readonly TIME_ALIGNMENT:
|
|
1747
|
+
readonly BASELINE: "baseline";
|
|
1748
|
+
readonly SENTENCE: "sentence";
|
|
1749
|
+
readonly WORD: "word";
|
|
1750
|
+
readonly SYNTACTIC_WORD: "syntactic-word";
|
|
1751
|
+
readonly MORPHEME: "morpheme";
|
|
1752
|
+
readonly TIME_ALIGNMENT: "time-alignment";
|
|
455
1753
|
};
|
|
456
1754
|
/** The role recorded on a layer's `config`, or null if none. */
|
|
457
1755
|
export function readRole(config?: object): string | null;
|
|
458
1756
|
/** The first layer in `layers` carrying the given role, or null. */
|
|
459
|
-
export function findByRole<T extends { config?: object }>(
|
|
1757
|
+
export function findByRole<T extends { config?: object }>(
|
|
1758
|
+
layers: T[] | undefined,
|
|
1759
|
+
role: string,
|
|
1760
|
+
): T | null;
|
|
460
1761
|
|
|
461
1762
|
// --- Service self-description helpers ----------------------------------------
|
|
462
1763
|
// Standardize how a service advertises (in `extras`) the tasks it serves, a
|
|
@@ -465,16 +1766,24 @@ export function findByRole<T extends { config?: object }>(layers: T[] | undefine
|
|
|
465
1766
|
// "Describing a service".
|
|
466
1767
|
/** The controlled task vocabulary — the fixed integration-point goals. */
|
|
467
1768
|
export const TASKS: {
|
|
468
|
-
readonly TOKENIZE:
|
|
469
|
-
readonly PARSE:
|
|
470
|
-
readonly TRANSCRIBE:
|
|
471
|
-
readonly LINK_VOCAB:
|
|
472
|
-
readonly ANALYZE:
|
|
1769
|
+
readonly TOKENIZE: "tokenize";
|
|
1770
|
+
readonly PARSE: "parse";
|
|
1771
|
+
readonly TRANSCRIBE: "transcribe";
|
|
1772
|
+
readonly LINK_VOCAB: "link-vocab";
|
|
1773
|
+
readonly ANALYZE: "analyze";
|
|
1774
|
+
readonly DRAFT_GRAPH: "draft-graph";
|
|
1775
|
+
readonly TRANSLATE: "translate";
|
|
1776
|
+
readonly ASSIST: "assist";
|
|
1777
|
+
readonly DETECT_SPEECH: "detect-speech";
|
|
1778
|
+
readonly COMPARE: "compare";
|
|
473
1779
|
};
|
|
474
1780
|
/** Whether a service serves a task (declared `extras.tasks`, legacy id-prefix fallback). */
|
|
475
1781
|
export function servesTask(service: DiscoveredService, task: string): boolean;
|
|
476
1782
|
/** The discovered services that serve `task`. */
|
|
477
|
-
export function filterServicesByTask(
|
|
1783
|
+
export function filterServicesByTask(
|
|
1784
|
+
services: DiscoveredService[] | undefined,
|
|
1785
|
+
task: string,
|
|
1786
|
+
): DiscoveredService[];
|
|
478
1787
|
/** The parameter schema a service declares (ordered), or []. */
|
|
479
1788
|
export function getParamSchema(service: DiscoveredService): ServiceParam[];
|
|
480
1789
|
/** A service's human summary: `extras.summary`, else `description`, else ''. */
|
|
@@ -482,7 +1791,10 @@ export function getServiceSummary(service: DiscoveredService): string;
|
|
|
482
1791
|
/** Default form values keyed by param key. */
|
|
483
1792
|
export function buildDefaultValues(schema: ServiceParam[]): Record<string, any>;
|
|
484
1793
|
/** Coerce/validate raw form values against the schema. */
|
|
485
|
-
export function coerceParamValues(
|
|
1794
|
+
export function coerceParamValues(
|
|
1795
|
+
schema: ServiceParam[],
|
|
1796
|
+
raw: Record<string, any>,
|
|
1797
|
+
): { values: Record<string, any>; errors: Record<string, string> };
|
|
486
1798
|
|
|
487
1799
|
// --- Provenance ---------------------------------------------------------------
|
|
488
1800
|
// Cross-app convention for machine-provided vs human-labeled information,
|
|
@@ -492,32 +1804,54 @@ export function coerceParamValues(schema: ServiceParam[], raw: Record<string, an
|
|
|
492
1804
|
// replace unverified machine material but must never touch human/verified
|
|
493
1805
|
// material without an explicit overwrite opt-in; any human edit verifies.
|
|
494
1806
|
// See the manual, "Provenance".
|
|
495
|
-
type ProvState =
|
|
1807
|
+
type ProvState = "human" | "machine" | "contributed" | "verified";
|
|
496
1808
|
export const PROV: {
|
|
497
|
-
readonly key:
|
|
498
|
-
readonly sourceKey:
|
|
499
|
-
readonly confirmedKey:
|
|
500
|
-
readonly probKey:
|
|
501
|
-
readonly detailKey:
|
|
502
|
-
readonly INFERRED:
|
|
1809
|
+
readonly key: "prov";
|
|
1810
|
+
readonly sourceKey: "provSource";
|
|
1811
|
+
readonly confirmedKey: "provConfirmed";
|
|
1812
|
+
readonly probKey: "provProb";
|
|
1813
|
+
readonly detailKey: "provDetail";
|
|
1814
|
+
readonly INFERRED: "inferred";
|
|
1815
|
+
readonly CONTRIBUTED: "contributed";
|
|
503
1816
|
};
|
|
504
1817
|
export const PROV_STATES: {
|
|
505
|
-
readonly HUMAN:
|
|
506
|
-
readonly MACHINE:
|
|
507
|
-
readonly
|
|
1818
|
+
readonly HUMAN: "human";
|
|
1819
|
+
readonly MACHINE: "machine";
|
|
1820
|
+
readonly CONTRIBUTED: "contributed";
|
|
1821
|
+
readonly VERIFIED: "verified";
|
|
508
1822
|
};
|
|
1823
|
+
/** The provenance keys Plaid itself owns — what a split carries and a reshape keeps. */
|
|
1824
|
+
export const PROVENANCE_KEYS: readonly string[];
|
|
509
1825
|
/** Optional prediction extras: prob = a probability in [0,1] for the chosen value
|
|
510
1826
|
* (flat + queryable; omit unless it honestly is one); detail = an open map of
|
|
511
1827
|
* producer extras (top-k alternatives, model version, raw scores; keep it small).
|
|
512
1828
|
* Both describe the ORIGINAL prediction — check provConfirmed before presenting
|
|
513
1829
|
* provProb as confidence in the current value. */
|
|
514
|
-
interface ProvExtras {
|
|
1830
|
+
interface ProvExtras {
|
|
1831
|
+
prob?: number;
|
|
1832
|
+
detail?: Record<string, any>;
|
|
1833
|
+
}
|
|
515
1834
|
/** The metadata fragment a machine writer merges into everything it creates. */
|
|
516
|
-
export function stampInferred(
|
|
517
|
-
|
|
1835
|
+
export function stampInferred(
|
|
1836
|
+
source: string,
|
|
1837
|
+
extras?: ProvExtras,
|
|
1838
|
+
): {
|
|
1839
|
+
prov: "inferred";
|
|
1840
|
+
provSource: string;
|
|
1841
|
+
provProb?: number;
|
|
1842
|
+
provDetail?: Record<string, any>;
|
|
1843
|
+
};
|
|
518
1844
|
/** stampInferred + provConfirmed — for machine material born verified (e.g. imports with upstream approval). */
|
|
519
|
-
export function confirmedInferred(
|
|
520
|
-
|
|
1845
|
+
export function confirmedInferred(
|
|
1846
|
+
source: string,
|
|
1847
|
+
extras?: ProvExtras,
|
|
1848
|
+
): {
|
|
1849
|
+
prov: "inferred";
|
|
1850
|
+
provSource: string;
|
|
1851
|
+
provConfirmed: true;
|
|
1852
|
+
provProb?: number;
|
|
1853
|
+
provDetail?: Record<string, any>;
|
|
1854
|
+
};
|
|
521
1855
|
/** Classify an entity's metadata into one of the three provenance states. */
|
|
522
1856
|
export function provState(metadata: object | null | undefined): ProvState;
|
|
523
1857
|
/** The verifying fragment, { provConfirmed: true }: PATCH it over existing metadata. */
|
|
@@ -527,6 +1861,154 @@ export function isMachine(metadata: object | null | undefined): boolean;
|
|
|
527
1861
|
/** Whether a machine writer must leave this entity alone (human or verified). !isMachine. */
|
|
528
1862
|
export function isProtected(metadata: object | null | undefined): boolean;
|
|
529
1863
|
/** The fragment a HUMAN edit should merge in: PROV_CONFIRMED iff machine-unverified, else null. */
|
|
530
|
-
export function verifyOnEdit(
|
|
1864
|
+
export function verifyOnEdit(
|
|
1865
|
+
metadata: object | null | undefined,
|
|
1866
|
+
): { readonly provConfirmed: true } | null;
|
|
531
1867
|
/** Canonical provSource for a service: 'service:<serviceId>'. */
|
|
532
1868
|
export function serviceSource(serviceId: string): string;
|
|
1869
|
+
/** Canonical provSource for a contributor: 'user:<userId>'. */
|
|
1870
|
+
export function userSource(userId: string): string;
|
|
1871
|
+
/** The metadata fragment a contributor's work carries. */
|
|
1872
|
+
export function stampContributed(userId: string): {
|
|
1873
|
+
prov: "contributed";
|
|
1874
|
+
provSource: string;
|
|
1875
|
+
};
|
|
1876
|
+
/** Where an entity came from, confirmed or not: what a verified entity's tooltip needs. */
|
|
1877
|
+
export function provOrigin(
|
|
1878
|
+
metadata: object | null | undefined,
|
|
1879
|
+
): null | "inferred" | "contributed";
|
|
1880
|
+
/** Whether a verifier still has to look at this entity: machine-made or contributed, unconfirmed. */
|
|
1881
|
+
export function needsReview(metadata: object | null | undefined): boolean;
|
|
1882
|
+
/** The fragment a CONTRIBUTOR's edit merges in: the contributed stamp, dropping any confirmation. */
|
|
1883
|
+
export function contributeOnEdit(
|
|
1884
|
+
metadata: object | null | undefined,
|
|
1885
|
+
userId: string,
|
|
1886
|
+
): { prov: "contributed"; provSource: string; provConfirmed: null };
|
|
1887
|
+
/** Merge a fragment into a local copy, a null value deleting the key: applyMetadataOps(metadata, metadataOps(fragment)), refused where the server would refuse it. Returns a new object. */
|
|
1888
|
+
export function mergeMetadata(
|
|
1889
|
+
metadata: object | null | undefined,
|
|
1890
|
+
fragment: object | null | undefined,
|
|
1891
|
+
): Record<string, any>;
|
|
1892
|
+
|
|
1893
|
+
// --- Create responses ---------------------------------------------------------
|
|
1894
|
+
/** The id a single create answered with, read off the call's response or its batch result (`{status, body}`). Undefined when it gave none. */
|
|
1895
|
+
/** Idempotency-Key seed for an operation run more than once (client.keySeed()). */
|
|
1896
|
+
export interface KeySeed {
|
|
1897
|
+
seed: string;
|
|
1898
|
+
stamps: Map<number, number | null>;
|
|
1899
|
+
}
|
|
1900
|
+
/** A fresh UUIDv7, for the id of something a client creates. */
|
|
1901
|
+
export function uuidv7(): string;
|
|
1902
|
+
/** Whether a write's answer was replayed from its Idempotency-Key's first send (`Idempotent-Replayed: true`), so it wrote nothing new. Marked on an object or list answer as a non-enumerable `replayed: true`. */
|
|
1903
|
+
export function wasReplayed(answer: unknown): boolean;
|
|
1904
|
+
export function createdId(result: any): string | undefined;
|
|
1905
|
+
/** The ids a bulk create answered with, in input order, read off the call's response or its batch result. Empty when it gave none. */
|
|
1906
|
+
export function createdIds(result: any): string[];
|
|
1907
|
+
|
|
1908
|
+
// --- Metadata ops -------------------------------------------------------------
|
|
1909
|
+
/** One metadata edit: the body of a metadata PATCH is a list of these. */
|
|
1910
|
+
export type MetadataOp =
|
|
1911
|
+
| { op: "set"; path: string[]; value: any }
|
|
1912
|
+
| { op: "delete"; path: string[] };
|
|
1913
|
+
/** The ops that set each top-level key of a fragment, a null value deleting it. */
|
|
1914
|
+
export function metadataOps(
|
|
1915
|
+
fragment: object | null | undefined,
|
|
1916
|
+
): MetadataOp[];
|
|
1917
|
+
/** Apply ops to a local copy the way the server does. Returns a new object; throws where the server would refuse. */
|
|
1918
|
+
export function applyMetadataOps(
|
|
1919
|
+
metadata: object | null | undefined,
|
|
1920
|
+
ops: MetadataOp[],
|
|
1921
|
+
): Record<string, any>;
|
|
1922
|
+
/** True for a top-level metadata key Plaid keeps for itself (`plaid` and the provenance keys), never a user's field. */
|
|
1923
|
+
export function isReservedMetadataKey(key: string): boolean;
|
|
1924
|
+
|
|
1925
|
+
// --- Review: whose work is reviewed (a project-config norm) -------------------
|
|
1926
|
+
/** The config key, under the `plaid` namespace, holding the review lists. */
|
|
1927
|
+
export const REVIEW_KEY: "review";
|
|
1928
|
+
/** The project roles a review list may name. */
|
|
1929
|
+
export const PROJECT_ROLES: readonly ["reader", "writer", "maintainer"];
|
|
1930
|
+
/** A project's review lists, normalized. */
|
|
1931
|
+
export function readReview(config?: object | null): {
|
|
1932
|
+
users: string[];
|
|
1933
|
+
roles: string[];
|
|
1934
|
+
};
|
|
1935
|
+
/** A person's role in a project from its ACL lists; an admin with no entry is a maintainer. */
|
|
1936
|
+
export function projectRole(
|
|
1937
|
+
project: object | null | undefined,
|
|
1938
|
+
userId: string | null | undefined,
|
|
1939
|
+
opts?: { isAdmin?: boolean },
|
|
1940
|
+
): "maintainer" | "writer" | "reader" | null;
|
|
1941
|
+
/** Whether this person's work is reviewed here: named in review.users, or holding a role in review.roles. */
|
|
1942
|
+
export function isReviewed(
|
|
1943
|
+
project: object | null | undefined,
|
|
1944
|
+
userId: string | null | undefined,
|
|
1945
|
+
opts?: { isAdmin?: boolean },
|
|
1946
|
+
): boolean;
|
|
1947
|
+
/** The review lists with one person added to or removed from `users`. Pure. */
|
|
1948
|
+
export function withReviewedUser(
|
|
1949
|
+
review: { users?: string[]; roles?: string[] } | null | undefined,
|
|
1950
|
+
userId: string,
|
|
1951
|
+
reviewed: boolean,
|
|
1952
|
+
): { users: string[]; roles: string[] };
|
|
1953
|
+
/** What one writer's writes carry and what their review gestures act on. */
|
|
1954
|
+
export function writerPolicy(contributorId?: string | null): {
|
|
1955
|
+
readonly contributorId: string | null;
|
|
1956
|
+
readonly isContributor: boolean;
|
|
1957
|
+
/** The metadata a NEW entity carries: null for a verifier. */
|
|
1958
|
+
readonly createStamp: Record<string, any> | null;
|
|
1959
|
+
/** The fragment an EDIT merges, or null when there is nothing to merge. */
|
|
1960
|
+
readonly editStamp: (
|
|
1961
|
+
metadata: object | null | undefined,
|
|
1962
|
+
) => Record<string, any> | null;
|
|
1963
|
+
/** The fragment an explicit confirm gesture merges, or null. */
|
|
1964
|
+
readonly confirmStamp: (
|
|
1965
|
+
metadata: object | null | undefined,
|
|
1966
|
+
) => Record<string, any> | null;
|
|
1967
|
+
/** What an adopted suggestion is written with. */
|
|
1968
|
+
readonly adoptStamp: (
|
|
1969
|
+
source: string,
|
|
1970
|
+
detail?: Record<string, any>,
|
|
1971
|
+
) => Record<string, any>;
|
|
1972
|
+
/** Whether this writer's review gesture acts on the entity. */
|
|
1973
|
+
readonly reviewable: (metadata: object | null | undefined) => boolean;
|
|
1974
|
+
/** The same test over a provState. */
|
|
1975
|
+
readonly reviewableState: (state: string) => boolean;
|
|
1976
|
+
};
|
|
1977
|
+
|
|
1978
|
+
// --- Layer constraints -------------------------------------------------------
|
|
1979
|
+
/** A constraint an app declares on a layer, e.g. {type: "value-set", values: ["N"]}. */
|
|
1980
|
+
export interface LayerConstraint {
|
|
1981
|
+
type:
|
|
1982
|
+
| "max-in-degree"
|
|
1983
|
+
| "acyclic"
|
|
1984
|
+
| "same-ancestor"
|
|
1985
|
+
| "single-span"
|
|
1986
|
+
| "value-set"
|
|
1987
|
+
| "coextensive"
|
|
1988
|
+
| "single-link";
|
|
1989
|
+
[param: string]: any;
|
|
1990
|
+
}
|
|
1991
|
+
/** `expected`: the list read for the namespace, null when it was absent. */
|
|
1992
|
+
export interface ConstraintWriteOptions {
|
|
1993
|
+
expected?: LayerConstraint[] | null;
|
|
1994
|
+
}
|
|
1995
|
+
/** One violation a 422 lists. */
|
|
1996
|
+
export interface ConstraintViolation {
|
|
1997
|
+
constraint: string;
|
|
1998
|
+
namespace: string | null;
|
|
1999
|
+
layer: string;
|
|
2000
|
+
layerName: string;
|
|
2001
|
+
document: string | null;
|
|
2002
|
+
at: string | null;
|
|
2003
|
+
ids: string[];
|
|
2004
|
+
value?: any;
|
|
2005
|
+
parts?: string[];
|
|
2006
|
+
}
|
|
2007
|
+
/** The constraint types. */
|
|
2008
|
+
export const CONSTRAINT_TYPES: readonly string[];
|
|
2009
|
+
/** The camelCased violations of a write refused by a layer constraint, or null. */
|
|
2010
|
+
export function violationsOf(err: any): ConstraintViolation[] | null;
|
|
2011
|
+
export function valueSetAllows(
|
|
2012
|
+
constraint: { values: string[]; delimiters?: string; parts?: "all" | "first" },
|
|
2013
|
+
value: any,
|
|
2014
|
+
): boolean;
|