@larc-iu/plaid-client 0.1.0-alpha.9 → 0.2.0-alpha.0

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 CHANGED
@@ -54,6 +54,10 @@ interface DiscoveredService {
54
54
  serviceName: string;
55
55
  description: string;
56
56
  extras: ServiceExtras;
57
+ /** true while the service holds an open request channel; false for previously-seen offline services. */
58
+ online: boolean;
59
+ /** ISO-8601 stamp of when the service was last seen alive, or null/undefined if never persisted. */
60
+ lastSeenAt?: string | null;
57
61
  }
58
62
 
59
63
  interface ServiceRegistration {
@@ -75,226 +79,250 @@ interface SSEConnection {
75
79
  }
76
80
 
77
81
  interface VocabLinksBundle {
78
- create(vocabItem: string, tokens: any[], metadata?: any): Promise<any>;
79
- setMetadata(id: string, body: any): Promise<any>;
80
- deleteMetadata(id: string): Promise<any>;
81
- patchMetadata(id: string, body: any): Promise<any>;
82
+ create(vocabItem: string, tokens: any[], metadata?: any, auditMessage?: string): Promise<any>;
83
+ bulkCreate(body: any[], auditMessage?: string): Promise<{ ids: string[] }>;
84
+ bulkDelete(body: any[], auditMessage?: string): Promise<void>;
85
+ setMetadata(id: string, body: any, auditMessage?: string): Promise<any>;
86
+ deleteMetadata(id: string, auditMessage?: string): Promise<any>;
87
+ patchMetadata(id: string, body: any, auditMessage?: string): Promise<any>;
82
88
  get(id: string, asOf?: string): Promise<any>;
83
- delete(id: string): Promise<any>;
89
+ delete(id: string, auditMessage?: string): Promise<any>;
84
90
  }
85
91
 
86
92
  interface VocabLayersBundle {
87
93
  get(id: string, includeItems?: boolean, asOf?: string): Promise<any>;
88
- delete(id: string): Promise<any>;
89
- update(id: string, name: string): Promise<any>;
90
- setConfig(id: string, namespace: string, configKey: string, configValue: any): Promise<any>;
91
- deleteConfig(id: string, namespace: string, configKey: string): Promise<any>;
94
+ delete(id: string, auditMessage?: string): Promise<any>;
95
+ update(id: string, name: string, auditMessage?: string): Promise<any>;
96
+ setConfig(id: string, namespace: string, configKey: string, configValue: any, auditMessage?: string): Promise<any>;
97
+ deleteConfig(id: string, namespace: string, configKey: string, auditMessage?: string): Promise<any>;
92
98
  list(asOf?: string): Promise<any[]>;
93
99
  listPage(opts?: { limit?: number; cursor?: string; asOf?: string }): Promise<Page>;
94
100
  iterPages(opts?: { pageSize?: number; asOf?: string }): AsyncGenerator<any[]>;
95
- create(name: string): Promise<any>;
96
- addMaintainer(id: string, userId: string): Promise<any>;
97
- removeMaintainer(id: string, userId: string): Promise<any>;
101
+ create(name: string, auditMessage?: string): Promise<any>;
102
+ addMaintainer(id: string, userId: string, auditMessage?: string): Promise<any>;
103
+ removeMaintainer(id: string, userId: string, auditMessage?: string): Promise<any>;
98
104
  }
99
105
 
100
106
  interface RelationsBundle {
101
- setMetadata(relationId: string, body: any): Promise<any>;
102
- deleteMetadata(relationId: string): Promise<any>;
103
- patchMetadata(relationId: string, body: any): Promise<any>;
104
- setTarget(relationId: string, spanId: string): Promise<any>;
107
+ setMetadata(relationId: string, body: any, auditMessage?: string): Promise<any>;
108
+ deleteMetadata(relationId: string, auditMessage?: string): Promise<any>;
109
+ patchMetadata(relationId: string, body: any, auditMessage?: string): Promise<any>;
110
+ setTarget(relationId: string, spanId: string, auditMessage?: string): Promise<any>;
105
111
  get(relationId: string, asOf?: string): Promise<any>;
106
- delete(relationId: string): Promise<any>;
107
- update(relationId: string, value: any): Promise<any>;
108
- setSource(relationId: string, spanId: string): Promise<any>;
109
- create(layerId: string, sourceId: string, targetId: string, value: any, metadata?: any): Promise<any>;
110
- bulkCreate(body: any[]): Promise<any>;
111
- bulkDelete(body: any[]): Promise<any>;
112
+ delete(relationId: string, auditMessage?: string): Promise<any>;
113
+ update(relationId: string, value: any, auditMessage?: string): Promise<any>;
114
+ setSource(relationId: string, spanId: string, auditMessage?: string): Promise<any>;
115
+ create(layerId: string, sourceId: string, targetId: string, value: any, metadata?: any, auditMessage?: string): Promise<any>;
116
+ bulkCreate(body: any[], auditMessage?: string): Promise<{ ids: string[] }>;
117
+ bulkDelete(body: any[], auditMessage?: string): Promise<void>;
112
118
  }
113
119
 
114
120
  interface SpanLayersBundle {
115
- setConfig(spanLayerId: string, namespace: string, configKey: string, configValue: any): Promise<any>;
116
- deleteConfig(spanLayerId: string, namespace: string, configKey: string): Promise<any>;
121
+ setConfig(spanLayerId: string, namespace: string, configKey: string, configValue: any, auditMessage?: string): Promise<any>;
122
+ deleteConfig(spanLayerId: string, namespace: string, configKey: string, auditMessage?: string): Promise<any>;
117
123
  get(spanLayerId: string, asOf?: string): Promise<any>;
118
- delete(spanLayerId: string): Promise<any>;
119
- update(spanLayerId: string, name: string): Promise<any>;
120
- create(tokenLayerId: string, name: string): Promise<any>;
121
- shift(spanLayerId: string, direction: string): Promise<any>;
124
+ delete(spanLayerId: string, auditMessage?: string): Promise<any>;
125
+ update(spanLayerId: string, name: string, auditMessage?: string): Promise<any>;
126
+ create(tokenLayerId: string, name: string, auditMessage?: string): Promise<any>;
127
+ shift(spanLayerId: string, direction: string, auditMessage?: string): Promise<any>;
122
128
  }
123
129
 
124
130
  interface SpansBundle {
125
- setTokens(spanId: string, tokens: any[]): Promise<any>;
126
- create(spanLayerId: string, tokens: any[], value: any, metadata?: any): Promise<any>;
131
+ setTokens(spanId: string, tokens: any[], auditMessage?: string): Promise<any>;
132
+ create(spanLayerId: string, tokens: any[], value: any, metadata?: any, auditMessage?: string): Promise<any>;
127
133
  get(spanId: string, asOf?: string): Promise<any>;
128
- delete(spanId: string): Promise<any>;
129
- update(spanId: string, value: any): Promise<any>;
130
- bulkCreate(body: any[]): Promise<any>;
131
- bulkDelete(body: any[]): Promise<any>;
132
- setMetadata(spanId: string, body: any): Promise<any>;
133
- deleteMetadata(spanId: string): Promise<any>;
134
- patchMetadata(spanId: string, body: any): Promise<any>;
134
+ delete(spanId: string, auditMessage?: string): Promise<any>;
135
+ update(spanId: string, value: any, auditMessage?: string): Promise<any>;
136
+ bulkCreate(body: any[], auditMessage?: string): Promise<{ ids: string[] }>;
137
+ bulkDelete(body: any[], auditMessage?: string): Promise<void>;
138
+ setMetadata(spanId: string, body: any, auditMessage?: string): Promise<any>;
139
+ deleteMetadata(spanId: string, auditMessage?: string): Promise<any>;
140
+ patchMetadata(spanId: string, body: any, auditMessage?: string): Promise<any>;
135
141
  }
136
142
 
137
143
  interface BatchBundle {
138
- submit(body: any[]): Promise<any>;
144
+ submit(body: any[], auditMessage?: string): Promise<any>;
139
145
  }
140
146
 
141
147
  interface TextsBundle {
142
- setMetadata(textId: string, body: any): Promise<any>;
143
- deleteMetadata(textId: string): Promise<any>;
144
- patchMetadata(textId: string, body: any): Promise<any>;
145
- create(textLayerId: string, documentId: string, body: string, metadata?: any): Promise<any>;
148
+ setMetadata(textId: string, body: any, auditMessage?: string): Promise<any>;
149
+ deleteMetadata(textId: string, auditMessage?: string): Promise<any>;
150
+ patchMetadata(textId: string, body: any, auditMessage?: string): Promise<any>;
151
+ create(textLayerId: string, documentId: string, body: string, metadata?: any, auditMessage?: string): Promise<any>;
146
152
  get(textId: string, asOf?: string): Promise<any>;
147
- delete(textId: string): Promise<any>;
148
- update(textId: string, body: any): Promise<any>;
153
+ delete(textId: string, auditMessage?: string): Promise<any>;
154
+ update(textId: string, body: any, auditMessage?: string): Promise<any>;
149
155
  }
150
156
 
151
157
  interface UsersBundle {
152
158
  list(asOf?: string): Promise<any[]>;
153
159
  listPage(opts?: { limit?: number; cursor?: string; asOf?: string }): Promise<Page>;
154
160
  iterPages(opts?: { pageSize?: number; asOf?: string }): AsyncGenerator<any[]>;
155
- create(username: string, password: string, isAdmin: boolean): Promise<any>;
161
+ create(username: string, password: string, isAdmin: boolean, auditMessage?: string): Promise<any>;
156
162
  audit(userId: string, startTime?: string, endTime?: string, asOf?: string): Promise<any[]>;
157
163
  get(id: string, asOf?: string): Promise<any>;
158
- delete(id: string): Promise<any>;
159
- update(id: string, password?: string, username?: string, isAdmin?: boolean): Promise<any>;
164
+ delete(id: string, auditMessage?: string): Promise<any>;
165
+ activate(id: string, auditMessage?: string): Promise<any>;
166
+ update(id: string, password?: string, username?: string, isAdmin?: boolean, auditMessage?: string): Promise<any>;
160
167
  }
161
168
 
162
169
  interface ApiTokensBundle {
163
170
  list(userId: string): Promise<any[]>;
164
171
  listPage(userId: string, opts?: { limit?: number; cursor?: string }): Promise<Page>;
165
172
  iterPages(userId: string, opts?: { pageSize?: number }): AsyncGenerator<any[]>;
166
- create(userId: string, name: string): Promise<{ id: string; name: string; token: string }>;
167
- revoke(userId: string, tokenId: string): Promise<any>;
173
+ create(userId: string, name: string, auditMessage?: string): Promise<{ id: string; name: string; token: string }>;
174
+ revoke(userId: string, tokenId: string, auditMessage?: string): Promise<any>;
168
175
  }
169
176
 
170
177
  interface TokenLayersBundle {
171
- shift(tokenLayerId: string, direction: string): Promise<any>;
172
- create(textLayerId: string, name: string, overlapMode?: string, parentTokenLayerId?: string): Promise<any>;
173
- setConfig(tokenLayerId: string, namespace: string, configKey: string, configValue: any): Promise<any>;
174
- deleteConfig(tokenLayerId: string, namespace: string, configKey: string): Promise<any>;
178
+ shift(tokenLayerId: string, direction: string, auditMessage?: string): Promise<any>;
179
+ create(textLayerId: string, name: string, overlapMode?: string, parentTokenLayerId?: string, auditMessage?: string): Promise<any>;
180
+ setConfig(tokenLayerId: string, namespace: string, configKey: string, configValue: any, auditMessage?: string): Promise<any>;
181
+ deleteConfig(tokenLayerId: string, namespace: string, configKey: string, auditMessage?: string): Promise<any>;
175
182
  get(tokenLayerId: string, asOf?: string): Promise<any>;
176
- delete(tokenLayerId: string): Promise<any>;
177
- update(tokenLayerId: string, name: string): Promise<any>;
183
+ delete(tokenLayerId: string, auditMessage?: string): Promise<any>;
184
+ update(tokenLayerId: string, name: string, auditMessage?: string): Promise<any>;
178
185
  }
179
186
 
180
187
  interface DocumentsBundle {
181
188
  checkLock(documentId: string, asOf?: string): Promise<any>;
182
- acquireLock(documentId: string): Promise<any>;
183
- releaseLock(documentId: string): Promise<any>;
189
+ acquireLock(documentId: string, auditMessage?: string): Promise<any>;
190
+ releaseLock(documentId: string, auditMessage?: string): Promise<any>;
184
191
  getMedia(documentId: string, asOf?: string): Promise<ArrayBuffer>;
185
- uploadMedia(documentId: string, file: File): Promise<any>;
186
- deleteMedia(documentId: string): Promise<any>;
187
- setMetadata(documentId: string, body: any): Promise<any>;
188
- deleteMetadata(documentId: string): Promise<any>;
189
- patchMetadata(documentId: string, body: any): Promise<any>;
192
+ uploadMedia(documentId: string, file: File, auditMessage?: string): Promise<any>;
193
+ deleteMedia(documentId: string, auditMessage?: string): Promise<any>;
194
+ setMetadata(documentId: string, body: any, auditMessage?: string): Promise<any>;
195
+ deleteMetadata(documentId: string, auditMessage?: string): Promise<any>;
196
+ patchMetadata(documentId: string, body: any, auditMessage?: string): Promise<any>;
190
197
  audit(documentId: string, startTime?: string, endTime?: string, asOf?: string): Promise<any[]>;
191
198
  get(documentId: string, includeBody?: boolean, asOf?: string): Promise<any>;
192
- delete(documentId: string): Promise<any>;
193
- update(documentId: string, name: string): Promise<any>;
194
- create(projectId: string, name: string, metadata?: any): Promise<any>;
199
+ delete(documentId: string, auditMessage?: string): Promise<any>;
200
+ update(documentId: string, name: string, auditMessage?: string): Promise<any>;
201
+ create(projectId: string, name: string, metadata?: any, auditMessage?: string): Promise<any>;
195
202
  }
196
203
 
197
204
  interface MessagesBundle {
198
- sendMessage(projectId: string, data: any): Promise<any>;
205
+ sendMessage(projectId: string, data: any, auditMessage?: string): Promise<any>;
199
206
  listen(projectId: string, onEvent: (eventType: string, data: any) => void | boolean, path?: string): SSEConnection;
200
- /** Discover the services currently connected to a project. `timeout` is ignored (kept for back-compat). */
201
- discoverServices(projectId: string, timeout?: number): Promise<DiscoveredService[]>;
207
+ /** Discover the services seen on a project: online ones plus previously-seen offline ones (check `online`). */
208
+ discoverServices(projectId: string): Promise<DiscoveredService[]>;
209
+ /** Forget a previously-seen (offline) service. Maintainer-only; 409 if currently connected. */
210
+ discardService(projectId: string, serviceId: string): Promise<void>;
202
211
  serve(projectId: string, serviceInfo: ServiceInfo, onServiceRequest: (data: any, responseHelper: ResponseHelper) => void, extras?: any): ServiceRegistration;
203
212
  /** Submit work to a service; streams progress to `onProgress`, resolves with the result. */
204
213
  requestService(projectId: string, serviceId: string, data: any, timeout?: number, onProgress?: (progress: any) => void): Promise<any>;
205
214
  }
206
215
 
207
216
  interface ProjectsBundle {
208
- addWriter(id: string, userId: string): Promise<any>;
209
- removeWriter(id: string, userId: string): Promise<any>;
210
- addReader(id: string, userId: string): Promise<any>;
211
- removeReader(id: string, userId: string): Promise<any>;
212
- setConfig(id: string, namespace: string, configKey: string, configValue: any): Promise<any>;
213
- deleteConfig(id: string, namespace: string, configKey: string): Promise<any>;
214
- addMaintainer(id: string, userId: string): Promise<any>;
215
- removeMaintainer(id: string, userId: string): Promise<any>;
217
+ addWriter(id: string, userId: string, auditMessage?: string): Promise<any>;
218
+ removeWriter(id: string, userId: string, auditMessage?: string): Promise<any>;
219
+ addReader(id: string, userId: string, auditMessage?: string): Promise<any>;
220
+ removeReader(id: string, userId: string, auditMessage?: string): Promise<any>;
221
+ setConfig(id: string, namespace: string, configKey: string, configValue: any, auditMessage?: string): Promise<any>;
222
+ deleteConfig(id: string, namespace: string, configKey: string, auditMessage?: string): Promise<any>;
223
+ addMaintainer(id: string, userId: string, auditMessage?: string): Promise<any>;
224
+ removeMaintainer(id: string, userId: string, auditMessage?: string): Promise<any>;
216
225
  audit(projectId: string, startTime?: string, endTime?: string, asOf?: string): Promise<any[]>;
217
- linkVocab(id: string, vocabId: string): Promise<any>;
218
- unlinkVocab(id: string, vocabId: string): Promise<any>;
226
+ linkVocab(id: string, vocabId: string, auditMessage?: string): Promise<any>;
227
+ unlinkVocab(id: string, vocabId: string, auditMessage?: string): Promise<any>;
219
228
  get(id: string, asOf?: string): Promise<any>;
220
229
  listDocuments(id: string): Promise<any[]>;
221
230
  listDocumentsPage(id: string, opts?: { limit?: number; cursor?: string }): Promise<Page>;
222
231
  iterDocuments(id: string, opts?: { pageSize?: number }): AsyncGenerator<any[]>;
223
- delete(id: string): Promise<any>;
224
- update(id: string, name: string): Promise<any>;
232
+ delete(id: string, auditMessage?: string): Promise<any>;
233
+ update(id: string, name: string, auditMessage?: string): Promise<any>;
225
234
  list(asOf?: string): Promise<any[]>;
226
235
  listPage(opts?: { limit?: number; cursor?: string; asOf?: string }): Promise<Page>;
227
236
  iterPages(opts?: { pageSize?: number; asOf?: string }): AsyncGenerator<any[]>;
228
- create(name: string): Promise<any>;
237
+ create(name: string, auditMessage?: string): Promise<any>;
229
238
  }
230
239
 
231
240
  interface TextLayersBundle {
232
- setConfig(textLayerId: string, namespace: string, configKey: string, configValue: any): Promise<any>;
233
- deleteConfig(textLayerId: string, namespace: string, configKey: string): Promise<any>;
241
+ setConfig(textLayerId: string, namespace: string, configKey: string, configValue: any, auditMessage?: string): Promise<any>;
242
+ deleteConfig(textLayerId: string, namespace: string, configKey: string, auditMessage?: string): Promise<any>;
234
243
  get(textLayerId: string, asOf?: string): Promise<any>;
235
- delete(textLayerId: string): Promise<any>;
236
- update(textLayerId: string, name: string): Promise<any>;
237
- shift(textLayerId: string, direction: string): Promise<any>;
238
- create(projectId: string, name: string): Promise<any>;
244
+ delete(textLayerId: string, auditMessage?: string): Promise<any>;
245
+ update(textLayerId: string, name: string, auditMessage?: string): Promise<any>;
246
+ shift(textLayerId: string, direction: string, auditMessage?: string): Promise<any>;
247
+ create(projectId: string, name: string, auditMessage?: string): Promise<any>;
239
248
  }
240
249
 
241
250
  interface VocabItemsBundle {
242
- setMetadata(id: string, body: any): Promise<any>;
243
- deleteMetadata(id: string): Promise<any>;
244
- patchMetadata(id: string, body: any): Promise<any>;
245
- create(vocabLayerId: string, form: string, metadata?: any): Promise<any>;
251
+ setMetadata(id: string, body: any, auditMessage?: string): Promise<any>;
252
+ deleteMetadata(id: string, auditMessage?: string): Promise<any>;
253
+ patchMetadata(id: string, body: any, auditMessage?: string): Promise<any>;
254
+ create(vocabLayerId: string, form: string, metadata?: any, auditMessage?: string): Promise<any>;
255
+ bulkCreate(body: any[], auditMessage?: string): Promise<{ ids: string[] }>;
256
+ bulkDelete(body: any[], auditMessage?: string): Promise<void>;
246
257
  get(id: string, asOf?: string): Promise<any>;
247
- delete(id: string): Promise<any>;
248
- update(id: string, form: string): Promise<any>;
258
+ delete(id: string, auditMessage?: string): Promise<any>;
259
+ update(id: string, form: string, auditMessage?: string): Promise<any>;
249
260
  }
250
261
 
251
262
  interface RelationLayersBundle {
252
- shift(relationLayerId: string, direction: string): Promise<any>;
253
- create(spanLayerId: string, name: string): Promise<any>;
254
- setConfig(relationLayerId: string, namespace: string, configKey: string, configValue: any): Promise<any>;
255
- deleteConfig(relationLayerId: string, namespace: string, configKey: string): Promise<any>;
263
+ shift(relationLayerId: string, direction: string, auditMessage?: string): Promise<any>;
264
+ create(spanLayerId: string, name: string, auditMessage?: string): Promise<any>;
265
+ setConfig(relationLayerId: string, namespace: string, configKey: string, configValue: any, auditMessage?: string): Promise<any>;
266
+ deleteConfig(relationLayerId: string, namespace: string, configKey: string, auditMessage?: string): Promise<any>;
256
267
  get(relationLayerId: string, asOf?: string): Promise<any>;
257
- delete(relationLayerId: string): Promise<any>;
258
- update(relationLayerId: string, name: string): Promise<any>;
268
+ delete(relationLayerId: string, auditMessage?: string): Promise<any>;
269
+ update(relationLayerId: string, name: string, auditMessage?: string): Promise<any>;
259
270
  }
260
271
 
261
272
  interface TokensBundle {
262
- create(tokenLayerId: string, text: string, begin: number, end: number, precedence?: number | null, metadata?: any): Promise<any>;
273
+ create(tokenLayerId: string, text: string, begin: number, end: number, precedence?: number | null, metadata?: any, auditMessage?: string): Promise<any>;
263
274
  get(tokenId: string, asOf?: string): Promise<any>;
264
- delete(tokenId: string): Promise<any>;
265
- update(tokenId: string, begin?: number, end?: number, precedence?: number | null): Promise<any>;
266
- bulkCreate(body: any[]): Promise<any>;
267
- bulkDelete(body: any[]): Promise<any>;
268
- split(tokenId: string, position: number): Promise<any>;
269
- merge(tokenId: string, otherTokenId: string): Promise<any>;
270
- shift(tokenId: string, begin?: number, end?: number): Promise<any>;
271
- setMetadata(tokenId: string, body: any): Promise<any>;
272
- deleteMetadata(tokenId: string): Promise<any>;
273
- patchMetadata(tokenId: string, body: any): Promise<any>;
275
+ delete(tokenId: string, auditMessage?: string): Promise<any>;
276
+ update(tokenId: string, begin?: number, end?: number, precedence?: number | null, auditMessage?: string): Promise<any>;
277
+ bulkCreate(body: any[], auditMessage?: string): Promise<{ ids: string[] }>;
278
+ bulkDelete(body: any[], auditMessage?: string): Promise<void>;
279
+ split(tokenId: string, position: number, auditMessage?: string): Promise<any>;
280
+ merge(tokenId: string, otherTokenId: string, auditMessage?: string): Promise<any>;
281
+ shift(tokenId: string, begin?: number, end?: number, auditMessage?: string): Promise<any>;
282
+ setMetadata(tokenId: string, body: any, auditMessage?: string): Promise<any>;
283
+ deleteMetadata(tokenId: string, auditMessage?: string): Promise<any>;
284
+ patchMetadata(tokenId: string, body: any, auditMessage?: string): Promise<any>;
274
285
  }
275
286
 
276
287
  interface PlaidClientOptions {
277
288
  /** Per-request timeout in ms (default 30000; 0 or null disables it). */
278
289
  timeout?: number | null;
290
+ /**
291
+ * Fired once when a request returns HTTP 401 (missing/expired/invalid token).
292
+ * Use it to discard the stored token and route back to login. 403 (forbidden)
293
+ * does NOT trigger it.
294
+ */
295
+ onAuthError?: ((error: Error) => void) | null;
279
296
  }
280
297
 
281
298
  export declare class PlaidClient {
282
299
  constructor(baseUrl: string, token: string, options?: PlaidClientOptions);
283
300
  static login(baseUrl: string, userId: string, password: string, options?: PlaidClientOptions): Promise<PlaidClient>;
284
301
  timeout: number | null;
302
+ /** Fired once on HTTP 401 (see PlaidClientOptions.onAuthError). */
303
+ onAuthError: ((error: Error) => void) | null;
285
304
 
286
305
  // Batch control methods
287
306
  beginBatch(): void;
288
307
  submitBatch(): Promise<any[]>;
289
308
  abortBatch(): void;
290
309
  isBatchMode(): boolean;
310
+ /** Run `fn` with a batch open, then submit atomically (or abort if `fn` throws). Resolves to the results array. */
311
+ batched(fn: () => void | Promise<void>): Promise<any[]>;
291
312
 
292
313
  // Strict mode methods
293
314
  enterStrictMode(documentId: string): void;
294
315
  exitStrictMode(): void;
295
316
 
317
+ // Custom audit-log message (overrides the auto-generated description; may
318
+ // template the endpoint's path/query/body params with {param} placeholders).
319
+ auditMessage: string | null;
320
+ setAuditMessage(message: string): this;
321
+ clearAuditMessage(): this;
322
+ withAuditMessage<T>(message: string, fn: () => Promise<T> | T): Promise<T>;
323
+
296
324
  // Query
297
- query(body: any): Promise<any>;
325
+ query(body: any, auditMessage?: string): Promise<any>;
298
326
 
299
327
  vocabLinks: VocabLinksBundle;
300
328
  vocabLayers: VocabLayersBundle;
@@ -377,3 +405,46 @@ export function getServiceSummary(service: DiscoveredService): string;
377
405
  export function buildDefaultValues(schema: ServiceParam[]): Record<string, any>;
378
406
  /** Coerce/validate raw form values against the schema. */
379
407
  export function coerceParamValues(schema: ServiceParam[], raw: Record<string, any>): { values: Record<string, any>; errors: Record<string, string> };
408
+
409
+ // --- Provenance ---------------------------------------------------------------
410
+ // Cross-app convention for machine-provided vs human-labeled information,
411
+ // expressed as flat metadata keys on annotation entities. Absent keys = human;
412
+ // { prov: 'inferred', provSource } = machine-made, unverified;
413
+ // + { provConfirmed: true } = machine-made, human-verified. Machine writers may
414
+ // replace unverified machine material but must never touch human/verified
415
+ // material without an explicit overwrite opt-in; any human edit verifies.
416
+ // See the manual, "Provenance".
417
+ type ProvState = 'human' | 'machine' | 'verified';
418
+ export const PROV: {
419
+ readonly key: 'prov';
420
+ readonly sourceKey: 'provSource';
421
+ readonly confirmedKey: 'provConfirmed';
422
+ readonly probKey: 'provProb';
423
+ readonly detailKey: 'provDetail';
424
+ readonly INFERRED: 'inferred';
425
+ };
426
+ export const PROV_STATES: {
427
+ readonly HUMAN: 'human';
428
+ readonly MACHINE: 'machine';
429
+ readonly VERIFIED: 'verified';
430
+ };
431
+ /** Optional prediction extras: prob = a probability in [0,1] for the chosen value
432
+ * (flat + queryable; omit unless it honestly is one); detail = an open map of
433
+ * producer extras (top-k alternatives, model version, raw scores; keep it small).
434
+ * Both describe the ORIGINAL prediction — check provConfirmed before presenting
435
+ * provProb as confidence in the current value. */
436
+ interface ProvExtras { prob?: number; detail?: Record<string, any> }
437
+ /** The metadata fragment a machine writer merges into everything it creates. */
438
+ export function stampInferred(source: string, extras?: ProvExtras):
439
+ { prov: 'inferred'; provSource: string; provProb?: number; provDetail?: Record<string, any> };
440
+ /** stampInferred + provConfirmed — for machine material born verified (e.g. imports with upstream approval). */
441
+ export function confirmedInferred(source: string, extras?: ProvExtras):
442
+ { prov: 'inferred'; provSource: string; provConfirmed: true; provProb?: number; provDetail?: Record<string, any> };
443
+ /** Classify an entity's metadata into one of the three provenance states. */
444
+ export function provState(metadata: object | null | undefined): ProvState;
445
+ /** Whether a machine writer must leave this entity alone (human or verified). */
446
+ export function isProtected(metadata: object | null | undefined): boolean;
447
+ /** The fragment a HUMAN edit should merge in: { provConfirmed: true } iff machine-unverified, else null. */
448
+ export function verifyOnEdit(metadata: object | null | undefined): { provConfirmed: true } | null;
449
+ /** Canonical provSource for a service: 'service:<serviceId>'. */
450
+ export function serviceSource(serviceId: string): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@larc-iu/plaid-client",
3
- "version": "0.1.0-alpha.9",
3
+ "version": "0.2.0-alpha.0",
4
4
  "description": "JavaScript client for the Plaid annotation API",
5
5
  "type": "module",
6
6
  "repository": {
package/src/http.js CHANGED
@@ -94,6 +94,9 @@ export function timeoutSignal(timeout) {
94
94
  * skipResponseTransform - Return raw parsed JSON (no transformResponse)
95
95
  * noAuth - Skip Authorization header
96
96
  * binaryResponse - Return arrayBuffer instead of JSON/text
97
+ * timeout - Per-request timeout in ms overriding client.timeout
98
+ * for this call (0/null disables). Used for known-long
99
+ * ops like project delete.
97
100
  */
98
101
  export async function makeRequest(client, method, path, options = {}) {
99
102
  const {
@@ -105,6 +108,8 @@ export async function makeRequest(client, method, path, options = {}) {
105
108
  skipResponseTransform,
106
109
  noAuth,
107
110
  binaryResponse,
111
+ auditMessage,
112
+ timeout,
108
113
  } = options;
109
114
 
110
115
  // Build URL
@@ -135,16 +140,35 @@ export async function makeRequest(client, method, path, options = {}) {
135
140
  requestBody = transformRequest(body);
136
141
  }
137
142
 
138
- // Strict mode: append document-version for non-GET requests
139
- if (client.strictModeDocumentId && method !== 'GET') {
143
+ // Strict mode: append document-version for non-GET requests.
144
+ // Inside a batch, stamp ONLY the first write: batches run atomically
145
+ // server-side, so a version check on the first op gives whole-batch OCC
146
+ // semantics, while stamping every op would 409 the second op against the
147
+ // version bump the first op itself caused (every queued op captures the
148
+ // same pre-batch version).
149
+ if (client.strictModeDocumentId && method !== 'GET'
150
+ && !(client.isBatching && client.batchVersionStamped)) {
140
151
  const docId = client.strictModeDocumentId;
141
152
  if (client.documentVersions[docId]) {
142
153
  const docVersion = client.documentVersions[docId];
143
154
  const separator = url.includes('?') ? '&' : '?';
144
155
  url += `${separator}document-version=${encodeURIComponent(docVersion)}`;
156
+ if (client.isBatching) client.batchVersionStamped = true;
145
157
  }
146
158
  }
147
159
 
160
+ // Custom audit-log message (overrides the auto-generated description).
161
+ // Per-call `auditMessage` option wins, else the ambient `client.auditMessage`
162
+ // (see setAuditMessage/withAuditMessage). Unlike document-version this has no
163
+ // OCC self-conflict, so it is stamped on EVERY queued batch op, not just the
164
+ // first. The server templates `{param}` placeholders against the endpoint's
165
+ // own path/query/body params.
166
+ const effectiveAuditMessage = auditMessage !== undefined ? auditMessage : client.auditMessage;
167
+ if (effectiveAuditMessage && method !== 'GET') {
168
+ const separator = url.includes('?') ? '&' : '?';
169
+ url += `${separator}audit-message=${encodeURIComponent(effectiveAuditMessage)}`;
170
+ }
171
+
148
172
  // Batch mode
149
173
  if (client.isBatching) {
150
174
  if (noBatch) {
@@ -174,14 +198,22 @@ export async function makeRequest(client, method, path, options = {}) {
174
198
  if (requestBody !== undefined) {
175
199
  fetchOptions.body = formData ? requestBody : JSON.stringify(requestBody);
176
200
  }
177
- const signal = timeoutSignal(client.timeout);
201
+ const signal = timeoutSignal(timeout !== undefined ? timeout : client.timeout);
178
202
  if (signal) fetchOptions.signal = signal;
179
203
 
180
204
  try {
181
205
  const response = await fetch(url, fetchOptions);
182
206
 
183
207
  if (!response.ok) {
184
- throw makeHttpError(response, await parseErrorBody(response), url, method);
208
+ const error = makeHttpError(response, await parseErrorBody(response), url, method);
209
+ // 401 means the token is missing/expired/invalid. Fire the app's auth-error
210
+ // handler once (it discards the token and routes back to login). 403
211
+ // (forbidden — authenticated but not permitted) deliberately does NOT.
212
+ if (response.status === 401 && typeof client.onAuthError === 'function' && !client._authErrorFired) {
213
+ client._authErrorFired = true;
214
+ try { client.onAuthError(error); } catch (_) { /* handler must not mask the original error */ }
215
+ }
216
+ throw error;
185
217
  }
186
218
 
187
219
  // Binary response (getMedia)