@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.
Files changed (73) hide show
  1. package/README.md +39 -0
  2. package/package.json +13 -6
  3. package/src/apiAnnotations.d.ts +508 -0
  4. package/src/apiAnnotations.js +543 -0
  5. package/src/apiDocuments.d.ts +569 -0
  6. package/src/apiDocuments.js +551 -0
  7. package/src/apiLayers.d.ts +369 -0
  8. package/src/apiLayers.js +222 -0
  9. package/src/apiMessages.d.ts +293 -0
  10. package/src/apiMessages.js +265 -0
  11. package/src/apiPeople.d.ts +626 -0
  12. package/src/apiPeople.js +698 -0
  13. package/src/apiProject.d.ts +761 -0
  14. package/src/apiProject.js +774 -0
  15. package/src/apiServer.d.ts +457 -0
  16. package/src/apiServer.js +424 -0
  17. package/src/apiVocab.d.ts +456 -0
  18. package/src/apiVocab.js +425 -0
  19. package/src/batch.d.ts +54 -0
  20. package/src/batch.js +323 -0
  21. package/src/batchRef.d.ts +30 -0
  22. package/src/batchRef.js +128 -0
  23. package/src/client.d.ts +1321 -0
  24. package/src/client.js +743 -0
  25. package/src/codepoint.d.ts +94 -0
  26. package/src/codepoint.js +131 -1
  27. package/src/constraints.d.ts +85 -0
  28. package/src/constraints.js +112 -0
  29. package/src/created.d.ts +2 -0
  30. package/src/created.js +29 -0
  31. package/src/documentLock.d.ts +172 -0
  32. package/src/documentLock.js +384 -0
  33. package/src/entryForms.d.ts +68 -0
  34. package/src/entryForms.js +164 -0
  35. package/src/events.d.ts +60 -0
  36. package/src/events.js +271 -0
  37. package/src/families.d.ts +349 -0
  38. package/src/families.js +396 -0
  39. package/src/http.d.ts +233 -0
  40. package/src/http.js +809 -93
  41. package/src/ids.d.ts +26 -0
  42. package/src/ids.js +96 -0
  43. package/src/index.d.ts +101 -0
  44. package/src/index.js +183 -2105
  45. package/src/metadataOps.d.ts +15 -0
  46. package/src/metadataOps.js +124 -0
  47. package/src/operations.d.ts +36 -0
  48. package/src/operations.js +164 -0
  49. package/src/pagination.d.ts +49 -0
  50. package/src/pagination.js +20 -53
  51. package/src/provenance.d.ts +243 -0
  52. package/src/provenance.js +458 -36
  53. package/src/replayed.d.ts +3 -0
  54. package/src/replayed.js +31 -0
  55. package/src/requester.d.ts +60 -0
  56. package/src/requester.js +74 -0
  57. package/src/roles.d.ts +104 -0
  58. package/src/roles.js +64 -2
  59. package/src/serviceSchema.d.ts +337 -0
  60. package/src/serviceSchema.js +177 -60
  61. package/src/services.d.ts +319 -0
  62. package/src/services.js +742 -58
  63. package/src/sse.d.ts +30 -0
  64. package/src/sse.js +80 -3
  65. package/src/testing.d.ts +128 -0
  66. package/src/testing.js +379 -0
  67. package/src/textEdits.d.ts +59 -0
  68. package/src/textEdits.js +234 -0
  69. package/src/transforms.d.ts +25 -0
  70. package/src/transforms.js +11 -1
  71. package/src/types.d.ts +867 -0
  72. package/src/types.js +663 -0
  73. package/index.d.ts +0 -532
@@ -16,16 +16,26 @@
16
16
  *
17
17
  * {
18
18
  * schemaVersion: 1,
19
- * tasks: ["tokenize"], // controlled vocab; REPLACES tok:/asr: id prefixes
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?, // number
25
- * placeholder?, multiline? } // string
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: 'tokenize',
47
- PARSE: 'parse',
48
- TRANSCRIBE: 'transcribe',
56
+ TOKENIZE: "tokenize",
57
+ PARSE: "parse",
58
+ TRANSCRIBE: "transcribe",
49
59
  /** Create vocab links for unlinked tokens. */
50
- LINK_VOCAB: 'link-vocab',
60
+ LINK_VOCAB: "link-vocab",
51
61
  /** Propose an interlinear analysis (morpheme segmentation + glosses) for words. */
52
- ANALYZE: '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
- * Legacy id-prefix → task map, for services that have not yet migrated to a
57
- * declared `tasks` array. Drop once all services advertise `tasks`.
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`? Prefers the declared `extras.tasks` array; falls
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
- if (Array.isArray(declared) && declared.length) {
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 {Array} services result of client.messages.discoverServices()
182
+ * @param {DiscoveredService[] | undefined} services result of client.messages.discoverServices()
83
183
  * @param {string} task one of TASKS
84
- * @returns {Array}
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?: Array}}} service
93
- * @returns {Array}
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 === 'enum') {
123
- if (param.default != null && opts.includes(param.default)) return param.default;
124
- return opts[0] ?? '';
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 === 'multiselect') {
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) return param.default;
231
+ if (param.default !== undefined && param.default !== null)
232
+ return param.default;
131
233
  switch (param.type) {
132
- case 'number': return typeof param.min === 'number' ? param.min : 0;
133
- case 'boolean': return false;
134
- case 'string':
135
- default: return '';
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 {Array} schema getParamSchema(service)
142
- * @returns {Object} { [key]: defaultValue }
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 {Array} schema getParamSchema(service)
158
- * @param {Object} raw current form values
159
- * @returns {{values: Object, errors: Object}}
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 'number': {
173
- // Blank / nullish counts as "missing" → the param's default (matches the
174
- // Python client, where float('') raises and falls back to the default).
175
- let n;
176
- if (v === '' || v == null || (typeof v === 'string' && v.trim() === '')) {
177
- n = defaultForParam(param);
178
- } else {
179
- n = typeof v === 'number' ? v : Number(v);
180
- if (Number.isNaN(n)) n = defaultForParam(param);
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 'boolean':
188
- v = v === true || v === 'true';
303
+ case "boolean":
304
+ v = v === true || v === "true";
189
305
  break;
190
- case 'enum': {
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 'multiselect': {
311
+ case "multiselect": {
196
312
  const opts = optionValues(param);
197
- const arr = Array.isArray(v) ? v : (v == null || 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 'string':
317
+ case "string":
202
318
  default:
203
- v = v == null ? '' : String(v);
319
+ v = v == null ? "" : String(v);
204
320
  break;
205
321
  }
206
322
 
207
323
  if (param.required) {
208
- const empty = v === '' || v == null || (Array.isArray(v) && v.length === 0);
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
+ };