@larc-iu/plaid-client 0.1.0-alpha.8 → 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/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)