@larc-iu/plaid-client 0.1.0-alpha.9 → 0.2.0-alpha.1
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 +263 -111
- package/package.json +1 -1
- package/src/http.js +45 -4
- package/src/index.js +654 -225
- package/src/provenance.js +139 -0
- package/src/serviceSchema.js +10 -4
- package/src/services.js +32 -6
- package/src/sse.js +7 -0
package/src/index.js
CHANGED
|
@@ -11,6 +11,7 @@ import { listAll, listPage, iterPages } from './pagination.js';
|
|
|
11
11
|
import { createSSEConnection } from './sse.js';
|
|
12
12
|
import {
|
|
13
13
|
discoverServices,
|
|
14
|
+
discardService,
|
|
14
15
|
serve,
|
|
15
16
|
requestService,
|
|
16
17
|
} from './services.js';
|
|
@@ -24,6 +25,32 @@ function bodyOf(obj) {
|
|
|
24
25
|
return result;
|
|
25
26
|
}
|
|
26
27
|
|
|
28
|
+
// POST to an endpoint that takes no Authorization header (login, invite lookup
|
|
29
|
+
// and redemption). Deliberately does not go through PlaidClient._request: these
|
|
30
|
+
// are called before any client exists, which is the whole point.
|
|
31
|
+
async function anonymousPost(baseUrl, path, body, options = {}) {
|
|
32
|
+
const base = baseUrl.replace(/\/$/, '');
|
|
33
|
+
const url = `${base}${path}`;
|
|
34
|
+
try {
|
|
35
|
+
const fetchOptions = {
|
|
36
|
+
method: 'POST',
|
|
37
|
+
headers: { 'Content-Type': 'application/json' },
|
|
38
|
+
body: JSON.stringify(body),
|
|
39
|
+
};
|
|
40
|
+
const signal = timeoutSignal(options.timeout !== undefined ? options.timeout : DEFAULT_TIMEOUT_MS);
|
|
41
|
+
if (signal) fetchOptions.signal = signal;
|
|
42
|
+
|
|
43
|
+
const response = await fetch(url, fetchOptions);
|
|
44
|
+
if (!response.ok) {
|
|
45
|
+
throw makeHttpError(response, await parseErrorBody(response), url, 'POST');
|
|
46
|
+
}
|
|
47
|
+
return transformResponse(await response.json());
|
|
48
|
+
} catch (error) {
|
|
49
|
+
if (error.status) throw error;
|
|
50
|
+
throw makeNetworkError(error, url, 'POST');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
27
54
|
class PlaidClient {
|
|
28
55
|
/**
|
|
29
56
|
* Create a new PlaidClient instance
|
|
@@ -40,6 +67,16 @@ class PlaidClient {
|
|
|
40
67
|
this.batchOperations = [];
|
|
41
68
|
this.documentVersions = {};
|
|
42
69
|
this.strictModeDocumentId = null;
|
|
70
|
+
// The open logical operation (audit-log group), or null. While set, every
|
|
71
|
+
// write is stamped with `?group-id=` (+ `group-message`) so the audit log
|
|
72
|
+
// folds them into ONE expandable entry. See beginOperation / withOperation.
|
|
73
|
+
// Shape: { id, message, depth, written, refined }.
|
|
74
|
+
this.operationGroup = null;
|
|
75
|
+
// Optional callback fired once (per client) when any request returns HTTP
|
|
76
|
+
// 401 — i.e. the token is missing/expired/invalid. Apps use it to discard
|
|
77
|
+
// the stored token and route back to login. See makeRequest in http.js.
|
|
78
|
+
this.onAuthError = options.onAuthError || null;
|
|
79
|
+
this._authErrorFired = false;
|
|
43
80
|
|
|
44
81
|
// --- API Bundles ---
|
|
45
82
|
|
|
@@ -50,25 +87,40 @@ class PlaidClient {
|
|
|
50
87
|
* @param {Array} tokens - The tokens to link
|
|
51
88
|
* @param {any} [metadata] - Metadata for the link. Omit to leave unset; pass null to send JSON null.
|
|
52
89
|
*/
|
|
53
|
-
create: (vocabItem, tokens, metadata) =>
|
|
54
|
-
this._request('POST', '/api/v1/vocab-links', {
|
|
90
|
+
create: (vocabItem, tokens, metadata, auditMessage) =>
|
|
91
|
+
this._request('POST', '/api/v1/vocab-links', { auditMessage,
|
|
55
92
|
body: bodyOf({ 'vocab-item': vocabItem, tokens, metadata }),
|
|
56
93
|
}),
|
|
94
|
+
/**
|
|
95
|
+
* Create multiple vocab links in a single operation. Entries may
|
|
96
|
+
* reference different vocab items, but all tokens across the call must
|
|
97
|
+
* belong to one document.
|
|
98
|
+
* @param {Array<{vocabItem: string, tokens: string[], metadata?: any}>} body - The vocab links to create
|
|
99
|
+
* @returns {Promise<{ids: string[]}>} The created entity IDs, in input order. (bulkDelete resolves to no value.)
|
|
100
|
+
*/
|
|
101
|
+
bulkCreate: (body, auditMessage) =>
|
|
102
|
+
this._request('POST', '/api/v1/vocab-links/bulk', { auditMessage, body }),
|
|
103
|
+
/**
|
|
104
|
+
* Delete multiple vocab links in a single operation. Provide an array of IDs.
|
|
105
|
+
* @param {string[]} body - The vocab link IDs to delete
|
|
106
|
+
*/
|
|
107
|
+
bulkDelete: (body, auditMessage) =>
|
|
108
|
+
this._request('DELETE', '/api/v1/vocab-links/bulk', { auditMessage, body }),
|
|
57
109
|
/**
|
|
58
110
|
* Replace all metadata for a vocab link. The entire metadata map is replaced - existing metadata keys not included in the request will be removed.
|
|
59
111
|
* @param {string} id - The resource ID
|
|
60
112
|
* @param {any} body - The request body
|
|
61
113
|
*/
|
|
62
|
-
setMetadata: (id, body) =>
|
|
63
|
-
this._request('PUT', `/api/v1/vocab-links/${id}/metadata`, {
|
|
114
|
+
setMetadata: (id, body, auditMessage) =>
|
|
115
|
+
this._request('PUT', `/api/v1/vocab-links/${id}/metadata`, { auditMessage,
|
|
64
116
|
rawBody: body, skipResponseTransform: true,
|
|
65
117
|
}),
|
|
66
118
|
/**
|
|
67
119
|
* Remove all metadata from a vocab link.
|
|
68
120
|
* @param {string} id - The resource ID
|
|
69
121
|
*/
|
|
70
|
-
deleteMetadata: (id) =>
|
|
71
|
-
this._request('DELETE', `/api/v1/vocab-links/${id}/metadata`, {
|
|
122
|
+
deleteMetadata: (id, auditMessage) =>
|
|
123
|
+
this._request('DELETE', `/api/v1/vocab-links/${id}/metadata`, { auditMessage,
|
|
72
124
|
skipResponseTransform: true,
|
|
73
125
|
}),
|
|
74
126
|
/**
|
|
@@ -76,8 +128,8 @@ class PlaidClient {
|
|
|
76
128
|
* @param {string} id - The resource ID
|
|
77
129
|
* @param {any} body - The metadata patch
|
|
78
130
|
*/
|
|
79
|
-
patchMetadata: (id, body) =>
|
|
80
|
-
this._request('PATCH', `/api/v1/vocab-links/${id}/metadata`, {
|
|
131
|
+
patchMetadata: (id, body, auditMessage) =>
|
|
132
|
+
this._request('PATCH', `/api/v1/vocab-links/${id}/metadata`, { auditMessage,
|
|
81
133
|
rawBody: body, skipResponseTransform: true,
|
|
82
134
|
}),
|
|
83
135
|
/**
|
|
@@ -93,8 +145,8 @@ class PlaidClient {
|
|
|
93
145
|
* Delete a vocab link
|
|
94
146
|
* @param {string} id - The resource ID
|
|
95
147
|
*/
|
|
96
|
-
delete: (id) =>
|
|
97
|
-
this._request('DELETE', `/api/v1/vocab-links/${id}
|
|
148
|
+
delete: (id, auditMessage) =>
|
|
149
|
+
this._request('DELETE', `/api/v1/vocab-links/${id}`, { auditMessage }),
|
|
98
150
|
};
|
|
99
151
|
|
|
100
152
|
this.vocabLayers = {
|
|
@@ -112,15 +164,15 @@ class PlaidClient {
|
|
|
112
164
|
* Delete a vocab layer.
|
|
113
165
|
* @param {string} id - The resource ID
|
|
114
166
|
*/
|
|
115
|
-
delete: (id) =>
|
|
116
|
-
this._request('DELETE', `/api/v1/vocab-layers/${id}
|
|
167
|
+
delete: (id, auditMessage) =>
|
|
168
|
+
this._request('DELETE', `/api/v1/vocab-layers/${id}`, { auditMessage }),
|
|
117
169
|
/**
|
|
118
170
|
* Update a vocab layer's name.
|
|
119
171
|
* @param {string} id - The resource ID
|
|
120
172
|
* @param {string} name - The name
|
|
121
173
|
*/
|
|
122
|
-
update: (id, name) =>
|
|
123
|
-
this._request('PATCH', `/api/v1/vocab-layers/${id}`, {
|
|
174
|
+
update: (id, name, auditMessage) =>
|
|
175
|
+
this._request('PATCH', `/api/v1/vocab-layers/${id}`, { auditMessage,
|
|
124
176
|
body: bodyOf({ name }),
|
|
125
177
|
}),
|
|
126
178
|
/**
|
|
@@ -130,8 +182,8 @@ class PlaidClient {
|
|
|
130
182
|
* @param {string} configKey - The config key
|
|
131
183
|
* @param {any} configValue - Configuration value to set
|
|
132
184
|
*/
|
|
133
|
-
setConfig: (id, namespace, configKey, configValue) =>
|
|
134
|
-
this._request('PUT', `/api/v1/vocab-layers/${id}/config/${namespace}/${configKey}`, {
|
|
185
|
+
setConfig: (id, namespace, configKey, configValue, auditMessage) =>
|
|
186
|
+
this._request('PUT', `/api/v1/vocab-layers/${id}/config/${namespace}/${configKey}`, { auditMessage,
|
|
135
187
|
rawBody: configValue, skipResponseTransform: true,
|
|
136
188
|
}),
|
|
137
189
|
/**
|
|
@@ -140,8 +192,8 @@ class PlaidClient {
|
|
|
140
192
|
* @param {string} namespace - The config namespace
|
|
141
193
|
* @param {string} configKey - The config key
|
|
142
194
|
*/
|
|
143
|
-
deleteConfig: (id, namespace, configKey) =>
|
|
144
|
-
this._request('DELETE', `/api/v1/vocab-layers/${id}/config/${namespace}/${configKey}`, {
|
|
195
|
+
deleteConfig: (id, namespace, configKey, auditMessage) =>
|
|
196
|
+
this._request('DELETE', `/api/v1/vocab-layers/${id}/config/${namespace}/${configKey}`, { auditMessage,
|
|
145
197
|
skipResponseTransform: true,
|
|
146
198
|
}),
|
|
147
199
|
/**
|
|
@@ -176,8 +228,8 @@ class PlaidClient {
|
|
|
176
228
|
* Create a new vocab layer. Note: this also registers the user as a maintainer.
|
|
177
229
|
* @param {string} name - The name
|
|
178
230
|
*/
|
|
179
|
-
create: (name) =>
|
|
180
|
-
this._request('POST', '/api/v1/vocab-layers', {
|
|
231
|
+
create: (name, auditMessage) =>
|
|
232
|
+
this._request('POST', '/api/v1/vocab-layers', { auditMessage,
|
|
181
233
|
body: bodyOf({ name }),
|
|
182
234
|
}),
|
|
183
235
|
/**
|
|
@@ -185,15 +237,15 @@ class PlaidClient {
|
|
|
185
237
|
* @param {string} id - The resource ID
|
|
186
238
|
* @param {string} userId - The user ID
|
|
187
239
|
*/
|
|
188
|
-
addMaintainer: (id, userId) =>
|
|
189
|
-
this._request('POST', `/api/v1/vocab-layers/${id}/maintainers/${userId}
|
|
240
|
+
addMaintainer: (id, userId, auditMessage) =>
|
|
241
|
+
this._request('POST', `/api/v1/vocab-layers/${id}/maintainers/${userId}`, { auditMessage }),
|
|
190
242
|
/**
|
|
191
243
|
* Remove a user's maintainer privileges for this vocab layer.
|
|
192
244
|
* @param {string} id - The resource ID
|
|
193
245
|
* @param {string} userId - The user ID
|
|
194
246
|
*/
|
|
195
|
-
removeMaintainer: (id, userId) =>
|
|
196
|
-
this._request('DELETE', `/api/v1/vocab-layers/${id}/maintainers/${userId}
|
|
247
|
+
removeMaintainer: (id, userId, auditMessage) =>
|
|
248
|
+
this._request('DELETE', `/api/v1/vocab-layers/${id}/maintainers/${userId}`, { auditMessage }),
|
|
197
249
|
};
|
|
198
250
|
|
|
199
251
|
this.relations = {
|
|
@@ -202,16 +254,16 @@ class PlaidClient {
|
|
|
202
254
|
* @param {string} relationId - The relation ID
|
|
203
255
|
* @param {any} body - The request body
|
|
204
256
|
*/
|
|
205
|
-
setMetadata: (relationId, body) =>
|
|
206
|
-
this._request('PUT', `/api/v1/relations/${relationId}/metadata`, {
|
|
257
|
+
setMetadata: (relationId, body, auditMessage) =>
|
|
258
|
+
this._request('PUT', `/api/v1/relations/${relationId}/metadata`, { auditMessage,
|
|
207
259
|
rawBody: body, skipResponseTransform: true,
|
|
208
260
|
}),
|
|
209
261
|
/**
|
|
210
262
|
* Remove all metadata from a relation.
|
|
211
263
|
* @param {string} relationId - The relation ID
|
|
212
264
|
*/
|
|
213
|
-
deleteMetadata: (relationId) =>
|
|
214
|
-
this._request('DELETE', `/api/v1/relations/${relationId}/metadata`, {
|
|
265
|
+
deleteMetadata: (relationId, auditMessage) =>
|
|
266
|
+
this._request('DELETE', `/api/v1/relations/${relationId}/metadata`, { auditMessage,
|
|
215
267
|
skipResponseTransform: true,
|
|
216
268
|
}),
|
|
217
269
|
/**
|
|
@@ -219,8 +271,8 @@ class PlaidClient {
|
|
|
219
271
|
* @param {string} relationId - The relation ID
|
|
220
272
|
* @param {any} body - The metadata patch
|
|
221
273
|
*/
|
|
222
|
-
patchMetadata: (relationId, body) =>
|
|
223
|
-
this._request('PATCH', `/api/v1/relations/${relationId}/metadata`, {
|
|
274
|
+
patchMetadata: (relationId, body, auditMessage) =>
|
|
275
|
+
this._request('PATCH', `/api/v1/relations/${relationId}/metadata`, { auditMessage,
|
|
224
276
|
rawBody: body, skipResponseTransform: true,
|
|
225
277
|
}),
|
|
226
278
|
/**
|
|
@@ -228,8 +280,8 @@ class PlaidClient {
|
|
|
228
280
|
* @param {string} relationId - The relation ID
|
|
229
281
|
* @param {string} spanId - The span ID
|
|
230
282
|
*/
|
|
231
|
-
setTarget: (relationId, spanId) =>
|
|
232
|
-
this._request('PUT', `/api/v1/relations/${relationId}/target`, {
|
|
283
|
+
setTarget: (relationId, spanId, auditMessage) =>
|
|
284
|
+
this._request('PUT', `/api/v1/relations/${relationId}/target`, { auditMessage,
|
|
233
285
|
body: bodyOf({ 'span-id': spanId }),
|
|
234
286
|
}),
|
|
235
287
|
/**
|
|
@@ -245,15 +297,15 @@ class PlaidClient {
|
|
|
245
297
|
* Delete a relation.
|
|
246
298
|
* @param {string} relationId - The relation ID
|
|
247
299
|
*/
|
|
248
|
-
delete: (relationId) =>
|
|
249
|
-
this._request('DELETE', `/api/v1/relations/${relationId}
|
|
300
|
+
delete: (relationId, auditMessage) =>
|
|
301
|
+
this._request('DELETE', `/api/v1/relations/${relationId}`, { auditMessage }),
|
|
250
302
|
/**
|
|
251
303
|
* Update a relation's value.
|
|
252
304
|
* @param {string} relationId - The relation ID
|
|
253
305
|
* @param {any} value - The value
|
|
254
306
|
*/
|
|
255
|
-
update: (relationId, value) =>
|
|
256
|
-
this._request('PATCH', `/api/v1/relations/${relationId}`, {
|
|
307
|
+
update: (relationId, value, auditMessage) =>
|
|
308
|
+
this._request('PATCH', `/api/v1/relations/${relationId}`, { auditMessage,
|
|
257
309
|
body: bodyOf({ value }),
|
|
258
310
|
}),
|
|
259
311
|
/**
|
|
@@ -261,8 +313,8 @@ class PlaidClient {
|
|
|
261
313
|
* @param {string} relationId - The relation ID
|
|
262
314
|
* @param {string} spanId - The span ID
|
|
263
315
|
*/
|
|
264
|
-
setSource: (relationId, spanId) =>
|
|
265
|
-
this._request('PUT', `/api/v1/relations/${relationId}/source`, {
|
|
316
|
+
setSource: (relationId, spanId, auditMessage) =>
|
|
317
|
+
this._request('PUT', `/api/v1/relations/${relationId}/source`, { auditMessage,
|
|
266
318
|
body: bodyOf({ 'span-id': spanId }),
|
|
267
319
|
}),
|
|
268
320
|
/**
|
|
@@ -275,22 +327,23 @@ class PlaidClient {
|
|
|
275
327
|
* @param {any} value - The value
|
|
276
328
|
* @param {any} [metadata] - Metadata map. Omit to leave unset; pass null to send JSON null.
|
|
277
329
|
*/
|
|
278
|
-
create: (layerId, sourceId, targetId, value, metadata) =>
|
|
279
|
-
this._request('POST', '/api/v1/relations', {
|
|
330
|
+
create: (layerId, sourceId, targetId, value, metadata, auditMessage) =>
|
|
331
|
+
this._request('POST', '/api/v1/relations', { auditMessage,
|
|
280
332
|
body: bodyOf({ 'layer-id': layerId, 'source-id': sourceId, 'target-id': targetId, value, metadata }),
|
|
281
333
|
}),
|
|
282
334
|
/**
|
|
283
335
|
* Create multiple relations in a single operation.
|
|
284
336
|
* @param {Array} body - The request body
|
|
337
|
+
* @returns {Promise<{ids: string[]}>} The created entity IDs, in input order. (bulkDelete resolves to no value.)
|
|
285
338
|
*/
|
|
286
|
-
bulkCreate: (body) =>
|
|
287
|
-
this._request('POST', '/api/v1/relations/bulk', { body }),
|
|
339
|
+
bulkCreate: (body, auditMessage) =>
|
|
340
|
+
this._request('POST', '/api/v1/relations/bulk', { auditMessage, body }),
|
|
288
341
|
/**
|
|
289
342
|
* Delete multiple relations in a single operation. Provide an array of IDs.
|
|
290
343
|
* @param {Array} body - The request body
|
|
291
344
|
*/
|
|
292
|
-
bulkDelete: (body) =>
|
|
293
|
-
this._request('DELETE', '/api/v1/relations/bulk', { body }),
|
|
345
|
+
bulkDelete: (body, auditMessage) =>
|
|
346
|
+
this._request('DELETE', '/api/v1/relations/bulk', { auditMessage, body }),
|
|
294
347
|
};
|
|
295
348
|
|
|
296
349
|
this.spanLayers = {
|
|
@@ -301,8 +354,8 @@ class PlaidClient {
|
|
|
301
354
|
* @param {string} configKey - The config key
|
|
302
355
|
* @param {any} configValue - Configuration value to set
|
|
303
356
|
*/
|
|
304
|
-
setConfig: (spanLayerId, namespace, configKey, configValue) =>
|
|
305
|
-
this._request('PUT', `/api/v1/span-layers/${spanLayerId}/config/${namespace}/${configKey}`, {
|
|
357
|
+
setConfig: (spanLayerId, namespace, configKey, configValue, auditMessage) =>
|
|
358
|
+
this._request('PUT', `/api/v1/span-layers/${spanLayerId}/config/${namespace}/${configKey}`, { auditMessage,
|
|
306
359
|
rawBody: configValue, skipResponseTransform: true,
|
|
307
360
|
}),
|
|
308
361
|
/**
|
|
@@ -311,8 +364,8 @@ class PlaidClient {
|
|
|
311
364
|
* @param {string} namespace - The config namespace
|
|
312
365
|
* @param {string} configKey - The config key
|
|
313
366
|
*/
|
|
314
|
-
deleteConfig: (spanLayerId, namespace, configKey) =>
|
|
315
|
-
this._request('DELETE', `/api/v1/span-layers/${spanLayerId}/config/${namespace}/${configKey}`, {
|
|
367
|
+
deleteConfig: (spanLayerId, namespace, configKey, auditMessage) =>
|
|
368
|
+
this._request('DELETE', `/api/v1/span-layers/${spanLayerId}/config/${namespace}/${configKey}`, { auditMessage,
|
|
316
369
|
skipResponseTransform: true,
|
|
317
370
|
}),
|
|
318
371
|
/**
|
|
@@ -328,15 +381,15 @@ class PlaidClient {
|
|
|
328
381
|
* Delete a span layer.
|
|
329
382
|
* @param {string} spanLayerId - The span layer ID
|
|
330
383
|
*/
|
|
331
|
-
delete: (spanLayerId) =>
|
|
332
|
-
this._request('DELETE', `/api/v1/span-layers/${spanLayerId}
|
|
384
|
+
delete: (spanLayerId, auditMessage) =>
|
|
385
|
+
this._request('DELETE', `/api/v1/span-layers/${spanLayerId}`, { auditMessage }),
|
|
333
386
|
/**
|
|
334
387
|
* Update a span layer's name.
|
|
335
388
|
* @param {string} spanLayerId - The span layer ID
|
|
336
389
|
* @param {string} name - The name
|
|
337
390
|
*/
|
|
338
|
-
update: (spanLayerId, name) =>
|
|
339
|
-
this._request('PATCH', `/api/v1/span-layers/${spanLayerId}`, {
|
|
391
|
+
update: (spanLayerId, name, auditMessage) =>
|
|
392
|
+
this._request('PATCH', `/api/v1/span-layers/${spanLayerId}`, { auditMessage,
|
|
340
393
|
body: bodyOf({ name }),
|
|
341
394
|
}),
|
|
342
395
|
/**
|
|
@@ -344,8 +397,8 @@ class PlaidClient {
|
|
|
344
397
|
* @param {string} tokenLayerId - The token layer ID
|
|
345
398
|
* @param {string} name - The name
|
|
346
399
|
*/
|
|
347
|
-
create: (tokenLayerId, name) =>
|
|
348
|
-
this._request('POST', '/api/v1/span-layers', {
|
|
400
|
+
create: (tokenLayerId, name, auditMessage) =>
|
|
401
|
+
this._request('POST', '/api/v1/span-layers', { auditMessage,
|
|
349
402
|
body: bodyOf({ 'token-layer-id': tokenLayerId, name }),
|
|
350
403
|
}),
|
|
351
404
|
/**
|
|
@@ -353,8 +406,8 @@ class PlaidClient {
|
|
|
353
406
|
* @param {string} spanLayerId - The span layer ID
|
|
354
407
|
* @param {string} direction - The direction ("up" or "down")
|
|
355
408
|
*/
|
|
356
|
-
shift: (spanLayerId, direction) =>
|
|
357
|
-
this._request('POST', `/api/v1/span-layers/${spanLayerId}/shift`, {
|
|
409
|
+
shift: (spanLayerId, direction, auditMessage) =>
|
|
410
|
+
this._request('POST', `/api/v1/span-layers/${spanLayerId}/shift`, { auditMessage,
|
|
358
411
|
body: bodyOf({ direction }),
|
|
359
412
|
}),
|
|
360
413
|
};
|
|
@@ -365,8 +418,8 @@ class PlaidClient {
|
|
|
365
418
|
* @param {string} spanId - The span ID
|
|
366
419
|
* @param {Array} tokens - The tokens
|
|
367
420
|
*/
|
|
368
|
-
setTokens: (spanId, tokens) =>
|
|
369
|
-
this._request('PUT', `/api/v1/spans/${spanId}/tokens`, {
|
|
421
|
+
setTokens: (spanId, tokens, auditMessage) =>
|
|
422
|
+
this._request('PUT', `/api/v1/spans/${spanId}/tokens`, { auditMessage,
|
|
370
423
|
body: bodyOf({ tokens }),
|
|
371
424
|
}),
|
|
372
425
|
/**
|
|
@@ -377,8 +430,8 @@ class PlaidClient {
|
|
|
377
430
|
* @param {any} value - The value
|
|
378
431
|
* @param {any} [metadata] - Metadata map. Omit to leave unset; pass null to send JSON null.
|
|
379
432
|
*/
|
|
380
|
-
create: (spanLayerId, tokens, value, metadata) =>
|
|
381
|
-
this._request('POST', '/api/v1/spans', {
|
|
433
|
+
create: (spanLayerId, tokens, value, metadata, auditMessage) =>
|
|
434
|
+
this._request('POST', '/api/v1/spans', { auditMessage,
|
|
382
435
|
body: bodyOf({ 'span-layer-id': spanLayerId, tokens, value, metadata }),
|
|
383
436
|
}),
|
|
384
437
|
/**
|
|
@@ -394,44 +447,45 @@ class PlaidClient {
|
|
|
394
447
|
* Delete a span.
|
|
395
448
|
* @param {string} spanId - The span ID
|
|
396
449
|
*/
|
|
397
|
-
delete: (spanId) =>
|
|
398
|
-
this._request('DELETE', `/api/v1/spans/${spanId}
|
|
450
|
+
delete: (spanId, auditMessage) =>
|
|
451
|
+
this._request('DELETE', `/api/v1/spans/${spanId}`, { auditMessage }),
|
|
399
452
|
/**
|
|
400
453
|
* Update a span's value.
|
|
401
454
|
* @param {string} spanId - The span ID
|
|
402
455
|
* @param {any} value - The value
|
|
403
456
|
*/
|
|
404
|
-
update: (spanId, value) =>
|
|
405
|
-
this._request('PATCH', `/api/v1/spans/${spanId}`, {
|
|
457
|
+
update: (spanId, value, auditMessage) =>
|
|
458
|
+
this._request('PATCH', `/api/v1/spans/${spanId}`, { auditMessage,
|
|
406
459
|
body: bodyOf({ value }),
|
|
407
460
|
}),
|
|
408
461
|
/**
|
|
409
462
|
* Create multiple spans in a single operation.
|
|
410
463
|
* @param {Array} body - The request body
|
|
464
|
+
* @returns {Promise<{ids: string[]}>} The created entity IDs, in input order. (bulkDelete resolves to no value.)
|
|
411
465
|
*/
|
|
412
|
-
bulkCreate: (body) =>
|
|
413
|
-
this._request('POST', '/api/v1/spans/bulk', { body }),
|
|
466
|
+
bulkCreate: (body, auditMessage) =>
|
|
467
|
+
this._request('POST', '/api/v1/spans/bulk', { auditMessage, body }),
|
|
414
468
|
/**
|
|
415
469
|
* Delete multiple spans in a single operation. Provide an array of IDs.
|
|
416
470
|
* @param {Array} body - The request body
|
|
417
471
|
*/
|
|
418
|
-
bulkDelete: (body) =>
|
|
419
|
-
this._request('DELETE', '/api/v1/spans/bulk', { body }),
|
|
472
|
+
bulkDelete: (body, auditMessage) =>
|
|
473
|
+
this._request('DELETE', '/api/v1/spans/bulk', { auditMessage, body }),
|
|
420
474
|
/**
|
|
421
475
|
* Replace all metadata for a span.
|
|
422
476
|
* @param {string} spanId - The span ID
|
|
423
477
|
* @param {any} body - The request body
|
|
424
478
|
*/
|
|
425
|
-
setMetadata: (spanId, body) =>
|
|
426
|
-
this._request('PUT', `/api/v1/spans/${spanId}/metadata`, {
|
|
479
|
+
setMetadata: (spanId, body, auditMessage) =>
|
|
480
|
+
this._request('PUT', `/api/v1/spans/${spanId}/metadata`, { auditMessage,
|
|
427
481
|
rawBody: body, skipResponseTransform: true,
|
|
428
482
|
}),
|
|
429
483
|
/**
|
|
430
484
|
* Remove all metadata from a span.
|
|
431
485
|
* @param {string} spanId - The span ID
|
|
432
486
|
*/
|
|
433
|
-
deleteMetadata: (spanId) =>
|
|
434
|
-
this._request('DELETE', `/api/v1/spans/${spanId}/metadata`, {
|
|
487
|
+
deleteMetadata: (spanId, auditMessage) =>
|
|
488
|
+
this._request('DELETE', `/api/v1/spans/${spanId}/metadata`, { auditMessage,
|
|
435
489
|
skipResponseTransform: true,
|
|
436
490
|
}),
|
|
437
491
|
/**
|
|
@@ -439,8 +493,8 @@ class PlaidClient {
|
|
|
439
493
|
* @param {string} spanId - The span ID
|
|
440
494
|
* @param {any} body - The metadata patch
|
|
441
495
|
*/
|
|
442
|
-
patchMetadata: (spanId, body) =>
|
|
443
|
-
this._request('PATCH', `/api/v1/spans/${spanId}/metadata`, {
|
|
496
|
+
patchMetadata: (spanId, body, auditMessage) =>
|
|
497
|
+
this._request('PATCH', `/api/v1/spans/${spanId}/metadata`, { auditMessage,
|
|
444
498
|
rawBody: body, skipResponseTransform: true,
|
|
445
499
|
}),
|
|
446
500
|
};
|
|
@@ -451,8 +505,8 @@ class PlaidClient {
|
|
|
451
505
|
* changes are rolled back.
|
|
452
506
|
* @param {Array} body - The request body
|
|
453
507
|
*/
|
|
454
|
-
submit: (body) =>
|
|
455
|
-
this._request('POST', '/api/v1/batch', {
|
|
508
|
+
submit: (body, auditMessage) =>
|
|
509
|
+
this._request('POST', '/api/v1/batch', { auditMessage,
|
|
456
510
|
body, noBatch: true,
|
|
457
511
|
}),
|
|
458
512
|
};
|
|
@@ -463,16 +517,16 @@ class PlaidClient {
|
|
|
463
517
|
* @param {string} textId - The text ID
|
|
464
518
|
* @param {any} body - The request body
|
|
465
519
|
*/
|
|
466
|
-
setMetadata: (textId, body) =>
|
|
467
|
-
this._request('PUT', `/api/v1/texts/${textId}/metadata`, {
|
|
520
|
+
setMetadata: (textId, body, auditMessage) =>
|
|
521
|
+
this._request('PUT', `/api/v1/texts/${textId}/metadata`, { auditMessage,
|
|
468
522
|
rawBody: body, skipResponseTransform: true,
|
|
469
523
|
}),
|
|
470
524
|
/**
|
|
471
525
|
* Remove all metadata from a text.
|
|
472
526
|
* @param {string} textId - The text ID
|
|
473
527
|
*/
|
|
474
|
-
deleteMetadata: (textId) =>
|
|
475
|
-
this._request('DELETE', `/api/v1/texts/${textId}/metadata`, {
|
|
528
|
+
deleteMetadata: (textId, auditMessage) =>
|
|
529
|
+
this._request('DELETE', `/api/v1/texts/${textId}/metadata`, { auditMessage,
|
|
476
530
|
skipResponseTransform: true,
|
|
477
531
|
}),
|
|
478
532
|
/**
|
|
@@ -480,8 +534,8 @@ class PlaidClient {
|
|
|
480
534
|
* @param {string} textId - The text ID
|
|
481
535
|
* @param {any} body - The metadata patch
|
|
482
536
|
*/
|
|
483
|
-
patchMetadata: (textId, body) =>
|
|
484
|
-
this._request('PATCH', `/api/v1/texts/${textId}/metadata`, {
|
|
537
|
+
patchMetadata: (textId, body, auditMessage) =>
|
|
538
|
+
this._request('PATCH', `/api/v1/texts/${textId}/metadata`, { auditMessage,
|
|
485
539
|
rawBody: body, skipResponseTransform: true,
|
|
486
540
|
}),
|
|
487
541
|
/**
|
|
@@ -492,8 +546,8 @@ class PlaidClient {
|
|
|
492
546
|
* @param {string} body - The request body
|
|
493
547
|
* @param {any} [metadata] - Metadata map. Omit to leave unset; pass null to send JSON null.
|
|
494
548
|
*/
|
|
495
|
-
create: (textLayerId, documentId, body, metadata) =>
|
|
496
|
-
this._request('POST', '/api/v1/texts', {
|
|
549
|
+
create: (textLayerId, documentId, body, metadata, auditMessage) =>
|
|
550
|
+
this._request('POST', '/api/v1/texts', { auditMessage,
|
|
497
551
|
body: bodyOf({ 'text-layer-id': textLayerId, 'document-id': documentId, body, metadata }),
|
|
498
552
|
}),
|
|
499
553
|
/**
|
|
@@ -509,8 +563,8 @@ class PlaidClient {
|
|
|
509
563
|
* Delete a text and all dependent data.
|
|
510
564
|
* @param {string} textId - The text ID
|
|
511
565
|
*/
|
|
512
|
-
delete: (textId) =>
|
|
513
|
-
this._request('DELETE', `/api/v1/texts/${textId}
|
|
566
|
+
delete: (textId, auditMessage) =>
|
|
567
|
+
this._request('DELETE', `/api/v1/texts/${textId}`, { auditMessage }),
|
|
514
568
|
/**
|
|
515
569
|
* Update a text's body. A diff is computed and token indices are updated
|
|
516
570
|
* so that tokens remain intact. Alternatively, `body` can be a list of
|
|
@@ -518,8 +572,8 @@ class PlaidClient {
|
|
|
518
572
|
* @param {string} textId - The text ID
|
|
519
573
|
* @param {any} body - The request body
|
|
520
574
|
*/
|
|
521
|
-
update: (textId, body) =>
|
|
522
|
-
this._request('PATCH', `/api/v1/texts/${textId}`, {
|
|
575
|
+
update: (textId, body, auditMessage) =>
|
|
576
|
+
this._request('PATCH', `/api/v1/texts/${textId}`, { auditMessage,
|
|
523
577
|
body: bodyOf({ body }),
|
|
524
578
|
}),
|
|
525
579
|
};
|
|
@@ -563,8 +617,8 @@ class PlaidClient {
|
|
|
563
617
|
* @param {string} password - The password
|
|
564
618
|
* @param {boolean} isAdmin - Whether the user is an admin
|
|
565
619
|
*/
|
|
566
|
-
create: (username, password, isAdmin) =>
|
|
567
|
-
this._request('POST', '/api/v1/users', {
|
|
620
|
+
create: (username, password, isAdmin, auditMessage) =>
|
|
621
|
+
this._request('POST', '/api/v1/users', { auditMessage,
|
|
568
622
|
body: bodyOf({ username, password, 'is-admin': isAdmin }),
|
|
569
623
|
}),
|
|
570
624
|
/**
|
|
@@ -597,16 +651,16 @@ class PlaidClient {
|
|
|
597
651
|
* Reversible via activate(), which restores login only.
|
|
598
652
|
* @param {string} id - The resource ID
|
|
599
653
|
*/
|
|
600
|
-
delete: (id) =>
|
|
601
|
-
this._request('DELETE', `/api/v1/users/${id}
|
|
654
|
+
delete: (id, auditMessage) =>
|
|
655
|
+
this._request('DELETE', `/api/v1/users/${id}`, { auditMessage }),
|
|
602
656
|
/**
|
|
603
657
|
* Reactivate a deactivated user, restoring their ability to log in.
|
|
604
658
|
* Project memberships, vocab maintainerships, and API tokens removed
|
|
605
659
|
* at deactivation are NOT restored — re-grant them deliberately.
|
|
606
660
|
* @param {string} id - The resource ID
|
|
607
661
|
*/
|
|
608
|
-
activate: (id) =>
|
|
609
|
-
this._request('POST', `/api/v1/users/${id}/activate
|
|
662
|
+
activate: (id, auditMessage) =>
|
|
663
|
+
this._request('POST', `/api/v1/users/${id}/activate`, { auditMessage }),
|
|
610
664
|
/**
|
|
611
665
|
* Modify a user. Admins may change the username, password, and admin
|
|
612
666
|
* status of any user. All other users may only modify their own username
|
|
@@ -616,10 +670,64 @@ class PlaidClient {
|
|
|
616
670
|
* @param {string} [username] - New username
|
|
617
671
|
* @param {boolean} [isAdmin] - New admin status
|
|
618
672
|
*/
|
|
619
|
-
update: (id, password, username, isAdmin) =>
|
|
620
|
-
this._request('PATCH', `/api/v1/users/${id}`, {
|
|
673
|
+
update: (id, password, username, isAdmin, auditMessage) =>
|
|
674
|
+
this._request('PATCH', `/api/v1/users/${id}`, { auditMessage,
|
|
621
675
|
body: bodyOf({ password, username, 'is-admin': isAdmin }),
|
|
622
676
|
}),
|
|
677
|
+
/**
|
|
678
|
+
* Build a URL for a user's profile picture, suitable for use directly as
|
|
679
|
+
* an `<img>` src. An image element cannot send an Authorization header,
|
|
680
|
+
* so the session token rides in the query string, the same way document
|
|
681
|
+
* media does.
|
|
682
|
+
*
|
|
683
|
+
* Pass the user record's `avatarHash` as the second argument whenever you
|
|
684
|
+
* have it: the URL then addresses that exact picture, so the browser can
|
|
685
|
+
* cache it indefinitely and still pick up a replacement the moment the
|
|
686
|
+
* user changes it. Returns null when the user has no picture, so callers
|
|
687
|
+
* can fall back to initials without a wasted request.
|
|
688
|
+
* @param {string} id - The user ID
|
|
689
|
+
* @param {string} [avatarHash] - The user record's `avatarHash`
|
|
690
|
+
* @returns {string|null}
|
|
691
|
+
*/
|
|
692
|
+
avatarUrl: (id, avatarHash) => {
|
|
693
|
+
if (avatarHash === null) return null;
|
|
694
|
+
const params = new URLSearchParams({ token: this.token });
|
|
695
|
+
if (avatarHash) params.set('v', avatarHash);
|
|
696
|
+
return `${this.baseUrl}/api/v1/users/${id}/avatar?${params}`;
|
|
697
|
+
},
|
|
698
|
+
/**
|
|
699
|
+
* Fetch a user's profile picture as raw bytes. Most callers want
|
|
700
|
+
* avatarUrl() instead. This one is for non-browser consumers.
|
|
701
|
+
* @param {string} id - The user ID
|
|
702
|
+
*/
|
|
703
|
+
getAvatar: (id) =>
|
|
704
|
+
this._request('GET', `/api/v1/users/${id}/avatar`, {
|
|
705
|
+
noBatch: true,
|
|
706
|
+
binaryResponse: true,
|
|
707
|
+
}),
|
|
708
|
+
/**
|
|
709
|
+
* Upload a profile picture. Your own, or anyone's if you are an admin.
|
|
710
|
+
* The server center-crops to a square, scales to the configured edge
|
|
711
|
+
* length, and re-encodes, so no client-side resizing is needed. Accepts
|
|
712
|
+
* PNG, JPEG, WebP, and GIF. Resolves to the updated user record.
|
|
713
|
+
* @param {string} id - The user ID
|
|
714
|
+
* @param {File} file - The image to upload
|
|
715
|
+
*/
|
|
716
|
+
setAvatar: (id, file, auditMessage) => {
|
|
717
|
+
const fd = new FormData();
|
|
718
|
+
fd.append('file', file);
|
|
719
|
+
return this._request('PUT', `/api/v1/users/${id}/avatar`, { auditMessage,
|
|
720
|
+
body: fd, formData: true, noBatch: true,
|
|
721
|
+
});
|
|
722
|
+
},
|
|
723
|
+
/**
|
|
724
|
+
* Remove a profile picture. Your own, or anyone's if you are an admin.
|
|
725
|
+
* @param {string} id - The user ID
|
|
726
|
+
*/
|
|
727
|
+
deleteAvatar: (id, auditMessage) =>
|
|
728
|
+
this._request('DELETE', `/api/v1/users/${id}/avatar`, { auditMessage,
|
|
729
|
+
noBatch: true,
|
|
730
|
+
}),
|
|
623
731
|
};
|
|
624
732
|
|
|
625
733
|
this.apiTokens = {
|
|
@@ -661,8 +769,8 @@ class PlaidClient {
|
|
|
661
769
|
* @param {string} name - A human label, e.g. "Stanza Parser"
|
|
662
770
|
* @returns {Promise<{id: string, name: string, token: string}>}
|
|
663
771
|
*/
|
|
664
|
-
create: (userId, name) =>
|
|
665
|
-
this._request('POST', `/api/v1/users/${userId}/tokens`, {
|
|
772
|
+
create: (userId, name, auditMessage) =>
|
|
773
|
+
this._request('POST', `/api/v1/users/${userId}/tokens`, { auditMessage,
|
|
666
774
|
body: bodyOf({ name }),
|
|
667
775
|
}),
|
|
668
776
|
/**
|
|
@@ -670,8 +778,76 @@ class PlaidClient {
|
|
|
670
778
|
* @param {string} userId - The user ID who owns the token
|
|
671
779
|
* @param {string} tokenId - The token ID to revoke
|
|
672
780
|
*/
|
|
673
|
-
revoke: (userId, tokenId) =>
|
|
674
|
-
this._request('DELETE', `/api/v1/users/${userId}/tokens/${tokenId}
|
|
781
|
+
revoke: (userId, tokenId, auditMessage) =>
|
|
782
|
+
this._request('DELETE', `/api/v1/users/${userId}/tokens/${tokenId}`, { auditMessage }),
|
|
783
|
+
};
|
|
784
|
+
|
|
785
|
+
this.invites = {
|
|
786
|
+
/**
|
|
787
|
+
* List invites you minted, oldest first. With `projectId`, lists that
|
|
788
|
+
* project's invites instead (including co-maintainers'), which requires
|
|
789
|
+
* maintainer or admin on it. Never includes invite codes — the code is
|
|
790
|
+
* returned once, by create(), and is not recoverable afterward.
|
|
791
|
+
* Transparently follows pagination cursors and returns the full flat array.
|
|
792
|
+
* Cannot be used inside a batch (auto-paginates across requests); throws if called while batching — use listPage() for a single page in a batch.
|
|
793
|
+
* @param {object} [opts]
|
|
794
|
+
* @param {string} [opts.projectId] - List this project's invites instead of your own
|
|
795
|
+
*/
|
|
796
|
+
list: ({ projectId } = {}) =>
|
|
797
|
+
listAll(this, '/api/v1/invites', { query: { 'project-id': projectId } }),
|
|
798
|
+
/**
|
|
799
|
+
* Fetch a single page of invites.
|
|
800
|
+
* @param {object} [opts]
|
|
801
|
+
* @param {string} [opts.projectId] - List this project's invites instead of your own
|
|
802
|
+
* @param {number} [opts.limit] - Page size (1..1000; server default 100)
|
|
803
|
+
* @param {string} [opts.cursor] - Opaque cursor from a previous page
|
|
804
|
+
* @returns {Promise<{entries: Array, nextCursor: (string|null)}>}
|
|
805
|
+
*/
|
|
806
|
+
listPage: ({ projectId, limit, cursor } = {}) =>
|
|
807
|
+
listPage(this, '/api/v1/invites', { limit, cursor, query: { 'project-id': projectId } }),
|
|
808
|
+
/**
|
|
809
|
+
* Async-iterate invites page by page; yields each page's entries array.
|
|
810
|
+
* @param {object} [opts]
|
|
811
|
+
* @param {string} [opts.projectId] - List this project's invites instead of your own
|
|
812
|
+
* @param {number} [opts.pageSize] - Per-request page size
|
|
813
|
+
* Cannot be used inside a batch (auto-paginates across requests); throws on first iteration if called while batching — use listPage() for a single page in a batch.
|
|
814
|
+
* @returns {AsyncGenerator<Array>}
|
|
815
|
+
*/
|
|
816
|
+
iterPages: ({ projectId, pageSize } = {}) =>
|
|
817
|
+
iterPages(this, '/api/v1/invites', { pageSize, query: { 'project-id': projectId } }),
|
|
818
|
+
/**
|
|
819
|
+
* Mint an invite. The returned `code` is shown ONLY here — it is never
|
|
820
|
+
* stored and cannot be recovered, so build and hand off the link now.
|
|
821
|
+
* Use PlaidClient.inviteUrl() to turn it into one.
|
|
822
|
+
*
|
|
823
|
+
* Admins may mint anything. A project maintainer may mint role grants on
|
|
824
|
+
* projects they maintain, and nothing else: no admin grant, no grantless
|
|
825
|
+
* invite, no password resets.
|
|
826
|
+
* @param {object} opts
|
|
827
|
+
* @param {string} [opts.projectId] - Project the redeemer joins (with projectRole)
|
|
828
|
+
* @param {string} [opts.projectRole] - "reader" | "writer" | "maintainer"
|
|
829
|
+
* @param {boolean} [opts.grantAdmin] - Make the new account a global admin (admin only)
|
|
830
|
+
* @param {string} [opts.targetUserId] - Make this a password reset for that user (admin only)
|
|
831
|
+
* @param {number} [opts.maxUses] - How many accounts this link may create (default 1)
|
|
832
|
+
* @param {number} [opts.ttlDays] - Days until it expires (default 14, max 365)
|
|
833
|
+
* @param {string} [opts.note] - Human label shown in your invite list
|
|
834
|
+
* @returns {Promise<{id: string, code: string, kind: string, status: string}>}
|
|
835
|
+
*/
|
|
836
|
+
create: ({ projectId, projectRole, grantAdmin, targetUserId, maxUses, ttlDays, note } = {}, auditMessage) =>
|
|
837
|
+
this._request('POST', '/api/v1/invites', { auditMessage,
|
|
838
|
+
body: bodyOf({
|
|
839
|
+
'project-id': projectId, 'project-role': projectRole,
|
|
840
|
+
'grant-admin': grantAdmin, 'target-user-id': targetUserId,
|
|
841
|
+
'max-uses': maxUses, 'ttl-days': ttlDays, note,
|
|
842
|
+
}),
|
|
843
|
+
}),
|
|
844
|
+
/**
|
|
845
|
+
* Revoke an invite, killing the link immediately. Idempotent. Allowed for
|
|
846
|
+
* the creator, an admin, or a maintainer of the invite's project.
|
|
847
|
+
* @param {string} id - The invite ID
|
|
848
|
+
*/
|
|
849
|
+
revoke: (id, auditMessage) =>
|
|
850
|
+
this._request('DELETE', `/api/v1/invites/${id}`, { auditMessage }),
|
|
675
851
|
};
|
|
676
852
|
|
|
677
853
|
this.tokenLayers = {
|
|
@@ -680,8 +856,8 @@ class PlaidClient {
|
|
|
680
856
|
* @param {string} tokenLayerId - The token layer ID
|
|
681
857
|
* @param {string} direction - The direction ("up" or "down")
|
|
682
858
|
*/
|
|
683
|
-
shift: (tokenLayerId, direction) =>
|
|
684
|
-
this._request('POST', `/api/v1/token-layers/${tokenLayerId}/shift`, {
|
|
859
|
+
shift: (tokenLayerId, direction, auditMessage) =>
|
|
860
|
+
this._request('POST', `/api/v1/token-layers/${tokenLayerId}/shift`, { auditMessage,
|
|
685
861
|
body: bodyOf({ direction }),
|
|
686
862
|
}),
|
|
687
863
|
/**
|
|
@@ -691,8 +867,8 @@ class PlaidClient {
|
|
|
691
867
|
* @param {string} [overlapMode] - Per-layer, immutable token invariant: "any" (default), "non-overlapping", or "partitioning". On partitioning layers, single token create/update/delete are rejected; use bulkCreate plus split/merge/shift.
|
|
692
868
|
* @param {string} [parentTokenLayerId] - Optional immutable parent token layer. Tokens in this layer must nest within a parent-layer token; the parent layer must be in the same text layer and be "non-overlapping" or "partitioning" (an "any" parent is rejected). A nested layer may be "any" or "non-overlapping" but not "partitioning" (partitioning is only for root layers), e.g. words (non-overlapping, parent=sentences) within sentences (partitioning).
|
|
693
869
|
*/
|
|
694
|
-
create: (textLayerId, name, overlapMode, parentTokenLayerId) =>
|
|
695
|
-
this._request('POST', '/api/v1/token-layers', {
|
|
870
|
+
create: (textLayerId, name, overlapMode, parentTokenLayerId, auditMessage) =>
|
|
871
|
+
this._request('POST', '/api/v1/token-layers', { auditMessage,
|
|
696
872
|
body: bodyOf({ 'text-layer-id': textLayerId, name, 'overlap-mode': overlapMode, 'parent-token-layer-id': parentTokenLayerId }),
|
|
697
873
|
}),
|
|
698
874
|
/**
|
|
@@ -702,8 +878,8 @@ class PlaidClient {
|
|
|
702
878
|
* @param {string} configKey - The config key
|
|
703
879
|
* @param {any} configValue - Configuration value to set
|
|
704
880
|
*/
|
|
705
|
-
setConfig: (tokenLayerId, namespace, configKey, configValue) =>
|
|
706
|
-
this._request('PUT', `/api/v1/token-layers/${tokenLayerId}/config/${namespace}/${configKey}`, {
|
|
881
|
+
setConfig: (tokenLayerId, namespace, configKey, configValue, auditMessage) =>
|
|
882
|
+
this._request('PUT', `/api/v1/token-layers/${tokenLayerId}/config/${namespace}/${configKey}`, { auditMessage,
|
|
707
883
|
rawBody: configValue, skipResponseTransform: true,
|
|
708
884
|
}),
|
|
709
885
|
/**
|
|
@@ -712,8 +888,8 @@ class PlaidClient {
|
|
|
712
888
|
* @param {string} namespace - The config namespace
|
|
713
889
|
* @param {string} configKey - The config key
|
|
714
890
|
*/
|
|
715
|
-
deleteConfig: (tokenLayerId, namespace, configKey) =>
|
|
716
|
-
this._request('DELETE', `/api/v1/token-layers/${tokenLayerId}/config/${namespace}/${configKey}`, {
|
|
891
|
+
deleteConfig: (tokenLayerId, namespace, configKey, auditMessage) =>
|
|
892
|
+
this._request('DELETE', `/api/v1/token-layers/${tokenLayerId}/config/${namespace}/${configKey}`, { auditMessage,
|
|
717
893
|
skipResponseTransform: true,
|
|
718
894
|
}),
|
|
719
895
|
/**
|
|
@@ -729,15 +905,15 @@ class PlaidClient {
|
|
|
729
905
|
* Delete a token layer.
|
|
730
906
|
* @param {string} tokenLayerId - The token layer ID
|
|
731
907
|
*/
|
|
732
|
-
delete: (tokenLayerId) =>
|
|
733
|
-
this._request('DELETE', `/api/v1/token-layers/${tokenLayerId}
|
|
908
|
+
delete: (tokenLayerId, auditMessage) =>
|
|
909
|
+
this._request('DELETE', `/api/v1/token-layers/${tokenLayerId}`, { auditMessage }),
|
|
734
910
|
/**
|
|
735
911
|
* Update a token layer's name.
|
|
736
912
|
* @param {string} tokenLayerId - The token layer ID
|
|
737
913
|
* @param {string} name - The name
|
|
738
914
|
*/
|
|
739
|
-
update: (tokenLayerId, name) =>
|
|
740
|
-
this._request('PATCH', `/api/v1/token-layers/${tokenLayerId}`, {
|
|
915
|
+
update: (tokenLayerId, name, auditMessage) =>
|
|
916
|
+
this._request('PATCH', `/api/v1/token-layers/${tokenLayerId}`, { auditMessage,
|
|
741
917
|
body: bodyOf({ name }),
|
|
742
918
|
}),
|
|
743
919
|
};
|
|
@@ -756,14 +932,14 @@ class PlaidClient {
|
|
|
756
932
|
* Acquire or refresh a document lock
|
|
757
933
|
* @param {string} documentId - The document ID
|
|
758
934
|
*/
|
|
759
|
-
acquireLock: (documentId) =>
|
|
760
|
-
this._request('POST', `/api/v1/documents/${documentId}/lock
|
|
935
|
+
acquireLock: (documentId, auditMessage) =>
|
|
936
|
+
this._request('POST', `/api/v1/documents/${documentId}/lock`, { auditMessage }),
|
|
761
937
|
/**
|
|
762
938
|
* Release a document lock
|
|
763
939
|
* @param {string} documentId - The document ID
|
|
764
940
|
*/
|
|
765
|
-
releaseLock: (documentId) =>
|
|
766
|
-
this._request('DELETE', `/api/v1/documents/${documentId}/lock
|
|
941
|
+
releaseLock: (documentId, auditMessage) =>
|
|
942
|
+
this._request('DELETE', `/api/v1/documents/${documentId}/lock`, { auditMessage }),
|
|
767
943
|
/**
|
|
768
944
|
* Get media file for a document
|
|
769
945
|
* @param {string} documentId - The document ID
|
|
@@ -780,10 +956,10 @@ class PlaidClient {
|
|
|
780
956
|
* @param {string} documentId - The document ID
|
|
781
957
|
* @param {File} file - The file to upload
|
|
782
958
|
*/
|
|
783
|
-
uploadMedia: (documentId, file) => {
|
|
959
|
+
uploadMedia: (documentId, file, auditMessage) => {
|
|
784
960
|
const fd = new FormData();
|
|
785
961
|
fd.append('file', file);
|
|
786
|
-
return this._request('PUT', `/api/v1/documents/${documentId}/media`, {
|
|
962
|
+
return this._request('PUT', `/api/v1/documents/${documentId}/media`, { auditMessage,
|
|
787
963
|
body: fd, formData: true, noBatch: true,
|
|
788
964
|
});
|
|
789
965
|
},
|
|
@@ -791,8 +967,8 @@ class PlaidClient {
|
|
|
791
967
|
* Delete media file for a document
|
|
792
968
|
* @param {string} documentId - The document ID
|
|
793
969
|
*/
|
|
794
|
-
deleteMedia: (documentId) =>
|
|
795
|
-
this._request('DELETE', `/api/v1/documents/${documentId}/media`, {
|
|
970
|
+
deleteMedia: (documentId, auditMessage) =>
|
|
971
|
+
this._request('DELETE', `/api/v1/documents/${documentId}/media`, { auditMessage,
|
|
796
972
|
noBatch: true,
|
|
797
973
|
}),
|
|
798
974
|
/**
|
|
@@ -800,16 +976,16 @@ class PlaidClient {
|
|
|
800
976
|
* @param {string} documentId - The document ID
|
|
801
977
|
* @param {any} body - The request body
|
|
802
978
|
*/
|
|
803
|
-
setMetadata: (documentId, body) =>
|
|
804
|
-
this._request('PUT', `/api/v1/documents/${documentId}/metadata`, {
|
|
979
|
+
setMetadata: (documentId, body, auditMessage) =>
|
|
980
|
+
this._request('PUT', `/api/v1/documents/${documentId}/metadata`, { auditMessage,
|
|
805
981
|
rawBody: body, skipResponseTransform: true,
|
|
806
982
|
}),
|
|
807
983
|
/**
|
|
808
984
|
* Remove all metadata from a document.
|
|
809
985
|
* @param {string} documentId - The document ID
|
|
810
986
|
*/
|
|
811
|
-
deleteMetadata: (documentId) =>
|
|
812
|
-
this._request('DELETE', `/api/v1/documents/${documentId}/metadata`, {
|
|
987
|
+
deleteMetadata: (documentId, auditMessage) =>
|
|
988
|
+
this._request('DELETE', `/api/v1/documents/${documentId}/metadata`, { auditMessage,
|
|
813
989
|
skipResponseTransform: true,
|
|
814
990
|
}),
|
|
815
991
|
/**
|
|
@@ -817,8 +993,8 @@ class PlaidClient {
|
|
|
817
993
|
* @param {string} documentId - The document ID
|
|
818
994
|
* @param {any} body - The metadata patch
|
|
819
995
|
*/
|
|
820
|
-
patchMetadata: (documentId, body) =>
|
|
821
|
-
this._request('PATCH', `/api/v1/documents/${documentId}/metadata`, {
|
|
996
|
+
patchMetadata: (documentId, body, auditMessage) =>
|
|
997
|
+
this._request('PATCH', `/api/v1/documents/${documentId}/metadata`, { auditMessage,
|
|
822
998
|
rawBody: body, skipResponseTransform: true,
|
|
823
999
|
}),
|
|
824
1000
|
/**
|
|
@@ -848,15 +1024,15 @@ class PlaidClient {
|
|
|
848
1024
|
* Delete a document and all data contained.
|
|
849
1025
|
* @param {string} documentId - The document ID
|
|
850
1026
|
*/
|
|
851
|
-
delete: (documentId) =>
|
|
852
|
-
this._request('DELETE', `/api/v1/documents/${documentId}
|
|
1027
|
+
delete: (documentId, auditMessage) =>
|
|
1028
|
+
this._request('DELETE', `/api/v1/documents/${documentId}`, { auditMessage }),
|
|
853
1029
|
/**
|
|
854
1030
|
* Update a document's name.
|
|
855
1031
|
* @param {string} documentId - The document ID
|
|
856
1032
|
* @param {string} name - The name
|
|
857
1033
|
*/
|
|
858
|
-
update: (documentId, name) =>
|
|
859
|
-
this._request('PATCH', `/api/v1/documents/${documentId}`, {
|
|
1034
|
+
update: (documentId, name, auditMessage) =>
|
|
1035
|
+
this._request('PATCH', `/api/v1/documents/${documentId}`, { auditMessage,
|
|
860
1036
|
body: bodyOf({ name }),
|
|
861
1037
|
}),
|
|
862
1038
|
/**
|
|
@@ -865,8 +1041,8 @@ class PlaidClient {
|
|
|
865
1041
|
* @param {string} name - The name
|
|
866
1042
|
* @param {any} [metadata] - Metadata map. Omit to leave unset; pass null to send JSON null.
|
|
867
1043
|
*/
|
|
868
|
-
create: (projectId, name, metadata) =>
|
|
869
|
-
this._request('POST', '/api/v1/documents', {
|
|
1044
|
+
create: (projectId, name, metadata, auditMessage) =>
|
|
1045
|
+
this._request('POST', '/api/v1/documents', { auditMessage,
|
|
870
1046
|
body: bodyOf({ 'project-id': projectId, name, metadata }),
|
|
871
1047
|
}),
|
|
872
1048
|
};
|
|
@@ -877,29 +1053,29 @@ class PlaidClient {
|
|
|
877
1053
|
* @param {string} id - The resource ID
|
|
878
1054
|
* @param {string} userId - The user ID
|
|
879
1055
|
*/
|
|
880
|
-
addWriter: (id, userId) =>
|
|
881
|
-
this._request('POST', `/api/v1/projects/${id}/writers/${userId}
|
|
1056
|
+
addWriter: (id, userId, auditMessage) =>
|
|
1057
|
+
this._request('POST', `/api/v1/projects/${id}/writers/${userId}`, { auditMessage }),
|
|
882
1058
|
/**
|
|
883
1059
|
* Remove a user's writer privileges for this project.
|
|
884
1060
|
* @param {string} id - The resource ID
|
|
885
1061
|
* @param {string} userId - The user ID
|
|
886
1062
|
*/
|
|
887
|
-
removeWriter: (id, userId) =>
|
|
888
|
-
this._request('DELETE', `/api/v1/projects/${id}/writers/${userId}
|
|
1063
|
+
removeWriter: (id, userId, auditMessage) =>
|
|
1064
|
+
this._request('DELETE', `/api/v1/projects/${id}/writers/${userId}`, { auditMessage }),
|
|
889
1065
|
/**
|
|
890
1066
|
* Set a user's access level to read-only for this project.
|
|
891
1067
|
* @param {string} id - The resource ID
|
|
892
1068
|
* @param {string} userId - The user ID
|
|
893
1069
|
*/
|
|
894
|
-
addReader: (id, userId) =>
|
|
895
|
-
this._request('POST', `/api/v1/projects/${id}/readers/${userId}
|
|
1070
|
+
addReader: (id, userId, auditMessage) =>
|
|
1071
|
+
this._request('POST', `/api/v1/projects/${id}/readers/${userId}`, { auditMessage }),
|
|
896
1072
|
/**
|
|
897
1073
|
* Remove a user's reader privileges for this project.
|
|
898
1074
|
* @param {string} id - The resource ID
|
|
899
1075
|
* @param {string} userId - The user ID
|
|
900
1076
|
*/
|
|
901
|
-
removeReader: (id, userId) =>
|
|
902
|
-
this._request('DELETE', `/api/v1/projects/${id}/readers/${userId}
|
|
1077
|
+
removeReader: (id, userId, auditMessage) =>
|
|
1078
|
+
this._request('DELETE', `/api/v1/projects/${id}/readers/${userId}`, { auditMessage }),
|
|
903
1079
|
/**
|
|
904
1080
|
* Set a configuration value for a project in an editor namespace.
|
|
905
1081
|
* @param {string} id - The resource ID
|
|
@@ -907,8 +1083,8 @@ class PlaidClient {
|
|
|
907
1083
|
* @param {string} configKey - The config key
|
|
908
1084
|
* @param {any} configValue - Configuration value to set
|
|
909
1085
|
*/
|
|
910
|
-
setConfig: (id, namespace, configKey, configValue) =>
|
|
911
|
-
this._request('PUT', `/api/v1/projects/${id}/config/${namespace}/${configKey}`, {
|
|
1086
|
+
setConfig: (id, namespace, configKey, configValue, auditMessage) =>
|
|
1087
|
+
this._request('PUT', `/api/v1/projects/${id}/config/${namespace}/${configKey}`, { auditMessage,
|
|
912
1088
|
rawBody: configValue, skipResponseTransform: true,
|
|
913
1089
|
}),
|
|
914
1090
|
/**
|
|
@@ -917,8 +1093,8 @@ class PlaidClient {
|
|
|
917
1093
|
* @param {string} namespace - The config namespace
|
|
918
1094
|
* @param {string} configKey - The config key
|
|
919
1095
|
*/
|
|
920
|
-
deleteConfig: (id, namespace, configKey) =>
|
|
921
|
-
this._request('DELETE', `/api/v1/projects/${id}/config/${namespace}/${configKey}`, {
|
|
1096
|
+
deleteConfig: (id, namespace, configKey, auditMessage) =>
|
|
1097
|
+
this._request('DELETE', `/api/v1/projects/${id}/config/${namespace}/${configKey}`, { auditMessage,
|
|
922
1098
|
skipResponseTransform: true,
|
|
923
1099
|
}),
|
|
924
1100
|
/**
|
|
@@ -926,15 +1102,15 @@ class PlaidClient {
|
|
|
926
1102
|
* @param {string} id - The resource ID
|
|
927
1103
|
* @param {string} userId - The user ID
|
|
928
1104
|
*/
|
|
929
|
-
addMaintainer: (id, userId) =>
|
|
930
|
-
this._request('POST', `/api/v1/projects/${id}/maintainers/${userId}
|
|
1105
|
+
addMaintainer: (id, userId, auditMessage) =>
|
|
1106
|
+
this._request('POST', `/api/v1/projects/${id}/maintainers/${userId}`, { auditMessage }),
|
|
931
1107
|
/**
|
|
932
1108
|
* Remove a user's maintainer privileges for this project.
|
|
933
1109
|
* @param {string} id - The resource ID
|
|
934
1110
|
* @param {string} userId - The user ID
|
|
935
1111
|
*/
|
|
936
|
-
removeMaintainer: (id, userId) =>
|
|
937
|
-
this._request('DELETE', `/api/v1/projects/${id}/maintainers/${userId}
|
|
1112
|
+
removeMaintainer: (id, userId, auditMessage) =>
|
|
1113
|
+
this._request('DELETE', `/api/v1/projects/${id}/maintainers/${userId}`, { auditMessage }),
|
|
938
1114
|
/**
|
|
939
1115
|
* Get audit log for a project. Transparently follows pagination cursors
|
|
940
1116
|
* and returns the full flat array.
|
|
@@ -953,15 +1129,15 @@ class PlaidClient {
|
|
|
953
1129
|
* @param {string} id - The resource ID
|
|
954
1130
|
* @param {string} vocabId - The vocab layer ID
|
|
955
1131
|
*/
|
|
956
|
-
linkVocab: (id, vocabId) =>
|
|
957
|
-
this._request('POST', `/api/v1/projects/${id}/vocabs/${vocabId}
|
|
1132
|
+
linkVocab: (id, vocabId, auditMessage) =>
|
|
1133
|
+
this._request('POST', `/api/v1/projects/${id}/vocabs/${vocabId}`, { auditMessage }),
|
|
958
1134
|
/**
|
|
959
1135
|
* Unlink a vocabulary from a project.
|
|
960
1136
|
* @param {string} id - The resource ID
|
|
961
1137
|
* @param {string} vocabId - The vocab layer ID
|
|
962
1138
|
*/
|
|
963
|
-
unlinkVocab: (id, vocabId) =>
|
|
964
|
-
this._request('DELETE', `/api/v1/projects/${id}/vocabs/${vocabId}
|
|
1139
|
+
unlinkVocab: (id, vocabId, auditMessage) =>
|
|
1140
|
+
this._request('DELETE', `/api/v1/projects/${id}/vocabs/${vocabId}`, { auditMessage }),
|
|
965
1141
|
/**
|
|
966
1142
|
* Get a project by ID. To fetch the project's documents, use
|
|
967
1143
|
* listDocuments(id) — the include-documents flag has been removed.
|
|
@@ -1011,18 +1187,25 @@ class PlaidClient {
|
|
|
1011
1187
|
iterDocuments: (id, { pageSize } = {}) =>
|
|
1012
1188
|
iterPages(this, `/api/v1/projects/${id}/documents`, { pageSize }),
|
|
1013
1189
|
/**
|
|
1014
|
-
* Delete a project.
|
|
1190
|
+
* Delete a project and everything in it. This is irrecoverable.
|
|
1191
|
+
*
|
|
1192
|
+
* For a large project this can take a long time, so the client's
|
|
1193
|
+
* per-request timeout is DISABLED by default. Pass `{ timeout }` to
|
|
1194
|
+
* impose a finite bound.
|
|
1015
1195
|
* @param {string} id - The resource ID
|
|
1196
|
+
* @param {string} [auditMessage] - Custom audit-log message
|
|
1197
|
+
* @param {object} [options]
|
|
1198
|
+
* @param {number} [options.timeout=0] - Per-request timeout in ms (0/null disables)
|
|
1016
1199
|
*/
|
|
1017
|
-
delete: (id) =>
|
|
1018
|
-
this._request('DELETE', `/api/v1/projects/${id}
|
|
1200
|
+
delete: (id, auditMessage, { timeout = 0 } = {}) =>
|
|
1201
|
+
this._request('DELETE', `/api/v1/projects/${id}`, { auditMessage, timeout }),
|
|
1019
1202
|
/**
|
|
1020
1203
|
* Update a project's name.
|
|
1021
1204
|
* @param {string} id - The resource ID
|
|
1022
1205
|
* @param {string} name - The name
|
|
1023
1206
|
*/
|
|
1024
|
-
update: (id, name) =>
|
|
1025
|
-
this._request('PATCH', `/api/v1/projects/${id}`, {
|
|
1207
|
+
update: (id, name, auditMessage) =>
|
|
1208
|
+
this._request('PATCH', `/api/v1/projects/${id}`, { auditMessage,
|
|
1026
1209
|
body: bodyOf({ name }),
|
|
1027
1210
|
}),
|
|
1028
1211
|
/**
|
|
@@ -1057,8 +1240,8 @@ class PlaidClient {
|
|
|
1057
1240
|
* Create a new project. Note: this also registers the user as a maintainer.
|
|
1058
1241
|
* @param {string} name - The name
|
|
1059
1242
|
*/
|
|
1060
|
-
create: (name) =>
|
|
1061
|
-
this._request('POST', '/api/v1/projects', {
|
|
1243
|
+
create: (name, auditMessage) =>
|
|
1244
|
+
this._request('POST', '/api/v1/projects', { auditMessage,
|
|
1062
1245
|
body: bodyOf({ name }),
|
|
1063
1246
|
}),
|
|
1064
1247
|
};
|
|
@@ -1071,8 +1254,8 @@ class PlaidClient {
|
|
|
1071
1254
|
* @param {string} configKey - The config key
|
|
1072
1255
|
* @param {any} configValue - Configuration value to set
|
|
1073
1256
|
*/
|
|
1074
|
-
setConfig: (textLayerId, namespace, configKey, configValue) =>
|
|
1075
|
-
this._request('PUT', `/api/v1/text-layers/${textLayerId}/config/${namespace}/${configKey}`, {
|
|
1257
|
+
setConfig: (textLayerId, namespace, configKey, configValue, auditMessage) =>
|
|
1258
|
+
this._request('PUT', `/api/v1/text-layers/${textLayerId}/config/${namespace}/${configKey}`, { auditMessage,
|
|
1076
1259
|
rawBody: configValue, skipResponseTransform: true,
|
|
1077
1260
|
}),
|
|
1078
1261
|
/**
|
|
@@ -1081,8 +1264,8 @@ class PlaidClient {
|
|
|
1081
1264
|
* @param {string} namespace - The config namespace
|
|
1082
1265
|
* @param {string} configKey - The config key
|
|
1083
1266
|
*/
|
|
1084
|
-
deleteConfig: (textLayerId, namespace, configKey) =>
|
|
1085
|
-
this._request('DELETE', `/api/v1/text-layers/${textLayerId}/config/${namespace}/${configKey}`, {
|
|
1267
|
+
deleteConfig: (textLayerId, namespace, configKey, auditMessage) =>
|
|
1268
|
+
this._request('DELETE', `/api/v1/text-layers/${textLayerId}/config/${namespace}/${configKey}`, { auditMessage,
|
|
1086
1269
|
skipResponseTransform: true,
|
|
1087
1270
|
}),
|
|
1088
1271
|
/**
|
|
@@ -1098,15 +1281,15 @@ class PlaidClient {
|
|
|
1098
1281
|
* Delete a text layer.
|
|
1099
1282
|
* @param {string} textLayerId - The text layer ID
|
|
1100
1283
|
*/
|
|
1101
|
-
delete: (textLayerId) =>
|
|
1102
|
-
this._request('DELETE', `/api/v1/text-layers/${textLayerId}
|
|
1284
|
+
delete: (textLayerId, auditMessage) =>
|
|
1285
|
+
this._request('DELETE', `/api/v1/text-layers/${textLayerId}`, { auditMessage }),
|
|
1103
1286
|
/**
|
|
1104
1287
|
* Update a text layer's name.
|
|
1105
1288
|
* @param {string} textLayerId - The text layer ID
|
|
1106
1289
|
* @param {string} name - The name
|
|
1107
1290
|
*/
|
|
1108
|
-
update: (textLayerId, name) =>
|
|
1109
|
-
this._request('PATCH', `/api/v1/text-layers/${textLayerId}`, {
|
|
1291
|
+
update: (textLayerId, name, auditMessage) =>
|
|
1292
|
+
this._request('PATCH', `/api/v1/text-layers/${textLayerId}`, { auditMessage,
|
|
1110
1293
|
body: bodyOf({ name }),
|
|
1111
1294
|
}),
|
|
1112
1295
|
/**
|
|
@@ -1114,8 +1297,8 @@ class PlaidClient {
|
|
|
1114
1297
|
* @param {string} textLayerId - The text layer ID
|
|
1115
1298
|
* @param {string} direction - The direction ("up" or "down")
|
|
1116
1299
|
*/
|
|
1117
|
-
shift: (textLayerId, direction) =>
|
|
1118
|
-
this._request('POST', `/api/v1/text-layers/${textLayerId}/shift`, {
|
|
1300
|
+
shift: (textLayerId, direction, auditMessage) =>
|
|
1301
|
+
this._request('POST', `/api/v1/text-layers/${textLayerId}/shift`, { auditMessage,
|
|
1119
1302
|
body: bodyOf({ direction }),
|
|
1120
1303
|
}),
|
|
1121
1304
|
/**
|
|
@@ -1123,8 +1306,8 @@ class PlaidClient {
|
|
|
1123
1306
|
* @param {string} projectId - The project ID
|
|
1124
1307
|
* @param {string} name - The name
|
|
1125
1308
|
*/
|
|
1126
|
-
create: (projectId, name) =>
|
|
1127
|
-
this._request('POST', '/api/v1/text-layers', {
|
|
1309
|
+
create: (projectId, name, auditMessage) =>
|
|
1310
|
+
this._request('POST', '/api/v1/text-layers', { auditMessage,
|
|
1128
1311
|
body: bodyOf({ 'project-id': projectId, name }),
|
|
1129
1312
|
}),
|
|
1130
1313
|
};
|
|
@@ -1135,16 +1318,16 @@ class PlaidClient {
|
|
|
1135
1318
|
* @param {string} id - The resource ID
|
|
1136
1319
|
* @param {any} body - The request body
|
|
1137
1320
|
*/
|
|
1138
|
-
setMetadata: (id, body) =>
|
|
1139
|
-
this._request('PUT', `/api/v1/vocab-items/${id}/metadata`, {
|
|
1321
|
+
setMetadata: (id, body, auditMessage) =>
|
|
1322
|
+
this._request('PUT', `/api/v1/vocab-items/${id}/metadata`, { auditMessage,
|
|
1140
1323
|
rawBody: body, skipResponseTransform: true,
|
|
1141
1324
|
}),
|
|
1142
1325
|
/**
|
|
1143
1326
|
* Remove all metadata from a vocab item.
|
|
1144
1327
|
* @param {string} id - The resource ID
|
|
1145
1328
|
*/
|
|
1146
|
-
deleteMetadata: (id) =>
|
|
1147
|
-
this._request('DELETE', `/api/v1/vocab-items/${id}/metadata`, {
|
|
1329
|
+
deleteMetadata: (id, auditMessage) =>
|
|
1330
|
+
this._request('DELETE', `/api/v1/vocab-items/${id}/metadata`, { auditMessage,
|
|
1148
1331
|
skipResponseTransform: true,
|
|
1149
1332
|
}),
|
|
1150
1333
|
/**
|
|
@@ -1152,8 +1335,8 @@ class PlaidClient {
|
|
|
1152
1335
|
* @param {string} id - The resource ID
|
|
1153
1336
|
* @param {any} body - The metadata patch
|
|
1154
1337
|
*/
|
|
1155
|
-
patchMetadata: (id, body) =>
|
|
1156
|
-
this._request('PATCH', `/api/v1/vocab-items/${id}/metadata`, {
|
|
1338
|
+
patchMetadata: (id, body, auditMessage) =>
|
|
1339
|
+
this._request('PATCH', `/api/v1/vocab-items/${id}/metadata`, { auditMessage,
|
|
1157
1340
|
rawBody: body, skipResponseTransform: true,
|
|
1158
1341
|
}),
|
|
1159
1342
|
/**
|
|
@@ -1162,10 +1345,24 @@ class PlaidClient {
|
|
|
1162
1345
|
* @param {string} form - The vocab item form
|
|
1163
1346
|
* @param {any} [metadata] - Metadata map. Omit to leave unset; pass null to send JSON null.
|
|
1164
1347
|
*/
|
|
1165
|
-
create: (vocabLayerId, form, metadata) =>
|
|
1166
|
-
this._request('POST', '/api/v1/vocab-items', {
|
|
1348
|
+
create: (vocabLayerId, form, metadata, auditMessage) =>
|
|
1349
|
+
this._request('POST', '/api/v1/vocab-items', { auditMessage,
|
|
1167
1350
|
body: bodyOf({ 'vocab-layer-id': vocabLayerId, form, metadata }),
|
|
1168
1351
|
}),
|
|
1352
|
+
/**
|
|
1353
|
+
* Create multiple vocab items in a single operation. Entries may target
|
|
1354
|
+
* different vocab layers; the user must have write access to each.
|
|
1355
|
+
* @param {Array<{vocabLayerId: string, form: string, metadata?: any}>} body - The vocab items to create
|
|
1356
|
+
*/
|
|
1357
|
+
bulkCreate: (body, auditMessage) =>
|
|
1358
|
+
this._request('POST', '/api/v1/vocab-items/bulk', { auditMessage, body }),
|
|
1359
|
+
/**
|
|
1360
|
+
* Delete multiple vocab items in a single operation. Each item's
|
|
1361
|
+
* descendant vocab links are deleted too. Provide an array of IDs.
|
|
1362
|
+
* @param {string[]} body - The vocab item IDs to delete
|
|
1363
|
+
*/
|
|
1364
|
+
bulkDelete: (body, auditMessage) =>
|
|
1365
|
+
this._request('DELETE', '/api/v1/vocab-items/bulk', { auditMessage, body }),
|
|
1169
1366
|
/**
|
|
1170
1367
|
* Get a vocab item by ID
|
|
1171
1368
|
* @param {string} id - The resource ID
|
|
@@ -1179,15 +1376,15 @@ class PlaidClient {
|
|
|
1179
1376
|
* Delete a vocab item
|
|
1180
1377
|
* @param {string} id - The resource ID
|
|
1181
1378
|
*/
|
|
1182
|
-
delete: (id) =>
|
|
1183
|
-
this._request('DELETE', `/api/v1/vocab-items/${id}
|
|
1379
|
+
delete: (id, auditMessage) =>
|
|
1380
|
+
this._request('DELETE', `/api/v1/vocab-items/${id}`, { auditMessage }),
|
|
1184
1381
|
/**
|
|
1185
1382
|
* Update a vocab item's form
|
|
1186
1383
|
* @param {string} id - The resource ID
|
|
1187
1384
|
* @param {string} form - The vocab item form
|
|
1188
1385
|
*/
|
|
1189
|
-
update: (id, form) =>
|
|
1190
|
-
this._request('PATCH', `/api/v1/vocab-items/${id}`, {
|
|
1386
|
+
update: (id, form, auditMessage) =>
|
|
1387
|
+
this._request('PATCH', `/api/v1/vocab-items/${id}`, { auditMessage,
|
|
1191
1388
|
body: bodyOf({ form }),
|
|
1192
1389
|
}),
|
|
1193
1390
|
};
|
|
@@ -1198,8 +1395,8 @@ class PlaidClient {
|
|
|
1198
1395
|
* @param {string} relationLayerId - The relation layer ID
|
|
1199
1396
|
* @param {string} direction - The direction ("up" or "down")
|
|
1200
1397
|
*/
|
|
1201
|
-
shift: (relationLayerId, direction) =>
|
|
1202
|
-
this._request('POST', `/api/v1/relation-layers/${relationLayerId}/shift`, {
|
|
1398
|
+
shift: (relationLayerId, direction, auditMessage) =>
|
|
1399
|
+
this._request('POST', `/api/v1/relation-layers/${relationLayerId}/shift`, { auditMessage,
|
|
1203
1400
|
body: bodyOf({ direction }),
|
|
1204
1401
|
}),
|
|
1205
1402
|
/**
|
|
@@ -1207,8 +1404,8 @@ class PlaidClient {
|
|
|
1207
1404
|
* @param {string} spanLayerId - The span layer ID
|
|
1208
1405
|
* @param {string} name - The name
|
|
1209
1406
|
*/
|
|
1210
|
-
create: (spanLayerId, name) =>
|
|
1211
|
-
this._request('POST', '/api/v1/relation-layers', {
|
|
1407
|
+
create: (spanLayerId, name, auditMessage) =>
|
|
1408
|
+
this._request('POST', '/api/v1/relation-layers', { auditMessage,
|
|
1212
1409
|
body: bodyOf({ 'span-layer-id': spanLayerId, name }),
|
|
1213
1410
|
}),
|
|
1214
1411
|
/**
|
|
@@ -1218,8 +1415,8 @@ class PlaidClient {
|
|
|
1218
1415
|
* @param {string} configKey - The config key
|
|
1219
1416
|
* @param {any} configValue - Configuration value to set
|
|
1220
1417
|
*/
|
|
1221
|
-
setConfig: (relationLayerId, namespace, configKey, configValue) =>
|
|
1222
|
-
this._request('PUT', `/api/v1/relation-layers/${relationLayerId}/config/${namespace}/${configKey}`, {
|
|
1418
|
+
setConfig: (relationLayerId, namespace, configKey, configValue, auditMessage) =>
|
|
1419
|
+
this._request('PUT', `/api/v1/relation-layers/${relationLayerId}/config/${namespace}/${configKey}`, { auditMessage,
|
|
1223
1420
|
rawBody: configValue, skipResponseTransform: true,
|
|
1224
1421
|
}),
|
|
1225
1422
|
/**
|
|
@@ -1228,8 +1425,8 @@ class PlaidClient {
|
|
|
1228
1425
|
* @param {string} namespace - The config namespace
|
|
1229
1426
|
* @param {string} configKey - The config key
|
|
1230
1427
|
*/
|
|
1231
|
-
deleteConfig: (relationLayerId, namespace, configKey) =>
|
|
1232
|
-
this._request('DELETE', `/api/v1/relation-layers/${relationLayerId}/config/${namespace}/${configKey}`, {
|
|
1428
|
+
deleteConfig: (relationLayerId, namespace, configKey, auditMessage) =>
|
|
1429
|
+
this._request('DELETE', `/api/v1/relation-layers/${relationLayerId}/config/${namespace}/${configKey}`, { auditMessage,
|
|
1233
1430
|
skipResponseTransform: true,
|
|
1234
1431
|
}),
|
|
1235
1432
|
/**
|
|
@@ -1245,15 +1442,15 @@ class PlaidClient {
|
|
|
1245
1442
|
* Delete a relation layer.
|
|
1246
1443
|
* @param {string} relationLayerId - The relation layer ID
|
|
1247
1444
|
*/
|
|
1248
|
-
delete: (relationLayerId) =>
|
|
1249
|
-
this._request('DELETE', `/api/v1/relation-layers/${relationLayerId}
|
|
1445
|
+
delete: (relationLayerId, auditMessage) =>
|
|
1446
|
+
this._request('DELETE', `/api/v1/relation-layers/${relationLayerId}`, { auditMessage }),
|
|
1250
1447
|
/**
|
|
1251
1448
|
* Update a relation layer's name.
|
|
1252
1449
|
* @param {string} relationLayerId - The relation layer ID
|
|
1253
1450
|
* @param {string} name - The name
|
|
1254
1451
|
*/
|
|
1255
|
-
update: (relationLayerId, name) =>
|
|
1256
|
-
this._request('PATCH', `/api/v1/relation-layers/${relationLayerId}`, {
|
|
1452
|
+
update: (relationLayerId, name, auditMessage) =>
|
|
1453
|
+
this._request('PATCH', `/api/v1/relation-layers/${relationLayerId}`, { auditMessage,
|
|
1257
1454
|
body: bodyOf({ name }),
|
|
1258
1455
|
}),
|
|
1259
1456
|
};
|
|
@@ -1277,8 +1474,8 @@ class PlaidClient {
|
|
|
1277
1474
|
* @param {number} [precedence] - Ordering precedence
|
|
1278
1475
|
* @param {any} [metadata] - Metadata map. Omit to leave unset; pass null to send JSON null.
|
|
1279
1476
|
*/
|
|
1280
|
-
create: (tokenLayerId, text, begin, end, precedence, metadata) =>
|
|
1281
|
-
this._request('POST', '/api/v1/tokens', {
|
|
1477
|
+
create: (tokenLayerId, text, begin, end, precedence, metadata, auditMessage) =>
|
|
1478
|
+
this._request('POST', '/api/v1/tokens', { auditMessage,
|
|
1282
1479
|
body: bodyOf({ 'token-layer-id': tokenLayerId, text, begin, end, precedence, metadata }),
|
|
1283
1480
|
}),
|
|
1284
1481
|
/**
|
|
@@ -1295,8 +1492,8 @@ class PlaidClient {
|
|
|
1295
1492
|
* have no remaining tokens, the span will also be deleted.
|
|
1296
1493
|
* @param {string} tokenId - The token ID
|
|
1297
1494
|
*/
|
|
1298
|
-
delete: (tokenId) =>
|
|
1299
|
-
this._request('DELETE', `/api/v1/tokens/${tokenId}
|
|
1495
|
+
delete: (tokenId, auditMessage) =>
|
|
1496
|
+
this._request('DELETE', `/api/v1/tokens/${tokenId}`, { auditMessage }),
|
|
1300
1497
|
/**
|
|
1301
1498
|
* Update a token.
|
|
1302
1499
|
* @param {string} tokenId - The token ID
|
|
@@ -1307,30 +1504,31 @@ class PlaidClient {
|
|
|
1307
1504
|
* CLEAR it (revert to no explicit ordering). bodyOf keeps null but
|
|
1308
1505
|
* drops undefined, so the three cases map correctly to the server.
|
|
1309
1506
|
*/
|
|
1310
|
-
update: (tokenId, begin, end, precedence) =>
|
|
1311
|
-
this._request('PATCH', `/api/v1/tokens/${tokenId}`, {
|
|
1507
|
+
update: (tokenId, begin, end, precedence, auditMessage) =>
|
|
1508
|
+
this._request('PATCH', `/api/v1/tokens/${tokenId}`, { auditMessage,
|
|
1312
1509
|
body: bodyOf({ begin, end, precedence }),
|
|
1313
1510
|
}),
|
|
1314
1511
|
/**
|
|
1315
1512
|
* Create multiple tokens in a single operation.
|
|
1316
1513
|
* @param {Array} body - The request body
|
|
1514
|
+
* @returns {Promise<{ids: string[]}>} The created entity IDs, in input order. (bulkDelete resolves to no value.)
|
|
1317
1515
|
*/
|
|
1318
|
-
bulkCreate: (body) =>
|
|
1319
|
-
this._request('POST', '/api/v1/tokens/bulk', { body }),
|
|
1516
|
+
bulkCreate: (body, auditMessage) =>
|
|
1517
|
+
this._request('POST', '/api/v1/tokens/bulk', { auditMessage, body }),
|
|
1320
1518
|
/**
|
|
1321
1519
|
* Delete multiple tokens in a single operation. Provide an array of IDs.
|
|
1322
1520
|
* @param {Array} body - The request body
|
|
1323
1521
|
*/
|
|
1324
|
-
bulkDelete: (body) =>
|
|
1325
|
-
this._request('DELETE', '/api/v1/tokens/bulk', { body }),
|
|
1522
|
+
bulkDelete: (body, auditMessage) =>
|
|
1523
|
+
this._request('DELETE', '/api/v1/tokens/bulk', { auditMessage, body }),
|
|
1326
1524
|
/**
|
|
1327
1525
|
* Split a token at a Unicode code-point offset. The original token becomes the
|
|
1328
1526
|
* left half (keeps its ID, spans, vocab-links); the new right token's ID is returned.
|
|
1329
1527
|
* @param {string} tokenId - The token ID
|
|
1330
1528
|
* @param {number} position - Code-point offset to split at (strictly between begin and end)
|
|
1331
1529
|
*/
|
|
1332
|
-
split: (tokenId, position) =>
|
|
1333
|
-
this._request('POST', `/api/v1/tokens/${tokenId}/split`, {
|
|
1530
|
+
split: (tokenId, position, auditMessage) =>
|
|
1531
|
+
this._request('POST', `/api/v1/tokens/${tokenId}/split`, { auditMessage,
|
|
1334
1532
|
body: bodyOf({ position }),
|
|
1335
1533
|
}),
|
|
1336
1534
|
/**
|
|
@@ -1341,8 +1539,8 @@ class PlaidClient {
|
|
|
1341
1539
|
* @param {string} tokenId - The anchor token ID
|
|
1342
1540
|
* @param {string} otherTokenId - The other token to merge in
|
|
1343
1541
|
*/
|
|
1344
|
-
merge: (tokenId, otherTokenId) =>
|
|
1345
|
-
this._request('POST', `/api/v1/tokens/${tokenId}/merge`, {
|
|
1542
|
+
merge: (tokenId, otherTokenId, auditMessage) =>
|
|
1543
|
+
this._request('POST', `/api/v1/tokens/${tokenId}/merge`, { auditMessage,
|
|
1346
1544
|
body: bodyOf({ 'other-token-id': otherTokenId }),
|
|
1347
1545
|
}),
|
|
1348
1546
|
/**
|
|
@@ -1353,8 +1551,8 @@ class PlaidClient {
|
|
|
1353
1551
|
* @param {number} [begin] - New start offset, inclusive (Unicode code points)
|
|
1354
1552
|
* @param {number} [end] - New end offset, exclusive (Unicode code points)
|
|
1355
1553
|
*/
|
|
1356
|
-
shift: (tokenId, begin, end) =>
|
|
1357
|
-
this._request('POST', `/api/v1/tokens/${tokenId}/shift`, {
|
|
1554
|
+
shift: (tokenId, begin, end, auditMessage) =>
|
|
1555
|
+
this._request('POST', `/api/v1/tokens/${tokenId}/shift`, { auditMessage,
|
|
1358
1556
|
body: bodyOf({ begin, end }),
|
|
1359
1557
|
}),
|
|
1360
1558
|
/**
|
|
@@ -1362,16 +1560,16 @@ class PlaidClient {
|
|
|
1362
1560
|
* @param {string} tokenId - The token ID
|
|
1363
1561
|
* @param {any} body - The request body
|
|
1364
1562
|
*/
|
|
1365
|
-
setMetadata: (tokenId, body) =>
|
|
1366
|
-
this._request('PUT', `/api/v1/tokens/${tokenId}/metadata`, {
|
|
1563
|
+
setMetadata: (tokenId, body, auditMessage) =>
|
|
1564
|
+
this._request('PUT', `/api/v1/tokens/${tokenId}/metadata`, { auditMessage,
|
|
1367
1565
|
rawBody: body, skipResponseTransform: true,
|
|
1368
1566
|
}),
|
|
1369
1567
|
/**
|
|
1370
1568
|
* Remove all metadata from a token.
|
|
1371
1569
|
* @param {string} tokenId - The token ID
|
|
1372
1570
|
*/
|
|
1373
|
-
deleteMetadata: (tokenId) =>
|
|
1374
|
-
this._request('DELETE', `/api/v1/tokens/${tokenId}/metadata`, {
|
|
1571
|
+
deleteMetadata: (tokenId, auditMessage) =>
|
|
1572
|
+
this._request('DELETE', `/api/v1/tokens/${tokenId}/metadata`, { auditMessage,
|
|
1375
1573
|
skipResponseTransform: true,
|
|
1376
1574
|
}),
|
|
1377
1575
|
/**
|
|
@@ -1379,8 +1577,8 @@ class PlaidClient {
|
|
|
1379
1577
|
* @param {string} tokenId - The token ID
|
|
1380
1578
|
* @param {any} body - The metadata patch
|
|
1381
1579
|
*/
|
|
1382
|
-
patchMetadata: (tokenId, body) =>
|
|
1383
|
-
this._request('PATCH', `/api/v1/tokens/${tokenId}/metadata`, {
|
|
1580
|
+
patchMetadata: (tokenId, body, auditMessage) =>
|
|
1581
|
+
this._request('PATCH', `/api/v1/tokens/${tokenId}/metadata`, { auditMessage,
|
|
1384
1582
|
rawBody: body, skipResponseTransform: true,
|
|
1385
1583
|
}),
|
|
1386
1584
|
};
|
|
@@ -1402,19 +1600,30 @@ class PlaidClient {
|
|
|
1402
1600
|
* @param {any} data - The message data to send
|
|
1403
1601
|
* @returns {Promise<any>} Response from the send operation
|
|
1404
1602
|
*/
|
|
1405
|
-
sendMessage: (projectId, data) =>
|
|
1406
|
-
this._request('POST', `/api/v1/projects/${projectId}/message`, {
|
|
1603
|
+
sendMessage: (projectId, data, auditMessage) =>
|
|
1604
|
+
this._request('POST', `/api/v1/projects/${projectId}/message`, { auditMessage,
|
|
1407
1605
|
body: { body: data },
|
|
1408
1606
|
}),
|
|
1409
1607
|
|
|
1410
1608
|
/**
|
|
1411
|
-
* Discover the services
|
|
1609
|
+
* Discover the services seen on a project (synchronous GET). Currently
|
|
1610
|
+
* connected services carry `online: true`; previously-seen offline ones
|
|
1611
|
+
* carry `online: false` plus a `lastSeenAt` stamp.
|
|
1412
1612
|
* @param {string} projectId - The UUID of the project to query
|
|
1413
|
-
* @param {number} [timeout] - Ignored; kept for back-compat
|
|
1414
1613
|
* @returns {Promise<Array>} Array of discovered service information
|
|
1415
1614
|
*/
|
|
1416
|
-
discoverServices: (projectId
|
|
1417
|
-
discoverServices(this, projectId
|
|
1615
|
+
discoverServices: (projectId) =>
|
|
1616
|
+
discoverServices(this, projectId),
|
|
1617
|
+
|
|
1618
|
+
/**
|
|
1619
|
+
* Forget a previously-seen (offline) service. Maintainer-only; 409 if
|
|
1620
|
+
* the service is currently connected.
|
|
1621
|
+
* @param {string} projectId - The UUID of the project
|
|
1622
|
+
* @param {string} serviceId - The ID of the service to forget
|
|
1623
|
+
* @returns {Promise<void>}
|
|
1624
|
+
*/
|
|
1625
|
+
discardService: (projectId, serviceId) =>
|
|
1626
|
+
discardService(this, projectId, serviceId),
|
|
1418
1627
|
|
|
1419
1628
|
/**
|
|
1420
1629
|
* Register as a service and handle incoming work requests.
|
|
@@ -1475,8 +1684,27 @@ class PlaidClient {
|
|
|
1475
1684
|
* For 'count': {return: 'count', count}. Entity cells are full entity objects
|
|
1476
1685
|
* (same shape as the GET endpoints).
|
|
1477
1686
|
*/
|
|
1478
|
-
this.query = (body) =>
|
|
1479
|
-
this._request('POST', '/api/v1/query', { body });
|
|
1687
|
+
this.query = (body, auditMessage) =>
|
|
1688
|
+
this._request('POST', '/api/v1/query', { auditMessage, body });
|
|
1689
|
+
|
|
1690
|
+
// Logical-operation groups (audit-log grouping). There is no create: a
|
|
1691
|
+
// group row is made lazily by the first write carrying `?group-id=`
|
|
1692
|
+
// (see beginOperation). Not an audited write, so no auditMessage arg.
|
|
1693
|
+
this.operationGroups = {
|
|
1694
|
+
/**
|
|
1695
|
+
* Get a logical-operation group (its label + creator).
|
|
1696
|
+
* @param {string} id - The group id
|
|
1697
|
+
*/
|
|
1698
|
+
get: (id) =>
|
|
1699
|
+
this._request('GET', `/api/v1/operation-groups/${id}`),
|
|
1700
|
+
/**
|
|
1701
|
+
* Relabel a logical-operation group after the fact. Owner or admin only.
|
|
1702
|
+
* @param {string} id - The group id
|
|
1703
|
+
* @param {string|null} message - The new label
|
|
1704
|
+
*/
|
|
1705
|
+
update: (id, message) =>
|
|
1706
|
+
this._request('PATCH', `/api/v1/operation-groups/${id}`, { body: { message } }),
|
|
1707
|
+
};
|
|
1480
1708
|
}
|
|
1481
1709
|
|
|
1482
1710
|
// --- Core methods ---
|
|
@@ -1499,10 +1727,105 @@ class PlaidClient {
|
|
|
1499
1727
|
this.strictModeDocumentId = null;
|
|
1500
1728
|
}
|
|
1501
1729
|
|
|
1730
|
+
/**
|
|
1731
|
+
* Begin a LOGICAL OPERATION: a user-meaningful action ("Merge morphemes",
|
|
1732
|
+
* "Re-transcribe") implemented as many low-level writes, possibly across
|
|
1733
|
+
* several batches and even a service round-trip. Until `endOperation()`,
|
|
1734
|
+
* every write is stamped with a client-minted `?group-id=` (and the message)
|
|
1735
|
+
* so the audit log shows the whole run as ONE expandable entry labeled
|
|
1736
|
+
* `message`, with each write's own description underneath.
|
|
1737
|
+
*
|
|
1738
|
+
* Grouping is orthogonal to batches: a batch is a transaction boundary, an
|
|
1739
|
+
* operation is an intent boundary. An operation is NOT atomic — if write 3
|
|
1740
|
+
* of 5 fails, writes 1–2 stay committed (and logged under the group). Use a
|
|
1741
|
+
* batch inside the operation for any step that must be all-or-nothing.
|
|
1742
|
+
*
|
|
1743
|
+
* Nesting flattens: a `beginOperation` while one is open is a no-op that
|
|
1744
|
+
* joins the outer operation (the outer label wins), and the matching
|
|
1745
|
+
* `endOperation` is likewise a no-op. The label is recorded on the FIRST
|
|
1746
|
+
* write, so an operation that is never ended (crash, closed tab) is still
|
|
1747
|
+
* labeled in the log.
|
|
1748
|
+
*
|
|
1749
|
+
* @param {string} message - Human label for the operation.
|
|
1750
|
+
* @param {object} [opts] - Optional `{ id }`: adopt an existing group id instead of minting one (a service joining the requester's operation; `requestService` propagates an open operation to the service automatically).
|
|
1751
|
+
* @returns {string} The operation's group id.
|
|
1752
|
+
*/
|
|
1753
|
+
beginOperation(message, { id } = {}) {
|
|
1754
|
+
if (this.operationGroup) {
|
|
1755
|
+
this.operationGroup.depth += 1;
|
|
1756
|
+
return this.operationGroup.id;
|
|
1757
|
+
}
|
|
1758
|
+
this.operationGroup = {
|
|
1759
|
+
id: id || crypto.randomUUID(),
|
|
1760
|
+
message: message == null ? null : String(message),
|
|
1761
|
+
depth: 1,
|
|
1762
|
+
written: false,
|
|
1763
|
+
refined: undefined,
|
|
1764
|
+
};
|
|
1765
|
+
return this.operationGroup.id;
|
|
1766
|
+
}
|
|
1767
|
+
|
|
1768
|
+
/**
|
|
1769
|
+
* End the current logical operation. With no argument this is purely local
|
|
1770
|
+
* (no request). Pass a refined `message` to relabel the group now that the
|
|
1771
|
+
* outcome is known (e.g. `endOperation('Merged 3 morphemes')`) — that sends
|
|
1772
|
+
* one PATCH, skipped if the operation never wrote anything. A refine from a
|
|
1773
|
+
* nested (flattened) `endOperation` is ignored; the outer label wins.
|
|
1774
|
+
* @param {string} [message] - Optional refined label.
|
|
1775
|
+
* @returns {Promise<void>}
|
|
1776
|
+
*/
|
|
1777
|
+
async endOperation(message) {
|
|
1778
|
+
const group = this.operationGroup;
|
|
1779
|
+
if (!group) return;
|
|
1780
|
+
if (group.depth > 1) {
|
|
1781
|
+
group.depth -= 1;
|
|
1782
|
+
return;
|
|
1783
|
+
}
|
|
1784
|
+
this.operationGroup = null;
|
|
1785
|
+
const refined = message !== undefined ? message : group.refined;
|
|
1786
|
+
if (refined !== undefined && group.written) {
|
|
1787
|
+
try {
|
|
1788
|
+
await this.operationGroups.update(group.id, refined);
|
|
1789
|
+
} catch (e) {
|
|
1790
|
+
// 404: the group never materialized server-side (every tagged write
|
|
1791
|
+
// failed or a batch was aborted). Nothing to relabel — not an error.
|
|
1792
|
+
if (e.status !== 404) throw e;
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1797
|
+
/**
|
|
1798
|
+
* Run `fn` as one logical operation (see beginOperation), ending it when
|
|
1799
|
+
* `fn` settles — including on throw. `fn` receives a `setMessage(msg)`
|
|
1800
|
+
* callback to refine the label once the outcome is known.
|
|
1801
|
+
*
|
|
1802
|
+
* await client.withOperation('Merge morphemes', async (setMessage) => {
|
|
1803
|
+
* await client.batched(() => { ... });
|
|
1804
|
+
* setMessage(`Merged ${n} morphemes`);
|
|
1805
|
+
* });
|
|
1806
|
+
*
|
|
1807
|
+
* @param {string} message - Human label for the operation.
|
|
1808
|
+
* @param {function} fn - The work to run; receives `setMessage(msg)` to refine the label once the outcome is known.
|
|
1809
|
+
* @returns {Promise<any>} Whatever `fn` resolves to.
|
|
1810
|
+
*/
|
|
1811
|
+
async withOperation(message, fn) {
|
|
1812
|
+
this.beginOperation(message);
|
|
1813
|
+
const group = this.operationGroup;
|
|
1814
|
+
const setMessage = (msg) => { if (group.depth === 1) group.refined = msg; };
|
|
1815
|
+
try {
|
|
1816
|
+
return await fn(setMessage);
|
|
1817
|
+
} finally {
|
|
1818
|
+
await this.endOperation();
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1502
1822
|
/** Begin a batch of operations. Subsequent API calls will be queued. */
|
|
1503
1823
|
beginBatch() {
|
|
1504
1824
|
this.isBatching = true;
|
|
1505
1825
|
this.batchOperations = [];
|
|
1826
|
+
// Strict mode stamps the expected document-version on the FIRST write of
|
|
1827
|
+
// the batch only (see _request) — reset the marker per batch.
|
|
1828
|
+
this.batchVersionStamped = false;
|
|
1506
1829
|
}
|
|
1507
1830
|
|
|
1508
1831
|
/**
|
|
@@ -1587,6 +1910,38 @@ class PlaidClient {
|
|
|
1587
1910
|
return this.isBatching;
|
|
1588
1911
|
}
|
|
1589
1912
|
|
|
1913
|
+
/**
|
|
1914
|
+
* Run `fn` with a batch open, then submit all queued ops as ONE atomic
|
|
1915
|
+
* request — or abort the batch if `fn` throws, so a half-open batch can never
|
|
1916
|
+
* silently swallow later non-batch calls. `fn` makes the (queued) client
|
|
1917
|
+
* calls; it must NOT call submitBatch itself. Resolves to the batch results
|
|
1918
|
+
* array (`[]` if `fn` queued nothing).
|
|
1919
|
+
*
|
|
1920
|
+
* const [sentRes, wordRes] = await client.batched(async () => {
|
|
1921
|
+
* client.tokens.bulkCreate(sentenceOps);
|
|
1922
|
+
* client.tokens.bulkCreate(wordOps);
|
|
1923
|
+
* });
|
|
1924
|
+
*
|
|
1925
|
+
* Server-side a batch runs sequentially in one transaction (a child op sees
|
|
1926
|
+
* parents created earlier in the same `fn`; any op's failure rolls the whole
|
|
1927
|
+
* batch back). Not nestable. Named `batched()` because `client.batch` is the
|
|
1928
|
+
* low-level batch resource.
|
|
1929
|
+
* @param {() => (void | Promise<void>)} fn
|
|
1930
|
+
* @returns {Promise<Array>}
|
|
1931
|
+
*/
|
|
1932
|
+
async batched(fn) {
|
|
1933
|
+
this.beginBatch();
|
|
1934
|
+
try {
|
|
1935
|
+
await fn();
|
|
1936
|
+
} catch (e) {
|
|
1937
|
+
// fn failed: drop the queued ops so the client leaves batch mode and
|
|
1938
|
+
// later plain calls don't queue into a never-submitted batch.
|
|
1939
|
+
if (this.isBatchMode()) this.abortBatch();
|
|
1940
|
+
throw e;
|
|
1941
|
+
}
|
|
1942
|
+
return this.submitBatch();
|
|
1943
|
+
}
|
|
1944
|
+
|
|
1590
1945
|
/**
|
|
1591
1946
|
* Authenticate and return a new client instance with token. This is the
|
|
1592
1947
|
* single auth entry point — there is no `client.login` resource.
|
|
@@ -1596,6 +1951,64 @@ class PlaidClient {
|
|
|
1596
1951
|
* @param {object} [options] - Client options forwarded to the constructor (e.g. { timeout })
|
|
1597
1952
|
* @returns {Promise<PlaidClient>} - Authenticated client instance
|
|
1598
1953
|
*/
|
|
1954
|
+
/**
|
|
1955
|
+
* Build the link to hand someone for an invite code. The server never sees
|
|
1956
|
+
* an app URL, so the app that minted the invite is the one that names it.
|
|
1957
|
+
* Both SPAs use HashRouter, so the code rides in the fragment — which also
|
|
1958
|
+
* keeps it out of server access logs.
|
|
1959
|
+
* @param {string} appUrl - Where the SPA lives, e.g. "https://plaid.example.org/igt/"
|
|
1960
|
+
* @param {string} code - The code returned by invites.create()
|
|
1961
|
+
* @returns {string}
|
|
1962
|
+
*/
|
|
1963
|
+
static inviteUrl(appUrl, code) {
|
|
1964
|
+
return `${appUrl.replace(/#.*$/, '').replace(/\/$/, '')}/#/invite/${encodeURIComponent(code)}`;
|
|
1965
|
+
}
|
|
1966
|
+
|
|
1967
|
+
/**
|
|
1968
|
+
* Describe an invite code, with NO authentication — this is what a signup
|
|
1969
|
+
* page calls before the redeemer has an account. Returns the kind of link
|
|
1970
|
+
* ("signup" or "password-reset"), its status ("active", "used", "expired",
|
|
1971
|
+
* "revoked"), and the project it grants access to, if any.
|
|
1972
|
+
*
|
|
1973
|
+
* Throws a 404-shaped error if the code is unknown. A known-but-dead code
|
|
1974
|
+
* resolves normally with a non-"active" status, so the page can say why.
|
|
1975
|
+
* @param {string} baseUrl - The API base URL
|
|
1976
|
+
* @param {string} code - The invite code
|
|
1977
|
+
* @param {object} [options]
|
|
1978
|
+
* @returns {Promise<{kind: string, status: string, expiresAt: string, projectName?: string, projectRole?: string, username?: string, grantAdmin: boolean}>}
|
|
1979
|
+
*/
|
|
1980
|
+
static async lookupInvite(baseUrl, code, options = {}) {
|
|
1981
|
+
return anonymousPost(baseUrl, '/api/v1/invite-codes/lookup', { code }, options);
|
|
1982
|
+
}
|
|
1983
|
+
|
|
1984
|
+
/**
|
|
1985
|
+
* Redeem an invite code, with NO authentication.
|
|
1986
|
+
*
|
|
1987
|
+
* For a signup invite, pass `username` and `password` to create the account;
|
|
1988
|
+
* the invite's grants are applied in the same transaction. For a password
|
|
1989
|
+
* reset link, pass `password` only. Resolves to a logged-in client, exactly
|
|
1990
|
+
* like login() — the redeemer just chose these credentials, so there is no
|
|
1991
|
+
* reason to send them to a login form to retype them.
|
|
1992
|
+
* @param {string} baseUrl - The API base URL
|
|
1993
|
+
* @param {string} code - The invite code
|
|
1994
|
+
* @param {object} credentials
|
|
1995
|
+
* @param {string} [credentials.username] - Desired username (signup only)
|
|
1996
|
+
* @param {string} credentials.password - Desired password (min 8 characters)
|
|
1997
|
+
* @param {object} [options]
|
|
1998
|
+
* @returns {Promise<{client: PlaidClient, userId: string, kind: string}>}
|
|
1999
|
+
*/
|
|
2000
|
+
static async redeemInvite(baseUrl, code, { username, password } = {}, options = {}) {
|
|
2001
|
+
const data = await anonymousPost(
|
|
2002
|
+
baseUrl, '/api/v1/invite-codes/redeem',
|
|
2003
|
+
bodyOf({ code, username, password }), options,
|
|
2004
|
+
);
|
|
2005
|
+
return {
|
|
2006
|
+
client: new PlaidClient(baseUrl.replace(/\/$/, ''), data.token || '', options),
|
|
2007
|
+
userId: data.userId,
|
|
2008
|
+
kind: data.kind,
|
|
2009
|
+
};
|
|
2010
|
+
}
|
|
2011
|
+
|
|
1599
2012
|
static async login(baseUrl, userId, password, options = {}) {
|
|
1600
2013
|
baseUrl = baseUrl.replace(/\/$/, '');
|
|
1601
2014
|
const url = `${baseUrl}/api/v1/login`;
|
|
@@ -1642,3 +2055,19 @@ export {
|
|
|
1642
2055
|
buildDefaultValues,
|
|
1643
2056
|
coerceParamValues,
|
|
1644
2057
|
} from './serviceSchema.js';
|
|
2058
|
+
// Provenance: the cross-app convention for machine-provided vs human-labeled
|
|
2059
|
+
// information (flat prov/provSource/provConfirmed metadata; absence = human),
|
|
2060
|
+
// plus the machine-writer contract. See ./provenance.js and the manual,
|
|
2061
|
+
// "Provenance".
|
|
2062
|
+
export {
|
|
2063
|
+
PROV,
|
|
2064
|
+
PROV_STATES,
|
|
2065
|
+
PROV_CONFIRMED,
|
|
2066
|
+
stampInferred,
|
|
2067
|
+
confirmedInferred,
|
|
2068
|
+
provState,
|
|
2069
|
+
isMachine,
|
|
2070
|
+
isProtected,
|
|
2071
|
+
verifyOnEdit,
|
|
2072
|
+
serviceSource,
|
|
2073
|
+
} from './provenance.js';
|