@fluwa-tool/sdk 1.0.0 → 1.0.1

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.
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Interceptador de XMLHttpRequest
3
+ * Intercepta requisições axios, jQuery, XMLHttpRequest nativo
4
+ */
5
+ import { ILogger } from '../../core/Logger';
6
+ import { IRequestLogger } from './RequestLogger';
7
+ import { IMockResolver } from './MockResolver';
8
+ export interface IXMLHttpRequestInterceptor {
9
+ install(): void;
10
+ uninstall(): void;
11
+ }
12
+ export declare class XMLHttpRequestInterceptor implements IXMLHttpRequestInterceptor {
13
+ private logger;
14
+ private requestLogger;
15
+ private mockResolver;
16
+ private sessionId;
17
+ private appName;
18
+ private originalOpen;
19
+ private originalSend;
20
+ private originalSetRequestHeader;
21
+ private isInstalled;
22
+ constructor(logger: ILogger, requestLogger: IRequestLogger, mockResolver: IMockResolver, sessionId: string, appName: string);
23
+ install(): void;
24
+ uninstall(): void;
25
+ private safeParseBody;
26
+ private generateId;
27
+ }
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ /**
3
+ * Interceptador de XMLHttpRequest
4
+ * Intercepta requisições axios, jQuery, XMLHttpRequest nativo
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.XMLHttpRequestInterceptor = void 0;
8
+ const types_1 = require("../../types");
9
+ class XMLHttpRequestInterceptor {
10
+ constructor(logger, requestLogger, mockResolver, sessionId, appName) {
11
+ this.logger = logger;
12
+ this.requestLogger = requestLogger;
13
+ this.mockResolver = mockResolver;
14
+ this.sessionId = sessionId;
15
+ this.appName = appName;
16
+ this.isInstalled = false;
17
+ }
18
+ install() {
19
+ if (this.isInstalled) {
20
+ this.logger.warn('XMLHttpRequest interceptor já foi instalado');
21
+ return;
22
+ }
23
+ // Verificar se XMLHttpRequest está disponível (apenas em navegadores)
24
+ if (typeof XMLHttpRequest === 'undefined') {
25
+ this.logger.debug('XMLHttpRequest não disponível nesse ambiente (requer navegador)');
26
+ return;
27
+ }
28
+ const self = this;
29
+ const originalXHR = XMLHttpRequest.prototype;
30
+ // Armazenar referência ao open original
31
+ this.originalOpen = originalXHR.open;
32
+ this.originalSend = originalXHR.send;
33
+ this.originalSetRequestHeader = originalXHR.setRequestHeader;
34
+ // Interceptar open()
35
+ originalXHR.open = function (method, url, ...args) {
36
+ const xhr = this;
37
+ xhr._fluwaMethod = method.toUpperCase();
38
+ xhr._fluwaUrl = url;
39
+ xhr._fluwaRequestId = self.generateId();
40
+ xhr._fluwaHeaders = {};
41
+ xhr._fluwaStartTime = Date.now();
42
+ return self.originalOpen.apply(this, [method, url, ...args]);
43
+ };
44
+ // Interceptar setRequestHeader()
45
+ originalXHR.setRequestHeader = function (header, value) {
46
+ const xhr = this;
47
+ if (!xhr._fluwaHeaders) {
48
+ xhr._fluwaHeaders = {};
49
+ }
50
+ xhr._fluwaHeaders[header] = value;
51
+ return self.originalSetRequestHeader.apply(this, [header, value]);
52
+ };
53
+ // Interceptar send()
54
+ this.originalSend = originalXHR.send;
55
+ originalXHR.send = function (body) {
56
+ const xhr = this;
57
+ const method = (xhr._fluwaMethod || 'GET');
58
+ const url = xhr._fluwaUrl;
59
+ const requestId = xhr._fluwaRequestId;
60
+ const headers = xhr._fluwaHeaders || {};
61
+ const requestMetadata = {
62
+ id: requestId,
63
+ method,
64
+ url,
65
+ headers,
66
+ body: body ? self.safeParseBody(body) : undefined,
67
+ timestamp: new Date().toISOString(),
68
+ sessionId: self.sessionId,
69
+ appName: self.appName,
70
+ source: types_1.RequestSource.REAL,
71
+ };
72
+ // Verificar se há mock
73
+ self.mockResolver.resolve(method, url)
74
+ .then((mockResponse) => {
75
+ if (mockResponse) {
76
+ // Há mock disponível
77
+ requestMetadata.source = types_1.RequestSource.MOCK;
78
+ requestMetadata.status = mockResponse.status || 200;
79
+ requestMetadata.response = mockResponse.response;
80
+ // Logar
81
+ self.requestLogger.logStart(requestMetadata).catch(() => { });
82
+ // Aplicar delay se configurado
83
+ if (mockResponse.delay) {
84
+ return new Promise(resolve => setTimeout(resolve, mockResponse.delay));
85
+ }
86
+ }
87
+ else {
88
+ // Sem mock, será requisição real
89
+ self.requestLogger.logStart(requestMetadata).catch(() => { });
90
+ }
91
+ })
92
+ .catch(() => {
93
+ self.requestLogger.logStart(requestMetadata).catch(() => { });
94
+ });
95
+ // Interceptar mudanças de estado
96
+ const originalOnReadyStateChange = xhr.onreadystatechange;
97
+ xhr.onreadystatechange = function () {
98
+ if (xhr.readyState === 4) {
99
+ // Requisição completou
100
+ requestMetadata.status = xhr.status;
101
+ // Tentar extrair response
102
+ try {
103
+ if (xhr.responseText) {
104
+ requestMetadata.response = self.safeParseBody(xhr.responseText);
105
+ }
106
+ }
107
+ catch (e) {
108
+ requestMetadata.response = xhr.responseText;
109
+ }
110
+ const duration = Date.now() - (xhr._fluwaStartTime || 0);
111
+ requestMetadata.duration = duration;
112
+ self.requestLogger.logComplete(requestMetadata).catch(() => { });
113
+ }
114
+ // Chamar handler original
115
+ if (originalOnReadyStateChange) {
116
+ originalOnReadyStateChange.call(this);
117
+ }
118
+ };
119
+ // Chamar send original
120
+ return self.originalSend.apply(this, [body]);
121
+ };
122
+ this.isInstalled = true;
123
+ this.logger.success('XMLHttpRequest interceptor instalado');
124
+ }
125
+ uninstall() {
126
+ if (!this.isInstalled || !this.originalOpen) {
127
+ return;
128
+ }
129
+ const originalXHR = XMLHttpRequest.prototype;
130
+ originalXHR.open = this.originalOpen;
131
+ originalXHR.send = this.originalSend;
132
+ originalXHR.setRequestHeader = this.originalSetRequestHeader;
133
+ this.isInstalled = false;
134
+ this.logger.success('XMLHttpRequest interceptor desinstalado');
135
+ }
136
+ safeParseBody(body) {
137
+ if (typeof body === 'string') {
138
+ try {
139
+ return JSON.parse(body);
140
+ }
141
+ catch {
142
+ return body;
143
+ }
144
+ }
145
+ return body;
146
+ }
147
+ generateId() {
148
+ return `${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
149
+ }
150
+ }
151
+ exports.XMLHttpRequestInterceptor = XMLHttpRequestInterceptor;
package/dist/index.js CHANGED
@@ -33,6 +33,7 @@ const Config_1 = require("./core/Config");
33
33
  const HttpClient_1 = require("./features/communication/HttpClient");
34
34
  const WebSocketClient_1 = require("./features/communication/WebSocketClient");
35
35
  const FetchInterceptor_1 = require("./features/network/FetchInterceptor");
36
+ const XMLHttpRequestInterceptor_1 = require("./features/network/XMLHttpRequestInterceptor");
36
37
  const RequestLogger_1 = require("./features/network/RequestLogger");
37
38
  const MockResolver_1 = require("./features/network/MockResolver");
38
39
  const IdGenerator_1 = require("./core/IdGenerator");
@@ -46,6 +47,7 @@ let sessionId;
46
47
  let httpClient;
47
48
  let wsClient;
48
49
  let fetchInterceptor;
50
+ let xmlHttpRequestInterceptor;
49
51
  let mockResolver;
50
52
  // ============================================
51
53
  // INICIALIZAÇÃO
@@ -82,8 +84,11 @@ async function initFluwaTool(partialConfig = {}) {
82
84
  const requestLogger = new RequestLogger_1.RequestLogger(httpClient, logger);
83
85
  // 6. Criar interceptador de fetch
84
86
  fetchInterceptor = new FetchInterceptor_1.FetchInterceptor(logger, requestLogger, mockResolver, sessionId, config.getAppName());
87
+ // 6b. Criar interceptador de XMLHttpRequest (para axios, jQuery, etc)
88
+ xmlHttpRequestInterceptor = new XMLHttpRequestInterceptor_1.XMLHttpRequestInterceptor(logger, requestLogger, mockResolver, sessionId, config.getAppName());
85
89
  // 7. Instalar interceptadores
86
90
  fetchInterceptor.install();
91
+ xmlHttpRequestInterceptor.install();
87
92
  // 8. Conectar WebSocket
88
93
  logger.debug('Conectando ao WebSocket...');
89
94
  try {
@@ -139,6 +144,7 @@ function disableFluwaTool() {
139
144
  return;
140
145
  }
141
146
  fetchInterceptor.uninstall();
147
+ xmlHttpRequestInterceptor.uninstall();
142
148
  wsClient.disconnect();
143
149
  isInitialized = false;
144
150
  logger.success('Fluwa-Tool desativado');
@@ -151,6 +157,7 @@ async function enableFluwaTool() {
151
157
  return;
152
158
  }
153
159
  fetchInterceptor.install();
160
+ xmlHttpRequestInterceptor.install();
154
161
  try {
155
162
  await wsClient.connect();
156
163
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluwa-tool/sdk",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Fluwa DevTools SDK for network interception and mocking",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",