path.js 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.path = exports.createPathTagFunction = void 0;
  4. exports.encodeURIPath = encodeURIPath;
  5. const error_1 = require("../../core/error.js");
  6. /**
  7. * Percent-encode everything that isn't safe to have in a path without encoding safe chars.
  8. *
  9. * Taken from https://datatracker.ietf.org/doc/html/rfc3986#section-3.3:
  10. * > unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
  11. * > sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
  12. * > pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
  13. */
  14. function encodeURIPath(str) {
  15. return str.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent);
  16. }
  17. const EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null));
  18. const createPathTagFunction = (pathEncoder = encodeURIPath) => function path(statics, ...params) {
  19. // If there are no params, no processing is needed.
  20. if (statics.length === 1)
  21. return statics[0];
  22. let postPath = false;
  23. const invalidSegments = [];
  24. const path = statics.reduce((previousValue, currentValue, index) => {
  25. if (/[?#]/.test(currentValue)) {
  26. postPath = true;
  27. }
  28. const value = params[index];
  29. let encoded = (postPath ? encodeURIComponent : pathEncoder)('' + value);
  30. if (index !== params.length &&
  31. (value == null ||
  32. (typeof value === 'object' &&
  33. // handle values from other realms
  34. value.toString ===
  35. Object.getPrototypeOf(Object.getPrototypeOf(value.hasOwnProperty ?? EMPTY) ?? EMPTY)
  36. ?.toString))) {
  37. encoded = value + '';
  38. invalidSegments.push({
  39. start: previousValue.length + currentValue.length,
  40. length: encoded.length,
  41. error: `Value of type ${Object.prototype.toString
  42. .call(value)
  43. .slice(8, -1)} is not a valid path parameter`,
  44. });
  45. }
  46. return previousValue + currentValue + (index === params.length ? '' : encoded);
  47. }, '');
  48. const pathOnly = path.split(/[?#]/, 1)[0];
  49. const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi;
  50. let match;
  51. // Find all invalid segments
  52. while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) {
  53. invalidSegments.push({
  54. start: match.index,
  55. length: match[0].length,
  56. error: `Value "${match[0]}" can\'t be safely passed as a path parameter`,
  57. });
  58. }
  59. invalidSegments.sort((a, b) => a.start - b.start);
  60. if (invalidSegments.length > 0) {
  61. let lastEnd = 0;
  62. const underline = invalidSegments.reduce((acc, segment) => {
  63. const spaces = ' '.repeat(segment.start - lastEnd);
  64. const arrows = '^'.repeat(segment.length);
  65. lastEnd = segment.start + segment.length;
  66. return acc + spaces + arrows;
  67. }, '');
  68. throw new error_1.OpenAIError(`Path parameters result in path with invalid segments:\n${invalidSegments
  69. .map((e) => e.error)
  70. .join('\n')}\n${path}\n${underline}`);
  71. }
  72. return path;
  73. };
  74. exports.createPathTagFunction = createPathTagFunction;
  75. /**
  76. * URI-encodes path params and ensures no unsafe /./ or /../ path segments are introduced.
  77. */
  78. exports.path = (0, exports.createPathTagFunction)(encodeURIPath);
  79. //# sourceMappingURL=path.js.map