@fluwa-tool/sdk 1.0.50 → 1.0.52

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.
@@ -82,7 +82,7 @@ class XMLHttpRequestInterceptor {
82
82
  };
83
83
  checkMockWithRetry().then(mockResponse => {
84
84
  if (mockResponse) {
85
- // Mock encontrado - simular resposta XHR
85
+ // Mock encontrado - usar proxy do Fluwa Server
86
86
  self.logger.debug(`🎯 [XMLHttpRequestInterceptor] Mock encontrado para ${method} ${url}`, {
87
87
  status: mockResponse.status,
88
88
  hasResponse: !!mockResponse.response,
@@ -90,143 +90,41 @@ class XMLHttpRequestInterceptor {
90
90
  requestMetadata.source = types_1.RequestSource.MOCK;
91
91
  requestMetadata.status = mockResponse.status || 200;
92
92
  requestMetadata.response = mockResponse.response;
93
- const delay = mockResponse.delay || 0;
94
- // Aguardar axios anexar seus handlers
95
- // Usar múltiplos microtasks e macrotasks para garantir timing correto
96
- Promise.resolve().then(() => {
97
- // Dar 50ms extra para axios configurar tudo
98
- setTimeout(() => {
99
- self.logger.debug(`⏱️ [XMLHttpRequestInterceptor] Iniciando simulação de resposta com delay: ${delay}ms`);
100
- const executeSimulation = () => {
101
- const duration = Date.now() - (xhr._fluwaStartTime || 0);
102
- requestMetadata.duration = duration;
103
- self.requestLogger.logComplete(requestMetadata).catch(() => { });
104
- // Simular readyState progression usando defineProperty (Hermes engine compat)
105
- const setReadyState = (state) => {
106
- try {
107
- Object.defineProperty(xhr, 'readyState', {
108
- value: state,
109
- writable: true,
110
- configurable: true,
111
- });
112
- self.logger.debug(`📊 [XMLHttpRequestInterceptor] readyState = ${state}`);
113
- }
114
- catch (e) {
115
- // Fallback: try direct assignment se defineProperty falhar
116
- xhr.readyState = state;
117
- self.logger.debug(`📊 [XMLHttpRequestInterceptor] readyState = ${state} (fallback)`);
118
- }
119
- };
120
- // Primeiro: configurar todas as propriedades de resposta ANTES de começar readyState
121
- self.logger.debug(`🔧 [XMLHttpRequestInterceptor] Configurando propriedades de resposta`);
122
- try {
123
- // Override status (read-only property in Hermes)
124
- try {
125
- Object.defineProperty(xhr, 'status', {
126
- value: mockResponse.status || 200,
127
- writable: true,
128
- configurable: true,
129
- });
130
- self.logger.debug(`✅ [XMLHttpRequestInterceptor] status = ${mockResponse.status || 200}`);
131
- }
132
- catch (statusErr) {
133
- self.logger.debug(`⚠️ [XMLHttpRequestInterceptor] Não foi possível setar status:`, statusErr);
134
- }
135
- // Override responseText (read-only property in Hermes)
136
- try {
137
- Object.defineProperty(xhr, 'responseText', {
138
- value: JSON.stringify(mockResponse.response),
139
- writable: true,
140
- configurable: true,
141
- });
142
- self.logger.debug(`✅ [XMLHttpRequestInterceptor] responseText configurado`);
143
- }
144
- catch (textErr) {
145
- self.logger.debug(`⚠️ [XMLHttpRequestInterceptor] Não foi possível setar responseText:`, textErr);
146
- }
147
- // Override response (read-only property in Hermes)
148
- try {
149
- Object.defineProperty(xhr, 'response', {
150
- value: mockResponse.response,
151
- writable: true,
152
- configurable: true,
153
- });
154
- self.logger.debug(`✅ [XMLHttpRequestInterceptor] response configurado`);
155
- }
156
- catch (respErr) {
157
- self.logger.debug(`⚠️ [XMLHttpRequestInterceptor] Não foi possível setar response:`, respErr);
158
- }
159
- }
160
- catch (e) {
161
- self.logger.debug('❌ Erro ao injetar propriedades mock:', e);
162
- }
163
- // Simular readyState progression - apenas chamar callbacks diretos
164
- // (dispatchEvent pode não funcionar em React Native)
165
- const fireCallback = (state, delayMs) => {
166
- setTimeout(() => {
167
- setReadyState(state);
168
- self.logger.debug(`📞 [XMLHttpRequestInterceptor] readyState=${state} - Tentando chamar onreadystatechange`);
169
- if (xhr.onreadystatechange && typeof xhr.onreadystatechange === 'function') {
170
- try {
171
- xhr.onreadystatechange();
172
- self.logger.debug(`✅ [XMLHttpRequestInterceptor] onreadystatechange chamado com sucesso`);
173
- }
174
- catch (e) {
175
- self.logger.debug(`❌ Erro ao chamar onreadystatechange(${state}):`, e);
176
- }
177
- }
178
- else {
179
- self.logger.debug(`⚠️ [XMLHttpRequestInterceptor] onreadystatechange não é função:`, typeof xhr.onreadystatechange);
180
- }
181
- }, delayMs);
182
- };
183
- // Disparar callbacks para cada readyState
184
- fireCallback(1, 50); // readyState = 1 em 50ms
185
- fireCallback(2, 100); // readyState = 2 em 100ms
186
- fireCallback(3, 150); // readyState = 3 em 150ms
187
- // Final: readyState = 4 com callbacks
188
- setTimeout(() => {
189
- setReadyState(4);
190
- self.logger.debug(`📞 [XMLHttpRequestInterceptor] readyState=4 - Tentando chamar onreadystatechange`);
191
- // Chamar onreadystatechange
192
- if (xhr.onreadystatechange && typeof xhr.onreadystatechange === 'function') {
193
- try {
194
- xhr.onreadystatechange();
195
- self.logger.debug(`✅ [XMLHttpRequestInterceptor] onreadystatechange(4) chamado com sucesso`);
196
- }
197
- catch (e) {
198
- self.logger.debug(`❌ Erro ao chamar onreadystatechange(4):`, e);
199
- }
200
- }
201
- else {
202
- self.logger.debug(`⚠️ [XMLHttpRequestInterceptor] onreadystatechange não é função em readyState=4`);
203
- }
204
- // Chamar onload
205
- self.logger.debug(`📞 [XMLHttpRequestInterceptor] Tentando chamar onload`);
206
- if (xhr.onload && typeof xhr.onload === 'function') {
207
- try {
208
- xhr.onload();
209
- self.logger.debug(`✅ [XMLHttpRequestInterceptor] onload chamado com sucesso`);
210
- }
211
- catch (e) {
212
- self.logger.debug(`❌ Erro ao chamar onload:`, e);
213
- }
214
- }
215
- else {
216
- self.logger.debug(`⚠️ [XMLHttpRequestInterceptor] onload não é função`);
217
- }
218
- self.logger.debug(`✅ [XMLHttpRequestInterceptor] Simulação de resposta COMPLETA`);
219
- }, 200);
220
- };
221
- // Executar após o delay do mock
222
- if (delay > 0) {
223
- setTimeout(executeSimulation, delay);
224
- }
225
- else {
226
- executeSimulation();
227
- }
228
- }, 50); // 50ms para axios anexar handlers
93
+ // NOVA ABORDAGEM: Redirecionar para endpoint do Fluwa que retorna o mock
94
+ // Em vez de tentar simular a resposta XHR, fazemos uma requisição REAL para o Fluwa Server
95
+ const mockProxyUrl = `http://192.168.0.6:5555/api/mock-proxy`;
96
+ self.logger.debug(`🔀 [XMLHttpRequestInterceptor] Redirecionando para proxy do Fluwa: ${mockProxyUrl}`);
97
+ // Modifi car URL e corpo para chamar o endpoint proxy
98
+ const mockRequestBody = JSON.stringify({
99
+ originalMethod: method,
100
+ originalUrl: url,
101
+ mockStatus: mockResponse.status || 200,
102
+ mockResponse: mockResponse.response,
103
+ mockDelay: mockResponse.delay || 0,
229
104
  });
105
+ // Chamar originalSend com URL do proxy
106
+ // Isso faz axios fazer uma requisição REAL para o Fluwa Server
107
+ // que retorna o mock como resposta HTTP normal
108
+ try {
109
+ // Restaurar para o método proxy (POST para o endpoint /api/mock-proxy)
110
+ self.originalOpen.call(xhr, 'POST', mockProxyUrl, true);
111
+ // Copiar headers originais
112
+ Object.keys(headers).forEach(header => {
113
+ self.originalSetRequestHeader.call(xhr, header, headers[header]);
114
+ });
115
+ // Adicionar header especial para o Fluwa Server saber que é um mock proxy
116
+ self.originalSetRequestHeader.call(xhr, 'X-Fluwa-Mock-Proxy', 'true');
117
+ const duration = Date.now() - (xhr._fluwaStartTime || 0);
118
+ requestMetadata.duration = duration;
119
+ self.requestLogger.logComplete(requestMetadata).catch(() => { });
120
+ self.logger.debug(`✅ [XMLHttpRequestInterceptor] Enviando mock via proxy do Fluwa`);
121
+ self.originalSend.call(xhr, mockRequestBody);
122
+ }
123
+ catch (e) {
124
+ self.logger.debug(`❌ [XMLHttpRequestInterceptor] Erro ao chamar proxy:`, e);
125
+ // Fallback: tentar fazer requisição real
126
+ self.originalSend.apply(xhr, [body]);
127
+ }
230
128
  return;
231
129
  }
232
130
  // Sem mock - fazer request real
package/dist/index.js CHANGED
@@ -52,6 +52,47 @@ let xmlHttpRequestInterceptor;
52
52
  let mockResolver;
53
53
  let urlFilter = null; // URL filter para evitar loops infinitos
54
54
  // ============================================
55
+ // CONFIGURAÇÃO DE AXIOS
56
+ // ============================================
57
+ /**
58
+ * Forçar axios a usar fetch em vez de XMLHttpRequest
59
+ * Permite que FetchInterceptor mocke requisições de axios
60
+ */
61
+ function configureAxiosToUseFetch(logger) {
62
+ try {
63
+ // Verificar se axios está disponível globalmente
64
+ const globalObj = typeof window !== 'undefined' ? window : globalThis;
65
+ const axios = globalObj.axios;
66
+ if (!axios) {
67
+ logger.debug('axios não encontrado globalmente - vai ser necessário importar manualmente');
68
+ return;
69
+ }
70
+ // Configurar axios para usar fetch adapter
71
+ // Isso faz com que axios use fetch internamente, que é interceptado por FetchInterceptor
72
+ axios.defaults.adapter = async (config) => {
73
+ logger.debug(`📡 [axios -> fetch] Usando fetch para: ${config.method?.toUpperCase()} ${config.url}`);
74
+ const fetchConfig = {
75
+ method: config.method?.toUpperCase() || 'GET',
76
+ headers: config.headers || {},
77
+ body: config.data,
78
+ };
79
+ const response = await fetch(config.url, fetchConfig);
80
+ return {
81
+ data: await response.json(),
82
+ status: response.status,
83
+ statusText: response.statusText,
84
+ headers: response.headers,
85
+ config,
86
+ request: {},
87
+ };
88
+ };
89
+ logger.success('✅ axios configurado para usar fetch (FetchInterceptor ativo)');
90
+ }
91
+ catch (error) {
92
+ logger.debug('Erro ao configurar axios para fetch:', error);
93
+ }
94
+ }
95
+ // ============================================
55
96
  // INICIALIZAÇÃO
56
97
  // ============================================
57
98
  /**
@@ -91,11 +132,12 @@ async function initFluwaTool(partialConfig = {}) {
91
132
  logger.debug(`URL Filter configurado com ${urlFilter.getExcludedPatterns().length} padrões excluídos`);
92
133
  // 7. Criar interceptador de fetch
93
134
  fetchInterceptor = new FetchInterceptor_1.FetchInterceptor(logger, requestLogger, mockResolver, sessionId, config.getAppName(), urlFilter);
94
- // 7b. Criar interceptador de XMLHttpRequest (para axios, jQuery, etc)
135
+ // 7b. Criar interceptador de XMLHttpRequest (DESABILITADO)
136
+ // axios agora usa fetch via configureAxiosToUseFetch(), então não precisa mais de XHR
95
137
  xmlHttpRequestInterceptor = new XMLHttpRequestInterceptor_1.XMLHttpRequestInterceptor(logger, requestLogger, mockResolver, sessionId, config.getAppName(), urlFilter);
96
138
  // 8. Instalar interceptadores
97
139
  fetchInterceptor.install();
98
- xmlHttpRequestInterceptor.install();
140
+ // xmlHttpRequestInterceptor.install(); // ❌ Desabilitado - axios agora usa fetch
99
141
  // 9. Conectar WebSocket
100
142
  logger.debug('Conectando ao WebSocket...');
101
143
  try {
@@ -113,6 +155,9 @@ async function initFluwaTool(partialConfig = {}) {
113
155
  });
114
156
  isInitialized = true;
115
157
  logger.success('Fluwa-Tool inicializado com sucesso!');
158
+ // ✅ FORÇA AXIOS USAR FETCH EM VEZ DE XMLHttpRequest
159
+ // Isso permite que FetchInterceptor mocke requisições de axios
160
+ configureAxiosToUseFetch(logger);
116
161
  }
117
162
  catch (error) {
118
163
  logger.error('Erro ao inicializar Fluwa', error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluwa-tool/sdk",
3
- "version": "1.0.50",
3
+ "version": "1.0.52",
4
4
  "description": "Fluwa DevTools SDK for network interception and mocking",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",