swagger-typescript-api 13.12.0 → 13.12.2

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.
@@ -54,6 +54,10 @@ let _apidevtools_swagger_parser = require("@apidevtools/swagger-parser");
54
54
  _apidevtools_swagger_parser = __toESM(_apidevtools_swagger_parser, 1);
55
55
  let yaml = require("yaml");
56
56
  yaml = __toESM(yaml, 1);
57
+ let node_dns_promises = require("node:dns/promises");
58
+ node_dns_promises = __toESM(node_dns_promises, 1);
59
+ let node_net = require("node:net");
60
+ node_net = __toESM(node_net, 1);
57
61
  let node_module = require("node:module");
58
62
  node_module = __toESM(node_module, 1);
59
63
  let node_url = require("node:url");
@@ -208,7 +212,7 @@ var ComponentTypeNameResolver = class extends NameResolver {
208
212
  //#endregion
209
213
  //#region package.json
210
214
  var name = "swagger-typescript-api";
211
- var version = "13.12.0";
215
+ var version = "13.12.2";
212
216
  var description = "Generate the API client for Fetch or Axios from an OpenAPI Specification";
213
217
  //#endregion
214
218
  //#region src/constants.ts
@@ -276,6 +280,12 @@ const SCHEMA_TYPES$1 = {
276
280
  COMPLEX_UNKNOWN: "__unknown"
277
281
  };
278
282
  //#endregion
283
+ //#region src/util/escape-js-string-literal.ts
284
+ /** Escapes a value for insertion into a double-quoted JS/TS string literal (without surrounding quotes). */
285
+ function escapeJsStringLiteral(value) {
286
+ return JSON.stringify(value).slice(1, -1);
287
+ }
288
+ //#endregion
279
289
  //#region src/util/object-assign.ts
280
290
  const objectAssign = (target, updater) => {
281
291
  if (!updater) return;
@@ -501,7 +511,7 @@ var CodeGenConfig = class {
501
511
  /**
502
512
  * "$A"
503
513
  */
504
- StringValue: (content) => `"${content}"`,
514
+ StringValue: (content) => `"${escapeJsStringLiteral(String(content))}"`,
505
515
  /**
506
516
  * $A
507
517
  */
@@ -722,6 +732,7 @@ const OPENAPI_COMPONENT_NAMES = new Set([
722
732
  "pathItems"
723
733
  ]);
724
734
  var SchemaComponentsMap = class {
735
+ config;
725
736
  _data = [];
726
737
  constructor(config) {
727
738
  this.config = config;
@@ -1643,6 +1654,9 @@ var SchemaParser = class {
1643
1654
  //#endregion
1644
1655
  //#region src/schema-parser/schema-utils.ts
1645
1656
  var SchemaUtils = class {
1657
+ config;
1658
+ schemaComponentsMap;
1659
+ typeNameFormatter;
1646
1660
  constructor(config, schemaComponentsMap, typeNameFormatter) {
1647
1661
  this.config = config;
1648
1662
  this.schemaComponentsMap = schemaComponentsMap;
@@ -1877,6 +1891,15 @@ var SchemaParserFabric = class {
1877
1891
  };
1878
1892
  };
1879
1893
  //#endregion
1894
+ //#region src/util/escape-js-template-literal-with-path-params.ts
1895
+ /**
1896
+ * Escapes `\`, backticks, and `${` for insertion into a JS template literal
1897
+ * (without surrounding backticks).
1898
+ */
1899
+ function escapeJsTemplateLiteralStatic(value) {
1900
+ return value.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
1901
+ }
1902
+ //#endregion
1880
1903
  //#region src/util/id.ts
1881
1904
  const generateId = () => node_crypto.randomUUID();
1882
1905
  //#endregion
@@ -1908,6 +1931,11 @@ const CONTENT_KIND = {
1908
1931
  */
1909
1932
  const MAX_EXTRACT_SCHEMA_KEY_COLLISION_ATTEMPTS = 32;
1910
1933
  var SchemaRoutes = class {
1934
+ config;
1935
+ schemaParserFabric;
1936
+ schemaComponentsMap;
1937
+ templatesWorker;
1938
+ typeNameFormatter;
1911
1939
  schemaUtils;
1912
1940
  FORM_DATA_TYPES = [];
1913
1941
  routes = [];
@@ -1994,10 +2022,11 @@ var SchemaRoutes = class {
1994
2022
  in: "path"
1995
2023
  });
1996
2024
  }
2025
+ const escapedRouteName = escapeJsTemplateLiteralStatic(routeName || "");
1997
2026
  let fixedRoute = pathParams.reduce((fixedRoute, pathParam, i, arr) => {
1998
2027
  const insertion = this.config.hooks.onInsertPathParam(pathParam.name, i, arr, fixedRoute) || pathParam.name;
1999
2028
  return fixedRoute.replace(pathParam.$match, `\${${insertion}}`);
2000
- }, routeName || "");
2029
+ }, escapedRouteName);
2001
2030
  const queryParamMatches = fixedRoute.match(/(\{\?.*\})/g);
2002
2031
  const queryParams = [];
2003
2032
  if (queryParamMatches?.length) {
@@ -2703,8 +2732,124 @@ function parseSchemaContent(content) {
2703
2732
  }
2704
2733
  }
2705
2734
  //#endregion
2735
+ //#region src/util/remote-schema-fetch.ts
2736
+ const MAX_REDIRECTS = 5;
2737
+ function isPrivateIpv4(ip) {
2738
+ const match = ip.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
2739
+ if (!match) return false;
2740
+ const octets = match.slice(1).map(Number);
2741
+ if (octets.some((octet) => octet > 255)) return false;
2742
+ const [a, b] = octets;
2743
+ return a === 0 || a === 10 || a === 127 || a === 169 && b === 254 || a === 172 && b >= 16 && b <= 31 || a === 192 && b === 168;
2744
+ }
2745
+ function isPrivateIpv6(ip) {
2746
+ const normalized = ip.toLowerCase();
2747
+ if (normalized === "::" || normalized === "::1") return true;
2748
+ if (normalized.startsWith("fe80:")) return true;
2749
+ const firstHextet = normalized.split(":")[0] ?? "";
2750
+ if (firstHextet >= "fc00" && firstHextet <= "fdff") return true;
2751
+ const ipv4Mapped = normalized.match(/^::ffff:(\d+\.\d+\.\d+\.\d+)$/);
2752
+ if (ipv4Mapped?.[1]) return isPrivateIpv4(ipv4Mapped[1]);
2753
+ const ipv4MappedHex = normalized.match(/^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/);
2754
+ if (ipv4MappedHex?.[1] && ipv4MappedHex?.[2]) {
2755
+ const h1 = parseInt(ipv4MappedHex[1], 16);
2756
+ const h2 = parseInt(ipv4MappedHex[2], 16);
2757
+ return isPrivateIpv4(`${h1 >> 8 & 255}.${h1 & 255}.${h2 >> 8 & 255}.${h2 & 255}`);
2758
+ }
2759
+ return false;
2760
+ }
2761
+ function isPrivateIp(ip) {
2762
+ const family = node_net.isIP(ip);
2763
+ if (family === 4) return isPrivateIpv4(ip);
2764
+ if (family === 6) return isPrivateIpv6(ip);
2765
+ return false;
2766
+ }
2767
+ function isBlockedHostname(hostname) {
2768
+ const normalized = hostname.toLowerCase();
2769
+ return normalized === "localhost" || normalized.endsWith(".localhost");
2770
+ }
2771
+ async function resolveHostnameAddresses(hostname) {
2772
+ try {
2773
+ return (await node_dns_promises.lookup(hostname, {
2774
+ all: true,
2775
+ verbatim: true
2776
+ })).map((record) => record.address);
2777
+ } catch {
2778
+ return [];
2779
+ }
2780
+ }
2781
+ async function isPublicRemoteHost(urlString) {
2782
+ let parsed;
2783
+ try {
2784
+ parsed = new URL(urlString);
2785
+ } catch {
2786
+ return false;
2787
+ }
2788
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return false;
2789
+ const hostname = parsed.hostname.startsWith("[") && parsed.hostname.endsWith("]") ? parsed.hostname.slice(1, -1) : parsed.hostname;
2790
+ if (isBlockedHostname(hostname)) return false;
2791
+ if (node_net.isIP(hostname)) return !isPrivateIp(hostname);
2792
+ const addresses = await resolveHostnameAddresses(hostname);
2793
+ if (addresses.length === 0) return false;
2794
+ return addresses.every((address) => !isPrivateIp(address));
2795
+ }
2796
+ function isSameHttpOrigin(a, b) {
2797
+ if (typeof b !== "string") return false;
2798
+ try {
2799
+ const urlA = new URL(a);
2800
+ const urlB = new URL(b);
2801
+ return urlA.protocol === urlB.protocol && urlA.host === urlB.host;
2802
+ } catch {
2803
+ return false;
2804
+ }
2805
+ }
2806
+ async function isRemoteSchemaFetchAllowed(urlString, policy) {
2807
+ const { specSourceUrl, allowExplicitSpecUrl = false } = policy;
2808
+ if (allowExplicitSpecUrl && typeof specSourceUrl === "string" && stripUrlHash(urlString) === stripUrlHash(specSourceUrl)) return true;
2809
+ if (typeof specSourceUrl === "string" && isSameHttpOrigin(urlString, specSourceUrl)) return true;
2810
+ return isPublicRemoteHost(urlString);
2811
+ }
2812
+ function stripUrlHash(urlString) {
2813
+ return urlString.split("#")[0] || urlString;
2814
+ }
2815
+ function resolveRedirectUrl(location, baseUrl) {
2816
+ try {
2817
+ return new URL(location, baseUrl).toString();
2818
+ } catch {
2819
+ return null;
2820
+ }
2821
+ }
2822
+ async function fetchRemoteSchemaResponse(urlString, init, policy) {
2823
+ let currentUrl = urlString;
2824
+ let redirectCount = 0;
2825
+ while (true) {
2826
+ if (!await isRemoteSchemaFetchAllowed(currentUrl, {
2827
+ specSourceUrl: policy.specSourceUrl,
2828
+ allowExplicitSpecUrl: policy.allowExplicitSpecUrl && redirectCount === 0
2829
+ })) return null;
2830
+ const response = await fetch(currentUrl, {
2831
+ ...init,
2832
+ redirect: "manual"
2833
+ });
2834
+ if (response.status >= 300 && response.status < 400) {
2835
+ const location = response.headers.get("location");
2836
+ if (!location || redirectCount >= MAX_REDIRECTS) return null;
2837
+ const redirectUrl = resolveRedirectUrl(location, currentUrl);
2838
+ if (!redirectUrl) return null;
2839
+ currentUrl = redirectUrl;
2840
+ redirectCount += 1;
2841
+ continue;
2842
+ }
2843
+ return response;
2844
+ }
2845
+ }
2846
+ //#endregion
2706
2847
  //#region src/resolved-swagger-schema.ts
2707
2848
  var ResolvedSwaggerSchema = class ResolvedSwaggerSchema {
2849
+ config;
2850
+ usageSchema;
2851
+ originalSchema;
2852
+ resolvers;
2708
2853
  parsedRefsCache = /* @__PURE__ */ new Map();
2709
2854
  externalSchemaCache = /* @__PURE__ */ new Map();
2710
2855
  httpMethodSegments = new Set([
@@ -2741,8 +2886,13 @@ var ResolvedSwaggerSchema = class ResolvedSwaggerSchema {
2741
2886
  isHttpUrl(value) {
2742
2887
  return /^https?:\/\//i.test(value);
2743
2888
  }
2744
- getRemoteRequestHeaders() {
2745
- return Object.assign({}, this.config.authorizationToken ? { Authorization: this.config.authorizationToken } : {}, this.config.requestOptions?.headers || {});
2889
+ isExplicitSpecUrl(url) {
2890
+ return typeof this.config.url === "string" && this.stripHash(url) === this.stripHash(this.config.url);
2891
+ }
2892
+ getRemoteRequestHeaders(targetUrl) {
2893
+ const headers = {};
2894
+ if (this.config.authorizationToken && targetUrl && typeof this.config.url === "string" && isSameHttpOrigin(targetUrl, this.config.url)) headers.Authorization = this.config.authorizationToken;
2895
+ return Object.assign(headers, this.config.requestOptions?.headers || {});
2746
2896
  }
2747
2897
  stripHash(urlOrPath) {
2748
2898
  return urlOrPath.split("#")[0] || urlOrPath;
@@ -2887,8 +3037,11 @@ var ResolvedSwaggerSchema = class ResolvedSwaggerSchema {
2887
3037
  }
2888
3038
  async fetchRemoteSchemaDocument(url) {
2889
3039
  try {
2890
- const response = await fetch(url, { headers: this.getRemoteRequestHeaders() });
2891
- if (!response.ok) return null;
3040
+ const response = await fetchRemoteSchemaResponse(url, { headers: this.getRemoteRequestHeaders(url) }, {
3041
+ specSourceUrl: typeof this.config.url === "string" ? this.config.url : void 0,
3042
+ allowExplicitSpecUrl: this.isExplicitSpecUrl(url)
3043
+ });
3044
+ if (!response?.ok) return null;
2892
3045
  const content = await response.text();
2893
3046
  try {
2894
3047
  const parsed = parseSchemaContent(content);
@@ -2919,7 +3072,7 @@ var ResolvedSwaggerSchema = class ResolvedSwaggerSchema {
2919
3072
  const [externalPath = ""] = normalizedRef.split("#");
2920
3073
  if (!externalPath) continue;
2921
3074
  const absoluteUrl = this.resolveAbsoluteUrl(externalPath, currentUrl);
2922
- if (absoluteUrl && !visited.has(absoluteUrl)) queue.push(absoluteUrl);
3075
+ if (absoluteUrl && !visited.has(absoluteUrl) && await isRemoteSchemaFetchAllowed(absoluteUrl, { specSourceUrl: this.config.url })) queue.push(absoluteUrl);
2923
3076
  }
2924
3077
  }
2925
3078
  }
@@ -3139,7 +3292,7 @@ var ResolvedSwaggerSchema = class ResolvedSwaggerSchema {
3139
3292
  external: true,
3140
3293
  http: {
3141
3294
  ...config.requestOptions,
3142
- headers: Object.assign({}, config.authorizationToken ? { Authorization: config.authorizationToken } : {}, config.requestOptions?.headers ?? {})
3295
+ headers: config.requestOptions?.headers ?? {}
3143
3296
  }
3144
3297
  }
3145
3298
  };
@@ -3928,7 +4081,7 @@ var CodeGenProcess = class {
3928
4081
  description: ""
3929
4082
  }, externalDocs || {}),
3930
4083
  tags: (0, es_toolkit.compact)(tags || []),
3931
- baseUrl: serverUrl,
4084
+ baseUrl: escapeJsStringLiteral(serverUrl ?? ""),
3932
4085
  title,
3933
4086
  version
3934
4087
  };
@@ -4170,4 +4323,4 @@ Object.defineProperty(exports, "version", {
4170
4323
  }
4171
4324
  });
4172
4325
 
4173
- //# sourceMappingURL=src-t0Ockaa6.cjs.map
4326
+ //# sourceMappingURL=src-VxYc58-l.cjs.map