n8n-nodes-jygse-vw-weconnect 0.2.13 → 0.2.15

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.
@@ -32,10 +32,16 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
35
38
  Object.defineProperty(exports, "__esModule", { value: true });
36
39
  exports.VwWeConnect = void 0;
37
40
  const n8n_workflow_1 = require("n8n-workflow");
38
41
  const crypto = __importStar(require("crypto"));
42
+ const axios_1 = __importDefault(require("axios"));
43
+ const axios_cookiejar_support_1 = require("axios-cookiejar-support");
44
+ const tough_cookie_1 = require("tough-cookie");
39
45
  class VwWeConnect {
40
46
  constructor() {
41
47
  this.description = {
@@ -216,6 +222,9 @@ async function vwLogin(context, email, password) {
216
222
  const state = generateTraceId(); // Use UUID as state
217
223
  const traceId = generateTraceId(); // For weconnect-trace-id header
218
224
  const codeVerifier = generateCodeVerifier();
225
+ // Create cookie jar for session management (like ioBroker)
226
+ const jar = new tough_cookie_1.CookieJar();
227
+ const client = (0, axios_cookiejar_support_1.wrapper)(axios_1.default.create({ jar }));
219
228
  // Browser-like headers (EXACTLY from ioBroker.vw-connect)
220
229
  const browserHeaders = {
221
230
  'User-Agent': VW_USER_AGENT,
@@ -238,48 +247,39 @@ async function vwLogin(context, email, password) {
238
247
  '&state=' + state +
239
248
  '&code_challenge=' + codeChallenge +
240
249
  '&code_challenge_method=S256';
241
- // Use browser-like headers for initial request
242
- // Skip auto redirects so we can handle vwconnect:// redirect manually
243
- const authorizeResponse = await context.helpers.httpRequest({
244
- method: 'GET',
245
- url: authorizeUrl,
250
+ // Use axios with cookie jar for session management
251
+ const authorizeResponse = await client.get(authorizeUrl, {
246
252
  headers: browserHeaders,
247
- encoding: 'text',
248
- returnFullResponse: true,
249
- ignoreHttpStatusErrors: true,
250
- skipAutoFollowRedirects: true,
253
+ maxRedirects: 0, // Don't follow any redirects
254
+ validateStatus: () => true, // Accept any status code
255
+ }).catch(err => {
256
+ // axios throws on redirect when maxRedirects=0, but we can get the response
257
+ if (err.response)
258
+ return err.response;
259
+ throw err;
251
260
  });
252
- // Extract response body and check for redirect
261
+ // Extract response body and check for redirect (axios format)
253
262
  let htmlContent;
254
263
  let currentUrl = '';
255
264
  let stateToken = '';
256
265
  let httpStatusCode = 0;
257
- if (typeof authorizeResponse === 'string') {
258
- htmlContent = authorizeResponse;
259
- }
260
- else if (authorizeResponse && typeof authorizeResponse === 'object') {
261
- const respObj = authorizeResponse;
262
- const respHeaders = respObj.headers;
263
- httpStatusCode = respObj.statusCode || 0;
264
- // Check for redirect in headers (case-insensitive)
265
- if (respHeaders) {
266
- const locationHeader = respHeaders.location || respHeaders.Location;
267
- if (locationHeader) {
268
- currentUrl = locationHeader;
269
- }
270
- }
271
- if (respObj.body && typeof respObj.body === 'string') {
272
- htmlContent = respObj.body;
273
- }
274
- else if (respObj.data && typeof respObj.data === 'string') {
275
- htmlContent = respObj.data;
276
- }
277
- else {
278
- htmlContent = JSON.stringify(respObj);
266
+ // axios response format: { data, status, headers, ... }
267
+ httpStatusCode = authorizeResponse.status || 0;
268
+ // Check for redirect in headers
269
+ if (authorizeResponse.headers) {
270
+ const locationHeader = authorizeResponse.headers.location || authorizeResponse.headers.Location;
271
+ if (locationHeader) {
272
+ currentUrl = locationHeader;
279
273
  }
280
274
  }
275
+ if (typeof authorizeResponse.data === 'string') {
276
+ htmlContent = authorizeResponse.data;
277
+ }
278
+ else if (authorizeResponse.data) {
279
+ htmlContent = JSON.stringify(authorizeResponse.data);
280
+ }
281
281
  else {
282
- htmlContent = String(authorizeResponse);
282
+ htmlContent = '';
283
283
  }
284
284
  // Debug: If we got an error page (status 400/500 or "Oops" in content), throw with details
285
285
  if (httpStatusCode >= 400 || htmlContent.includes('Oops!, something went wrong')) {
@@ -306,38 +306,23 @@ async function vwLogin(context, email, password) {
306
306
  if (!currentUrl.startsWith('http') && !currentUrl.startsWith('/')) {
307
307
  break;
308
308
  }
309
- // Follow the redirect using API headers
309
+ // Follow the redirect using axios with cookie jar
310
310
  const followUrl = currentUrl.startsWith('http') ? currentUrl : `https://identity.vwgroup.io${currentUrl}`;
311
- const followResponse = await context.helpers.httpRequest({
312
- method: 'GET',
313
- url: followUrl,
311
+ const followResponse = await client.get(followUrl, {
314
312
  headers: browserHeaders,
315
- encoding: 'text',
316
- returnFullResponse: true,
317
- ignoreHttpStatusErrors: true,
318
- skipAutoFollowRedirects: true,
319
- });
320
- if (typeof followResponse === 'string') {
321
- htmlContent = followResponse;
322
- currentUrl = '';
323
- }
324
- else if (followResponse && typeof followResponse === 'object') {
325
- const respObj = followResponse;
326
- const respHeaders = respObj.headers;
327
- currentUrl = '';
328
- if (respHeaders) {
329
- const locationHeader = respHeaders.location || respHeaders.Location;
330
- if (locationHeader) {
331
- currentUrl = locationHeader;
332
- }
333
- }
334
- if (respObj.body && typeof respObj.body === 'string') {
335
- htmlContent = respObj.body;
336
- }
337
- else if (respObj.data && typeof respObj.data === 'string') {
338
- htmlContent = respObj.data;
313
+ maxRedirects: 0,
314
+ validateStatus: () => true,
315
+ }).catch(err => err.response || { data: '', headers: {}, status: 0 });
316
+ currentUrl = '';
317
+ if (followResponse.headers) {
318
+ const locationHeader = followResponse.headers.location || followResponse.headers.Location;
319
+ if (locationHeader) {
320
+ currentUrl = locationHeader;
339
321
  }
340
322
  }
323
+ if (typeof followResponse.data === 'string') {
324
+ htmlContent = followResponse.data;
325
+ }
341
326
  maxInitialRedirects--;
342
327
  }
343
328
  // Try to extract state token from the final HTML if not found in URL
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-jygse-vw-weconnect",
3
- "version": "0.2.13",
3
+ "version": "0.2.15",
4
4
  "description": "n8n community node for VW We Connect - Control your Volkswagen T6.1 and other VW vehicles",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",
@@ -43,8 +43,14 @@
43
43
  "dist/nodes/VwWeConnect/VwWeConnect.node.js"
44
44
  ]
45
45
  },
46
+ "dependencies": {
47
+ "axios": "^1.6.0",
48
+ "axios-cookiejar-support": "^5.0.0",
49
+ "tough-cookie": "^4.1.0"
50
+ },
46
51
  "devDependencies": {
47
52
  "@types/node": "^20.10.0",
53
+ "@types/tough-cookie": "^4.0.5",
48
54
  "@typescript-eslint/parser": "^6.0.0",
49
55
  "eslint": "^8.56.0",
50
56
  "gulp": "^4.0.2",