teraprox-core-sdk 0.3.3 → 0.3.6

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/dist/index.js CHANGED
@@ -30,13 +30,21 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ CoreServiceBuilder: () => CoreServiceBuilder,
33
34
  CoreServiceContext: () => CoreServiceContext,
34
35
  DevAutoLogin: () => DevAutoLogin,
35
36
  FederatedBridge: () => FederatedBridge,
37
+ FetchHttpAdapter: () => FetchHttpAdapter,
38
+ NullCoreService: () => NullCoreService,
39
+ NullHttpController: () => NullHttpController,
40
+ NullObservabilityAdapter: () => NullObservabilityAdapter,
41
+ NullToastService: () => NullToastService,
36
42
  RecursoDisplayer: () => RecursoDisplayer_default,
37
43
  StandaloneProvider: () => StandaloneProvider,
44
+ TracingHttpAdapter: () => TracingHttpAdapter,
38
45
  addDays: () => addDays,
39
46
  branchLevelReducer: () => branchLevelReducer_default,
47
+ buildTraceparent: () => buildTraceparent,
40
48
  capitalize: () => capitalize,
41
49
  clearBranchLevelForm: () => clearBranchLevelForm,
42
50
  clearPicker: () => clearPicker,
@@ -44,6 +52,9 @@ __export(index_exports, {
44
52
  daysBetween: () => daysBetween,
45
53
  formatDate: () => formatDate,
46
54
  formatDateTime: () => formatDateTime,
55
+ generateSpanId: () => generateSpanId,
56
+ generateTraceId: () => generateTraceId,
57
+ initWebVitals: () => initWebVitals,
47
58
  isBlank: () => isBlank,
48
59
  isDateAfter: () => isDateAfter,
49
60
  isDateBefore: () => isDateBefore,
@@ -72,6 +83,7 @@ __export(index_exports, {
72
83
  useMatchingObject: () => useMatchingObject,
73
84
  useNavigator: () => useNavigator,
74
85
  useNotifications: () => useNotifications,
86
+ useObservability: () => useObservability,
75
87
  usePostData: () => usePostData,
76
88
  useSmartSearch: () => useSmartSearch,
77
89
  useToast: () => useToast,
@@ -83,14 +95,340 @@ module.exports = __toCommonJS(index_exports);
83
95
  var import_react = require("react");
84
96
  var CoreServiceContext = (0, import_react.createContext)(null);
85
97
 
98
+ // src/adapters/null/NullObservabilityAdapter.ts
99
+ var NullObservabilityAdapter = class {
100
+ trackInteraction(payload) {
101
+ var _a;
102
+ console.info(`[Observability] INTERACTION: ${payload.name}`, (_a = payload.properties) != null ? _a : {});
103
+ }
104
+ captureVitals(payload) {
105
+ var _a, _b;
106
+ const unit = (_a = payload.unit) != null ? _a : "";
107
+ console.info(`[Observability] VITAL: ${payload.name} = ${payload.value}${unit}`, (_b = payload.meta) != null ? _b : {});
108
+ }
109
+ logBreadcrumb(payload) {
110
+ var _a;
111
+ console.info(`[Observability] BREADCRUMB [${payload.category}]: ${payload.message}`, (_a = payload.data) != null ? _a : {});
112
+ }
113
+ };
114
+
115
+ // src/adapters/null/NullObjectAdapters.ts
116
+ var NullToastService = class {
117
+ success(message) {
118
+ console.log(`[Toast Fallback] SUCCESS: ${message}`);
119
+ }
120
+ warning(message) {
121
+ console.warn(`[Toast Fallback] WARNING: ${message}`);
122
+ }
123
+ error(message) {
124
+ console.error(`[Toast Fallback] ERROR: ${message}`);
125
+ }
126
+ info(message) {
127
+ console.info(`[Toast Fallback] INFO: ${message}`);
128
+ }
129
+ };
130
+ var NullHttpController = class {
131
+ logAndResolve(method, path, context) {
132
+ console.warn(`[Http Fallback] MOCK ${method} requisitado para ${path} (Contexto: ${context})`);
133
+ if (process.env.NODE_ENV !== "production") {
134
+ if (context === "arvoreEstrutural" && path && path.includes("branchByBranchLevel")) {
135
+ return Promise.resolve([
136
+ {
137
+ id: 1,
138
+ nome: "Planta Industrial Mock",
139
+ branchLevel: { level: 1 },
140
+ status: "Ativo"
141
+ }
142
+ ]);
143
+ }
144
+ if (context === "branchLevel" && method === "READ_ALL") {
145
+ return Promise.resolve([
146
+ { id: 1, level: 1, nome: "Empresa" },
147
+ { id: 2, level: 2, nome: "Unidade" },
148
+ { id: 3, level: 3, nome: "\xC1rea" },
149
+ { id: 4, level: 4, nome: "M\xE1quina" }
150
+ ]);
151
+ }
152
+ }
153
+ return Promise.resolve([]);
154
+ }
155
+ get(path) {
156
+ return this.logAndResolve("GET", path, this.context);
157
+ }
158
+ post(path) {
159
+ return this.logAndResolve("POST", path, this.context);
160
+ }
161
+ put(path) {
162
+ return this.logAndResolve("PUT", path, this.context);
163
+ }
164
+ patch(path) {
165
+ return this.logAndResolve("PATCH", path, this.context);
166
+ }
167
+ delete(path, id) {
168
+ return this.logAndResolve("DELETE", `${path}/${id}`, this.context);
169
+ }
170
+ deleteSimple(path) {
171
+ return this.logAndResolve("DELETE", path, this.context);
172
+ }
173
+ save(path) {
174
+ return this.logAndResolve("SAVE", path, this.context);
175
+ }
176
+ read(path, id) {
177
+ return this.logAndResolve("READ", `${path}/${id}`, this.context);
178
+ }
179
+ readAll(path) {
180
+ return this.logAndResolve("READ_ALL", path, this.context);
181
+ }
182
+ readAllwithPage(path) {
183
+ return this.logAndResolve("READ_ALL_PAGE", path, this.context);
184
+ }
185
+ bulkDelete(path) {
186
+ return this.logAndResolve("BULK_DELETE", path, this.context);
187
+ }
188
+ };
189
+ var NullCoreService = {
190
+ toast: new NullToastService(),
191
+ createController: (context) => {
192
+ console.warn(`[CoreService Fallback] createController chamado para "${context}" sem Adapter. Usando NullHttpController.`);
193
+ const controller = new NullHttpController();
194
+ controller.context = context;
195
+ return controller;
196
+ },
197
+ subscribe: (mo) => console.log(`[CoreService Fallback] Inscri\xE7\xE3o simulada RTDB: ${mo.context}`),
198
+ unsubscribe: (mo) => console.log(`[CoreService Fallback] Desinscri\xE7\xE3o simulada RTDB: ${mo.context}`),
199
+ subscribeEvent: (evt) => console.log(`[CoreService Fallback] Inscri\xE7\xE3o Evento: ${evt}`),
200
+ unsubscribeEvent: (evt) => console.log(`[CoreService Fallback] Desinscri\xE7\xE3o Evento: ${evt}`),
201
+ handleLogout: () => console.log(`[CoreService Fallback] Realizando logout...`),
202
+ hostedByCore: false,
203
+ observability: new NullObservabilityAdapter()
204
+ };
205
+
206
+ // src/utils/tracing.ts
207
+ function toHex(bytes) {
208
+ return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
209
+ }
210
+ function generateTraceId() {
211
+ const bytes = new Uint8Array(16);
212
+ crypto.getRandomValues(bytes);
213
+ return toHex(bytes);
214
+ }
215
+ function generateSpanId() {
216
+ const bytes = new Uint8Array(8);
217
+ crypto.getRandomValues(bytes);
218
+ return toHex(bytes);
219
+ }
220
+ function buildTraceparent(traceId, spanId, sampled = true) {
221
+ return `00-${traceId}-${spanId}-${sampled ? "01" : "00"}`;
222
+ }
223
+
224
+ // src/adapters/TracingHttpAdapter.ts
225
+ var TracingHttpAdapter = class {
226
+ constructor(endpoint, extraHeaders) {
227
+ this.endpoint = endpoint;
228
+ this.extraHeaders = extraHeaders;
229
+ this.traceId = generateTraceId();
230
+ }
231
+ mergeHeaders(extraHeaders, withContentType = false) {
232
+ const spanId = generateSpanId();
233
+ const headers = {
234
+ traceparent: buildTraceparent(this.traceId, spanId),
235
+ ...this.extraHeaders,
236
+ ...extraHeaders
237
+ };
238
+ if (withContentType && !headers["Content-Type"]) {
239
+ headers["Content-Type"] = "application/json";
240
+ }
241
+ return headers;
242
+ }
243
+ async request(method, extraPath, data, extraHeaders) {
244
+ const url = extraPath ? `${this.endpoint}/${extraPath}` : this.endpoint;
245
+ const isFormData = data instanceof FormData;
246
+ const headers = this.mergeHeaders(extraHeaders, data !== void 0 && !isFormData);
247
+ try {
248
+ const res = await fetch(url, {
249
+ method,
250
+ headers,
251
+ body: data !== void 0 ? isFormData ? data : JSON.stringify(data) : void 0
252
+ });
253
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
254
+ return await res.json();
255
+ } catch (e) {
256
+ console.warn(`[TracingHttpAdapter] Falha ao fazer ${method} para ${url}:`, e);
257
+ return [];
258
+ }
259
+ }
260
+ get(path) {
261
+ return this.request("GET", path || "");
262
+ }
263
+ post(path, data, extraHeaders) {
264
+ return this.request("POST", path || "", data, extraHeaders);
265
+ }
266
+ put(path, data, extraHeaders) {
267
+ return this.request("PUT", path || "", data, extraHeaders);
268
+ }
269
+ patch(path, data, extraHeaders) {
270
+ return this.request("PATCH", path || "", data, extraHeaders);
271
+ }
272
+ delete(path, id, extraHeaders) {
273
+ return this.request("DELETE", `${path || ""}/${id}`, void 0, extraHeaders);
274
+ }
275
+ deleteSimple(path, extraHeaders) {
276
+ return this.request("DELETE", path || "", void 0, extraHeaders);
277
+ }
278
+ save(path, data, extraHeaders) {
279
+ return this.request("POST", path || "", data, extraHeaders);
280
+ }
281
+ read(path, id, extraHeaders) {
282
+ return this.request("GET", `${path || ""}/${id}`, void 0, extraHeaders);
283
+ }
284
+ readAll(path, extraHeaders) {
285
+ return this.request("GET", path || "", void 0, extraHeaders);
286
+ }
287
+ readAllwithPage(path) {
288
+ return this.request("GET", path || "");
289
+ }
290
+ bulkDelete(path, ids, extraHeaders) {
291
+ return this.request("DELETE", path || "", ids, extraHeaders);
292
+ }
293
+ };
294
+
295
+ // src/factories/CoreServiceBuilder.ts
296
+ var FetchHttpAdapter = class {
297
+ constructor(endpoint, extraHeaders) {
298
+ this.endpoint = endpoint;
299
+ this.extraHeaders = extraHeaders;
300
+ }
301
+ async request(method, extraPath, data) {
302
+ const url = extraPath ? `${this.endpoint}/${extraPath}` : this.endpoint;
303
+ try {
304
+ const res = await fetch(url, {
305
+ method,
306
+ headers: {
307
+ ...this.extraHeaders,
308
+ ...data ? { "Content-Type": "application/json" } : {}
309
+ },
310
+ body: data ? JSON.stringify(data) : void 0
311
+ });
312
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
313
+ return await res.json();
314
+ } catch (e) {
315
+ console.warn(`[FetchHttpAdapter] Falha ao fazer ${method} para ${url}:`, e);
316
+ return [];
317
+ }
318
+ }
319
+ get(path) {
320
+ return this.request("GET", path || "");
321
+ }
322
+ post(path, data) {
323
+ return this.request("POST", path || "", data);
324
+ }
325
+ put(path, data) {
326
+ return this.request("PUT", path || "", data);
327
+ }
328
+ patch(path, data) {
329
+ return this.request("PATCH", path || "", data);
330
+ }
331
+ delete(path, id) {
332
+ return this.request("DELETE", `${path || ""}/${id}`);
333
+ }
334
+ deleteSimple(path) {
335
+ return this.request("DELETE", path || "");
336
+ }
337
+ save(path, data) {
338
+ return this.request("POST", path || "", data);
339
+ }
340
+ read(path, id) {
341
+ return this.request("GET", `${path || ""}/${id}`);
342
+ }
343
+ readAll(path) {
344
+ return this.request("GET", path || "");
345
+ }
346
+ readAllwithPage(path) {
347
+ return this.request("GET", path || "");
348
+ }
349
+ bulkDelete(path) {
350
+ return this.request("DELETE", path || "");
351
+ }
352
+ };
353
+ var CoreServiceBuilder = class {
354
+ constructor() {
355
+ this._toast = new NullToastService();
356
+ this._hostedByCore = false;
357
+ this._observability = new NullObservabilityAdapter();
358
+ this._tracing = false;
359
+ }
360
+ withToast(toast) {
361
+ this._toast = toast;
362
+ return this;
363
+ }
364
+ withHttpEndpoint(url) {
365
+ this._httpEndpoint = url;
366
+ return this;
367
+ }
368
+ withRtdbConfig(config) {
369
+ this._rtdbConfig = config;
370
+ return this;
371
+ }
372
+ setHostedByCore(hosted) {
373
+ this._hostedByCore = hosted;
374
+ return this;
375
+ }
376
+ withObservability(observability) {
377
+ this._observability = observability;
378
+ return this;
379
+ }
380
+ /**
381
+ * Ativa Distributed Tracing W3C nos controllers HTTP.
382
+ * Quando habilitado, `createController` retorna `TracingHttpAdapter` em vez de `FetchHttpAdapter`.
383
+ * O header `traceparent` é injetado em todas as requisições automaticamente.
384
+ */
385
+ withTracing(enabled = true) {
386
+ this._tracing = enabled;
387
+ return this;
388
+ }
389
+ build() {
390
+ return {
391
+ toast: this._toast,
392
+ createController: (context, baseEndPoint) => {
393
+ const endpoint = baseEndPoint != null ? baseEndPoint : this._httpEndpoint ? `${this._httpEndpoint}/${context}` : null;
394
+ if (!endpoint) {
395
+ console.warn(`[CoreServiceBuilder] HttpEndpoint nulo para "${context}". Usando NullHttpController.`);
396
+ const controller = new NullHttpController();
397
+ controller.context = context;
398
+ return controller;
399
+ }
400
+ const xTeraproxHost = context === "solicitacaoDeServico" || context === "manutencao" ? "manutencao" : context;
401
+ const extraHeaders = { "x-teraprox-host": xTeraproxHost };
402
+ return this._tracing ? new TracingHttpAdapter(endpoint, extraHeaders) : new FetchHttpAdapter(endpoint, extraHeaders);
403
+ },
404
+ subscribe: (mo) => {
405
+ console.log(`[CoreServiceBuilder RTDB] Subscribe > ${mo.context}`);
406
+ },
407
+ unsubscribe: (mo) => {
408
+ console.log(`[CoreServiceBuilder RTDB] Unsubscribe > ${mo.context}`);
409
+ },
410
+ subscribeEvent: (evt) => {
411
+ },
412
+ unsubscribeEvent: (evt) => {
413
+ },
414
+ handleLogout: () => console.log("Logout invocado no Standalone mode"),
415
+ hostedByCore: this._hostedByCore,
416
+ observability: this._observability
417
+ };
418
+ }
419
+ };
420
+
86
421
  // src/hooks/useCoreService.ts
87
422
  var import_react2 = require("react");
88
423
  function useCoreService() {
89
424
  const ctx = (0, import_react2.useContext)(CoreServiceContext);
90
425
  if (!ctx) {
91
- throw new Error(
92
- "useCoreService must be used within a CoreServiceProvider. Are you running outside Core (standalone mode)?"
93
- );
426
+ if (process.env.NODE_ENV !== "production") {
427
+ console.warn(
428
+ "[useCoreService] rodando sem Provider. O SDK ativou os Fallbacks (Null Object Pattern)."
429
+ );
430
+ }
431
+ return NullCoreService;
94
432
  }
95
433
  return ctx;
96
434
  }
@@ -191,6 +529,11 @@ function useNavigator(config) {
191
529
  );
192
530
  }
193
531
 
532
+ // src/hooks/useObservability.ts
533
+ function useObservability() {
534
+ return useCoreService().observability;
535
+ }
536
+
194
537
  // src/hooks/useFetchData.ts
195
538
  var import_react6 = require("react");
196
539
  function useFetchData() {
@@ -1246,6 +1589,39 @@ var {
1246
1589
  } = pickerSlice.actions;
1247
1590
  var pickerReducer_default = pickerSlice.reducer;
1248
1591
 
1592
+ // src/utils/webVitals.ts
1593
+ function initWebVitals(observability) {
1594
+ if (typeof PerformanceObserver === "undefined") return;
1595
+ try {
1596
+ const lcpObserver = new PerformanceObserver((list) => {
1597
+ const entries = list.getEntries();
1598
+ if (!entries.length) return;
1599
+ const last = entries[entries.length - 1];
1600
+ observability.captureVitals({ name: "LCP", value: Math.round(last.startTime), unit: "ms" });
1601
+ });
1602
+ lcpObserver.observe({ type: "largest-contentful-paint", buffered: true });
1603
+ } catch (_) {
1604
+ }
1605
+ try {
1606
+ let clsValue = 0;
1607
+ const clsObserver = new PerformanceObserver((list) => {
1608
+ for (const entry of list.getEntries()) {
1609
+ const ls = entry;
1610
+ if (!ls.hadRecentInput && typeof ls.value === "number") {
1611
+ clsValue += ls.value;
1612
+ }
1613
+ }
1614
+ observability.captureVitals({
1615
+ name: "CLS",
1616
+ value: parseFloat(clsValue.toFixed(4)),
1617
+ unit: "score"
1618
+ });
1619
+ });
1620
+ clsObserver.observe({ type: "layout-shift", buffered: true });
1621
+ } catch (_) {
1622
+ }
1623
+ }
1624
+
1249
1625
  // src/utils/dateUtils.ts
1250
1626
  var import_dayjs = __toESM(require("dayjs"));
1251
1627
  function formatDate(date, format = "DD/MM/YYYY") {
@@ -1559,7 +1935,8 @@ function StandaloneProvider({ createController, addToast, firebaseConfig, emulat
1559
1935
  },
1560
1936
  handleLogout: () => {
1561
1937
  },
1562
- hostedByCore: false
1938
+ hostedByCore: false,
1939
+ observability: new NullObservabilityAdapter()
1563
1940
  }),
1564
1941
  [createController, toast, subscribe, unsubscribe]
1565
1942
  );
@@ -1578,14 +1955,14 @@ var DEFAULT_DEV_USER = {
1578
1955
  lastName: "User",
1579
1956
  token: "dev-standalone-token",
1580
1957
  email: "dev@teraprox.local",
1581
- id: "dev-user-id",
1958
+ id: "1",
1582
1959
  role: "admin",
1583
1960
  user: "devuser",
1584
1961
  userName: "devuser",
1585
1962
  setor: "Desenvolvimento",
1586
- userSetor: { setorId: "dev-setor-id" },
1963
+ userSetor: { setorId: "1" },
1587
1964
  companyName: "Dev Company",
1588
- companyId: "dev-company-id",
1965
+ companyId: "1",
1589
1966
  filters: []
1590
1967
  };
1591
1968
  function DevAutoLogin({ actions, devUser, children }) {
@@ -1606,13 +1983,21 @@ function DevAutoLogin({ actions, devUser, children }) {
1606
1983
  }
1607
1984
  // Annotate the CommonJS export names for ESM import in node:
1608
1985
  0 && (module.exports = {
1986
+ CoreServiceBuilder,
1609
1987
  CoreServiceContext,
1610
1988
  DevAutoLogin,
1611
1989
  FederatedBridge,
1990
+ FetchHttpAdapter,
1991
+ NullCoreService,
1992
+ NullHttpController,
1993
+ NullObservabilityAdapter,
1994
+ NullToastService,
1612
1995
  RecursoDisplayer,
1613
1996
  StandaloneProvider,
1997
+ TracingHttpAdapter,
1614
1998
  addDays,
1615
1999
  branchLevelReducer,
2000
+ buildTraceparent,
1616
2001
  capitalize,
1617
2002
  clearBranchLevelForm,
1618
2003
  clearPicker,
@@ -1620,6 +2005,9 @@ function DevAutoLogin({ actions, devUser, children }) {
1620
2005
  daysBetween,
1621
2006
  formatDate,
1622
2007
  formatDateTime,
2008
+ generateSpanId,
2009
+ generateTraceId,
2010
+ initWebVitals,
1623
2011
  isBlank,
1624
2012
  isDateAfter,
1625
2013
  isDateBefore,
@@ -1648,6 +2036,7 @@ function DevAutoLogin({ actions, devUser, children }) {
1648
2036
  useMatchingObject,
1649
2037
  useNavigator,
1650
2038
  useNotifications,
2039
+ useObservability,
1651
2040
  usePostData,
1652
2041
  useSmartSearch,
1653
2042
  useToast,