@larc-iu/plaid-client 0.2.0-alpha.3 → 0.2.0-alpha.32
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/README.md +39 -0
- package/package.json +13 -6
- package/src/apiAnnotations.d.ts +508 -0
- package/src/apiAnnotations.js +543 -0
- package/src/apiDocuments.d.ts +569 -0
- package/src/apiDocuments.js +551 -0
- package/src/apiLayers.d.ts +369 -0
- package/src/apiLayers.js +222 -0
- package/src/apiMessages.d.ts +293 -0
- package/src/apiMessages.js +265 -0
- package/src/apiPeople.d.ts +626 -0
- package/src/apiPeople.js +698 -0
- package/src/apiProject.d.ts +761 -0
- package/src/apiProject.js +774 -0
- package/src/apiServer.d.ts +457 -0
- package/src/apiServer.js +424 -0
- package/src/apiVocab.d.ts +456 -0
- package/src/apiVocab.js +425 -0
- package/src/batch.d.ts +54 -0
- package/src/batch.js +323 -0
- package/src/batchRef.d.ts +30 -0
- package/src/batchRef.js +128 -0
- package/src/client.d.ts +1321 -0
- package/src/client.js +743 -0
- package/src/codepoint.d.ts +94 -0
- package/src/codepoint.js +131 -1
- package/src/constraints.d.ts +85 -0
- package/src/constraints.js +112 -0
- package/src/created.d.ts +2 -0
- package/src/created.js +29 -0
- package/src/documentLock.d.ts +172 -0
- package/src/documentLock.js +384 -0
- package/src/entryForms.d.ts +68 -0
- package/src/entryForms.js +164 -0
- package/src/events.d.ts +60 -0
- package/src/events.js +271 -0
- package/src/families.d.ts +349 -0
- package/src/families.js +396 -0
- package/src/http.d.ts +233 -0
- package/src/http.js +809 -93
- package/src/ids.d.ts +26 -0
- package/src/ids.js +96 -0
- package/src/index.d.ts +101 -0
- package/src/index.js +183 -2105
- package/src/metadataOps.d.ts +15 -0
- package/src/metadataOps.js +124 -0
- package/src/operations.d.ts +36 -0
- package/src/operations.js +164 -0
- package/src/pagination.d.ts +49 -0
- package/src/pagination.js +20 -53
- package/src/provenance.d.ts +243 -0
- package/src/provenance.js +458 -36
- package/src/replayed.d.ts +3 -0
- package/src/replayed.js +31 -0
- package/src/requester.d.ts +60 -0
- package/src/requester.js +74 -0
- package/src/roles.d.ts +104 -0
- package/src/roles.js +64 -2
- package/src/serviceSchema.d.ts +337 -0
- package/src/serviceSchema.js +177 -60
- package/src/services.d.ts +319 -0
- package/src/services.js +742 -58
- package/src/sse.d.ts +30 -0
- package/src/sse.js +80 -3
- package/src/testing.d.ts +128 -0
- package/src/testing.js +379 -0
- package/src/textEdits.d.ts +59 -0
- package/src/textEdits.js +234 -0
- package/src/transforms.d.ts +25 -0
- package/src/transforms.js +11 -1
- package/src/types.d.ts +867 -0
- package/src/types.js +663 -0
- package/index.d.ts +0 -532
package/src/serviceSchema.js
CHANGED
|
@@ -16,16 +16,26 @@
|
|
|
16
16
|
*
|
|
17
17
|
* {
|
|
18
18
|
* schemaVersion: 1,
|
|
19
|
-
* tasks: ["tokenize"], // controlled vocab
|
|
19
|
+
* tasks: ["tokenize"], // controlled vocab (TASKS)
|
|
20
20
|
* summary: "## markdown …", // rich human description
|
|
21
21
|
* parameters: [ // ordered; rendered into a form
|
|
22
22
|
* { key, label, type, description?, default?, required?,
|
|
23
23
|
* options?: [{value, label}], // enum / multiselect
|
|
24
|
-
* min?, max?, step?,
|
|
25
|
-
* placeholder?, multiline
|
|
24
|
+
* min?, max?, step?, slider?, // number (slider: drag, don't type)
|
|
25
|
+
* placeholder?, multiline?, // string
|
|
26
|
+
* scope?, role? } // field: 'Sentence' | 'Word' | 'Morpheme'
|
|
26
27
|
* ]
|
|
27
28
|
* }
|
|
28
29
|
*
|
|
30
|
+
* A `field` parameter names one of the project's annotation fields at its
|
|
31
|
+
* `scope`. A UI that knows the project offers those fields to choose from; to
|
|
32
|
+
* everything here, and to a UI that does not, it is a string. Its optional
|
|
33
|
+
* `role` names a lexicon role ("gloss") or, at Sentence scope, a sentence
|
|
34
|
+
* field's role ("translation", "literalTranslation", "note"): a UI that knows
|
|
35
|
+
* the project fills the parameter with the one field at `scope` whose stored
|
|
36
|
+
* Lexicon field holds that role, or whose stored role it is. A field is never
|
|
37
|
+
* chosen by its name.
|
|
38
|
+
*
|
|
29
39
|
* A parameter's `key` is a string VALUE, so it passes over the wire verbatim;
|
|
30
40
|
* the UI sends `{ [param.key]: value }` in the request data. Declare each `key`
|
|
31
41
|
* in your service's own convention (Python: snake_case; JS: camelCase) and read
|
|
@@ -43,45 +53,135 @@
|
|
|
43
53
|
* without an explicit `overwrite` parameter. See the manual, "Provenance".
|
|
44
54
|
*/
|
|
45
55
|
export const TASKS = Object.freeze({
|
|
46
|
-
TOKENIZE:
|
|
47
|
-
PARSE:
|
|
48
|
-
TRANSCRIBE:
|
|
56
|
+
TOKENIZE: "tokenize",
|
|
57
|
+
PARSE: "parse",
|
|
58
|
+
TRANSCRIBE: "transcribe",
|
|
49
59
|
/** Create vocab links for unlinked tokens. */
|
|
50
|
-
LINK_VOCAB:
|
|
60
|
+
LINK_VOCAB: "link-vocab",
|
|
51
61
|
/** Propose an interlinear analysis (morpheme segmentation + glosses) for words. */
|
|
52
|
-
ANALYZE:
|
|
62
|
+
ANALYZE: "analyze",
|
|
63
|
+
/**
|
|
64
|
+
* Draft a meaning representation graph over the sentences of a document,
|
|
65
|
+
* for correction by hand. The request names a `scope` ('document' or
|
|
66
|
+
* 'sentence'), a `sentence` number when the scope is one sentence, and
|
|
67
|
+
* `overwrite`. See plaid-umr's drafting services.
|
|
68
|
+
*
|
|
69
|
+
* Apart from `analyze` on purpose. A task is the CONTRACT a spot offers a
|
|
70
|
+
* service against, and these two share almost none of it: an analyze
|
|
71
|
+
* request names the three token layers plus the language and metalanguage,
|
|
72
|
+
* and writes morphemes and glosses. Both claimed `analyze` for
|
|
73
|
+
* a while, so every app offering an analyze spot offered the other app's
|
|
74
|
+
* services, which could not answer the request they would have been given.
|
|
75
|
+
*/
|
|
76
|
+
DRAFT_GRAPH: "draft-graph",
|
|
77
|
+
/** Propose a free translation for each sentence. */
|
|
78
|
+
TRANSLATE: "translate",
|
|
79
|
+
/**
|
|
80
|
+
* Propose time-aligned speech regions for a recording.
|
|
81
|
+
*
|
|
82
|
+
* The odd one out: a detect-speech service RETURNS its regions and writes
|
|
83
|
+
* nothing, because a time-aligned segment is a stretch of the baseline and
|
|
84
|
+
* cannot exist without text. The response carries
|
|
85
|
+
* `{segments: [{timeBegin, timeEnd, speaker?}]}` (seconds), and the app
|
|
86
|
+
* holds them as proposals until a person types into one.
|
|
87
|
+
*/
|
|
88
|
+
DETECT_SPEECH: "detect-speech",
|
|
89
|
+
/** A conversational assistant over a project (chat turns; see plaid-agent). */
|
|
90
|
+
ASSIST: "assist",
|
|
91
|
+
/**
|
|
92
|
+
* Score one document's annotation against another document's of the same
|
|
93
|
+
* text (two annotators' copies), writing a report on the scored document's
|
|
94
|
+
* metadata and never an annotation. The request names the other document
|
|
95
|
+
* as `against`. See plaid-umr's AnCast service.
|
|
96
|
+
*/
|
|
97
|
+
COMPARE: "compare",
|
|
53
98
|
});
|
|
54
99
|
|
|
55
100
|
/**
|
|
56
|
-
*
|
|
57
|
-
*
|
|
101
|
+
* One choice for an `enum` or `multiselect` service parameter.
|
|
102
|
+
* @typedef {{value: string, label: string}} ServiceParamOption
|
|
103
|
+
*/
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* A single user-controllable argument a service advertises.
|
|
107
|
+
* @typedef {object} ServiceParam
|
|
108
|
+
* @property {string} key Key the value is sent under in the request payload.
|
|
109
|
+
* @property {string} label
|
|
110
|
+
* @property {"string" | "number" | "boolean" | "enum" | "multiselect" | "field"} type
|
|
111
|
+
* @property {string} [description]
|
|
112
|
+
* @property {any} [default]
|
|
113
|
+
* @property {boolean} [required]
|
|
114
|
+
* @property {ServiceParamOption[]} [options] Required for `enum` and `multiselect`.
|
|
115
|
+
* @property {number} [min] `number` only.
|
|
116
|
+
* @property {number} [max] `number` only.
|
|
117
|
+
* @property {number} [step] `number` only.
|
|
118
|
+
* @property {boolean} [slider] `number` only: render as a slider to drag
|
|
119
|
+
* rather than a box to type in.
|
|
120
|
+
* @property {string} [placeholder] `string` only.
|
|
121
|
+
* @property {boolean} [multiline] `string` only.
|
|
122
|
+
* @property {"Sentence" | "Word" | "Morpheme"} [scope] `field` only: the
|
|
123
|
+
* scope of the project's annotation fields the value names one of. A
|
|
124
|
+
* `field` value is a string everywhere else.
|
|
125
|
+
* @property {string} [role] `field` only: the lexicon role whose paired field,
|
|
126
|
+
* or the sentence role whose field, fills the parameter when nothing else
|
|
127
|
+
* does.
|
|
128
|
+
*/
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* A service's standardized self-description (lives in `extras`).
|
|
132
|
+
* @typedef {object} ServiceExtras
|
|
133
|
+
* @property {number} [schemaVersion]
|
|
134
|
+
* @property {string[]} [tasks] Tasks this service serves, from the TASKS vocabulary.
|
|
135
|
+
* @property {string} [summary] Rich human description (Markdown), beyond the
|
|
136
|
+
* short `description`.
|
|
137
|
+
* @property {ServiceParam[]} [parameters] Ordered parameter schema, rendered
|
|
138
|
+
* into a form by the UI.
|
|
139
|
+
*/
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* What a service says about itself when it registers.
|
|
143
|
+
* @typedef {object} ServiceInfo
|
|
144
|
+
* @property {string} serviceId
|
|
145
|
+
* @property {string} serviceName
|
|
146
|
+
* @property {string} description
|
|
147
|
+
* @property {ServiceExtras & Record<string, any>} [extras]
|
|
148
|
+
*/
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* A service as `messages.discoverServices` lists it.
|
|
152
|
+
* @typedef {object} DiscoveredService
|
|
153
|
+
* @property {string} serviceId
|
|
154
|
+
* @property {string} serviceName
|
|
155
|
+
* @property {string} description
|
|
156
|
+
* @property {ServiceExtras & Record<string, any>} extras
|
|
157
|
+
* @property {boolean} online True while the service holds an open request
|
|
158
|
+
* channel, false for a previously seen offline service.
|
|
159
|
+
* @property {string | null} [lastSeenAt] ISO-8601 stamp of when the service
|
|
160
|
+
* was last seen alive, or null when never stored.
|
|
161
|
+
* @property {string} [runnerName] Online services only: the display name of
|
|
162
|
+
* the account that runs the service.
|
|
163
|
+
* @property {boolean} [runByYou] Online services only: the caller runs it.
|
|
164
|
+
* @property {boolean} [servesYou] Online services only: it would take the
|
|
165
|
+
* caller's requests on this project. A delegating service serves members
|
|
166
|
+
* other than its runner only where the runner is a maintainer or an admin.
|
|
58
167
|
*/
|
|
59
|
-
const LEGACY_TASK_PREFIXES = Object.freeze({
|
|
60
|
-
[TASKS.TOKENIZE]: 'tok:',
|
|
61
|
-
[TASKS.TRANSCRIBE]: 'asr:',
|
|
62
|
-
});
|
|
63
168
|
|
|
64
169
|
/**
|
|
65
|
-
* Does `service` serve `task
|
|
66
|
-
* back to the legacy id-prefix convention for un-migrated services.
|
|
170
|
+
* Does `service` serve `task`, as its declared `extras.tasks` says?
|
|
67
171
|
* @param {{serviceId?: string, extras?: {tasks?: string[]}}} service
|
|
68
172
|
* @param {string} task one of TASKS
|
|
69
173
|
* @returns {boolean}
|
|
70
174
|
*/
|
|
71
175
|
export function servesTask(service, task) {
|
|
72
176
|
const declared = service?.extras?.tasks;
|
|
73
|
-
|
|
74
|
-
return declared.includes(task);
|
|
75
|
-
}
|
|
76
|
-
const prefix = LEGACY_TASK_PREFIXES[task];
|
|
77
|
-
return !!prefix && typeof service?.serviceId === 'string' && service.serviceId.startsWith(prefix);
|
|
177
|
+
return Array.isArray(declared) && declared.includes(task);
|
|
78
178
|
}
|
|
79
179
|
|
|
80
180
|
/**
|
|
81
181
|
* The discovered services that serve `task`.
|
|
82
|
-
* @param {
|
|
182
|
+
* @param {DiscoveredService[] | undefined} services result of client.messages.discoverServices()
|
|
83
183
|
* @param {string} task one of TASKS
|
|
84
|
-
* @returns {
|
|
184
|
+
* @returns {DiscoveredService[]}
|
|
85
185
|
*/
|
|
86
186
|
export function filterServicesByTask(services, task) {
|
|
87
187
|
return (services || []).filter((s) => servesTask(s, task));
|
|
@@ -89,8 +189,8 @@ export function filterServicesByTask(services, task) {
|
|
|
89
189
|
|
|
90
190
|
/**
|
|
91
191
|
* The parameter schema a service declares (ordered array), or [].
|
|
92
|
-
* @param {{extras?: {parameters?:
|
|
93
|
-
* @returns {
|
|
192
|
+
* @param {{extras?: {parameters?: ServiceParam[]}}} service
|
|
193
|
+
* @returns {ServiceParam[]}
|
|
94
194
|
*/
|
|
95
195
|
export function getParamSchema(service) {
|
|
96
196
|
const params = service?.extras?.parameters;
|
|
@@ -104,7 +204,7 @@ export function getParamSchema(service) {
|
|
|
104
204
|
* @returns {string}
|
|
105
205
|
*/
|
|
106
206
|
export function getServiceSummary(service) {
|
|
107
|
-
return service?.extras?.summary || service?.description ||
|
|
207
|
+
return service?.extras?.summary || service?.description || "";
|
|
108
208
|
}
|
|
109
209
|
|
|
110
210
|
/** Valid option values for an enum/multiselect param. */
|
|
@@ -119,27 +219,32 @@ function optionValues(param) {
|
|
|
119
219
|
*/
|
|
120
220
|
function defaultForParam(param) {
|
|
121
221
|
const opts = optionValues(param);
|
|
122
|
-
if (param.type ===
|
|
123
|
-
if (param.default != null && opts.includes(param.default))
|
|
124
|
-
|
|
222
|
+
if (param.type === "enum") {
|
|
223
|
+
if (param.default != null && opts.includes(param.default))
|
|
224
|
+
return param.default;
|
|
225
|
+
return opts[0] ?? "";
|
|
125
226
|
}
|
|
126
|
-
if (param.type ===
|
|
227
|
+
if (param.type === "multiselect") {
|
|
127
228
|
const arr = Array.isArray(param.default) ? param.default : [];
|
|
128
229
|
return opts.length ? arr.filter((x) => opts.includes(x)) : arr;
|
|
129
230
|
}
|
|
130
|
-
if (param.default !== undefined && param.default !== null)
|
|
231
|
+
if (param.default !== undefined && param.default !== null)
|
|
232
|
+
return param.default;
|
|
131
233
|
switch (param.type) {
|
|
132
|
-
case
|
|
133
|
-
|
|
134
|
-
case
|
|
135
|
-
|
|
234
|
+
case "number":
|
|
235
|
+
return typeof param.min === "number" ? param.min : 0;
|
|
236
|
+
case "boolean":
|
|
237
|
+
return false;
|
|
238
|
+
case "string":
|
|
239
|
+
default:
|
|
240
|
+
return "";
|
|
136
241
|
}
|
|
137
242
|
}
|
|
138
243
|
|
|
139
244
|
/**
|
|
140
245
|
* Default values keyed by param key — the initial form state.
|
|
141
|
-
* @param {
|
|
142
|
-
* @returns {
|
|
246
|
+
* @param {ServiceParam[]} schema getParamSchema(service)
|
|
247
|
+
* @returns {Record<string, any>} { [key]: defaultValue }
|
|
143
248
|
*/
|
|
144
249
|
export function buildDefaultValues(schema) {
|
|
145
250
|
const out = {};
|
|
@@ -154,10 +259,24 @@ export function buildDefaultValues(schema) {
|
|
|
154
259
|
* Coerce/validate raw form values against the schema. Returns the cleaned
|
|
155
260
|
* values (keyed by param key, ready to merge into the request payload) plus any
|
|
156
261
|
* validation errors keyed by param key. Unknown keys in `raw` are dropped.
|
|
157
|
-
* @param {
|
|
158
|
-
* @param {
|
|
159
|
-
* @returns {{values:
|
|
262
|
+
* @param {ServiceParam[]} schema getParamSchema(service)
|
|
263
|
+
* @param {Record<string, any>} raw current form values
|
|
264
|
+
* @returns {{values: Record<string, any>, errors: Record<string, string>}}
|
|
160
265
|
*/
|
|
266
|
+
// A decimal number as a person types one: an optional sign, digits with an
|
|
267
|
+
// optional fraction (or a bare fraction), an optional exponent, with spaces
|
|
268
|
+
// around it allowed. ASCII whitespace only, as in Python (each language's \s
|
|
269
|
+
// holds characters the other's lacks).
|
|
270
|
+
const DECIMAL = /^[ \t\n\v\f\r]*[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?[ \t\n\v\f\r]*$/;
|
|
271
|
+
|
|
272
|
+
/** `v` as a finite number when it is one or a decimal string, else null. */
|
|
273
|
+
function numberOf(v) {
|
|
274
|
+
let n = null;
|
|
275
|
+
if (typeof v === "number") n = v;
|
|
276
|
+
else if (typeof v === "string" && DECIMAL.test(v)) n = Number(v);
|
|
277
|
+
return n !== null && Number.isFinite(n) ? n : null;
|
|
278
|
+
}
|
|
279
|
+
|
|
161
280
|
export function coerceParamValues(schema, raw) {
|
|
162
281
|
const values = {};
|
|
163
282
|
const errors = {};
|
|
@@ -169,43 +288,41 @@ export function coerceParamValues(schema, raw) {
|
|
|
169
288
|
if (v === undefined) v = defaultForParam(param);
|
|
170
289
|
|
|
171
290
|
switch (param.type) {
|
|
172
|
-
case
|
|
173
|
-
//
|
|
174
|
-
//
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
182
|
-
if (typeof param.min === 'number') n = Math.max(param.min, n);
|
|
183
|
-
if (typeof param.max === 'number') n = Math.min(param.max, n);
|
|
291
|
+
case "number": {
|
|
292
|
+
// A finite number, or a string holding a decimal one; anything else
|
|
293
|
+
// (blank, a boolean, a list, hex, an underscore, Infinity, a value too
|
|
294
|
+
// large to be finite) is the param's default. The Python client's
|
|
295
|
+
// `coerce` reads the same rule.
|
|
296
|
+
let n = numberOf(v);
|
|
297
|
+
if (n === null) n = defaultForParam(param);
|
|
298
|
+
if (typeof param.min === "number") n = Math.max(param.min, n);
|
|
299
|
+
if (typeof param.max === "number") n = Math.min(param.max, n);
|
|
184
300
|
v = n;
|
|
185
301
|
break;
|
|
186
302
|
}
|
|
187
|
-
case
|
|
188
|
-
v = v === true || v ===
|
|
303
|
+
case "boolean":
|
|
304
|
+
v = v === true || v === "true";
|
|
189
305
|
break;
|
|
190
|
-
case
|
|
306
|
+
case "enum": {
|
|
191
307
|
const opts = optionValues(param);
|
|
192
308
|
if (opts.length && !opts.includes(v)) v = defaultForParam(param);
|
|
193
309
|
break;
|
|
194
310
|
}
|
|
195
|
-
case
|
|
311
|
+
case "multiselect": {
|
|
196
312
|
const opts = optionValues(param);
|
|
197
|
-
const arr = Array.isArray(v) ? v :
|
|
313
|
+
const arr = Array.isArray(v) ? v : v == null || v === "" ? [] : [v];
|
|
198
314
|
v = opts.length ? arr.filter((x) => opts.includes(x)) : arr;
|
|
199
315
|
break;
|
|
200
316
|
}
|
|
201
|
-
case
|
|
317
|
+
case "string":
|
|
202
318
|
default:
|
|
203
|
-
v = v == null ?
|
|
319
|
+
v = v == null ? "" : String(v);
|
|
204
320
|
break;
|
|
205
321
|
}
|
|
206
322
|
|
|
207
323
|
if (param.required) {
|
|
208
|
-
const empty =
|
|
324
|
+
const empty =
|
|
325
|
+
v === "" || v == null || (Array.isArray(v) && v.length === 0);
|
|
209
326
|
if (empty) errors[k] = `${param.label || k} is required`;
|
|
210
327
|
}
|
|
211
328
|
values[k] = v;
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One line about a failure that is safe to show the person who asked.
|
|
3
|
+
*
|
|
4
|
+
* Strips absolute URLs (so an internal host never reaches a requester's screen)
|
|
5
|
+
* and any `secrets` given (a model provider's API key can come back inside its
|
|
6
|
+
* own error text). The whole error still goes to the operator's console: this
|
|
7
|
+
* is the requester's half only. The Python twin is `requester_message`.
|
|
8
|
+
*
|
|
9
|
+
* Only a connection that never opened is "could not be reached". A write whose
|
|
10
|
+
* answer never came (a reset, a timeout) may have been saved, and says so
|
|
11
|
+
* (`UNKNOWN_OUTCOME`).
|
|
12
|
+
*
|
|
13
|
+
* @param {any} error
|
|
14
|
+
* @param {string[]} [secrets]
|
|
15
|
+
* @returns {string}
|
|
16
|
+
*/
|
|
17
|
+
export function requesterMessage(error: any, secrets?: string[]): string;
|
|
18
|
+
/**
|
|
19
|
+
* What the requester is told when a request fails, named by the service.
|
|
20
|
+
*
|
|
21
|
+
* Every path that reports a failed request goes through here, so a raw message
|
|
22
|
+
* cannot reach a requester from one of them. (Python's twin additionally lets a
|
|
23
|
+
* `ValueError` through unprefixed, as an authored refusal; JS has no
|
|
24
|
+
* distinguished refusal type, so every failure is named by the service.)
|
|
25
|
+
*
|
|
26
|
+
* @param {any} error
|
|
27
|
+
* @param {string} [serviceName]
|
|
28
|
+
* @param {string[]} [secrets]
|
|
29
|
+
* @returns {string}
|
|
30
|
+
*/
|
|
31
|
+
export function serviceErrorMessage(error: any, serviceName?: string, secrets?: string[]): string;
|
|
32
|
+
/**
|
|
33
|
+
* Discover the services seen on a project — a synchronous GET. Returns every
|
|
34
|
+
* service ever registered on the project: currently connected ones carry
|
|
35
|
+
* `online: true`; previously-seen offline ones carry `online: false` plus a
|
|
36
|
+
* `lastSeenAt` stamp. Callers that need a service they can actually submit
|
|
37
|
+
* work to should filter on `online`. A connected service also names who runs
|
|
38
|
+
* it, as the caller sees it: `runnerName` (the runner's display name),
|
|
39
|
+
* `runByYou`, and `servesYou`, whether it would take the caller's requests on
|
|
40
|
+
* this project. A delegating service serves members other than its runner
|
|
41
|
+
* only where the runner is a maintainer or an admin. Every entry whose id an
|
|
42
|
+
* account holds gives its display name in `claimedByName`. An admin also gets
|
|
43
|
+
* the account in `claimedBy` (see `releaseService`), and an entry with
|
|
44
|
+
* `seen: false` for each held id whose registration was forgotten. Goes over
|
|
45
|
+
* the wire even while a batch is open on the client.
|
|
46
|
+
*
|
|
47
|
+
* @param {Object} client - PlaidClient instance
|
|
48
|
+
* @param {string} projectId - Project UUID
|
|
49
|
+
* @returns {Promise<Array>} [{serviceId, serviceName, description, extras, online, lastSeenAt, runnerName, runByYou, servesYou, claimedByName, claimedBy, seen}]
|
|
50
|
+
*/
|
|
51
|
+
export function discoverServices(client: any, projectId: string): Promise<any[]>;
|
|
52
|
+
/**
|
|
53
|
+
* Forget a previously-seen (offline) service: removes its row from the
|
|
54
|
+
* project's persistent registry. Maintainer-only; 409 if the service is
|
|
55
|
+
* currently connected (it would just re-register).
|
|
56
|
+
*
|
|
57
|
+
* @param {Object} client - PlaidClient instance
|
|
58
|
+
* @param {string} projectId - Project UUID
|
|
59
|
+
* @param {string} serviceId - Service ID to forget
|
|
60
|
+
* @returns {Promise<void>}
|
|
61
|
+
*/
|
|
62
|
+
export function discardService(client: any, projectId: string, serviceId: string): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Release a service id from the account that first registered it on the
|
|
65
|
+
* project. A service id belongs to that account, and the server refuses any
|
|
66
|
+
* other account's registration (403) until an admin releases it. The next
|
|
67
|
+
* account to register it then claims it. Deactivating the account releases
|
|
68
|
+
* every id it holds. Admin-only; 409 while the service is connected, 404 when
|
|
69
|
+
* no account holds it.
|
|
70
|
+
*
|
|
71
|
+
* @param {Object} client - PlaidClient instance
|
|
72
|
+
* @param {string} projectId - Project UUID
|
|
73
|
+
* @param {string} serviceId - Service ID to release
|
|
74
|
+
* @returns {Promise<void>}
|
|
75
|
+
*/
|
|
76
|
+
export function releaseService(client: any, projectId: string, serviceId: string): Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* POST a progress, result or error event for an in-flight request; the server
|
|
79
|
+
* relays it to the waiting requester. The Python twin is `_report_event`.
|
|
80
|
+
*
|
|
81
|
+
* outOfBand: these are signals to whoever is waiting, not writes to the
|
|
82
|
+
* project (see the note at the top of http.js). A service may report them on
|
|
83
|
+
* the batch it is filling, where queueing them would hold every one back until
|
|
84
|
+
* submit, deliver none at all if the batch aborts, and take slots in the
|
|
85
|
+
* batch's results. The requester would hear nothing and wait out its idle
|
|
86
|
+
* timeout on work that had already finished.
|
|
87
|
+
*
|
|
88
|
+
* @param {Object} client - PlaidClient instance
|
|
89
|
+
* @param {string} projectId - Project UUID
|
|
90
|
+
* @param {string} requestId - The request id
|
|
91
|
+
* @param {Object} body - The event payload
|
|
92
|
+
* @returns {Promise<any>}
|
|
93
|
+
*/
|
|
94
|
+
export function reportRequestEvent(client: any, projectId: string, requestId: string, body: any): Promise<any>;
|
|
95
|
+
/**
|
|
96
|
+
* The cancellation half of a responseHelper, on its own.
|
|
97
|
+
* @typedef {object} CancelScope
|
|
98
|
+
* @property {boolean} cancelled True once the requester has asked this request
|
|
99
|
+
* to stop.
|
|
100
|
+
* @property {() => void} raiseIfCancelled Stop here if the requester has asked
|
|
101
|
+
* the request to stop.
|
|
102
|
+
* @property {<T>(fn: () => T | Promise<T>) => Promise<T>} critical Run `fn` as
|
|
103
|
+
* a stretch that must finish once begun, usually the writes.
|
|
104
|
+
*/
|
|
105
|
+
/**
|
|
106
|
+
* What a `serve` handler gets for each request.
|
|
107
|
+
* @typedef {CancelScope & {
|
|
108
|
+
* requestId: string,
|
|
109
|
+
* requesterId: string | null,
|
|
110
|
+
* progress(percent: number, message: string, extra?: Record<string, any>): void,
|
|
111
|
+
* complete(data: any): void,
|
|
112
|
+
* stopped(data?: any): void,
|
|
113
|
+
* error(error: string | Error): void,
|
|
114
|
+
* }} ResponseHelper `progress` is also a cancellation checkpoint: it throws
|
|
115
|
+
* `ServiceCancelled` once a stop has been asked for. `stopped` ends the
|
|
116
|
+
* request because it was asked to stop, and its result carries `stopped: true`.
|
|
117
|
+
*/
|
|
118
|
+
/**
|
|
119
|
+
* A connection-state transition of a service registration. "stopped": the
|
|
120
|
+
* server refused the channel for a reason retrying cannot fix (a revoked
|
|
121
|
+
* token, no write access, no such project), which ends the registration.
|
|
122
|
+
* @typedef {"registered" | "reconnected" | "disconnected" | "stopped"} ServiceStatusEvent
|
|
123
|
+
*/
|
|
124
|
+
/**
|
|
125
|
+
* What `serve` returns.
|
|
126
|
+
* @typedef {object} ServiceRegistration
|
|
127
|
+
* @property {() => void} stop
|
|
128
|
+
* @property {() => boolean} isRunning Still serving, including while retrying
|
|
129
|
+
* a channel through a server restart.
|
|
130
|
+
* @property {() => boolean} isConnected Channel open right now, so the server
|
|
131
|
+
* sees this service as online.
|
|
132
|
+
* @property {import("./serviceSchema.js").ServiceInfo & {extras: any}} serviceInfo
|
|
133
|
+
*/
|
|
134
|
+
/**
|
|
135
|
+
* Register a service and handle incoming work requests.
|
|
136
|
+
*
|
|
137
|
+
* Opens the service's dedicated request channel — which registers it for
|
|
138
|
+
* discovery (presence = open channel) — and handles work on it. For each
|
|
139
|
+
* request, runs `onServiceRequest(data, responseHelper)` where `responseHelper`
|
|
140
|
+
* has `progress(percent, msg)` / `complete(data)` / `error(err)`.
|
|
141
|
+
*
|
|
142
|
+
* @param {Object} client - PlaidClient instance
|
|
143
|
+
* @param {string} projectId - Project UUID
|
|
144
|
+
* @param {import("./serviceSchema.js").ServiceInfo} serviceInfo - {serviceId, serviceName, description}
|
|
145
|
+
* @param {(data: any, responseHelper: ResponseHelper) => void} onServiceRequest - Handler callback (data, responseHelper)
|
|
146
|
+
* @param {Object} [extras] - Optional additional metadata
|
|
147
|
+
* @param {((event: ServiceStatusEvent, projectId: string, detail?: string) => void) | null} [onStatus] - Optional callback (event, projectId, detail) for
|
|
148
|
+
* connection-state transitions: 'registered', 'reconnected', 'disconnected',
|
|
149
|
+
* and 'stopped' when the server refuses the channel for a reason retrying
|
|
150
|
+
* cannot fix (see PERMANENT_STATUSES), which ends the registration.
|
|
151
|
+
* Called once per transition, not once per retry.
|
|
152
|
+
* @returns {ServiceRegistration}
|
|
153
|
+
*/
|
|
154
|
+
export function serve(client: any, projectId: string, serviceInfo: import("./serviceSchema.js").ServiceInfo, onServiceRequest: (data: any, responseHelper: ResponseHelper) => void, extras?: any, onStatus?: ((event: ServiceStatusEvent, projectId: string, detail?: string) => void) | null): ServiceRegistration;
|
|
155
|
+
/**
|
|
156
|
+
* Submit work to a service and await its result.
|
|
157
|
+
*
|
|
158
|
+
* Streams the service's progress + result back over a single server-mediated
|
|
159
|
+
* response (no broadcast). Rejects if no service is connected (503), if the
|
|
160
|
+
* service reports an error, or after `timeout` of SILENCE.
|
|
161
|
+
*
|
|
162
|
+
* The request outlives this call: after a timeout, an abort, or a dropped
|
|
163
|
+
* connection the service goes on, and `attachServiceRequest` collects the
|
|
164
|
+
* result given the request id, which `opts.onAccepted` receives as soon as
|
|
165
|
+
* the server has taken the request. Pass `opts.requestId` (a UUID you mint)
|
|
166
|
+
* to know the id before submitting; submitting an id that names a request
|
|
167
|
+
* you already made rejoins it instead of starting another.
|
|
168
|
+
*
|
|
169
|
+
* Errors that leave the request alive carry `pending: true`: a timeout, a
|
|
170
|
+
* stop, a dropped connection, a proxy's 502 or 504. An error without it is
|
|
171
|
+
* the end of the request. With `opts.requestId`, a request whose answer went
|
|
172
|
+
* missing (a dropped connection, a 502 or 504) is rejoined by that id a few
|
|
173
|
+
* times before the error is given.
|
|
174
|
+
*
|
|
175
|
+
* @param {Object} client - PlaidClient instance
|
|
176
|
+
* @param {string} projectId - Project UUID
|
|
177
|
+
* @param {string} serviceId - Service ID to request
|
|
178
|
+
* @param {any} data - Request payload
|
|
179
|
+
* @param {number} [timeout=10000] - How long the service may say NOTHING, in ms.
|
|
180
|
+
* Every event it sends starts the clock again, so this does not cap a long run.
|
|
181
|
+
* 0, a negative number or null: no limit (wait until `signal` stops it)
|
|
182
|
+
* @param {function} [onProgress] - Called with each progress payload {percent, message}
|
|
183
|
+
* @param {AbortSignal} [signal] - Abort to stop waiting; rejects with an AbortError
|
|
184
|
+
* @param {Object} [opts]
|
|
185
|
+
* @param {string} [opts.requestId] - A client-minted request id (UUID)
|
|
186
|
+
* @param {function} [opts.onAccepted] - Called with the request id once the server has it
|
|
187
|
+
* @param {string[]} [opts.projectIds] - Other projects the request is about, beside
|
|
188
|
+
* `projectId`. A delegating service's token is scoped to `projectId` and to those of
|
|
189
|
+
* these the requester can read, and reaches nothing else
|
|
190
|
+
* @param {boolean} [opts.noOperation] - Carry no open operation: the service's writes
|
|
191
|
+
* are a group of their own, not part of whatever operation this client has open
|
|
192
|
+
* @returns {Promise<any>} The service's result
|
|
193
|
+
*/
|
|
194
|
+
export function requestService(client: any, projectId: string, serviceId: string, data: any, timeout?: number, onProgress?: Function, signal?: AbortSignal, opts?: {
|
|
195
|
+
requestId?: string;
|
|
196
|
+
onAccepted?: Function;
|
|
197
|
+
projectIds?: string[];
|
|
198
|
+
noOperation?: boolean;
|
|
199
|
+
}): Promise<any>;
|
|
200
|
+
/**
|
|
201
|
+
* Rejoin a service request made earlier (by this user) and await its result:
|
|
202
|
+
* the latest progress is replayed, then the result comes, or at once if the
|
|
203
|
+
* request already finished. Rejects with an error whose `status` is 404 when
|
|
204
|
+
* the request is unknown or expired (the server keeps a finished request's
|
|
205
|
+
* result for a while, not forever). As with `requestService`, `timeout` is
|
|
206
|
+
* how long the service may be silent, and an error carrying `pending: true`
|
|
207
|
+
* means the request is still there to rejoin again.
|
|
208
|
+
*
|
|
209
|
+
* @param {Object} client - PlaidClient instance
|
|
210
|
+
* @param {string} projectId - Project UUID
|
|
211
|
+
* @param {string} requestId - The request id (from `onAccepted` or your own)
|
|
212
|
+
* @param {number} [timeout=10000] - How long the service may say NOTHING, in ms
|
|
213
|
+
* (0, a negative number or null: no limit)
|
|
214
|
+
* @param {function} [onProgress] - Called with each progress payload {percent, message}
|
|
215
|
+
* @param {AbortSignal} [signal] - Abort to stop waiting; rejects with an AbortError
|
|
216
|
+
* @returns {Promise<any>} The service's result
|
|
217
|
+
*/
|
|
218
|
+
export function attachServiceRequest(client: any, projectId: string, requestId: string, timeout?: number, onProgress?: Function, signal?: AbortSignal): Promise<any>;
|
|
219
|
+
/**
|
|
220
|
+
* The cancellation half of a responseHelper: a flag, a depth counter, and one
|
|
221
|
+
* rule about when a checkpoint may raise. Split from the transport so it can
|
|
222
|
+
* be reasoned about on its own. Mirrors `CancelScope` in the Python client.
|
|
223
|
+
* @param {() => boolean} isCancelled
|
|
224
|
+
* @returns {CancelScope}
|
|
225
|
+
*/
|
|
226
|
+
export function createCancelScope(isCancelled: () => boolean): CancelScope;
|
|
227
|
+
/**
|
|
228
|
+
* Ask the service to stop a request made earlier (by this user). The request
|
|
229
|
+
* still ends with whatever the service then reports, on the stream of whoever
|
|
230
|
+
* is awaiting it. Rejects with 404 if unknown or expired, 409 once finished.
|
|
231
|
+
*
|
|
232
|
+
* outOfBand: a DELETE, but not a write. It signals a running service and
|
|
233
|
+
* changes no project data (see the note at the top of http.js).
|
|
234
|
+
*
|
|
235
|
+
* @param {Object} client - PlaidClient instance
|
|
236
|
+
* @param {string} projectId - Project UUID
|
|
237
|
+
* @param {string} requestId - The request id
|
|
238
|
+
* @returns {Promise<void>}
|
|
239
|
+
*/
|
|
240
|
+
export function cancelServiceRequest(client: any, projectId: string, requestId: string): Promise<void>;
|
|
241
|
+
/**
|
|
242
|
+
* What a requester is told when an error carries no message of its own.
|
|
243
|
+
* Naming the JS class instead would say nothing they can act on.
|
|
244
|
+
*/
|
|
245
|
+
export const UNKNOWN_FAILURE: "The service could not finish this request.";
|
|
246
|
+
/** A write sent to the server whose answer never came back. */
|
|
247
|
+
export const UNKNOWN_OUTCOME: "The Plaid server did not answer. This change may or may not have been saved.";
|
|
248
|
+
/** The server was never reached, so nothing was sent. */
|
|
249
|
+
export const UNREACHABLE: "The Plaid server could not be reached.";
|
|
250
|
+
/**
|
|
251
|
+
* Thrown inside a handler when the requester has asked it to stop.
|
|
252
|
+
*
|
|
253
|
+
* Cooperative cancellation: nothing interrupts a handler, so the request ends
|
|
254
|
+
* at the next point the handler looks. `responseHelper.progress` is that
|
|
255
|
+
* point, which is why a long service that already reports progress needs no
|
|
256
|
+
* changes at all. `serve` catches this and ends the request as STOPPED rather
|
|
257
|
+
* than failed.
|
|
258
|
+
*/
|
|
259
|
+
export class ServiceCancelled extends Error {
|
|
260
|
+
constructor(message?: string);
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* The cancellation half of a responseHelper, on its own.
|
|
264
|
+
*/
|
|
265
|
+
export type CancelScope = {
|
|
266
|
+
/**
|
|
267
|
+
* True once the requester has asked this request
|
|
268
|
+
* to stop.
|
|
269
|
+
*/
|
|
270
|
+
cancelled: boolean;
|
|
271
|
+
/**
|
|
272
|
+
* Stop here if the requester has asked
|
|
273
|
+
* the request to stop.
|
|
274
|
+
*/
|
|
275
|
+
raiseIfCancelled: () => void;
|
|
276
|
+
/**
|
|
277
|
+
* Run `fn` as
|
|
278
|
+
* a stretch that must finish once begun, usually the writes.
|
|
279
|
+
*/
|
|
280
|
+
critical: <T>(fn: () => T | Promise<T>) => Promise<T>;
|
|
281
|
+
};
|
|
282
|
+
/**
|
|
283
|
+
* `progress` is also a cancellation checkpoint: it throws
|
|
284
|
+
* `ServiceCancelled` once a stop has been asked for. `stopped` ends the
|
|
285
|
+
* request because it was asked to stop, and its result carries `stopped: true`.
|
|
286
|
+
*/
|
|
287
|
+
export type ResponseHelper = CancelScope & {
|
|
288
|
+
requestId: string;
|
|
289
|
+
requesterId: string | null;
|
|
290
|
+
progress(percent: number, message: string, extra?: Record<string, any>): void;
|
|
291
|
+
complete(data: any): void;
|
|
292
|
+
stopped(data?: any): void;
|
|
293
|
+
error(error: string | Error): void;
|
|
294
|
+
};
|
|
295
|
+
/**
|
|
296
|
+
* A connection-state transition of a service registration. "stopped": the
|
|
297
|
+
* server refused the channel for a reason retrying cannot fix (a revoked
|
|
298
|
+
* token, no write access, no such project), which ends the registration.
|
|
299
|
+
*/
|
|
300
|
+
export type ServiceStatusEvent = "registered" | "reconnected" | "disconnected" | "stopped";
|
|
301
|
+
/**
|
|
302
|
+
* What `serve` returns.
|
|
303
|
+
*/
|
|
304
|
+
export type ServiceRegistration = {
|
|
305
|
+
stop: () => void;
|
|
306
|
+
/**
|
|
307
|
+
* Still serving, including while retrying
|
|
308
|
+
* a channel through a server restart.
|
|
309
|
+
*/
|
|
310
|
+
isRunning: () => boolean;
|
|
311
|
+
/**
|
|
312
|
+
* Channel open right now, so the server
|
|
313
|
+
* sees this service as online.
|
|
314
|
+
*/
|
|
315
|
+
isConnected: () => boolean;
|
|
316
|
+
serviceInfo: import("./serviceSchema.js").ServiceInfo & {
|
|
317
|
+
extras: any;
|
|
318
|
+
};
|
|
319
|
+
};
|