@larc-iu/plaid-client 0.2.0-alpha.12 → 0.2.0-alpha.14
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 +132 -3
- package/package.json +1 -1
- package/src/documentLock.js +299 -0
- package/src/http.js +87 -14
- package/src/index.js +268 -47
- package/src/pagination.js +23 -35
- package/src/services.js +145 -21
package/src/index.js
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
DEFAULT_BATCH_TIMEOUT_MS,
|
|
16
16
|
} from "./http.js";
|
|
17
17
|
import { listAll, listPage, iterPages } from "./pagination.js";
|
|
18
|
+
import { withDocumentLock } from "./documentLock.js";
|
|
18
19
|
import { createSSEConnection } from "./sse.js";
|
|
19
20
|
import {
|
|
20
21
|
discoverServices,
|
|
@@ -145,6 +146,10 @@ class PlaidClient {
|
|
|
145
146
|
this.batchOperations = [];
|
|
146
147
|
this.documentVersions = {};
|
|
147
148
|
this.strictModeDocumentId = null;
|
|
149
|
+
// Set to a DocumentLockLost while a `documents.locked()` block's keep-alive
|
|
150
|
+
// has failed. Every write throws it until the block exits; see
|
|
151
|
+
// documentLock.js.
|
|
152
|
+
this.documentLockLost = null;
|
|
148
153
|
// The open logical operation (audit-log group), or null. While set, every
|
|
149
154
|
// write is stamped with `?group-id=` (+ `group-message`) so the audit log
|
|
150
155
|
// folds them into ONE expandable entry. See beginOperation / withOperation.
|
|
@@ -229,6 +234,7 @@ class PlaidClient {
|
|
|
229
234
|
*/
|
|
230
235
|
get: (id, asOf) =>
|
|
231
236
|
this._request("GET", `/api/v1/vocab-links/${id}`, {
|
|
237
|
+
bypassBatch: true,
|
|
232
238
|
queryParams: { "as-of": asOf },
|
|
233
239
|
}),
|
|
234
240
|
/**
|
|
@@ -248,6 +254,7 @@ class PlaidClient {
|
|
|
248
254
|
*/
|
|
249
255
|
get: (id, includeItems, asOf) =>
|
|
250
256
|
this._request("GET", `/api/v1/vocab-layers/${id}`, {
|
|
257
|
+
bypassBatch: true,
|
|
251
258
|
queryParams: { "include-items": includeItems, "as-of": asOf },
|
|
252
259
|
}),
|
|
253
260
|
/**
|
|
@@ -294,7 +301,6 @@ class PlaidClient {
|
|
|
294
301
|
/**
|
|
295
302
|
* List all vocab layers accessible to user. Transparently follows
|
|
296
303
|
* pagination cursors and returns the full flat array.
|
|
297
|
-
* Cannot be used inside a batch (auto-paginates across requests); throws if called while batching — use listPage() for a single page in a batch.
|
|
298
304
|
* @param {string} [asOf] - Temporal query timestamp
|
|
299
305
|
*/
|
|
300
306
|
list: (asOf) =>
|
|
@@ -318,7 +324,6 @@ class PlaidClient {
|
|
|
318
324
|
* @param {object} [opts]
|
|
319
325
|
* @param {number} [opts.pageSize] - Per-request page size
|
|
320
326
|
* @param {string} [opts.asOf] - Temporal query timestamp
|
|
321
|
-
* 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.
|
|
322
327
|
* @returns {AsyncGenerator<Array>}
|
|
323
328
|
*/
|
|
324
329
|
iterPages: ({ pageSize, asOf } = {}) =>
|
|
@@ -408,6 +413,7 @@ class PlaidClient {
|
|
|
408
413
|
*/
|
|
409
414
|
get: (relationId, asOf) =>
|
|
410
415
|
this._request("GET", `/api/v1/relations/${relationId}`, {
|
|
416
|
+
bypassBatch: true,
|
|
411
417
|
queryParams: { "as-of": asOf },
|
|
412
418
|
}),
|
|
413
419
|
/**
|
|
@@ -475,6 +481,16 @@ class PlaidClient {
|
|
|
475
481
|
auditMessage,
|
|
476
482
|
body,
|
|
477
483
|
}),
|
|
484
|
+
/**
|
|
485
|
+
* Update many relations in a single operation: set values and/or patch metadata.
|
|
486
|
+
* @param {Array} body - Objects of the shape `{id, value?, metadata?}`. `value` is set only when the key is present (null sends JSON null); `metadata` is a patch, a null value deleting that key. The relations may lie in several documents of one project; every document touched has its version bumped and every new version comes back in `X-Document-Versions`. A `document-version` precondition is accepted only when every entry lies in one document. An unknown id refuses the whole update.
|
|
487
|
+
* @returns {Promise<{count: number}>} How many relations were updated.
|
|
488
|
+
*/
|
|
489
|
+
bulkUpdate: (body, auditMessage) =>
|
|
490
|
+
this._request("PATCH", "/api/v1/relations/bulk", {
|
|
491
|
+
auditMessage,
|
|
492
|
+
body,
|
|
493
|
+
}),
|
|
478
494
|
};
|
|
479
495
|
|
|
480
496
|
this.spanLayers = {
|
|
@@ -516,6 +532,7 @@ class PlaidClient {
|
|
|
516
532
|
*/
|
|
517
533
|
get: (spanLayerId, asOf) =>
|
|
518
534
|
this._request("GET", `/api/v1/span-layers/${spanLayerId}`, {
|
|
535
|
+
bypassBatch: true,
|
|
519
536
|
queryParams: { "as-of": asOf },
|
|
520
537
|
}),
|
|
521
538
|
/**
|
|
@@ -594,6 +611,7 @@ class PlaidClient {
|
|
|
594
611
|
*/
|
|
595
612
|
get: (spanId, asOf) =>
|
|
596
613
|
this._request("GET", `/api/v1/spans/${spanId}`, {
|
|
614
|
+
bypassBatch: true,
|
|
597
615
|
queryParams: { "as-of": asOf },
|
|
598
616
|
}),
|
|
599
617
|
/**
|
|
@@ -625,6 +643,16 @@ class PlaidClient {
|
|
|
625
643
|
*/
|
|
626
644
|
bulkDelete: (body, auditMessage) =>
|
|
627
645
|
this._request("DELETE", "/api/v1/spans/bulk", { auditMessage, body }),
|
|
646
|
+
/**
|
|
647
|
+
* Update many spans in a single operation: set values and/or patch metadata.
|
|
648
|
+
* @param {Array} body - Objects of the shape `{id, value?, metadata?}`. `value` is set only when the key is present (null sends JSON null); `metadata` is a patch, a null value deleting that key. The spans may lie in several documents of one project; every document touched has its version bumped and every new version comes back in `X-Document-Versions`. A `document-version` precondition is accepted only when every entry lies in one document. An unknown id refuses the whole update.
|
|
649
|
+
* @returns {Promise<{count: number}>} How many spans were updated.
|
|
650
|
+
*/
|
|
651
|
+
bulkUpdate: (body, auditMessage) =>
|
|
652
|
+
this._request("PATCH", "/api/v1/spans/bulk", {
|
|
653
|
+
auditMessage,
|
|
654
|
+
body,
|
|
655
|
+
}),
|
|
628
656
|
/**
|
|
629
657
|
* Replace all metadata for a span.
|
|
630
658
|
* @param {string} spanId - The span ID
|
|
@@ -765,6 +793,7 @@ class PlaidClient {
|
|
|
765
793
|
*/
|
|
766
794
|
get: (textId, asOf) =>
|
|
767
795
|
this._request("GET", `/api/v1/texts/${textId}`, {
|
|
796
|
+
bypassBatch: true,
|
|
768
797
|
queryParams: { "as-of": asOf },
|
|
769
798
|
}),
|
|
770
799
|
/**
|
|
@@ -796,7 +825,6 @@ class PlaidClient {
|
|
|
796
825
|
/**
|
|
797
826
|
* List (or search) users. Transparently follows pagination cursors and
|
|
798
827
|
* returns the full flat array. Admin-or-maintainer only.
|
|
799
|
-
* Cannot be used inside a batch (auto-paginates across requests); throws if called while batching — use listPage() for a single page in a batch.
|
|
800
828
|
* @param {object} [opts]
|
|
801
829
|
* @param {string} [opts.q] - Filter to users whose display name or email contains this text (case-insensitive)
|
|
802
830
|
* @param {string} [opts.asOf] - Temporal query timestamp
|
|
@@ -824,7 +852,6 @@ class PlaidClient {
|
|
|
824
852
|
* @param {string} [opts.q] - Filter to users whose display name or email contains this text (case-insensitive)
|
|
825
853
|
* @param {number} [opts.pageSize] - Per-request page size
|
|
826
854
|
* @param {string} [opts.asOf] - Temporal query timestamp
|
|
827
|
-
* 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.
|
|
828
855
|
* @returns {AsyncGenerator<Array>}
|
|
829
856
|
*/
|
|
830
857
|
iterPages: ({ q, pageSize, asOf } = {}) =>
|
|
@@ -854,7 +881,6 @@ class PlaidClient {
|
|
|
854
881
|
/**
|
|
855
882
|
* Get audit log for a user's actions. Transparently follows pagination
|
|
856
883
|
* cursors and returns the full flat array.
|
|
857
|
-
* Cannot be used inside a batch (auto-paginates across requests); throws if called while batching — use listPage() for a single page in a batch.
|
|
858
884
|
* @param {string} userId - The user ID
|
|
859
885
|
* @param {string} [startTime] - Start of time range
|
|
860
886
|
* @param {string} [endTime] - End of time range
|
|
@@ -905,6 +931,7 @@ class PlaidClient {
|
|
|
905
931
|
*/
|
|
906
932
|
get: (id, asOf) =>
|
|
907
933
|
this._request("GET", `/api/v1/users/${id}`, {
|
|
934
|
+
bypassBatch: true,
|
|
908
935
|
queryParams: { "as-of": asOf },
|
|
909
936
|
}),
|
|
910
937
|
/**
|
|
@@ -974,7 +1001,7 @@ class PlaidClient {
|
|
|
974
1001
|
*/
|
|
975
1002
|
getAvatar: (id) =>
|
|
976
1003
|
this._request("GET", `/api/v1/users/${id}/avatar`, {
|
|
977
|
-
|
|
1004
|
+
bypassBatch: true,
|
|
978
1005
|
binaryResponse: true,
|
|
979
1006
|
}),
|
|
980
1007
|
/**
|
|
@@ -999,25 +1026,86 @@ class PlaidClient {
|
|
|
999
1026
|
* Remove a profile picture. Your own, or anyone's if you are an admin.
|
|
1000
1027
|
* @param {string} id - The user ID
|
|
1001
1028
|
*/
|
|
1029
|
+
// No flag: the upload beside this one is multipart and cannot be
|
|
1030
|
+
// batched, but a DELETE carries no blob, so the batch transport takes
|
|
1031
|
+
// it. It is an ordinary audited write and queues like any other.
|
|
1002
1032
|
deleteAvatar: (id, auditMessage) =>
|
|
1003
1033
|
this._request("DELETE", `/api/v1/users/${id}/avatar`, {
|
|
1004
1034
|
auditMessage,
|
|
1005
|
-
noBatch: true,
|
|
1006
1035
|
}),
|
|
1007
1036
|
};
|
|
1008
1037
|
|
|
1009
1038
|
this.userData = {
|
|
1010
1039
|
/**
|
|
1011
1040
|
* List a user's private data entries ({key, updatedAt}, plus value when
|
|
1012
|
-
* includeValues). Owner or admin only.
|
|
1041
|
+
* includeValues), ordered by key. Owner or admin only. Transparently
|
|
1042
|
+
* follows pagination cursors and returns the full flat array.
|
|
1043
|
+
*
|
|
1044
|
+
* Narrow with `prefix` (the literal head of a key) and/or `pattern`, a
|
|
1045
|
+
* GLOB over the whole key (`*` any run, `?` one character) — the way to
|
|
1046
|
+
* ask for a key convention identified by a segment in the middle, e.g.
|
|
1047
|
+
* `igt:assistant:*:meta:*` for every conversation's sidebar entry across
|
|
1048
|
+
* every project without dragging down the transcripts beside them.
|
|
1049
|
+
*
|
|
1050
|
+
* `pageSize` is exposed here, and defaults lower than elsewhere, because
|
|
1051
|
+
* one value runs to 1 MB: a page of them with `includeValues` is the
|
|
1052
|
+
* largest response this API can be asked for. Raise it when the listing
|
|
1053
|
+
* is keys, or the values are known to be small.
|
|
1054
|
+
* @param {string} userId
|
|
1055
|
+
* @param {object} [opts]
|
|
1056
|
+
* @param {string} [opts.prefix] - Only keys starting with this prefix
|
|
1057
|
+
* @param {string} [opts.pattern] - Only keys matching this GLOB
|
|
1058
|
+
* @param {boolean} [opts.includeValues] - Also return each entry's value
|
|
1059
|
+
* @param {number} [opts.pageSize=100] - Entries per request (1..1000)
|
|
1060
|
+
*/
|
|
1061
|
+
list: (userId, { prefix, pattern, includeValues, pageSize = 100 } = {}) =>
|
|
1062
|
+
// Every page carries bypassBatch (the pagination helpers set it): a
|
|
1063
|
+
// read belongs to whoever asked for it, not to whatever batch happens
|
|
1064
|
+
// to be open on this shared client. The assistant panel is app chrome
|
|
1065
|
+
// in both SPAs, so it reads this store while an import or a bulk edit
|
|
1066
|
+
// holds a batch open. Queued, the read answered `{batched: true}` (the
|
|
1067
|
+
// sidebar then threw on `.map`) and took a slot in the batch's
|
|
1068
|
+
// results, shifting every index the caller counted on.
|
|
1069
|
+
listAll(this, `/api/v1/users/${userId}/data`, {
|
|
1070
|
+
pageSize,
|
|
1071
|
+
query: { prefix, pattern, "include-values": includeValues },
|
|
1072
|
+
}),
|
|
1073
|
+
/**
|
|
1074
|
+
* One page of a user's private data entries, ordered by key.
|
|
1075
|
+
* @param {string} userId
|
|
1076
|
+
* @param {object} [opts]
|
|
1077
|
+
* @param {string} [opts.prefix] - Only keys starting with this prefix
|
|
1078
|
+
* @param {string} [opts.pattern] - Only keys matching this GLOB
|
|
1079
|
+
* @param {boolean} [opts.includeValues] - Also return each entry's value
|
|
1080
|
+
* @param {number} [opts.limit] - Page size (1..1000; server default 100)
|
|
1081
|
+
* @param {string} [opts.cursor] - Opaque cursor from a previous page
|
|
1082
|
+
* @returns {Promise<{entries: Array, nextCursor: (string|null)}>}
|
|
1083
|
+
*/
|
|
1084
|
+
listPage: (
|
|
1085
|
+
userId,
|
|
1086
|
+
{ prefix, pattern, includeValues, limit, cursor } = {},
|
|
1087
|
+
) =>
|
|
1088
|
+
listPage(this, `/api/v1/users/${userId}/data`, {
|
|
1089
|
+
limit,
|
|
1090
|
+
cursor,
|
|
1091
|
+
query: { prefix, pattern, "include-values": includeValues },
|
|
1092
|
+
}),
|
|
1093
|
+
/**
|
|
1094
|
+
* Async generator over a user's private data entries, one page at a time.
|
|
1013
1095
|
* @param {string} userId
|
|
1014
1096
|
* @param {object} [opts]
|
|
1015
1097
|
* @param {string} [opts.prefix] - Only keys starting with this prefix
|
|
1098
|
+
* @param {string} [opts.pattern] - Only keys matching this GLOB
|
|
1016
1099
|
* @param {boolean} [opts.includeValues] - Also return each entry's value
|
|
1100
|
+
* @param {number} [opts.pageSize=100] - Entries per request (1..1000)
|
|
1017
1101
|
*/
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1102
|
+
iterPages: (
|
|
1103
|
+
userId,
|
|
1104
|
+
{ prefix, pattern, includeValues, pageSize = 100 } = {},
|
|
1105
|
+
) =>
|
|
1106
|
+
iterPages(this, `/api/v1/users/${userId}/data`, {
|
|
1107
|
+
pageSize,
|
|
1108
|
+
query: { prefix, pattern, "include-values": includeValues },
|
|
1021
1109
|
}),
|
|
1022
1110
|
/**
|
|
1023
1111
|
* Read one private data entry ({key, updatedAt, value}); 404 if absent.
|
|
@@ -1025,9 +1113,11 @@ class PlaidClient {
|
|
|
1025
1113
|
* @param {string} key
|
|
1026
1114
|
*/
|
|
1027
1115
|
get: (userId, key) =>
|
|
1116
|
+
// bypassBatch for the same reason as list() above.
|
|
1028
1117
|
this._request(
|
|
1029
1118
|
"GET",
|
|
1030
1119
|
`/api/v1/users/${userId}/data/${encodeURIComponent(key)}`,
|
|
1120
|
+
{ bypassBatch: true },
|
|
1031
1121
|
),
|
|
1032
1122
|
/**
|
|
1033
1123
|
* Create or replace one private data entry. `value` is any JSON (up to
|
|
@@ -1071,7 +1161,6 @@ class PlaidClient {
|
|
|
1071
1161
|
* List a user's named API tokens. Never includes the signed token
|
|
1072
1162
|
* string itself — that is only returned once, by create().
|
|
1073
1163
|
* Transparently follows pagination cursors and returns the full flat array.
|
|
1074
|
-
* Cannot be used inside a batch (auto-paginates across requests); throws if called while batching — use listPage() for a single page in a batch.
|
|
1075
1164
|
* @param {string} userId - The user ID who owns the tokens
|
|
1076
1165
|
*/
|
|
1077
1166
|
list: (userId) => listAll(this, `/api/v1/users/${userId}/tokens`),
|
|
@@ -1091,7 +1180,6 @@ class PlaidClient {
|
|
|
1091
1180
|
* @param {string} userId - The user ID who owns the tokens
|
|
1092
1181
|
* @param {object} [opts]
|
|
1093
1182
|
* @param {number} [opts.pageSize] - Per-request page size
|
|
1094
|
-
* 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.
|
|
1095
1183
|
* @returns {AsyncGenerator<Array>}
|
|
1096
1184
|
*/
|
|
1097
1185
|
iterPages: (userId, { pageSize } = {}) =>
|
|
@@ -1127,7 +1215,6 @@ class PlaidClient {
|
|
|
1127
1215
|
* maintainer or admin on it. Never includes invite codes — the code is
|
|
1128
1216
|
* returned once, by create(), and is not recoverable afterward.
|
|
1129
1217
|
* Transparently follows pagination cursors and returns the full flat array.
|
|
1130
|
-
* Cannot be used inside a batch (auto-paginates across requests); throws if called while batching — use listPage() for a single page in a batch.
|
|
1131
1218
|
* @param {object} [opts]
|
|
1132
1219
|
* @param {string} [opts.projectId] - List this project's invites instead of your own
|
|
1133
1220
|
* @param {boolean} [opts.all] - List every invite on the server (admin only)
|
|
@@ -1157,7 +1244,6 @@ class PlaidClient {
|
|
|
1157
1244
|
* @param {string} [opts.projectId] - List this project's invites instead of your own
|
|
1158
1245
|
* @param {boolean} [opts.all] - List every invite on the server (admin only)
|
|
1159
1246
|
* @param {number} [opts.pageSize] - Per-request page size
|
|
1160
|
-
* 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.
|
|
1161
1247
|
* @returns {AsyncGenerator<Array>}
|
|
1162
1248
|
*/
|
|
1163
1249
|
iterPages: ({ projectId, all, pageSize } = {}) =>
|
|
@@ -1232,35 +1318,48 @@ class PlaidClient {
|
|
|
1232
1318
|
* walks the media directory, so open it, do not poll it. Admin only.
|
|
1233
1319
|
* @returns {Promise<{version: string, jvm: object, database: object, media: object, backup: object, settings: object}>}
|
|
1234
1320
|
*/
|
|
1235
|
-
server: () =>
|
|
1321
|
+
server: () =>
|
|
1322
|
+
this._request("GET", "/api/v1/admin/server", { bypassBatch: true }),
|
|
1236
1323
|
/**
|
|
1237
1324
|
* Take a database backup right now, outside the nightly schedule.
|
|
1238
1325
|
* Resolves to the backup block with `ok` reporting whether the snapshot
|
|
1239
1326
|
* succeeded. Uses VACUUM INTO, which only reads, so it is safe while
|
|
1240
1327
|
* people are working. Admin only.
|
|
1241
1328
|
* @returns {Promise<{ok: boolean, directory: string, backups: Array}>}
|
|
1329
|
+
*
|
|
1330
|
+
* Goes over the wire even while a batch is open, as every admin action
|
|
1331
|
+
* on the server itself does: none of them writes project data, and a
|
|
1332
|
+
* backup taken inside somebody's open write transaction is not what the
|
|
1333
|
+
* caller asked for.
|
|
1242
1334
|
*/
|
|
1243
|
-
backup: () =>
|
|
1335
|
+
backup: () =>
|
|
1336
|
+
this._request("POST", "/api/v1/admin/backup", { bypassBatch: true }),
|
|
1244
1337
|
/**
|
|
1245
1338
|
* Documents currently held by an editing lock, with who holds each and
|
|
1246
1339
|
* when it expires on its own. Admin only.
|
|
1247
1340
|
* @returns {Promise<{entries: Array<{documentId: string, userId: string, expiresAt: number}>}>}
|
|
1248
1341
|
*/
|
|
1249
|
-
locks: () =>
|
|
1342
|
+
locks: () =>
|
|
1343
|
+
this._request("GET", "/api/v1/admin/locks", { bypassBatch: true }),
|
|
1250
1344
|
/**
|
|
1251
1345
|
* Drop the lock on a document whoever holds it. Idempotent. For a client
|
|
1252
1346
|
* that went away without releasing one. Admin only.
|
|
1253
1347
|
* @param {string} documentId - The document ID
|
|
1254
1348
|
*/
|
|
1255
1349
|
releaseLock: (documentId) =>
|
|
1256
|
-
this._request("DELETE", `/api/v1/admin/locks/${documentId}
|
|
1350
|
+
this._request("DELETE", `/api/v1/admin/locks/${documentId}`, {
|
|
1351
|
+
bypassBatch: true,
|
|
1352
|
+
}),
|
|
1257
1353
|
/**
|
|
1258
1354
|
* Live login and invite rate-limit buckets: the address, the account
|
|
1259
1355
|
* where there is one, failures inside the window, the limit, and whether
|
|
1260
1356
|
* it is currently blocking. Admin only.
|
|
1261
1357
|
* @returns {Promise<{windowMs: number, logins: Array, ips: Array, invites: Array}>}
|
|
1262
1358
|
*/
|
|
1263
|
-
rateLimits: () =>
|
|
1359
|
+
rateLimits: () =>
|
|
1360
|
+
this._request("GET", "/api/v1/admin/rate-limits", {
|
|
1361
|
+
bypassBatch: true,
|
|
1362
|
+
}),
|
|
1264
1363
|
/**
|
|
1265
1364
|
* Forget recorded rate-limit failures. With `ip`, clears that address,
|
|
1266
1365
|
* narrowed to one account with `userId`. With neither, clears every
|
|
@@ -1271,18 +1370,45 @@ class PlaidClient {
|
|
|
1271
1370
|
*/
|
|
1272
1371
|
clearRateLimits: ({ ip, userId } = {}) =>
|
|
1273
1372
|
this._request("DELETE", "/api/v1/admin/rate-limits", {
|
|
1373
|
+
bypassBatch: true,
|
|
1274
1374
|
queryParams: { ip, "user-id": userId },
|
|
1275
1375
|
}),
|
|
1276
1376
|
/**
|
|
1277
|
-
*
|
|
1278
|
-
*
|
|
1279
|
-
*
|
|
1377
|
+
* What the server has logged, structured and filtered, from an in-memory
|
|
1378
|
+
* buffer kept whether or not a log file is configured. `requests` is one
|
|
1379
|
+
* entry per HTTP request (method, path, status, duration, and who made
|
|
1380
|
+
* it), `events` is everything else, with a stack trace where there was
|
|
1381
|
+
* one. They are buffered separately so a burst of requests cannot evict
|
|
1382
|
+
* an error. Both come newest first, `matched` counts what passed the
|
|
1383
|
+
* filters, and request `stats` describe the filtered set. Covers Plaid's
|
|
1384
|
+
* own log stream since the last restart: for library messages and older
|
|
1385
|
+
* history, see `logFile`. Admin only.
|
|
1386
|
+
* @param {object} [opts]
|
|
1387
|
+
* @param {number} [opts.limit] - Max entries per kind (default 200, max 2000)
|
|
1388
|
+
* @param {string} [opts.q] - Substring of any field, case-insensitive
|
|
1389
|
+
* @param {string} [opts.level] - Minimum level for events, e.g. "warn"
|
|
1390
|
+
* @param {string} [opts.status] - "2xx".."5xx", an exact code, or "failures"
|
|
1391
|
+
* @param {string} [opts.user] - Only requests made by this account
|
|
1392
|
+
* @param {string} [opts.method] - Only requests with this HTTP method
|
|
1393
|
+
* @returns {Promise<{requests: object, events: object, file: (string|null)}>}
|
|
1394
|
+
*/
|
|
1395
|
+
logs: ({ limit, q, level, status, user, method } = {}) =>
|
|
1396
|
+
this._request("GET", "/api/v1/admin/logs", {
|
|
1397
|
+
bypassBatch: true,
|
|
1398
|
+
queryParams: { limit, q, level, status, user, method },
|
|
1399
|
+
}),
|
|
1400
|
+
/**
|
|
1401
|
+
* The tail of the configured log file, as text lines. The only place
|
|
1402
|
+
* third-party library messages and anything from before the last restart
|
|
1403
|
+
* can be read. Resolves with an `error` string instead of lines when no
|
|
1404
|
+
* log file is configured or it does not exist yet. Admin only.
|
|
1280
1405
|
* @param {object} [opts]
|
|
1281
1406
|
* @param {number} [opts.lines] - How many lines (default 200, max 2000)
|
|
1282
1407
|
* @returns {Promise<{file: (string|null), lines: string[], error?: string}>}
|
|
1283
1408
|
*/
|
|
1284
|
-
|
|
1285
|
-
this._request("GET", "/api/v1/admin/logs", {
|
|
1409
|
+
logFile: ({ lines } = {}) =>
|
|
1410
|
+
this._request("GET", "/api/v1/admin/logs/file", {
|
|
1411
|
+
bypassBatch: true,
|
|
1286
1412
|
queryParams: { lines },
|
|
1287
1413
|
}),
|
|
1288
1414
|
/**
|
|
@@ -1296,7 +1422,6 @@ class PlaidClient {
|
|
|
1296
1422
|
* ask for a key convention identified by a segment in the middle, e.g.
|
|
1297
1423
|
* `igt:assistant:*:meta:*`. Values come only with `includeValues`, and
|
|
1298
1424
|
* are recased like any other body (see `userData.put`).
|
|
1299
|
-
* Cannot be used inside a batch (auto-paginates across requests); throws if called while batching — use userDataPage() for a single page in a batch.
|
|
1300
1425
|
* @param {object} [opts]
|
|
1301
1426
|
* @param {string} [opts.prefix] - Only keys starting with this
|
|
1302
1427
|
* @param {string} [opts.pattern] - Only keys matching this GLOB
|
|
@@ -1340,7 +1465,6 @@ class PlaidClient {
|
|
|
1340
1465
|
* and op-type filter as the per-project read, with the entity scope
|
|
1341
1466
|
* dropped. Admin only. Transparently follows pagination cursors and
|
|
1342
1467
|
* returns the full flat array.
|
|
1343
|
-
* Cannot be used inside a batch (auto-paginates across requests); throws if called while batching — use listPage() for a single page in a batch.
|
|
1344
1468
|
* @param {object} [opts]
|
|
1345
1469
|
* @param {string} [opts.startTime] - Only operations at or after this instant
|
|
1346
1470
|
* @param {string} [opts.endTime] - Only operations at or before this instant
|
|
@@ -1378,7 +1502,6 @@ class PlaidClient {
|
|
|
1378
1502
|
}),
|
|
1379
1503
|
/**
|
|
1380
1504
|
* Async-iterate the instance-wide audit log page by page. Admin only.
|
|
1381
|
-
* 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.
|
|
1382
1505
|
* @returns {AsyncGenerator<Array>}
|
|
1383
1506
|
*/
|
|
1384
1507
|
iterPages: ({ startTime, endTime, opTypes, pageSize } = {}) =>
|
|
@@ -1413,6 +1536,7 @@ class PlaidClient {
|
|
|
1413
1536
|
? `/api/v1/projects/${projectId}/audit/tally`
|
|
1414
1537
|
: "/api/v1/audit/tally";
|
|
1415
1538
|
const result = await this._request("GET", path, {
|
|
1539
|
+
bypassBatch: true,
|
|
1416
1540
|
queryParams: {
|
|
1417
1541
|
"start-time": startTime,
|
|
1418
1542
|
"end-time": endTime,
|
|
@@ -1495,6 +1619,7 @@ class PlaidClient {
|
|
|
1495
1619
|
*/
|
|
1496
1620
|
get: (tokenLayerId, asOf) =>
|
|
1497
1621
|
this._request("GET", `/api/v1/token-layers/${tokenLayerId}`, {
|
|
1622
|
+
bypassBatch: true,
|
|
1498
1623
|
queryParams: { "as-of": asOf },
|
|
1499
1624
|
}),
|
|
1500
1625
|
/**
|
|
@@ -1525,24 +1650,72 @@ class PlaidClient {
|
|
|
1525
1650
|
*/
|
|
1526
1651
|
checkLock: (documentId, asOf) =>
|
|
1527
1652
|
this._request("GET", `/api/v1/documents/${documentId}/lock`, {
|
|
1653
|
+
bypassBatch: true,
|
|
1528
1654
|
queryParams: { "as-of": asOf },
|
|
1529
1655
|
}),
|
|
1530
1656
|
/**
|
|
1531
|
-
* Acquire or refresh a document lock
|
|
1657
|
+
* Acquire or refresh a document lock.
|
|
1658
|
+
*
|
|
1659
|
+
* Goes over the wire even while a batch is open. The lock is an
|
|
1660
|
+
* out-of-band signal, not project data: a queued acquire is taken only
|
|
1661
|
+
* when the batch submits, which is after every write it was meant to
|
|
1662
|
+
* guard, and until then it answers success to a caller that does not
|
|
1663
|
+
* hold it and cannot see the 423 saying somebody else does.
|
|
1532
1664
|
* @param {string} documentId - The document ID
|
|
1533
1665
|
*/
|
|
1534
1666
|
acquireLock: (documentId, auditMessage) =>
|
|
1535
1667
|
this._request("POST", `/api/v1/documents/${documentId}/lock`, {
|
|
1536
1668
|
auditMessage,
|
|
1669
|
+
bypassBatch: true,
|
|
1537
1670
|
}),
|
|
1538
1671
|
/**
|
|
1539
|
-
* Release a document lock
|
|
1672
|
+
* Release a document lock. Goes over the wire even while a batch is
|
|
1673
|
+
* open, for the same reason as acquireLock: queued, the lock is held
|
|
1674
|
+
* until the batch submits, and not released at all if it aborts.
|
|
1540
1675
|
* @param {string} documentId - The document ID
|
|
1541
1676
|
*/
|
|
1542
1677
|
releaseLock: (documentId, auditMessage) =>
|
|
1543
1678
|
this._request("DELETE", `/api/v1/documents/${documentId}/lock`, {
|
|
1544
1679
|
auditMessage,
|
|
1680
|
+
bypassBatch: true,
|
|
1545
1681
|
}),
|
|
1682
|
+
/**
|
|
1683
|
+
* Hold this document's server-enforced lock for the length of `fn`,
|
|
1684
|
+
* releasing it on the way out (including on error). Resolves to what
|
|
1685
|
+
* `fn` returned.
|
|
1686
|
+
*
|
|
1687
|
+
* await client.documents.locked(docId, async () => {
|
|
1688
|
+
* // delete + recreate tokens
|
|
1689
|
+
* });
|
|
1690
|
+
*
|
|
1691
|
+
* Wrap any multi-step, server-side mutation of a document that must not
|
|
1692
|
+
* interleave with a human editor or another service, e.g. a parser or
|
|
1693
|
+
* tokenizer that deletes and recreates a document's tokens, spans and
|
|
1694
|
+
* relations. A single atomic call does not need it. While the lock is
|
|
1695
|
+
* held, writes to the document by ANOTHER user are refused with HTTP
|
|
1696
|
+
* 423; the holder's own writes pass and renew it. If another user
|
|
1697
|
+
* already holds it this rejects with a readable 423 and `fn` does not
|
|
1698
|
+
* run.
|
|
1699
|
+
*
|
|
1700
|
+
* The lock is renewed for as long as `fn` runs, so work that computes
|
|
1701
|
+
* for minutes before it writes holds the lock the whole time rather than
|
|
1702
|
+
* only for its first minute. If a renewal fails the lock is gone: every
|
|
1703
|
+
* later write from this client throws `DocumentLockLost`, and a block
|
|
1704
|
+
* that got to the end anyway ends with that error rather than reporting
|
|
1705
|
+
* success. `fn` receives a lock handle and may read `lock.lost` (or call
|
|
1706
|
+
* `lock.raiseIfLost()`) to give up sooner.
|
|
1707
|
+
*
|
|
1708
|
+
* NOT re-entrant: nesting two `locked()` blocks on one document would
|
|
1709
|
+
* release on the inner exit and leave the outer unprotected. Lock at
|
|
1710
|
+
* exactly one level per call path. A lost lock is recorded on the
|
|
1711
|
+
* CLIENT, like batch and strict mode, so it stops every write the client
|
|
1712
|
+
* makes and not only the ones this block makes.
|
|
1713
|
+
* @param {string} documentId - The document ID
|
|
1714
|
+
* @param {(lock: DocumentLock) => any} fn - The work to run while holding it
|
|
1715
|
+
* @param {object} [options] - `{ keepAlive }`: renew on a timer (default true)
|
|
1716
|
+
*/
|
|
1717
|
+
locked: (documentId, fn, options) =>
|
|
1718
|
+
withDocumentLock(this, documentId, fn, options),
|
|
1546
1719
|
/**
|
|
1547
1720
|
* Get the media file for a document. Media is not versioned, so there is
|
|
1548
1721
|
* no as-of form: the route refuses the parameter. Prefer the document's
|
|
@@ -1551,7 +1724,7 @@ class PlaidClient {
|
|
|
1551
1724
|
*/
|
|
1552
1725
|
getMedia: (documentId) =>
|
|
1553
1726
|
this._request("GET", `/api/v1/documents/${documentId}/media`, {
|
|
1554
|
-
|
|
1727
|
+
bypassBatch: true,
|
|
1555
1728
|
binaryResponse: true,
|
|
1556
1729
|
}),
|
|
1557
1730
|
/**
|
|
@@ -1576,10 +1749,14 @@ class PlaidClient {
|
|
|
1576
1749
|
* Delete media file for a document
|
|
1577
1750
|
* @param {string} documentId - The document ID
|
|
1578
1751
|
*/
|
|
1752
|
+
// No flag: the upload above is multipart and cannot be batched, but a
|
|
1753
|
+
// DELETE carries no blob, so the batch transport takes it. It is a write
|
|
1754
|
+
// of the document's own data and queues like any other. Note that the
|
|
1755
|
+
// file removal happens outside the server's transaction, so a batch that
|
|
1756
|
+
// aborts after this op does not bring the file back.
|
|
1579
1757
|
deleteMedia: (documentId, auditMessage) =>
|
|
1580
1758
|
this._request("DELETE", `/api/v1/documents/${documentId}/media`, {
|
|
1581
1759
|
auditMessage,
|
|
1582
|
-
noBatch: true,
|
|
1583
1760
|
}),
|
|
1584
1761
|
/**
|
|
1585
1762
|
* Replace all metadata for a document.
|
|
@@ -1615,7 +1792,6 @@ class PlaidClient {
|
|
|
1615
1792
|
/**
|
|
1616
1793
|
* Get audit log for a document. Transparently follows pagination cursors
|
|
1617
1794
|
* and returns the full flat array.
|
|
1618
|
-
* Cannot be used inside a batch (auto-paginates across requests); throws if called while batching — use listPage() for a single page in a batch.
|
|
1619
1795
|
* @param {string} documentId - The document ID
|
|
1620
1796
|
* @param {string} [startTime] - Start of time range
|
|
1621
1797
|
* @param {string} [endTime] - End of time range
|
|
@@ -1698,6 +1874,7 @@ class PlaidClient {
|
|
|
1698
1874
|
*/
|
|
1699
1875
|
get: (documentId, includeBody, asOf, layers) =>
|
|
1700
1876
|
this._request("GET", `/api/v1/documents/${documentId}`, {
|
|
1877
|
+
bypassBatch: true,
|
|
1701
1878
|
queryParams: {
|
|
1702
1879
|
"include-body": includeBody,
|
|
1703
1880
|
"as-of": asOf,
|
|
@@ -1839,7 +2016,6 @@ class PlaidClient {
|
|
|
1839
2016
|
/**
|
|
1840
2017
|
* Get audit log for a project. Transparently follows pagination cursors
|
|
1841
2018
|
* and returns the full flat array.
|
|
1842
|
-
* Cannot be used inside a batch (auto-paginates across requests); throws if called while batching — use listPage() for a single page in a batch.
|
|
1843
2019
|
* @param {string} projectId - The project ID
|
|
1844
2020
|
* @param {string} [startTime] - Start of time range
|
|
1845
2021
|
* @param {string} [endTime] - End of time range
|
|
@@ -1895,6 +2071,7 @@ class PlaidClient {
|
|
|
1895
2071
|
*/
|
|
1896
2072
|
myLastEdits: (projectId) =>
|
|
1897
2073
|
this._request("GET", `/api/v1/projects/${projectId}/audit/last-edits`, {
|
|
2074
|
+
bypassBatch: true,
|
|
1898
2075
|
skipResponseTransform: true,
|
|
1899
2076
|
}),
|
|
1900
2077
|
/**
|
|
@@ -1923,12 +2100,12 @@ class PlaidClient {
|
|
|
1923
2100
|
*/
|
|
1924
2101
|
get: (id, asOf) =>
|
|
1925
2102
|
this._request("GET", `/api/v1/projects/${id}`, {
|
|
2103
|
+
bypassBatch: true,
|
|
1926
2104
|
queryParams: { "as-of": asOf },
|
|
1927
2105
|
}),
|
|
1928
2106
|
/**
|
|
1929
2107
|
* List all documents in a project. Transparently follows pagination
|
|
1930
2108
|
* cursors and returns the full flat array.
|
|
1931
|
-
* Cannot be used inside a batch (auto-paginates across requests); throws if called while batching — use listPage() for a single page in a batch.
|
|
1932
2109
|
*
|
|
1933
2110
|
* Note: this endpoint does not support temporal (`as-of`) queries; the
|
|
1934
2111
|
* server rejects `?as-of=` on the documents-list route with a 400.
|
|
@@ -1957,7 +2134,6 @@ class PlaidClient {
|
|
|
1957
2134
|
* @param {string} id - The project ID
|
|
1958
2135
|
* @param {object} [opts]
|
|
1959
2136
|
* @param {number} [opts.pageSize] - Per-request page size
|
|
1960
|
-
* 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.
|
|
1961
2137
|
* @returns {AsyncGenerator<Array>}
|
|
1962
2138
|
*/
|
|
1963
2139
|
iterDocuments: (id, { pageSize } = {}) =>
|
|
@@ -1991,7 +2167,6 @@ class PlaidClient {
|
|
|
1991
2167
|
/**
|
|
1992
2168
|
* List all projects accessible to user. Transparently follows pagination
|
|
1993
2169
|
* cursors and returns the full flat array.
|
|
1994
|
-
* Cannot be used inside a batch (auto-paginates across requests); throws if called while batching — use listPage() for a single page in a batch.
|
|
1995
2170
|
* @param {string} [asOf] - Temporal query timestamp
|
|
1996
2171
|
*/
|
|
1997
2172
|
list: (asOf) =>
|
|
@@ -2015,7 +2190,6 @@ class PlaidClient {
|
|
|
2015
2190
|
* @param {object} [opts]
|
|
2016
2191
|
* @param {number} [opts.pageSize] - Per-request page size
|
|
2017
2192
|
* @param {string} [opts.asOf] - Temporal query timestamp
|
|
2018
|
-
* 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.
|
|
2019
2193
|
* @returns {AsyncGenerator<Array>}
|
|
2020
2194
|
*/
|
|
2021
2195
|
iterPages: ({ pageSize, asOf } = {}) =>
|
|
@@ -2073,6 +2247,7 @@ class PlaidClient {
|
|
|
2073
2247
|
*/
|
|
2074
2248
|
get: (textLayerId, asOf) =>
|
|
2075
2249
|
this._request("GET", `/api/v1/text-layers/${textLayerId}`, {
|
|
2250
|
+
bypassBatch: true,
|
|
2076
2251
|
queryParams: { "as-of": asOf },
|
|
2077
2252
|
}),
|
|
2078
2253
|
/**
|
|
@@ -2185,6 +2360,7 @@ class PlaidClient {
|
|
|
2185
2360
|
*/
|
|
2186
2361
|
get: (id, asOf) =>
|
|
2187
2362
|
this._request("GET", `/api/v1/vocab-items/${id}`, {
|
|
2363
|
+
bypassBatch: true,
|
|
2188
2364
|
queryParams: { "as-of": asOf },
|
|
2189
2365
|
}),
|
|
2190
2366
|
/**
|
|
@@ -2265,6 +2441,7 @@ class PlaidClient {
|
|
|
2265
2441
|
*/
|
|
2266
2442
|
get: (relationLayerId, asOf) =>
|
|
2267
2443
|
this._request("GET", `/api/v1/relation-layers/${relationLayerId}`, {
|
|
2444
|
+
bypassBatch: true,
|
|
2268
2445
|
queryParams: { "as-of": asOf },
|
|
2269
2446
|
}),
|
|
2270
2447
|
/**
|
|
@@ -2333,6 +2510,7 @@ class PlaidClient {
|
|
|
2333
2510
|
*/
|
|
2334
2511
|
get: (tokenId, asOf) =>
|
|
2335
2512
|
this._request("GET", `/api/v1/tokens/${tokenId}`, {
|
|
2513
|
+
bypassBatch: true,
|
|
2336
2514
|
queryParams: { "as-of": asOf },
|
|
2337
2515
|
}),
|
|
2338
2516
|
/**
|
|
@@ -2370,6 +2548,16 @@ class PlaidClient {
|
|
|
2370
2548
|
*/
|
|
2371
2549
|
bulkDelete: (body, auditMessage) =>
|
|
2372
2550
|
this._request("DELETE", "/api/v1/tokens/bulk", { auditMessage, body }),
|
|
2551
|
+
/**
|
|
2552
|
+
* Update many tokens in a single operation: patch metadata.
|
|
2553
|
+
* @param {Array} body - Objects of the shape `{id, metadata}`. `metadata` is a patch, a null value deleting that key. The tokens may lie in several documents of one project; every document touched has its version bumped and every new version comes back in `X-Document-Versions`. A `document-version` precondition is accepted only when every entry lies in one document. An unknown id refuses the whole update.
|
|
2554
|
+
* @returns {Promise<{count: number}>} How many tokens were updated.
|
|
2555
|
+
*/
|
|
2556
|
+
bulkUpdate: (body, auditMessage) =>
|
|
2557
|
+
this._request("PATCH", "/api/v1/tokens/bulk", {
|
|
2558
|
+
auditMessage,
|
|
2559
|
+
body,
|
|
2560
|
+
}),
|
|
2373
2561
|
/**
|
|
2374
2562
|
* Split a token at a Unicode code-point offset. The original token becomes the
|
|
2375
2563
|
* left half (keeps its ID, spans, vocab-links); the new right token's ID is returned.
|
|
@@ -2473,7 +2661,8 @@ class PlaidClient {
|
|
|
2473
2661
|
/**
|
|
2474
2662
|
* Discover the services seen on a project (synchronous GET). Currently
|
|
2475
2663
|
* connected services carry `online: true`; previously-seen offline ones
|
|
2476
|
-
* carry `online: false` plus a `lastSeenAt` stamp.
|
|
2664
|
+
* carry `online: false` plus a `lastSeenAt` stamp. Goes over the wire
|
|
2665
|
+
* even while a batch is open on the client.
|
|
2477
2666
|
* @param {string} projectId - The UUID of the project to query
|
|
2478
2667
|
* @returns {Promise<Array>} Array of discovered service information
|
|
2479
2668
|
*/
|
|
@@ -2643,7 +2832,10 @@ class PlaidClient {
|
|
|
2643
2832
|
* Get a logical-operation group (its label + creator).
|
|
2644
2833
|
* @param {string} id - The group id
|
|
2645
2834
|
*/
|
|
2646
|
-
get: (id) =>
|
|
2835
|
+
get: (id) =>
|
|
2836
|
+
this._request("GET", `/api/v1/operation-groups/${id}`, {
|
|
2837
|
+
bypassBatch: true,
|
|
2838
|
+
}),
|
|
2647
2839
|
/**
|
|
2648
2840
|
* Relabel a logical-operation group after the fact. Owner or admin only.
|
|
2649
2841
|
* @param {string} id - The group id
|
|
@@ -2684,7 +2876,8 @@ class PlaidClient {
|
|
|
2684
2876
|
* Read one comment.
|
|
2685
2877
|
* @param {string} id - The comment id
|
|
2686
2878
|
*/
|
|
2687
|
-
get: (id) =>
|
|
2879
|
+
get: (id) =>
|
|
2880
|
+
this._request("GET", `/api/v1/comments/${id}`, { bypassBatch: true }),
|
|
2688
2881
|
/**
|
|
2689
2882
|
* Edit a comment's body. Only the comment's AUTHOR may do this - not
|
|
2690
2883
|
* maintainers, not admins. Sets `edited` on the comment.
|
|
@@ -2702,7 +2895,6 @@ class PlaidClient {
|
|
|
2702
2895
|
/**
|
|
2703
2896
|
* List comments in a project, oldest first. Transparently follows
|
|
2704
2897
|
* pagination cursors and returns the full flat array.
|
|
2705
|
-
* Cannot be used inside a batch (auto-paginates across requests); throws if called while batching - use listPage() for a single page in a batch.
|
|
2706
2898
|
* @param {string} projectId - The project to read
|
|
2707
2899
|
* @param {object} [filters] - Narrow the scope
|
|
2708
2900
|
* @param {string} [filters.documentId] - Every comment anywhere in one document
|
|
@@ -2743,7 +2935,6 @@ class PlaidClient {
|
|
|
2743
2935
|
}),
|
|
2744
2936
|
/**
|
|
2745
2937
|
* Async-iterate a project's comments page by page; yields each page's entries array.
|
|
2746
|
-
* 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.
|
|
2747
2938
|
* @param {string} projectId - The project to read
|
|
2748
2939
|
* @param {object} [opts]
|
|
2749
2940
|
* @param {number} [opts.pageSize] - Per-request page size
|
|
@@ -2778,6 +2969,7 @@ class PlaidClient {
|
|
|
2778
2969
|
*/
|
|
2779
2970
|
counts: (projectId, { documentId, entityType, entityId } = {}) =>
|
|
2780
2971
|
this._request("GET", `/api/v1/projects/${projectId}/comments/counts`, {
|
|
2972
|
+
bypassBatch: true,
|
|
2781
2973
|
queryParams: {
|
|
2782
2974
|
"document-id": documentId,
|
|
2783
2975
|
"entity-type": entityType,
|
|
@@ -2789,7 +2981,6 @@ class PlaidClient {
|
|
|
2789
2981
|
* List the comments on a vocabulary's entries, oldest first. Requires
|
|
2790
2982
|
* read access to the vocabulary. Transparently follows pagination
|
|
2791
2983
|
* cursors and returns the full flat array.
|
|
2792
|
-
* Cannot be used inside a batch (auto-paginates across requests); throws if called while batching - use listInVocabPage() for a single page in a batch.
|
|
2793
2984
|
* @param {string} vocabId - The vocab layer to read
|
|
2794
2985
|
* @param {object} [filters]
|
|
2795
2986
|
* @param {string} [filters.entityId] - One entry's thread
|
|
@@ -2826,6 +3017,7 @@ class PlaidClient {
|
|
|
2826
3017
|
"GET",
|
|
2827
3018
|
`/api/v1/vocab-layers/${vocabId}/comments/counts`,
|
|
2828
3019
|
{
|
|
3020
|
+
bypassBatch: true,
|
|
2829
3021
|
queryParams: { "entity-id": entityId },
|
|
2830
3022
|
skipResponseTransform: true,
|
|
2831
3023
|
},
|
|
@@ -2872,6 +3064,12 @@ class PlaidClient {
|
|
|
2872
3064
|
* write, so an operation that is never ended (crash, closed tab) is still
|
|
2873
3065
|
* labeled in the log.
|
|
2874
3066
|
*
|
|
3067
|
+
* "Every write" is the writes of project data. Reads never join, and neither
|
|
3068
|
+
* do the out-of-band signals shaped like a write (a document lock taken or
|
|
3069
|
+
* renewed, a stopped service request, a service reporting itself, an admin
|
|
3070
|
+
* control): none of them is audited, so there would be nothing under the
|
|
3071
|
+
* label.
|
|
3072
|
+
*
|
|
2875
3073
|
* @param {string} message - Human label for the operation.
|
|
2876
3074
|
* @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).
|
|
2877
3075
|
* @returns {string} The operation's group id.
|
|
@@ -2947,12 +3145,15 @@ class PlaidClient {
|
|
|
2947
3145
|
}
|
|
2948
3146
|
}
|
|
2949
3147
|
|
|
2950
|
-
/**
|
|
3148
|
+
/**
|
|
3149
|
+
* Begin a batch of operations. Subsequent WRITES are queued; reads and
|
|
3150
|
+
* out-of-band signals still go over the wire (see `batched`).
|
|
3151
|
+
*/
|
|
2951
3152
|
beginBatch() {
|
|
2952
3153
|
this.isBatching = true;
|
|
2953
3154
|
this.batchOperations = [];
|
|
2954
|
-
// Strict mode stamps the expected document-version on the FIRST
|
|
2955
|
-
// the batch only (see _request)
|
|
3155
|
+
// Strict mode stamps the expected document-version on the FIRST QUEUED
|
|
3156
|
+
// write of the batch only (see _request), so reset the marker per batch.
|
|
2956
3157
|
this.batchVersionStamped = false;
|
|
2957
3158
|
}
|
|
2958
3159
|
|
|
@@ -3085,6 +3286,18 @@ class PlaidClient {
|
|
|
3085
3286
|
* parents created earlier in the same `fn`; any op's failure rolls the whole
|
|
3086
3287
|
* batch back). Not nestable. Named `batched()` because `client.batch` is the
|
|
3087
3288
|
* low-level batch resource.
|
|
3289
|
+
*
|
|
3290
|
+
* WRITES are what a batch queues, and batch mode is one flag on the whole
|
|
3291
|
+
* client, so it catches every write made while it is open, including writes
|
|
3292
|
+
* made by code that knows nothing about this batch. READS are never caught:
|
|
3293
|
+
* every read method goes over the wire while a batch is open and is answered
|
|
3294
|
+
* from the state the batch has not committed yet, so a read cannot come back
|
|
3295
|
+
* as a batch marker and cannot take a slot in the results array. Neither are
|
|
3296
|
+
* the calls that signal something out of band rather than write project data:
|
|
3297
|
+
* stopping a service request, a service reporting its progress or result,
|
|
3298
|
+
* taking and dropping a document lock, and the admin actions on the server
|
|
3299
|
+
* itself. See the note at the top of `http.js` for which column a new
|
|
3300
|
+
* endpoint belongs in.
|
|
3088
3301
|
* @param {() => (void | Promise<void>)} fn
|
|
3089
3302
|
* @returns {Promise<Array>}
|
|
3090
3303
|
*/
|
|
@@ -3276,6 +3489,14 @@ export {
|
|
|
3276
3489
|
// request, and `critical()` holds that off around writes. See ./services.js
|
|
3277
3490
|
// and the manual, "Stopping a request".
|
|
3278
3491
|
export { ServiceCancelled, createCancelScope } from "./services.js";
|
|
3492
|
+
// Document locks: `client.documents.locked()` holds one for a block of work and
|
|
3493
|
+
// renews it while the block runs. DocumentLockLost is what a write throws once
|
|
3494
|
+
// a renewal has failed. See ./documentLock.js.
|
|
3495
|
+
export {
|
|
3496
|
+
DOCUMENT_LOCK_TTL_MS,
|
|
3497
|
+
DocumentLock,
|
|
3498
|
+
DocumentLockLost,
|
|
3499
|
+
} from "./documentLock.js";
|
|
3279
3500
|
// Provenance: the cross-app convention for who made an annotation (flat
|
|
3280
3501
|
// prov/provSource/provConfirmed metadata; absence = a verifier; 'inferred' =
|
|
3281
3502
|
// a machine; 'contributed' = a person whose work is reviewed), plus the
|