@revenexx/integrations-node-sdk 1.8.0 → 1.8.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.
package/dist/index.cjs CHANGED
@@ -496,6 +496,43 @@ var CROSS_ORIGIN_SAFE_HEADERS = /* @__PURE__ */ new Set([
496
496
  function headerCrossesOrigin(name) {
497
497
  return CROSS_ORIGIN_SAFE_HEADERS.has(name.trim().toLowerCase());
498
498
  }
499
+ var UNSENDABLE_IN_HEADER_VALUE = /[\0-\x08\x0a-\x1f\x7f\u0100-\uffff]/;
500
+ var HEADER_NAME_TOKEN = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
501
+ function isHttpWhitespace(code) {
502
+ return code === 9 || code === 10 || code === 13 || code === 32;
503
+ }
504
+ function trimHttpWhitespace(value) {
505
+ let start = 0;
506
+ let end = value.length;
507
+ while (start < end && isHttpWhitespace(value.charCodeAt(start))) start++;
508
+ while (end > start && isHttpWhitespace(value.charCodeAt(end - 1))) end--;
509
+ return value.slice(start, end);
510
+ }
511
+ function invalidHeader(detail) {
512
+ return new NodeError("INVALID_HEADER", detail, { status: 0 });
513
+ }
514
+ function sendableHeaders(headers) {
515
+ if (typeof headers !== "object" || headers === null) {
516
+ throw invalidHeader("Headers must be an object or a list of pairs");
517
+ }
518
+ if (!(Symbol.iterator in headers) && Object.getOwnPropertySymbols(headers).length > 0) {
519
+ throw invalidHeader("A header name must be a string, not a symbol");
520
+ }
521
+ const entries = Symbol.iterator in headers ? Array.from(headers) : Object.entries(headers);
522
+ return entries.map((entry, i) => {
523
+ const pair = typeof entry === "object" && entry !== null && Symbol.iterator in entry ? Array.from(entry) : [];
524
+ if (pair.length !== 2) throw invalidHeader(`Header entry ${i} is not a name/value pair`);
525
+ const name = String(pair[0]);
526
+ const value = String(pair[1]);
527
+ if (!HEADER_NAME_TOKEN.test(name)) {
528
+ throw invalidHeader(`Header name ${JSON.stringify(name)} cannot be sent`);
529
+ }
530
+ if (UNSENDABLE_IN_HEADER_VALUE.test(trimHttpWhitespace(value))) {
531
+ throw invalidHeader(`Header ${JSON.stringify(name)} has a character in its value that cannot be sent`);
532
+ }
533
+ return [name, value];
534
+ });
535
+ }
499
536
  var DEFAULT_RETRY_ATTEMPTS = 0;
500
537
  var MAX_RETRY_ATTEMPTS = 5;
501
538
  var DEFAULT_RETRY_DELAY_MS = 1e3;
@@ -568,7 +605,7 @@ async function guardedFetch(url, fetchOptions, ctxSignal, effectiveMs) {
568
605
  throw new NodeError("BLOCKED_ADDRESS", "Blocked https\u2192http downgrade on redirect", { status: 0 });
569
606
  }
570
607
  await guardUrl(nextUrl, ctxSignal, effectiveMs);
571
- const headers = new Headers(currentInit.headers ?? void 0);
608
+ const headers = new Headers(currentInit.headers);
572
609
  let method = (currentInit.method ?? "GET").toUpperCase();
573
610
  let body = currentInit.body;
574
611
  if (redirectStatus === 303 || (redirectStatus === 301 || redirectStatus === 302) && method === "POST") {
@@ -593,6 +630,8 @@ async function safeFetch(url, options = {}) {
593
630
  const safeAttempts = Number.isFinite(rawAttempts) ? Math.min(Math.max(0, rawAttempts), MAX_RETRY_ATTEMPTS) : DEFAULT_RETRY_ATTEMPTS;
594
631
  const maxAttempts = safeAttempts + 1;
595
632
  const retryDelayMs = retry?.delayMs ?? DEFAULT_RETRY_DELAY_MS;
633
+ if (ctxSignal?.aborted) throw ctxSignal.reason;
634
+ if (fetchOptions.headers !== void 0) fetchOptions.headers = sendableHeaders(fetchOptions.headers);
596
635
  let lastError;
597
636
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
598
637
  if (ctxSignal?.aborted) throw ctxSignal.reason;
package/dist/index.js CHANGED
@@ -404,6 +404,43 @@ var CROSS_ORIGIN_SAFE_HEADERS = /* @__PURE__ */ new Set([
404
404
  function headerCrossesOrigin(name) {
405
405
  return CROSS_ORIGIN_SAFE_HEADERS.has(name.trim().toLowerCase());
406
406
  }
407
+ var UNSENDABLE_IN_HEADER_VALUE = /[\0-\x08\x0a-\x1f\x7f\u0100-\uffff]/;
408
+ var HEADER_NAME_TOKEN = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
409
+ function isHttpWhitespace(code) {
410
+ return code === 9 || code === 10 || code === 13 || code === 32;
411
+ }
412
+ function trimHttpWhitespace(value) {
413
+ let start = 0;
414
+ let end = value.length;
415
+ while (start < end && isHttpWhitespace(value.charCodeAt(start))) start++;
416
+ while (end > start && isHttpWhitespace(value.charCodeAt(end - 1))) end--;
417
+ return value.slice(start, end);
418
+ }
419
+ function invalidHeader(detail) {
420
+ return new NodeError("INVALID_HEADER", detail, { status: 0 });
421
+ }
422
+ function sendableHeaders(headers) {
423
+ if (typeof headers !== "object" || headers === null) {
424
+ throw invalidHeader("Headers must be an object or a list of pairs");
425
+ }
426
+ if (!(Symbol.iterator in headers) && Object.getOwnPropertySymbols(headers).length > 0) {
427
+ throw invalidHeader("A header name must be a string, not a symbol");
428
+ }
429
+ const entries = Symbol.iterator in headers ? Array.from(headers) : Object.entries(headers);
430
+ return entries.map((entry, i) => {
431
+ const pair = typeof entry === "object" && entry !== null && Symbol.iterator in entry ? Array.from(entry) : [];
432
+ if (pair.length !== 2) throw invalidHeader(`Header entry ${i} is not a name/value pair`);
433
+ const name = String(pair[0]);
434
+ const value = String(pair[1]);
435
+ if (!HEADER_NAME_TOKEN.test(name)) {
436
+ throw invalidHeader(`Header name ${JSON.stringify(name)} cannot be sent`);
437
+ }
438
+ if (UNSENDABLE_IN_HEADER_VALUE.test(trimHttpWhitespace(value))) {
439
+ throw invalidHeader(`Header ${JSON.stringify(name)} has a character in its value that cannot be sent`);
440
+ }
441
+ return [name, value];
442
+ });
443
+ }
407
444
  var DEFAULT_RETRY_ATTEMPTS = 0;
408
445
  var MAX_RETRY_ATTEMPTS = 5;
409
446
  var DEFAULT_RETRY_DELAY_MS = 1e3;
@@ -476,7 +513,7 @@ async function guardedFetch(url, fetchOptions, ctxSignal, effectiveMs) {
476
513
  throw new NodeError("BLOCKED_ADDRESS", "Blocked https\u2192http downgrade on redirect", { status: 0 });
477
514
  }
478
515
  await guardUrl(nextUrl, ctxSignal, effectiveMs);
479
- const headers = new Headers(currentInit.headers ?? void 0);
516
+ const headers = new Headers(currentInit.headers);
480
517
  let method = (currentInit.method ?? "GET").toUpperCase();
481
518
  let body = currentInit.body;
482
519
  if (redirectStatus === 303 || (redirectStatus === 301 || redirectStatus === 302) && method === "POST") {
@@ -501,6 +538,8 @@ async function safeFetch(url, options = {}) {
501
538
  const safeAttempts = Number.isFinite(rawAttempts) ? Math.min(Math.max(0, rawAttempts), MAX_RETRY_ATTEMPTS) : DEFAULT_RETRY_ATTEMPTS;
502
539
  const maxAttempts = safeAttempts + 1;
503
540
  const retryDelayMs = retry?.delayMs ?? DEFAULT_RETRY_DELAY_MS;
541
+ if (ctxSignal?.aborted) throw ctxSignal.reason;
542
+ if (fetchOptions.headers !== void 0) fetchOptions.headers = sendableHeaders(fetchOptions.headers);
504
543
  let lastError;
505
544
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
506
545
  if (ctxSignal?.aborted) throw ctxSignal.reason;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@revenexx/integrations-node-sdk",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "description": "TypeScript interfaces and utilities for Revenexx integration nodes",
5
5
  "license": "MIT",
6
6
  "author": "revenexx GmbH",