@fluwa-tool/sdk 1.0.39 → 1.0.41

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.
@@ -14,7 +14,7 @@ class XMLHttpRequestInterceptor {
14
14
  this.sessionId = sessionId;
15
15
  this.appName = appName;
16
16
  this.isInstalled = false;
17
- this.urlFilter = null; // URL filter para evitar loops infinitos
17
+ this.urlFilter = null;
18
18
  this.urlFilter = urlFilter || null;
19
19
  }
20
20
  install() {
@@ -22,18 +22,15 @@ class XMLHttpRequestInterceptor {
22
22
  this.logger.warn('XMLHttpRequest interceptor já foi instalado');
23
23
  return;
24
24
  }
25
- // Verificar se XMLHttpRequest está disponível (apenas em navegadores)
26
25
  if (typeof XMLHttpRequest === 'undefined') {
27
26
  this.logger.debug('XMLHttpRequest não disponível nesse ambiente (requer navegador)');
28
27
  return;
29
28
  }
30
29
  const self = this;
31
30
  const originalXHR = XMLHttpRequest.prototype;
32
- // Armazenar referência ao open original
33
31
  this.originalOpen = originalXHR.open;
34
32
  this.originalSend = originalXHR.send;
35
33
  this.originalSetRequestHeader = originalXHR.setRequestHeader;
36
- // Interceptar open()
37
34
  originalXHR.open = function (method, url, ...args) {
38
35
  const xhr = this;
39
36
  xhr._fluwaMethod = method.toUpperCase();
@@ -43,7 +40,6 @@ class XMLHttpRequestInterceptor {
43
40
  xhr._fluwaStartTime = Date.now();
44
41
  return self.originalOpen.apply(this, [method, url, ...args]);
45
42
  };
46
- // Interceptar setRequestHeader()
47
43
  originalXHR.setRequestHeader = function (header, value) {
48
44
  const xhr = this;
49
45
  if (!xhr._fluwaHeaders) {
@@ -52,7 +48,6 @@ class XMLHttpRequestInterceptor {
52
48
  xhr._fluwaHeaders[header] = value;
53
49
  return self.originalSetRequestHeader.apply(this, [header, value]);
54
50
  };
55
- // Interceptar send()
56
51
  this.originalSend = originalXHR.send;
57
52
  originalXHR.send = function (body) {
58
53
  const xhr = this;
@@ -60,8 +55,6 @@ class XMLHttpRequestInterceptor {
60
55
  const url = xhr._fluwaUrl;
61
56
  const requestId = xhr._fluwaRequestId;
62
57
  const headers = xhr._fluwaHeaders || {};
63
- // ✅ Verificar URL Filter: ignorar requisições para servidor Fluwa ou URLs excluídas
64
- // Isso previne loops infinitos onde o servidor Fluwa faz requisições que são interceptadas
65
58
  if (self.urlFilter && !self.urlFilter.shouldIntercept(url)) {
66
59
  self.logger.debug(`🔧 [XMLHttpRequestInterceptor] Ignorando URL excluída: ${url} (bypass filtering)`);
67
60
  return self.originalSend.apply(this, [body]);
@@ -77,51 +70,92 @@ class XMLHttpRequestInterceptor {
77
70
  appName: self.appName,
78
71
  source: types_1.RequestSource.REAL,
79
72
  };
80
- // Logar início imediatamente
81
73
  self.requestLogger.logStart(requestMetadata).catch(() => { });
82
- // Interceptar mudanças de estado
83
74
  const originalOnReadyStateChange = xhr.onreadystatechange;
84
- xhr.onreadystatechange = function (event) {
85
- if (xhr.readyState === 4) {
86
- // Requisição completou
87
- requestMetadata.status = xhr.status;
88
- // Tentar extrair response
89
- try {
90
- if (xhr.responseType === '' || xhr.responseType === 'text') {
91
- if (xhr.responseText) {
92
- requestMetadata.response = self.safeParseBody(xhr.responseText);
75
+ // Verificar mock com retry
76
+ const checkMockWithRetry = async () => {
77
+ let mockResponse = await self.mockResolver.resolve(method, url);
78
+ if (!mockResponse) {
79
+ await new Promise(resolve => setTimeout(resolve, 200));
80
+ mockResponse = await self.mockResolver.resolve(method, url);
81
+ }
82
+ return mockResponse;
83
+ };
84
+ checkMockWithRetry().then(mockResponse => {
85
+ if (mockResponse) {
86
+ // Mock encontrado - simular resposta
87
+ requestMetadata.source = types_1.RequestSource.MOCK;
88
+ requestMetadata.status = mockResponse.status || 200;
89
+ requestMetadata.response = mockResponse.response;
90
+ const delay = mockResponse.delay || 0;
91
+ setTimeout(() => {
92
+ const duration = Date.now() - (xhr._fluwaStartTime || 0);
93
+ requestMetadata.duration = duration;
94
+ self.requestLogger.logComplete(requestMetadata).catch(() => { });
95
+ // Simular readyState = 4 chamando onreadystatechange 3x
96
+ try {
97
+ // Chamar para cada readyState
98
+ for (let state = 1; state <= 4; state++) {
99
+ Object.defineProperty(xhr, 'readyState', { value: state, configurable: true, writable: true });
100
+ if (state === 4) {
101
+ Object.defineProperty(xhr, 'status', { value: mockResponse.status || 200, configurable: true, writable: true });
102
+ Object.defineProperty(xhr, 'statusText', { value: 'Mock', configurable: true, writable: true });
103
+ Object.defineProperty(xhr, 'responseText', { value: JSON.stringify(mockResponse.response), configurable: true, writable: true });
104
+ Object.defineProperty(xhr, 'response', { value: mockResponse.response, configurable: true, writable: true });
105
+ }
106
+ if (originalOnReadyStateChange) {
107
+ originalOnReadyStateChange.call(xhr);
108
+ }
93
109
  }
94
110
  }
95
- else if (xhr.response) {
96
- if (typeof xhr.response === 'string') {
97
- requestMetadata.response = self.safeParseBody(xhr.response);
98
- }
99
- else {
100
- requestMetadata.response = `[${xhr.responseType}]`;
101
- }
111
+ catch (error) {
112
+ self.logger.debug('Erro ao simular resposta mockada, fallback para servidor real:', error);
113
+ self.originalSend.apply(xhr, [body]);
102
114
  }
103
- }
104
- catch (e) {
115
+ }, delay);
116
+ return;
117
+ }
118
+ // Sem mock - fazer request real
119
+ xhr.onreadystatechange = function (event) {
120
+ if (xhr.readyState === 4) {
121
+ requestMetadata.status = xhr.status;
105
122
  try {
106
- if (xhr.responseText) {
107
- requestMetadata.response = xhr.responseText;
123
+ if (xhr.responseType === '' || xhr.responseType === 'text') {
124
+ if (xhr.responseText) {
125
+ requestMetadata.response = self.safeParseBody(xhr.responseText);
126
+ }
127
+ }
128
+ else if (xhr.response) {
129
+ if (typeof xhr.response === 'string') {
130
+ requestMetadata.response = self.safeParseBody(xhr.response);
131
+ }
132
+ else {
133
+ requestMetadata.response = `[${xhr.responseType}]`;
134
+ }
108
135
  }
109
136
  }
110
- catch {
111
- requestMetadata.response = undefined;
137
+ catch (e) {
138
+ try {
139
+ if (xhr.responseText) {
140
+ requestMetadata.response = xhr.responseText;
141
+ }
142
+ }
143
+ catch {
144
+ requestMetadata.response = undefined;
145
+ }
112
146
  }
147
+ const duration = Date.now() - (xhr._fluwaStartTime || 0);
148
+ requestMetadata.duration = duration;
149
+ self.requestLogger.logComplete(requestMetadata).catch(() => { });
113
150
  }
114
- const duration = Date.now() - (xhr._fluwaStartTime || 0);
115
- requestMetadata.duration = duration;
116
- self.requestLogger.logComplete(requestMetadata).catch(() => { });
117
- }
118
- // Chamar handler original
119
- if (originalOnReadyStateChange) {
120
- originalOnReadyStateChange.call(this, event);
121
- }
122
- };
123
- // Chamar send original
124
- return self.originalSend.apply(this, [body]);
151
+ if (originalOnReadyStateChange) {
152
+ originalOnReadyStateChange.call(this, event);
153
+ }
154
+ };
155
+ self.originalSend.apply(xhr, [body]);
156
+ }).catch(() => {
157
+ self.originalSend.apply(xhr, [body]);
158
+ });
125
159
  };
126
160
  this.isInstalled = true;
127
161
  this.logger.success('XMLHttpRequest interceptor instalado');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluwa-tool/sdk",
3
- "version": "1.0.39",
3
+ "version": "1.0.41",
4
4
  "description": "Fluwa DevTools SDK for network interception and mocking",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",