@scalar/snippetz 0.9.32 → 0.10.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.
Files changed (40) hide show
  1. package/README.md +12 -0
  2. package/dist/libs/browser-request.d.ts.map +1 -1
  3. package/dist/libs/browser-request.js +17 -6
  4. package/dist/libs/http.d.ts.map +1 -1
  5. package/dist/libs/http.js +3 -2
  6. package/dist/libs/javascript.d.ts +3 -1
  7. package/dist/libs/javascript.d.ts.map +1 -1
  8. package/dist/libs/javascript.js +23 -24
  9. package/dist/plugins/c/libcurl/libcurl.js +1 -1
  10. package/dist/plugins/csharp/httpclient/httpclient.js +2 -2
  11. package/dist/plugins/csharp/restsharp/restsharp.d.ts.map +1 -1
  12. package/dist/plugins/csharp/restsharp/restsharp.js +7 -15
  13. package/dist/plugins/dart/http/http.d.ts.map +1 -1
  14. package/dist/plugins/dart/http/http.js +19 -2
  15. package/dist/plugins/http/http11/http11.d.ts.map +1 -1
  16. package/dist/plugins/http/http11/http11.js +2 -1
  17. package/dist/plugins/js/fetch/fetch.js +2 -2
  18. package/dist/plugins/js/ofetch/ofetch.js +2 -2
  19. package/dist/plugins/node/fetch/fetch.js +2 -2
  20. package/dist/plugins/node/ofetch/ofetch.js +2 -2
  21. package/dist/plugins/node/undici/undici.js +2 -2
  22. package/dist/plugins/php/curl/curl.d.ts.map +1 -1
  23. package/dist/plugins/php/curl/curl.js +2 -1
  24. package/dist/plugins/php/guzzle/guzzle.js +2 -2
  25. package/dist/plugins/php/laravel/laravel.js +2 -2
  26. package/dist/plugins/python/aiohttp/aiohttp.d.ts.map +1 -1
  27. package/dist/plugins/python/aiohttp/aiohttp.js +9 -5
  28. package/dist/plugins/python/requestsLike.d.ts.map +1 -1
  29. package/dist/plugins/python/requestsLike.js +6 -2
  30. package/dist/plugins/r/httr2/httr2.js +2 -2
  31. package/dist/plugins/ruby/native/native.d.ts.map +1 -1
  32. package/dist/plugins/ruby/native/native.js +4 -4
  33. package/dist/plugins/rust/reqwest/reqwest.js +5 -2
  34. package/dist/plugins/shared/axios.d.ts.map +1 -1
  35. package/dist/plugins/shared/axios.js +9 -25
  36. package/dist/plugins/shell/curl/curl.d.ts.map +1 -1
  37. package/dist/plugins/shell/curl/curl.js +11 -16
  38. package/dist/plugins/shell/wget/wget.d.ts.map +1 -1
  39. package/dist/plugins/shell/wget/wget.js +5 -16
  40. package/package.json +3 -3
package/README.md CHANGED
@@ -102,3 +102,15 @@ We are API nerds. You too? Let's chat on Discord: <https://discord.gg/scalar>
102
102
  ## License
103
103
 
104
104
  The source code in this repository is licensed under [MIT](https://github.com/scalar/scalar/blob/main/LICENSE).
105
+
106
+ ## Cookies in browser examples
107
+
108
+ XHR and jQuery examples use `document.cookie` and enable `withCredentials` whenever the HAR contains cookie values, including an explicit `Cookie` header without OpenAPI cookie-style parameters. This intentionally changes those legacy examples: browsers forbid setting the `Cookie` request header directly. Requests without cookies remain uncredentialed.
109
+
110
+ The setup writes cookies for the page's domain and cannot set cookies for an unrelated API domain or create HttpOnly cookies. For a cross-origin API, obtain cookies through that API's authentication flow instead. Cookie domain, path, Secure, SameSite, and browser third-party-cookie policies still apply.
111
+
112
+ [Credentialed cross-origin responses](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS#requests_with_credentials) must permit credentials and the specific calling origin through CORS (`Access-Control-Allow-Credentials: true` and a non-wildcard `Access-Control-Allow-Origin`). Enabling credentials does not itself require preflight; if the request otherwise requires preflight, that check must also succeed.
113
+
114
+ Cookie-style values remain serialized as authored, while legacy structured HAR cookies are percent-encoded. Do not decode and re-encode a combined Cookie header uniformly. Other generators retain their existing environment-specific header behavior.
115
+
116
+ For OpenAPI 3.2 `in: cookie, style: cookie` parameters, omit `explode` or set it to `true`. `explode: false` is invalid for cookies because comma-separated values violate cookie syntax. Scalar tolerates that invalid combination by expanding arrays and objects into separate cookie entries; it emits a developer-console warning once per parameter name. Values are passed through unchanged, so provide any required escaping in the API description.
@@ -1 +1 @@
1
- {"version":3,"file":"browser-request.d.ts","sourceRoot":"","sources":["../../src/libs/browser-request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAK7E,wFAAwF;AACxF,eAAO,MAAM,qBAAqB,GAChC,UAAS,OAAO,CAAC,UAAU,CAAM,EACjC,gBAAgB,mBAAmB,KAClC;IACD,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAC1C,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,eAAe,EAAE,OAAO,CAAA;CA8DzB,CAAA"}
1
+ {"version":3,"file":"browser-request.d.ts","sourceRoot":"","sources":["../../src/libs/browser-request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAK7E,wFAAwF;AACxF,eAAO,MAAM,qBAAqB,GAChC,UAAS,OAAO,CAAC,UAAU,CAAM,EACjC,gBAAgB,mBAAmB,KAClC;IACD,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAC1C,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,eAAe,EAAE,OAAO,CAAA;CAuEzB,CAAA"}
@@ -2,7 +2,16 @@ import { Base64 } from 'js-base64';
2
2
  import { joinUrlAndQuery, normalizeMethod } from './http.js';
3
3
  /** Builds browser request values without collapsing repeated headers or form fields. */
4
4
  export const prepareBrowserRequest = (request = {}, configuration) => {
5
- const headers = [...(request.headers ?? [])];
5
+ // Browsers forbid setting Cookie directly. Header values are already serialized,
6
+ // so preserve their escaping when transferring them to the browser cookie store.
7
+ const cookieValues = [
8
+ ...(request.cookies ?? []).map(({ name, value }) => `${encodeURIComponent(name)}=${encodeURIComponent(value)}`),
9
+ ...(request.headers ?? [])
10
+ .filter(({ name }) => name.toLowerCase() === 'cookie')
11
+ .flatMap(({ value }) => (value ?? '').split(';').map((cookie) => cookie.trim()))
12
+ .filter((cookie) => cookie.includes('=')),
13
+ ];
14
+ const headers = (request.headers ?? []).filter(({ name }) => name.toLowerCase() !== 'cookie');
6
15
  if (configuration?.auth?.username && configuration.auth.password) {
7
16
  headers.push({
8
17
  name: 'Authorization',
@@ -10,10 +19,10 @@ export const prepareBrowserRequest = (request = {}, configuration) => {
10
19
  });
11
20
  }
12
21
  const setup = [];
13
- if (request.cookies?.length) {
14
- setup.push('// Run on the request origin to set these cookies in the browser.');
15
- for (const { name, value } of request.cookies) {
16
- setup.push(`document.cookie = ${JSON.stringify(`${encodeURIComponent(name)}=${encodeURIComponent(value)}; path=/`)};`);
22
+ if (cookieValues.length) {
23
+ setup.push("// Run on the request origin; document.cookie writes cookies for the current page's domain.");
24
+ for (const cookie of cookieValues) {
25
+ setup.push(`document.cookie = ${JSON.stringify(`${cookie}; path=/`)};`);
17
26
  }
18
27
  }
19
28
  const postData = request.postData;
@@ -58,7 +67,9 @@ export const prepareBrowserRequest = (request = {}, configuration) => {
58
67
  // The browser must supply the boundary matching its FormData serialization.
59
68
  headers: multipart ? headers.filter(({ name }) => name.toLowerCase() !== 'content-type') : headers,
60
69
  setup,
61
- withCredentials: Boolean(request.cookies?.length),
70
+ // This intentionally includes explicit Cookie headers, even without cookie-style parameters.
71
+ // Cross-origin use additionally requires credentialed CORS and eligible stored cookies.
72
+ withCredentials: Boolean(cookieValues.length),
62
73
  body: multipart ? 'body' : formBody,
63
74
  };
64
75
  };
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/libs/http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAExD,KAAK,UAAU,GAAG;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,KAAK,qBAAqB,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAKvG;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,CAAC,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,MAAM,CAO7F;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,SAAS,MAAM,KAAG,MAAyC,CAAA;AAE3F;;GAEG;AACH,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,KAAG,MAgB1C,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,KAAK,MAAM,EAAE,cAAc,aAAa,EAAE,KAAG,MAY5E,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,UAAU,qBAAqB,EAAE,EAAE,UAAU,aAAa,EAAE,KAAG,UAAU,EAiBvG,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAAI,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,EAAE,MAAM,MAAM,EAAE,OAAO,MAAM,KAAG,IAU9G,CAAA;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,GAAE,UAAU,CAAC,aAAa,CAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAK1G;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAErE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAqBnF"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/libs/http.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAExD,KAAK,UAAU,GAAG;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,KAAK,qBAAqB,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAKvG;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,CAAC,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,MAAM,CAO7F;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,SAAS,MAAM,KAAG,MAC0D,CAAA;AAE5G;;GAEG;AACH,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,KAAG,MAgB1C,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,KAAK,MAAM,EAAE,cAAc,aAAa,EAAE,KAAG,MAY5E,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,UAAU,qBAAqB,EAAE,EAAE,UAAU,aAAa,EAAE,KAAG,UAAU,EAiBvG,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAAI,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,EAAE,MAAM,MAAM,EAAE,OAAO,MAAM,KAAG,IAU9G,CAAA;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,GAAE,UAAU,CAAC,aAAa,CAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAK1G;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAErE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAqBnF"}
package/dist/libs/http.js CHANGED
@@ -1,10 +1,11 @@
1
+ import { isHttpMethod } from '@scalar/helpers/http/is-http-method';
1
2
  /**
2
3
  * Normalizes the request object with defaults
3
4
  */
4
5
  export function normalizeRequest(request) {
5
6
  return {
6
7
  ...request,
7
- method: (request.method || 'GET').toUpperCase(),
8
+ method: normalizeMethod(request.method),
8
9
  };
9
10
  }
10
11
  /**
@@ -20,7 +21,7 @@ export function buildQueryString(queryParams) {
20
21
  /**
21
22
  * Normalizes a request method.
22
23
  */
23
- export const normalizeMethod = (method) => (method || 'GET').toUpperCase();
24
+ export const normalizeMethod = (method) => method ? (isHttpMethod(method) && method === method.toLowerCase() ? method.toUpperCase() : method) : 'GET';
24
25
  /**
25
26
  * Normalizes URL formatting while preserving origin-only paths.
26
27
  */
@@ -1,3 +1,5 @@
1
+ /** Escapes a value for a single-quoted JavaScript string literal. */
2
+ export declare const escapeJsString: (value: string) => string;
1
3
  /**
2
4
  * Represents a raw code that should not be quoted, e.g. `JSON.stringify(...)`.
3
5
  * If consists of multiple lines, they will be indented properly.
@@ -11,5 +13,5 @@ export declare class Raw {
11
13
  *
12
14
  * Handles nested objects, arrays, and special string values
13
15
  */
14
- export declare function objectToString(obj: Record<string, any>, indent?: number): string;
16
+ export declare function objectToString(obj: object, indent?: number): string;
15
17
  //# sourceMappingURL=javascript.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"javascript.d.ts","sourceRoot":"","sources":["../../src/libs/javascript.ts"],"names":[],"mappings":"AAaA;;;GAGG;AACH,qBAAa,GAAG;IACK,KAAK,EAAE,MAAM;gBAAb,KAAK,EAAE,MAAM;CACjC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,SAAI,GAAG,MAAM,CA2D3E"}
1
+ {"version":3,"file":"javascript.d.ts","sourceRoot":"","sources":["../../src/libs/javascript.ts"],"names":[],"mappings":"AASA,qEAAqE;AACrE,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,KAAG,MAE9C,CAAA;AAED;;;GAGG;AACH,qBAAa,GAAG;IACK,KAAK,EAAE,MAAM;gBAAb,KAAK,EAAE,MAAM;CACjC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,SAAI,GAAG,MAAM,CA4D9D"}
@@ -6,9 +6,10 @@
6
6
  function needsQuotes(key) {
7
7
  return !/^[$A-Z_][0-9A-Z_$]*$/i.test(key);
8
8
  }
9
- function escapeObjectKey(key) {
10
- return key.replaceAll('\\', '\\\\').replaceAll('\n', '\\n').replaceAll('\r', '\\r').replaceAll("'", "\\'");
11
- }
9
+ /** Escapes a value for a single-quoted JavaScript string literal. */
10
+ export const escapeJsString = (value) => {
11
+ return value.replaceAll('\\', '\\\\').replaceAll('\n', '\\n').replaceAll('\r', '\\r').replaceAll("'", "\\'");
12
+ };
12
13
  /**
13
14
  * Represents a raw code that should not be quoted, e.g. `JSON.stringify(...)`.
14
15
  * If consists of multiple lines, they will be indented properly.
@@ -28,11 +29,28 @@ export function objectToString(obj, indent = 0) {
28
29
  const parts = [];
29
30
  const indentation = ' '.repeat(indent);
30
31
  const innerIndentation = ' '.repeat(indent + 2);
32
+ // Arrays must be handled before Object.entries turns their indexes into object keys.
33
+ if (Array.isArray(obj)) {
34
+ const items = obj.map((item) => {
35
+ if (typeof item === 'string') {
36
+ return `'${escapeJsString(item)}'`;
37
+ }
38
+ if (item && typeof item === 'object') {
39
+ return objectToString(item);
40
+ }
41
+ return JSON.stringify(item);
42
+ });
43
+ if (items.some((item) => item.includes('\n'))) {
44
+ const arrayString = items.map((item) => indentString(item, indent + 2)).join(',\n');
45
+ return `[\n${arrayString}\n${indentation}]`;
46
+ }
47
+ return `[${items.join(', ')}]`;
48
+ }
31
49
  if (Object.keys(obj).length === 0) {
32
50
  return '{}';
33
51
  }
34
52
  for (const [key, value] of Object.entries(obj)) {
35
- const formattedKey = needsQuotes(key) ? `'${escapeObjectKey(key)}'` : key;
53
+ const formattedKey = needsQuotes(key) ? `'${escapeJsString(key)}'` : key;
36
54
  if (value instanceof Raw) {
37
55
  const lines = value.value.split('\n');
38
56
  let formattedValue = `${value.value}`;
@@ -48,30 +66,11 @@ export function objectToString(obj, indent = 0) {
48
66
  }
49
67
  parts.push(`${innerIndentation}${formattedKey}: ${formattedValue}`);
50
68
  }
51
- else if (Array.isArray(value)) {
52
- const items = value.map((item) => {
53
- if (typeof item === 'string') {
54
- return `'${item}'`;
55
- }
56
- if (item && typeof item === 'object') {
57
- return objectToString(item);
58
- }
59
- return JSON.stringify(item);
60
- });
61
- if (items.some((item) => item.includes('\n'))) {
62
- // format vertically if any array element contains a newline
63
- const arrayString = items.map((item) => indentString(item, indent + 4)).join(',\n');
64
- parts.push(`${innerIndentation}${formattedKey}: [\n${arrayString}\n${innerIndentation}]`);
65
- }
66
- else {
67
- parts.push(`${innerIndentation}${formattedKey}: [${items.join(', ')}]`);
68
- }
69
- }
70
69
  else if (value && typeof value === 'object') {
71
70
  parts.push(`${innerIndentation}${formattedKey}: ${objectToString(value, indent + 2)}`);
72
71
  }
73
72
  else if (typeof value === 'string') {
74
- const formattedValue = `'${value}'`;
73
+ const formattedValue = `'${escapeJsString(value)}'`;
75
74
  parts.push(`${innerIndentation}${formattedKey}: ${formattedValue}`);
76
75
  }
77
76
  else {
@@ -1,4 +1,4 @@
1
- const normalizeMethod = (method) => (method || 'GET').toUpperCase();
1
+ import { normalizeMethod } from '../../../libs/http.js';
2
2
  const escapeCString = (value) => value
3
3
  .replaceAll('\\', '\\\\')
4
4
  .replaceAll('"', '\\"')
@@ -1,5 +1,5 @@
1
1
  import { encode } from 'js-base64';
2
- import { buildQueryString } from '../../../libs/http.js';
2
+ import { buildQueryString, normalizeMethod } from '../../../libs/http.js';
3
3
  /**
4
4
  * csharp/httpclient
5
5
  */
@@ -15,7 +15,7 @@ export const csharpHttpclient = {
15
15
  ...request,
16
16
  };
17
17
  // Normalization
18
- normalizedRequest.method = normalizedRequest.method.toUpperCase();
18
+ normalizedRequest.method = normalizeMethod(normalizedRequest.method);
19
19
  // Build URL with query string
20
20
  const queryString = buildQueryString(normalizedRequest.queryString);
21
21
  const url = `${normalizedRequest.url}${queryString}`;
@@ -1 +1 @@
1
- {"version":3,"file":"restsharp.d.ts","sourceRoot":"","sources":["../../../../src/plugins/csharp/restsharp/restsharp.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAmDpD;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,MAkH7B,CAAA"}
1
+ {"version":3,"file":"restsharp.d.ts","sourceRoot":"","sources":["../../../../src/plugins/csharp/restsharp/restsharp.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAsCpD;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,MAyH7B,CAAA"}
@@ -1,18 +1,7 @@
1
+ import { isJsonMediaType } from '@scalar/helpers/http/is-json-media-type';
1
2
  import { parseMimeType } from '@scalar/helpers/http/mime-type';
2
3
  import { encode } from 'js-base64';
3
- import { joinUrlAndQuery } from '../../../libs/http.js';
4
- /**
5
- * True for `application/json`, any RFC 6839 `+json` structured-syntax suffix
6
- * (e.g. `application/vnd.api+json`), and parameterized variants
7
- * (e.g. `application/json;charset=utf-8`). Case-insensitive.
8
- */
9
- const isJsonContentType = (value) => {
10
- if (!value) {
11
- return false;
12
- }
13
- const { subtype } = parseMimeType(value);
14
- return subtype === 'json' || subtype.endsWith('+json');
15
- };
4
+ import { joinUrlAndQuery, normalizeMethod } from '../../../libs/http.js';
16
5
  /**
17
6
  * Maps an HTTP method to a RestSharp `Method` enum member. The enum uses
18
7
  * PascalCase members (`Method.Get`, `Method.Post`, ...), so we title-case the
@@ -57,7 +46,10 @@ export const csharpRestsharp = {
57
46
  ...request,
58
47
  };
59
48
  // Normalization
60
- normalizedRequest.method = normalizedRequest.method.toUpperCase();
49
+ normalizedRequest.method = normalizeMethod(normalizedRequest.method);
50
+ if (!['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS', 'COPY', 'SEARCH', 'MERGE'].includes(normalizedRequest.method)) {
51
+ return '// RestSharp does not support this HTTP method. Select HttpClient for a custom method.';
52
+ }
61
53
  // Build the full URL, appending the query string with the correct separator
62
54
  // (joinUrlAndQuery uses `&` when the URL already carries a query string)
63
55
  const url = joinUrlAndQuery(normalizedRequest.url, normalizedRequest.queryString);
@@ -97,7 +89,7 @@ export const csharpRestsharp = {
97
89
  // Compare against the essence so parameterized values (e.g. a `boundary` or
98
90
  // `charset`) still match the form, multipart, and octet-stream branches.
99
91
  const essence = mimeType ? parseMimeType(mimeType).essence : undefined;
100
- if (isJsonContentType(mimeType)) {
92
+ if (isJsonMediaType(mimeType)) {
101
93
  if (text) {
102
94
  let body = text;
103
95
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../../src/plugins/dart/http/http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAEpD;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,MAsGtB,CAAA"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../../src/plugins/dart/http/http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAIpD;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,MAqHtB,CAAA"}
@@ -1,3 +1,4 @@
1
+ import { normalizeMethod } from '../../../libs/http.js';
1
2
  /**
2
3
  * dart/http
3
4
  */
@@ -12,7 +13,7 @@ export const dartHttp = {
12
13
  ...request,
13
14
  };
14
15
  // Normalize method to uppercase
15
- normalizedRequest.method = normalizedRequest.method.toUpperCase();
16
+ normalizedRequest.method = normalizeMethod(normalizedRequest.method);
16
17
  // Start building the Dart code
17
18
  let code = `import 'package:http/http.dart' as http;\n\nvoid main() async {\n`;
18
19
  // Handle cookies
@@ -88,7 +89,23 @@ export const dartHttp = {
88
89
  const method = normalizedRequest.method.toLowerCase();
89
90
  const headersPart = Object.keys(headers).length > 0 ? ', headers: headers' : '';
90
91
  const bodyPart = body ? ', body: body' : '';
91
- code += ` final response = await http.${method}(Uri.parse('${url}')${headersPart}${bodyPart});\n`;
92
+ if (['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD'].includes(normalizedRequest.method)) {
93
+ code += ` final response = await http.${method}(Uri.parse('${url}')${headersPart}${bodyPart});\n`;
94
+ }
95
+ else {
96
+ const wireMethod = normalizedRequest.method.replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/\$/g, '\\$');
97
+ code += ` final request = http.Request('${wireMethod}', Uri.parse('${url}'));\n`;
98
+ if (Object.keys(headers).length > 0) {
99
+ code += ' request.headers.addAll(headers);\n';
100
+ }
101
+ if (body) {
102
+ code +=
103
+ normalizedRequest.postData?.mimeType === 'multipart/form-data'
104
+ ? ' request.bodyFields = body;\n'
105
+ : ' request.body = body;\n';
106
+ }
107
+ code += ' final response = await http.Response.fromStream(await request.send());\n';
108
+ }
92
109
  code += ' print(response.body);\n';
93
110
  code += '}';
94
111
  return code;
@@ -1 +1 @@
1
- {"version":3,"file":"http11.d.ts","sourceRoot":"","sources":["../../../../src/plugins/http/http11/http11.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAEpD;;GAEG;AACH,eAAO,MAAM,UAAU,EAAE,MAkHxB,CAAA"}
1
+ {"version":3,"file":"http11.d.ts","sourceRoot":"","sources":["../../../../src/plugins/http/http11/http11.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAIpD;;GAEG;AACH,eAAO,MAAM,UAAU,EAAE,MAkHxB,CAAA"}
@@ -1,3 +1,4 @@
1
+ import { normalizeMethod } from '../../../libs/http.js';
1
2
  /**
2
3
  * http/http1.1
3
4
  */
@@ -14,7 +15,7 @@ export const httpHttp11 = {
14
15
  ...request,
15
16
  };
16
17
  // Normalize method
17
- normalizedRequest.method = normalizedRequest.method.toUpperCase();
18
+ normalizedRequest.method = normalizeMethod(normalizedRequest.method);
18
19
  // Parse URL with error handling
19
20
  let url;
20
21
  let path;
@@ -1,4 +1,4 @@
1
- import { buildQueryString } from '../../../libs/http.js';
1
+ import { buildQueryString, normalizeMethod } from '../../../libs/http.js';
2
2
  import { Raw, objectToString } from '../../../libs/javascript.js';
3
3
  /**
4
4
  * js/fetch
@@ -15,7 +15,7 @@ export const jsFetch = {
15
15
  };
16
16
  let prefix = '';
17
17
  // Normalization
18
- normalizedRequest.method = normalizedRequest.method.toUpperCase();
18
+ normalizedRequest.method = normalizeMethod(normalizedRequest.method);
19
19
  // Reset fetch defaults
20
20
  const options = {
21
21
  method: normalizedRequest.method === 'GET' ? undefined : normalizedRequest.method,
@@ -1,4 +1,4 @@
1
- import { reduceQueryParams } from '../../../libs/http.js';
1
+ import { normalizeMethod, reduceQueryParams } from '../../../libs/http.js';
2
2
  import { objectToString } from '../../../libs/javascript.js';
3
3
  /**
4
4
  * js/ofetch
@@ -14,7 +14,7 @@ export const jsOfetch = {
14
14
  ...request,
15
15
  };
16
16
  // Normalization
17
- normalizedRequest.method = normalizedRequest.method.toUpperCase();
17
+ normalizedRequest.method = normalizeMethod(normalizedRequest.method);
18
18
  // Reset fetch defaults
19
19
  const options = {
20
20
  method: normalizedRequest.method === 'GET' ? undefined : normalizedRequest.method,
@@ -1,4 +1,4 @@
1
- import { buildQueryString } from '../../../libs/http.js';
1
+ import { buildQueryString, normalizeMethod } from '../../../libs/http.js';
2
2
  import { Raw, objectToString } from '../../../libs/javascript.js';
3
3
  /**
4
4
  * node/fetch
@@ -15,7 +15,7 @@ export const nodeFetch = {
15
15
  };
16
16
  let prefix = '';
17
17
  // Normalization
18
- normalizedRequest.method = normalizedRequest.method.toUpperCase();
18
+ normalizedRequest.method = normalizeMethod(normalizedRequest.method);
19
19
  // Reset fetch defaults
20
20
  const options = {
21
21
  method: normalizedRequest.method === 'GET' ? undefined : normalizedRequest.method,
@@ -1,4 +1,4 @@
1
- import { reduceQueryParams } from '../../../libs/http.js';
1
+ import { normalizeMethod, reduceQueryParams } from '../../../libs/http.js';
2
2
  import { objectToString } from '../../../libs/javascript.js';
3
3
  /**
4
4
  * node/ofetch
@@ -14,7 +14,7 @@ export const nodeOfetch = {
14
14
  ...request,
15
15
  };
16
16
  // Normalization
17
- normalizedRequest.method = normalizedRequest.method.toUpperCase();
17
+ normalizedRequest.method = normalizeMethod(normalizedRequest.method);
18
18
  // Reset fetch defaults
19
19
  const options = {
20
20
  method: normalizedRequest.method === 'GET' ? undefined : normalizedRequest.method,
@@ -1,4 +1,4 @@
1
- import { buildQueryString } from '../../../libs/http.js';
1
+ import { buildQueryString, normalizeMethod } from '../../../libs/http.js';
2
2
  import { Raw, objectToString } from '../../../libs/javascript.js';
3
3
  /**
4
4
  * node/undici
@@ -14,7 +14,7 @@ export const nodeUndici = {
14
14
  ...request,
15
15
  };
16
16
  // Normalization
17
- normalizedRequest.method = normalizedRequest.method.toUpperCase();
17
+ normalizedRequest.method = normalizeMethod(normalizedRequest.method);
18
18
  // Reset undici defaults
19
19
  const options = {
20
20
  method: normalizedRequest.method === 'GET' ? undefined : normalizedRequest.method,
@@ -1 +1 @@
1
- {"version":3,"file":"curl.d.ts","sourceRoot":"","sources":["../../../../src/plugins/php/curl/curl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAIpD;;GAEG;AACH,eAAO,MAAM,OAAO,EAAE,MAiKrB,CAAA"}
1
+ {"version":3,"file":"curl.d.ts","sourceRoot":"","sources":["../../../../src/plugins/php/curl/curl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAKpD;;GAEG;AACH,eAAO,MAAM,OAAO,EAAE,MAiKrB,CAAA"}
@@ -1,3 +1,4 @@
1
+ import { normalizeMethod } from '../../../libs/http.js';
1
2
  import { objectToString } from '../../../libs/php.js';
2
3
  /**
3
4
  * php/curl
@@ -13,7 +14,7 @@ export const phpCurl = {
13
14
  ...request,
14
15
  };
15
16
  // Normalization
16
- normalizedRequest.method = normalizedRequest.method.toUpperCase();
17
+ normalizedRequest.method = normalizeMethod(normalizedRequest.method);
17
18
  // Build PHP cURL code parts
18
19
  const parts = [];
19
20
  let hasMultipartMimeBody = false;
@@ -1,4 +1,4 @@
1
- import { reduceQueryParams } from '../../../libs/http.js';
1
+ import { normalizeMethod, reduceQueryParams } from '../../../libs/http.js';
2
2
  import { Raw, objectToString } from '../../../libs/php.js';
3
3
  /**
4
4
  * php/guzzle
@@ -12,7 +12,7 @@ export const phpGuzzle = {
12
12
  return '';
13
13
  }
14
14
  const options = {};
15
- const method = (request.method || 'GET').toUpperCase();
15
+ const method = normalizeMethod(request.method);
16
16
  const url = request.url || '';
17
17
  // Handle headers
18
18
  if (request.headers && Array.isArray(request.headers) && request.headers.length > 0) {
@@ -1,5 +1,5 @@
1
1
  import { isObjectLike } from '@scalar/helpers/object/is-object';
2
- import { accumulateRepeatedValue, buildQueryString } from '../../../libs/http.js';
2
+ import { accumulateRepeatedValue, buildQueryString, normalizeMethod } from '../../../libs/http.js';
3
3
  import { objectToString } from '../../../libs/php.js';
4
4
  const escapePhpString = (value) => value.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
5
5
  const quotePhpString = (value) => `'${escapePhpString(value)}'`;
@@ -39,7 +39,7 @@ export const phpLaravel = {
39
39
  method: 'GET',
40
40
  ...request,
41
41
  };
42
- normalizedRequest.method = normalizedRequest.method.toUpperCase();
42
+ normalizedRequest.method = normalizeMethod(normalizedRequest.method);
43
43
  const queryString = buildQueryString(normalizedRequest.queryString);
44
44
  const url = `${normalizedRequest.url ?? ''}${queryString}`;
45
45
  const chain = [];
@@ -1 +1 @@
1
- {"version":3,"file":"aiohttp.d.ts","sourceRoot":"","sources":["../../../../src/plugins/python/aiohttp/aiohttp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAyBhE;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,MA4G3B,CAAA"}
1
+ {"version":3,"file":"aiohttp.d.ts","sourceRoot":"","sources":["../../../../src/plugins/python/aiohttp/aiohttp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,MAAM,EAAE,MAAM,wBAAwB,CAAA;AA6BhE;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,MA4G3B,CAAA"}
@@ -1,4 +1,4 @@
1
- import { accumulateRepeatedValue, reduceQueryParams } from '../../../libs/http.js';
1
+ import { accumulateRepeatedValue, normalizeMethod, reduceQueryParams } from '../../../libs/http.js';
2
2
  import { LENGTH_CONSIDERED_AS_SHORT, formatPythonValue } from '../../../plugins/python/requestsLike.js';
3
3
  const indent = (value, prefix = ' ') => value
4
4
  .split('\n')
@@ -6,13 +6,17 @@ const indent = (value, prefix = ' ') => value
6
6
  .join('\n');
7
7
  const formatRequestCall = (clientVar, method, url, args) => {
8
8
  const urlParam = JSON.stringify(url);
9
+ if (!['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'].includes(method)) {
10
+ return `${clientVar}.request(${[JSON.stringify(method), urlParam, ...args].join(', ')})`;
11
+ }
12
+ const shortcut = method.toLowerCase();
9
13
  if (url.length > LENGTH_CONSIDERED_AS_SHORT) {
10
- return `${clientVar}.${method}(\n ${[urlParam, ...args].join(',\n ')}\n)`;
14
+ return `${clientVar}.${shortcut}(\n ${[urlParam, ...args].join(',\n ')}\n)`;
11
15
  }
12
16
  if (args.length === 0) {
13
- return `${clientVar}.${method}(${urlParam})`;
17
+ return `${clientVar}.${shortcut}(${urlParam})`;
14
18
  }
15
- return `${clientVar}.${method}(${urlParam},\n ${args.join(',\n ')}\n)`;
19
+ return `${clientVar}.${shortcut}(${urlParam},\n ${args.join(',\n ')}\n)`;
16
20
  };
17
21
  /**
18
22
  * python/aiohttp
@@ -27,7 +31,7 @@ export const pythonAiohttp = {
27
31
  method: 'get',
28
32
  ...request,
29
33
  };
30
- const method = normalizedRequest.method?.toLowerCase() ?? 'get';
34
+ const method = normalizeMethod(normalizedRequest.method);
31
35
  const requestArgs = [];
32
36
  const sessionArgs = [];
33
37
  const setupLines = [];
@@ -1 +1 @@
1
- {"version":3,"file":"requestsLike.d.ts","sourceRoot":"","sources":["../../../src/plugins/python/requestsLike.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAI7E,eAAO,MAAM,0BAA0B,KAAK,CAAA;AAsB5C,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,SAAI,GAAG,MAAM,CAOzE;AAED,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,EAC7B,aAAa,CAAC,EAAE,mBAAmB,UA8IpC"}
1
+ {"version":3,"file":"requestsLike.d.ts","sourceRoot":"","sources":["../../../src/plugins/python/requestsLike.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAI7E,eAAO,MAAM,0BAA0B,KAAK,CAAA;AAsB5C,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,SAAI,GAAG,MAAM,CAOzE;AAED,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,EAC7B,aAAa,CAAC,EAAE,mBAAmB,UAmJpC"}
@@ -1,4 +1,4 @@
1
- import { accumulateRepeatedValue, reduceQueryParams } from '../../libs/http.js';
1
+ import { accumulateRepeatedValue, normalizeMethod, reduceQueryParams } from '../../libs/http.js';
2
2
  export const LENGTH_CONSIDERED_AS_SHORT = 40;
3
3
  // Function to convert JavaScript boolean and null values to Python equivalents
4
4
  function convertToPythonSyntax(str) {
@@ -30,7 +30,8 @@ export function requestsLikeGenerate(clientVar, request, configuration) {
30
30
  ...request,
31
31
  };
32
32
  // Normalize method to lowercase for requests library
33
- const method = normalizedRequest.method.toLowerCase();
33
+ const wireMethod = normalizeMethod(normalizedRequest.method);
34
+ const method = wireMethod.toLowerCase();
34
35
  // Build options object
35
36
  const options = {};
36
37
  // Add headers if present
@@ -145,6 +146,9 @@ export function requestsLikeGenerate(clientVar, request, configuration) {
145
146
  formattedParams.push(`${key}=${str}`);
146
147
  }
147
148
  }
149
+ if (!['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'].includes(wireMethod)) {
150
+ return `${clientVar}.request(${[JSON.stringify(wireMethod), urlParam, ...formattedParams.slice(1)].join(', ')})`;
151
+ }
148
152
  // Build the final request string with conditional URL formatting
149
153
  if (normalizedRequest.url.length > LENGTH_CONSIDERED_AS_SHORT) {
150
154
  return `${clientVar}.${method}(\n ${formattedParams.join(',\n ')}\n)`;
@@ -1,5 +1,5 @@
1
1
  import { isObjectLike } from '@scalar/helpers/object/is-object';
2
- import { reduceQueryParams } from '../../../libs/http.js';
2
+ import { normalizeMethod, reduceQueryParams } from '../../../libs/http.js';
3
3
  /**
4
4
  * Formats JSON text as an R list structure
5
5
  */
@@ -58,7 +58,7 @@ export const rHttr2 = {
58
58
  method: 'GET',
59
59
  ...request,
60
60
  };
61
- const method = normalizedRequest.method.toUpperCase();
61
+ const method = normalizeMethod(normalizedRequest.method);
62
62
  const lines = ['library(httr2)', ''];
63
63
  // Start the pipe chain
64
64
  lines.push(`response <- request("${normalizedRequest.url}") |>`);
@@ -1 +1 @@
1
- {"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../../../../src/plugins/ruby/native/native.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AA8DpD;;GAEG;AACH,eAAO,MAAM,UAAU,EAAE,MAuGxB,CAAA"}
1
+ {"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../../../../src/plugins/ruby/native/native.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AA+DpD;;GAEG;AACH,eAAO,MAAM,UAAU,EAAE,MAuGxB,CAAA"}
@@ -1,4 +1,4 @@
1
- import { buildQueryString } from '../../../libs/http.js';
1
+ import { buildQueryString, normalizeMethod } from '../../../libs/http.js';
2
2
  const escapeRubyDoubleQuoted = (value) => value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
3
3
  const escapeRubySingleQuoted = (value) => value.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
4
4
  const encodeFormComponent = (value) => encodeURIComponent(value).replace(/'/g, '%27');
@@ -16,14 +16,14 @@ const standardMethods = new Set([
16
16
  'MOVE',
17
17
  'TRACE',
18
18
  ]);
19
- const toRubyMethodClass = (method) => method.charAt(0) + method.slice(1).toLowerCase();
19
+ const toRubyMethodClass = (method) => standardMethods.has(method) ? method.charAt(0) + method.slice(1).toLowerCase() : 'CustomRequest';
20
20
  const maybeAddCustomMethodClass = (lines, method, hasBody) => {
21
21
  if (standardMethods.has(method)) {
22
22
  return;
23
23
  }
24
24
  const methodClass = toRubyMethodClass(method);
25
25
  lines.push(`class Net::HTTP::${methodClass} < Net::HTTPRequest`);
26
- lines.push(` METHOD = '${method}'`);
26
+ lines.push(` METHOD = '${escapeRubySingleQuoted(method)}'`);
27
27
  lines.push(` REQUEST_HAS_BODY = '${hasBody ? 'true' : 'false'}'`);
28
28
  lines.push(' RESPONSE_HAS_BODY = true');
29
29
  lines.push('end');
@@ -58,7 +58,7 @@ export const rubyNative = {
58
58
  method: 'GET',
59
59
  ...request,
60
60
  };
61
- normalizedRequest.method = normalizedRequest.method.toUpperCase();
61
+ normalizedRequest.method = normalizeMethod(normalizedRequest.method);
62
62
  const queryString = buildQueryString(normalizedRequest.queryString);
63
63
  const rawUrl = `${normalizedRequest.url ?? ''}${queryString}`;
64
64
  const encodedUrl = encodeUrlWithPathPreservedBrackets(rawUrl);
@@ -119,15 +119,18 @@ const createBodyCall = (postData) => {
119
119
  */
120
120
  const buildRustCode = (url, method, chainedCalls) => {
121
121
  const code = ['let client = reqwest::Client::new();', ''];
122
+ const request = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD'].includes(method)
123
+ ? `${method.toLowerCase()}(${wrapInDoubleQuotes(url)})`
124
+ : `request(reqwest::Method::from_bytes(${wrapInDoubleQuotes(method)}.as_bytes())?, ${wrapInDoubleQuotes(url)})`;
122
125
  // Add chained calls with proper formatting
123
126
  if (chainedCalls.length > 0) {
124
127
  code.push('let request = client');
125
- code.push(indent(1, `.${method.toLowerCase()}(${wrapInDoubleQuotes(url)})`));
128
+ code.push(indent(1, `.${request}`));
126
129
  // Add a newline before the first chained call
127
130
  code.push(...chainedCalls);
128
131
  }
129
132
  else {
130
- code.push(`let request = client.${method.toLowerCase()}(${wrapInDoubleQuotes(url)})`);
133
+ code.push(`let request = client.${request}`);
131
134
  }
132
135
  // Add semicolon to the last chained call
133
136
  const lastPart = code[code.length - 1];
@@ -1 +1 @@
1
- {"version":3,"file":"axios.d.ts","sourceRoot":"","sources":["../../../src/plugins/shared/axios.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AAwI9D,eAAO,MAAM,iBAAiB,GAAI,CAAC,SAAS,OAAO,CAAC,QAAQ,EAAE,IAAI,GAAG,MAAM,CAAC,EAAE,QAAQ,CAAC,KAAG,MAmDxF,CAAA"}
1
+ {"version":3,"file":"axios.d.ts","sourceRoot":"","sources":["../../../src/plugins/shared/axios.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAA;AAkH9D,eAAO,MAAM,iBAAiB,GAAI,CAAC,SAAS,OAAO,CAAC,QAAQ,EAAE,IAAI,GAAG,MAAM,CAAC,EAAE,QAAQ,CAAC,KAAG,MAmDxF,CAAA"}
@@ -1,21 +1,5 @@
1
- import { accumulateRepeatedValue, reduceQueryParams } from '../../libs/http.js';
2
- import { Raw, objectToString } from '../../libs/javascript.js';
3
- const escapeJsString = (value) => value.replaceAll('\\', '\\\\').replaceAll('\n', '\\n').replaceAll('\r', '\\r').replaceAll("'", "\\'");
4
- const sanitizeForGeneratedCode = (value) => {
5
- if (typeof value === 'string') {
6
- return escapeJsString(value);
7
- }
8
- if (Array.isArray(value)) {
9
- return value.map((item) => sanitizeForGeneratedCode(item));
10
- }
11
- if (value && typeof value === 'object' && !(value instanceof Raw)) {
12
- return Object.entries(value).reduce((acc, [key, objectValue]) => {
13
- acc[key] = sanitizeForGeneratedCode(objectValue);
14
- return acc;
15
- }, {});
16
- }
17
- return value;
18
- };
1
+ import { accumulateRepeatedValue, normalizeMethod, reduceQueryParams } from '../../libs/http.js';
2
+ import { Raw, escapeJsString, objectToString } from '../../libs/javascript.js';
19
3
  const addHeaderValue = (headers, name, value) => {
20
4
  if (value === '') {
21
5
  headers[name] = value;
@@ -110,28 +94,28 @@ export const createAxiosPlugin = (target) => ({
110
94
  method: 'GET',
111
95
  ...request,
112
96
  };
113
- normalizedRequest.method = normalizedRequest.method.toUpperCase();
97
+ normalizedRequest.method = normalizeMethod(normalizedRequest.method);
114
98
  const options = {
115
99
  method: normalizedRequest.method,
116
- url: escapeJsString(normalizedRequest.url ?? ''),
100
+ url: normalizedRequest.url ?? '',
117
101
  };
118
102
  const params = reduceQueryParams(normalizedRequest.queryString);
119
103
  if (Object.keys(params).length) {
120
- options.params = sanitizeForGeneratedCode(params);
104
+ options.params = params;
121
105
  }
122
106
  const headers = buildHeaders(normalizedRequest);
123
107
  if (headers) {
124
- options.headers = sanitizeForGeneratedCode(headers);
108
+ options.headers = headers;
125
109
  }
126
110
  if (configuration?.auth?.username && configuration?.auth?.password) {
127
111
  options.auth = {
128
- username: escapeJsString(configuration.auth.username),
129
- password: escapeJsString(configuration.auth.password),
112
+ username: configuration.auth.username,
113
+ password: configuration.auth.password,
130
114
  };
131
115
  }
132
116
  const { setup, data } = buildData(normalizedRequest);
133
117
  if (data !== undefined) {
134
- options.data = data instanceof Raw ? data : sanitizeForGeneratedCode(data);
118
+ options.data = data;
135
119
  }
136
120
  const setupBlock = setup.length ? `${setup.join('\n')}\n\n` : '';
137
121
  return `import axios from 'axios'
@@ -1 +1 @@
1
- {"version":3,"file":"curl.d.ts","sourceRoot":"","sources":["../../../../src/plugins/shell/curl/curl.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAiBpD;;GAEG;AACH,eAAO,MAAM,SAAS,EAAE,MA6JvB,CAAA"}
1
+ {"version":3,"file":"curl.d.ts","sourceRoot":"","sources":["../../../../src/plugins/shell/curl/curl.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAKpD;;GAEG;AACH,eAAO,MAAM,SAAS,EAAE,MAiKvB,CAAA"}
@@ -1,17 +1,7 @@
1
- import { parseMimeType } from '@scalar/helpers/http/mime-type';
1
+ import { isJsonMediaType } from '@scalar/helpers/http/is-json-media-type';
2
+ import { isStreamingContentType } from '@scalar/helpers/http/is-streaming-content-type';
3
+ import { normalizeMethod } from '../../../libs/http.js';
2
4
  import { escapeSingleQuotes } from '../../../libs/shell.js';
3
- /**
4
- * True for `application/json`, any RFC 6839 `+json` structured-syntax suffix
5
- * (e.g. `application/vnd.api+json`), and parameterized variants
6
- * (e.g. `application/json;charset=utf-8`). Case-insensitive.
7
- */
8
- const isJsonContentType = (value) => {
9
- if (!value) {
10
- return false;
11
- }
12
- const { subtype } = parseMimeType(value);
13
- return subtype === 'json' || subtype.endsWith('+json');
14
- };
15
5
  /**
16
6
  * shell/curl
17
7
  */
@@ -26,7 +16,7 @@ export const shellCurl = {
26
16
  ...request,
27
17
  };
28
18
  // Normalization
29
- normalizedRequest.method = normalizedRequest.method.toUpperCase();
19
+ normalizedRequest.method = normalizeMethod(normalizedRequest.method);
30
20
  // Build curl command parts
31
21
  const parts = ['curl'];
32
22
  // Build the URL, joining extra query parameters with `&` when the URL already carries a query string
@@ -93,7 +83,7 @@ export const shellCurl = {
93
83
  }
94
84
  // Body
95
85
  if (normalizedRequest.postData) {
96
- if (isJsonContentType(normalizedRequest.postData.mimeType)) {
86
+ if (isJsonMediaType(normalizedRequest.postData.mimeType)) {
97
87
  // Pretty print JSON data
98
88
  if (normalizedRequest.postData.text) {
99
89
  try {
@@ -109,6 +99,11 @@ export const shellCurl = {
109
99
  }
110
100
  }
111
101
  }
102
+ else if (isStreamingContentType(normalizedRequest.postData.mimeType ?? '')) {
103
+ // Use the explicit binary mode consistently for framed streaming media types.
104
+ const escapedText = escapeSingleQuotes(normalizedRequest.postData.text ?? '');
105
+ parts.push(`--data-binary '${escapedText}'`);
106
+ }
112
107
  else if (normalizedRequest.postData.mimeType === 'application/octet-stream') {
113
108
  const escapedText = escapeSingleQuotes(normalizedRequest.postData.text ?? '');
114
109
  parts.push(`--data-binary '${escapedText}'`);
@@ -136,7 +131,7 @@ export const shellCurl = {
136
131
  const rawValue = param.value ?? '';
137
132
  // Pretty-print parts whose contentType is JSON so the snippet stays readable,
138
133
  // mirroring what we already do for `--data` JSON bodies above.
139
- const isJsonPart = isJsonContentType(param.contentType);
134
+ const isJsonPart = isJsonMediaType(param.contentType);
140
135
  let displayValue = rawValue;
141
136
  if (isJsonPart && rawValue) {
142
137
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"wget.d.ts","sourceRoot":"","sources":["../../../../src/plugins/shell/wget/wget.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AA6BpD;;GAEG;AACH,eAAO,MAAM,SAAS,EAAE,MAsFvB,CAAA"}
1
+ {"version":3,"file":"wget.d.ts","sourceRoot":"","sources":["../../../../src/plugins/shell/wget/wget.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAiBpD;;GAEG;AACH,eAAO,MAAM,SAAS,EAAE,MAsFvB,CAAA"}
@@ -1,17 +1,6 @@
1
- import { parseMimeType } from '@scalar/helpers/http/mime-type';
1
+ import { isJsonMediaType } from '@scalar/helpers/http/is-json-media-type';
2
+ import { normalizeMethod } from '../../../libs/http.js';
2
3
  import { escapeSingleQuotes } from '../../../libs/shell.js';
3
- /**
4
- * True for `application/json`, any RFC 6839 `+json` structured-syntax suffix
5
- * (e.g. `application/vnd.api+json`), and parameterized variants
6
- * (e.g. `application/json;charset=utf-8`). Case-insensitive.
7
- */
8
- const isJsonContentType = (value) => {
9
- if (!value) {
10
- return false;
11
- }
12
- const { subtype } = parseMimeType(value);
13
- return subtype === 'json' || subtype.endsWith('+json');
14
- };
15
4
  /**
16
5
  * Pretty-prints a JSON string and falls back to the original value when it
17
6
  * cannot be parsed. Keeps the generated snippet readable, mirroring curl.
@@ -36,7 +25,7 @@ export const shellWget = {
36
25
  // against an explicit `method: undefined`, which would otherwise overwrite the default.
37
26
  const normalizedRequest = {
38
27
  ...request,
39
- method: (request?.method ?? 'GET').toUpperCase(),
28
+ method: normalizeMethod(request?.method),
40
29
  };
41
30
  // Build the URL, joining extra query parameters with `&` when the URL already carries a query string
42
31
  const baseUrl = normalizedRequest.url ?? '';
@@ -72,7 +61,7 @@ export const shellWget = {
72
61
  // Body
73
62
  if (normalizedRequest.postData) {
74
63
  const { mimeType, text, params } = normalizedRequest.postData;
75
- if (isJsonContentType(mimeType)) {
64
+ if (isJsonMediaType(mimeType)) {
76
65
  if (text) {
77
66
  parts.push(`--body-data '${escapeSingleQuotes(prettyPrintJson(text))}'`);
78
67
  }
@@ -96,7 +85,7 @@ export const shellWget = {
96
85
  }
97
86
  else {
98
87
  const rawValue = param.value ?? '';
99
- const displayValue = isJsonContentType(param.contentType) && rawValue ? prettyPrintJson(rawValue) : rawValue;
88
+ const displayValue = isJsonMediaType(param.contentType) && rawValue ? prettyPrintJson(rawValue) : rawValue;
100
89
  parts.push(`--body-data '${escapeSingleQuotes(`${param.name}=${displayValue}`)}'`);
101
90
  }
102
91
  });
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "url": "git+https://github.com/scalar/scalar.git",
10
10
  "directory": "packages/snippetz"
11
11
  },
12
- "version": "0.9.32",
12
+ "version": "0.10.1",
13
13
  "engines": {
14
14
  "node": ">=22"
15
15
  },
@@ -238,8 +238,8 @@
238
238
  "CHANGELOG"
239
239
  ],
240
240
  "dependencies": {
241
- "@scalar/helpers": "0.12.0",
242
- "@scalar/types": "0.20.1",
241
+ "@scalar/helpers": "0.14.0",
242
+ "@scalar/types": "0.22.0",
243
243
  "js-base64": "^3.9.2"
244
244
  },
245
245
  "devDependencies": {