@credithub/harlan-components 1.129.0 → 1.131.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.
@@ -3,13 +3,19 @@ import { Client } from '@credithub/webservice';
3
3
  import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
4
4
  import Section from './section';
5
5
  import { RequestStatus } from './requestContextTypes';
6
+ import { classifyRequestError, isErrorWithPushFlag } from '../utils/classifyRequestError';
6
7
  export * from './requestContextTypes';
7
8
  export var WebService = createContext(new Client.WebService());
9
+ /** Marcador enviado em todas as consultas do shell Harlan (`harlan` como boolean). */
10
+ export var HARLAN_WS_MARKER = { harlan: true };
8
11
  export var RequestDefaultsContext = createContext({});
9
12
  export var WebServiceProvider = function (_a) {
10
13
  var credential = _a.credential, defaultData = _a.defaultData, defaultUrlData = _a.defaultUrlData, webserviceOptions = _a.webserviceOptions, children = _a.children;
11
14
  return (React.createElement(WebService.Provider, { value: new Client.WebService(credential, {}, 5, webserviceOptions !== null && webserviceOptions !== void 0 ? webserviceOptions : {}) },
12
- React.createElement(RequestDefaultsContext.Provider, { value: { data: defaultData, urlData: defaultUrlData } }, children)));
15
+ React.createElement(RequestDefaultsContext.Provider, { value: {
16
+ data: __assign(__assign({}, (defaultData !== null && defaultData !== void 0 ? defaultData : {})), HARLAN_WS_MARKER),
17
+ urlData: defaultUrlData
18
+ } }, children)));
13
19
  };
14
20
  var isDocument = function (value) {
15
21
  return typeof Document !== 'undefined' && value instanceof Document;
@@ -77,12 +83,20 @@ var extractExceptionFromDocument = function (document) {
77
83
  }
78
84
  return null;
79
85
  };
80
- var isErrorWithPush = function (error) {
81
- if (error && typeof error === 'object') {
82
- return (error === null || error === void 0 ? void 0 : error.push) === true;
83
- }
84
- return false;
85
- };
86
+ function pushNoticeFromError(requestError) {
87
+ var _a;
88
+ var err = requestError;
89
+ var trimmed = (_a = err === null || err === void 0 ? void 0 : err.message) === null || _a === void 0 ? void 0 : _a.trim();
90
+ var code = typeof (err === null || err === void 0 ? void 0 : err.code) === 'number' && !Number.isNaN(err.code)
91
+ ? err.code
92
+ : undefined;
93
+ var notice = {};
94
+ if (trimmed)
95
+ notice.message = trimmed;
96
+ if (code != null)
97
+ notice.code = code;
98
+ return notice;
99
+ }
86
100
  export function CustomProvider(Provider, query) {
87
101
  return function (_a) {
88
102
  var children = _a.children, data = _a.data, urlData = _a.urlData, _b = _a.depends, depends = _b === void 0 ? [] : _b;
@@ -96,6 +110,7 @@ export function CustomProvider(Provider, query) {
96
110
  var _j = useState(false), showLoadingBar = _j[0], setShowLoadingBar = _j[1];
97
111
  var _k = useState(false), shouldRetry = _k[0], setShouldRetry = _k[1];
98
112
  var _l = useState(false), requestCompleted = _l[0], setRequestCompleted = _l[1];
113
+ var _m = useState(null), pushNotice = _m[0], setPushNotice = _m[1];
99
114
  var dependentRequestsCompleted = useMemo(function () {
100
115
  return depends === null || depends === void 0 ? void 0 : depends.every(function (request) {
101
116
  return (request === null || request === void 0 ? void 0 : request.type) === RequestStatus.Success ||
@@ -121,6 +136,7 @@ export function CustomProvider(Provider, query) {
121
136
  return;
122
137
  setLoading(true);
123
138
  setError(null);
139
+ setPushNotice(null);
124
140
  setShowLoadingBar(true);
125
141
  simulateProgress();
126
142
  var requestId = Date.now();
@@ -137,17 +153,18 @@ export function CustomProvider(Provider, query) {
137
153
  .then(function (parsedResponse) {
138
154
  setResponse(parsedResponse);
139
155
  setError(null);
156
+ setPushNotice(null);
140
157
  setRequestCompleted(true);
141
158
  })
142
159
  .catch(function (requestError) {
143
- if (requestError.name !== 'AbortError') {
144
- // Se o erro tem push === true, não tratar como erro (caso esperado)
145
- if (isErrorWithPush(requestError)) {
146
- // Tratar como sucesso (sem erro)
160
+ if (classifyRequestError(requestError) !== 'aborted') {
161
+ if (isErrorWithPushFlag(requestError)) {
147
162
  setError(null);
163
+ setPushNotice(pushNoticeFromError(requestError));
148
164
  setRequestCompleted(true);
149
165
  }
150
166
  else {
167
+ setPushNotice(null);
151
168
  setError(requestError instanceof Error
152
169
  ? requestError
153
170
  : new Error(String(requestError)));
@@ -193,7 +210,8 @@ export function CustomProvider(Provider, query) {
193
210
  !loading &&
194
211
  requestsMap.size === 0 &&
195
212
  !requestCompleted &&
196
- dependentRequestsCompleted) {
213
+ dependentRequestsCompleted &&
214
+ !shouldRetry) {
197
215
  fetchData();
198
216
  }
199
217
  }, [
@@ -202,7 +220,8 @@ export function CustomProvider(Provider, query) {
202
220
  loading,
203
221
  requestsMap,
204
222
  requestCompleted,
205
- dependentRequestsCompleted
223
+ dependentRequestsCompleted,
224
+ shouldRetry
206
225
  ]);
207
226
  useEffect(function () {
208
227
  if (shouldRetry) {
@@ -214,6 +233,10 @@ export function CustomProvider(Provider, query) {
214
233
  var contextValue = useMemo(function () {
215
234
  var activeRequestsCount = requestsMap.size;
216
235
  var warningMessage = extractWarningFromDocument(response === null || response === void 0 ? void 0 : response.document);
236
+ var terminalPushSuccess = requestCompleted &&
237
+ !error &&
238
+ !response &&
239
+ pushNotice != null;
217
240
  return {
218
241
  type: error
219
242
  ? RequestStatus.Error
@@ -221,7 +244,9 @@ export function CustomProvider(Provider, query) {
221
244
  ? RequestStatus.Success
222
245
  : loading
223
246
  ? RequestStatus.Loading
224
- : RequestStatus.Empty,
247
+ : terminalPushSuccess
248
+ ? RequestStatus.Success
249
+ : RequestStatus.Empty,
225
250
  error: error,
226
251
  data: mergedData,
227
252
  urlData: mergedUrlData,
@@ -235,7 +260,8 @@ export function CustomProvider(Provider, query) {
235
260
  progress: progress,
236
261
  activeRequests: activeRequestsCount,
237
262
  showLoadingBar: showLoadingBar,
238
- warningMessage: warningMessage
263
+ warningMessage: warningMessage,
264
+ pushNotice: pushNotice
239
265
  };
240
266
  }, [
241
267
  error,
@@ -245,7 +271,9 @@ export function CustomProvider(Provider, query) {
245
271
  loading,
246
272
  progress,
247
273
  requestsMap,
248
- showLoadingBar
274
+ showLoadingBar,
275
+ pushNotice,
276
+ requestCompleted
249
277
  ]);
250
278
  return (React.createElement(Provider.Provider, { value: contextValue }, children));
251
279
  };
@@ -256,9 +284,10 @@ export function useQuery(query, data, enabled) {
256
284
  var _a = useContext(RequestDefaultsContext), defaultData = _a.data, defaultUrlData = _a.urlData;
257
285
  var _b = useState(null), response = _b[0], setResponse = _b[1];
258
286
  var _c = useState(null), error = _c[0], setError = _c[1];
259
- var _d = useState(false), isLoading = _d[0], setIsLoading = _d[1];
260
- var _e = useState(true), shouldFetch = _e[0], setShouldFetch = _e[1];
261
- var _f = useState(0), loadingProgress = _f[0], setProgress = _f[1];
287
+ var _d = useState(null), pushNotice = _d[0], setPushNotice = _d[1];
288
+ var _e = useState(false), isLoading = _e[0], setIsLoading = _e[1];
289
+ var _f = useState(true), shouldFetch = _f[0], setShouldFetch = _f[1];
290
+ var _g = useState(0), loadingProgress = _g[0], setProgress = _g[1];
262
291
  var memoizedData = useMemo(function () { return data; }, [JSON.stringify(data)]);
263
292
  var mergedData = useMemo(function () { return (__assign(__assign({}, (defaultData !== null && defaultData !== void 0 ? defaultData : {})), (memoizedData !== null && memoizedData !== void 0 ? memoizedData : {}))); }, [defaultData, memoizedData]);
264
293
  var simulateProgress = useCallback(function () {
@@ -277,6 +306,7 @@ export function useQuery(query, data, enabled) {
277
306
  return;
278
307
  setIsLoading(true);
279
308
  simulateProgress();
309
+ setPushNotice(null);
280
310
  var abortController = new AbortController();
281
311
  client
282
312
  .request(query, mergedData, defaultUrlData, abortController.signal)
@@ -289,17 +319,18 @@ export function useQuery(query, data, enabled) {
289
319
  .then(function (parsedResponse) {
290
320
  setResponse(parsedResponse);
291
321
  setError(null);
322
+ setPushNotice(null);
292
323
  setProgress(100);
293
324
  })
294
325
  .catch(function (requestError) {
295
- if (requestError.name !== 'AbortError') {
296
- // Se o erro tem push === true, não tratar como erro (caso esperado)
297
- if (isErrorWithPush(requestError)) {
298
- // Tratar como sucesso (sem erro)
326
+ if (classifyRequestError(requestError) !== 'aborted') {
327
+ if (isErrorWithPushFlag(requestError)) {
299
328
  setError(null);
329
+ setPushNotice(pushNoticeFromError(requestError));
300
330
  setProgress(100);
301
331
  }
302
332
  else {
333
+ setPushNotice(null);
303
334
  setError(requestError instanceof Error
304
335
  ? requestError
305
336
  : new Error(String(requestError)));
@@ -340,6 +371,7 @@ export function useQuery(query, data, enabled) {
340
371
  return {
341
372
  response: response,
342
373
  error: error,
374
+ pushNotice: pushNotice,
343
375
  isLoading: isLoading,
344
376
  loadingProgress: loadingProgress,
345
377
  refetch: refetch
@@ -365,10 +397,8 @@ export function useMutation(query, data) {
365
397
  })
366
398
  .then(function (document) { return setResponse(document); })
367
399
  .catch(function (requestError) {
368
- if (requestError.name !== 'AbortError') {
369
- // Se o erro tem push === true, não tratar como erro (caso esperado)
370
- if (isErrorWithPush(requestError)) {
371
- // Tratar como sucesso (sem erro)
400
+ if (classifyRequestError(requestError) !== 'aborted') {
401
+ if (isErrorWithPushFlag(requestError)) {
372
402
  setError(null);
373
403
  }
374
404
  else {
@@ -406,10 +436,8 @@ export function useFetch(query) {
406
436
  return document;
407
437
  })
408
438
  .catch(function (requestError) {
409
- if (requestError.name !== 'AbortError') {
410
- // Se o erro tem push === true, não tratar como erro (caso esperado)
411
- if (isErrorWithPush(requestError)) {
412
- // Tratar como sucesso (sem erro)
439
+ if (classifyRequestError(requestError) !== 'aborted') {
440
+ if (isErrorWithPushFlag(requestError)) {
413
441
  setError(null);
414
442
  }
415
443
  else {
@@ -442,7 +470,8 @@ export function query(query) {
442
470
  progress: 0,
443
471
  activeRequests: 0,
444
472
  showLoadingBar: false,
445
- warningMessage: null
473
+ warningMessage: null,
474
+ pushNotice: null
446
475
  });
447
476
  return Object.assign(RequestContext, {
448
477
  Request: CustomProvider(RequestContext, query)
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare function ManualPushSectionPreview(): React.JSX.Element;
@@ -0,0 +1,42 @@
1
+ import React, { useContext } from 'react';
2
+ import { ThemeProvider } from 'styled-components';
3
+ import GlobalStyle from '../styles/globalStyle';
4
+ import theme from '../styles/theme';
5
+ import Section from '../components/section';
6
+ import { Queries, RequestDefaultsContext, WebService } from '../components/webservice';
7
+ function readMockMessage() {
8
+ var _a;
9
+ var q = new URLSearchParams(window.location.search);
10
+ return (((_a = q.get('devPushMsg')) === null || _a === void 0 ? void 0 : _a.trim()) ||
11
+ 'Exceção simulada com push=true (teste manual).');
12
+ }
13
+ function buildMockWebService() {
14
+ var message = readMockMessage();
15
+ return {
16
+ request: function () {
17
+ return Promise.reject(Object.assign(new Error(message), { push: true }));
18
+ }
19
+ };
20
+ }
21
+ function FinderMockSection() {
22
+ var ctx = useContext(Queries.Finder);
23
+ if (!ctx)
24
+ return null;
25
+ return (React.createElement(Section, { ctx: ctx, title: "Finder \u2014 mock push=true", subtitle: "Query real: FINDER.BILLING; resposta: reject com push (s\u00F3 dev)" }));
26
+ }
27
+ export function ManualPushSectionPreview() {
28
+ return (React.createElement(ThemeProvider, { theme: theme },
29
+ React.createElement(GlobalStyle, null),
30
+ React.createElement("div", { style: { padding: 24, maxWidth: 720 } },
31
+ React.createElement("p", { style: { marginBottom: 16, fontSize: 14, opacity: 0.85 } },
32
+ "Par\u00E2metros: ",
33
+ React.createElement("code", null, "?devPushSection=1"),
34
+ " e opcionalmente",
35
+ ' ',
36
+ React.createElement("code", null, "devPushMsg=..."),
37
+ " (mensagem na exce\u00E7\u00E3o)."),
38
+ React.createElement(WebService.Provider, { value: buildMockWebService() },
39
+ React.createElement(RequestDefaultsContext.Provider, { value: {} },
40
+ React.createElement(Queries.Finder.Request, { data: { documento: '00000000000100' } },
41
+ React.createElement(FinderMockSection, null)))))));
42
+ }
@@ -1,6 +1,7 @@
1
1
  export declare function useSafeQuery<T>(query: string, params: Record<string, any>, skip?: boolean): {
2
2
  response: import("../components/webservice").ParsedResponse<T> | null;
3
3
  error: Error | null;
4
+ pushNotice: import("../components/webservice").PushNotice | null;
4
5
  isLoading: boolean;
5
6
  loadingProgress: number;
6
7
  refetch: () => void;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Classificação única de erros de request (transporte / webservice).
3
+ * Mantém semântica alinhada ao contrato Credithub (ex.: `push=true` = exceção esperada).
4
+ */
5
+ export type RequestErrorKind = 'aborted' | 'push_expected' | 'real_error';
6
+ export declare function isErrorWithPushFlag(error: unknown): boolean;
7
+ export declare function classifyRequestError(error: unknown): RequestErrorKind;
8
+ /** True quando o upstream deve bloquear refetch automático (erro real, não push nem abort). */
9
+ export declare function isRealRequestFailure(error: unknown): boolean;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Classificação única de erros de request (transporte / webservice).
3
+ * Mantém semântica alinhada ao contrato Credithub (ex.: `push=true` = exceção esperada).
4
+ */
5
+ export function isErrorWithPushFlag(error) {
6
+ if (error && typeof error === 'object') {
7
+ return error.push === true;
8
+ }
9
+ return false;
10
+ }
11
+ export function classifyRequestError(error) {
12
+ if (error &&
13
+ typeof error === 'object' &&
14
+ 'name' in error &&
15
+ error.name === 'AbortError') {
16
+ return 'aborted';
17
+ }
18
+ if (isErrorWithPushFlag(error)) {
19
+ return 'push_expected';
20
+ }
21
+ return 'real_error';
22
+ }
23
+ /** True quando o upstream deve bloquear refetch automático (erro real, não push nem abort). */
24
+ export function isRealRequestFailure(error) {
25
+ return classifyRequestError(error) === 'real_error';
26
+ }