@scalar/snippetz 0.8.0 → 0.9.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 (82) hide show
  1. package/dist/clients/index.d.ts.map +1 -1
  2. package/dist/clients/index.js +7 -5
  3. package/dist/libs/http.d.ts +29 -0
  4. package/dist/libs/http.d.ts.map +1 -1
  5. package/dist/libs/http.js +53 -0
  6. package/dist/libs/javascript.d.ts.map +1 -1
  7. package/dist/libs/javascript.js +6 -3
  8. package/dist/plugins/c/libcurl/libcurl.d.ts.map +1 -1
  9. package/dist/plugins/c/libcurl/libcurl.js +145 -5
  10. package/dist/plugins/go/native/native.d.ts.map +1 -1
  11. package/dist/plugins/go/native/native.js +150 -5
  12. package/dist/plugins/js/axios/axios.d.ts +1 -2
  13. package/dist/plugins/js/axios/axios.d.ts.map +1 -1
  14. package/dist/plugins/js/axios/axios.js +2 -11
  15. package/dist/plugins/node/axios/axios.d.ts +1 -2
  16. package/dist/plugins/node/axios/axios.d.ts.map +1 -1
  17. package/dist/plugins/node/axios/axios.js +2 -11
  18. package/dist/plugins/php/laravel/index.d.ts +2 -0
  19. package/dist/plugins/php/laravel/index.d.ts.map +1 -0
  20. package/dist/plugins/php/laravel/index.js +1 -0
  21. package/dist/plugins/php/laravel/laravel.d.ts +6 -0
  22. package/dist/plugins/php/laravel/laravel.d.ts.map +1 -0
  23. package/dist/plugins/php/laravel/laravel.js +134 -0
  24. package/dist/plugins/python/aiohttp/aiohttp.d.ts +6 -0
  25. package/dist/plugins/python/aiohttp/aiohttp.d.ts.map +1 -0
  26. package/dist/plugins/python/aiohttp/aiohttp.js +107 -0
  27. package/dist/plugins/python/aiohttp/index.d.ts +2 -0
  28. package/dist/plugins/python/aiohttp/index.d.ts.map +1 -0
  29. package/dist/plugins/python/aiohttp/index.js +1 -0
  30. package/dist/plugins/python/python3/python3.d.ts.map +1 -1
  31. package/dist/plugins/python/python3/python3.js +192 -5
  32. package/dist/plugins/python/requestsLike.d.ts +2 -0
  33. package/dist/plugins/python/requestsLike.d.ts.map +1 -1
  34. package/dist/plugins/python/requestsLike.js +9 -9
  35. package/dist/plugins/r/httr2/httr2.d.ts +6 -0
  36. package/dist/plugins/r/httr2/httr2.d.ts.map +1 -0
  37. package/dist/plugins/r/httr2/httr2.js +159 -0
  38. package/dist/plugins/r/httr2/index.d.ts +2 -0
  39. package/dist/plugins/r/httr2/index.d.ts.map +1 -0
  40. package/dist/plugins/r/httr2/index.js +1 -0
  41. package/dist/plugins/ruby/native/native.d.ts.map +1 -1
  42. package/dist/plugins/ruby/native/native.js +138 -5
  43. package/dist/plugins/shared/axios.d.ts +3 -0
  44. package/dist/plugins/shared/axios.d.ts.map +1 -0
  45. package/dist/plugins/shared/axios.js +148 -0
  46. package/dist/plugins/swift/nsurlsession/nsurlsession.d.ts.map +1 -1
  47. package/dist/plugins/swift/nsurlsession/nsurlsession.js +118 -5
  48. package/dist/snippetz.d.ts +2 -2
  49. package/package.json +17 -7
  50. package/dist/httpsnippet-lite/targets/c/libcurl/client.d.ts +0 -3
  51. package/dist/httpsnippet-lite/targets/c/libcurl/client.d.ts.map +0 -1
  52. package/dist/httpsnippet-lite/targets/c/libcurl/client.js +0 -74
  53. package/dist/httpsnippet-lite/targets/go/native/client.d.ts +0 -12
  54. package/dist/httpsnippet-lite/targets/go/native/client.d.ts.map +0 -1
  55. package/dist/httpsnippet-lite/targets/go/native/client.js +0 -157
  56. package/dist/httpsnippet-lite/targets/javascript/axios/client.d.ts +0 -12
  57. package/dist/httpsnippet-lite/targets/javascript/axios/client.d.ts.map +0 -1
  58. package/dist/httpsnippet-lite/targets/javascript/axios/client.js +0 -86
  59. package/dist/httpsnippet-lite/targets/node/axios/client.d.ts +0 -3
  60. package/dist/httpsnippet-lite/targets/node/axios/client.d.ts.map +0 -1
  61. package/dist/httpsnippet-lite/targets/node/axios/client.js +0 -78
  62. package/dist/httpsnippet-lite/targets/python/python3/client.d.ts +0 -12
  63. package/dist/httpsnippet-lite/targets/python/python3/client.d.ts.map +0 -1
  64. package/dist/httpsnippet-lite/targets/python/python3/client.js +0 -88
  65. package/dist/httpsnippet-lite/targets/r/httr/client.d.ts +0 -12
  66. package/dist/httpsnippet-lite/targets/r/httr/client.d.ts.map +0 -1
  67. package/dist/httpsnippet-lite/targets/r/httr/client.js +0 -115
  68. package/dist/httpsnippet-lite/targets/ruby/native/client.d.ts +0 -3
  69. package/dist/httpsnippet-lite/targets/ruby/native/client.d.ts.map +0 -1
  70. package/dist/httpsnippet-lite/targets/ruby/native/client.js +0 -67
  71. package/dist/httpsnippet-lite/targets/swift/helpers.d.ts +0 -15
  72. package/dist/httpsnippet-lite/targets/swift/helpers.d.ts.map +0 -1
  73. package/dist/httpsnippet-lite/targets/swift/helpers.js +0 -70
  74. package/dist/httpsnippet-lite/targets/swift/nsurlsession/client.d.ts +0 -12
  75. package/dist/httpsnippet-lite/targets/swift/nsurlsession/client.d.ts.map +0 -1
  76. package/dist/httpsnippet-lite/targets/swift/nsurlsession/client.js +0 -128
  77. package/dist/plugins/r/httr/httr.d.ts +0 -6
  78. package/dist/plugins/r/httr/httr.d.ts.map +0 -1
  79. package/dist/plugins/r/httr/httr.js +0 -14
  80. package/dist/plugins/r/httr/index.d.ts +0 -2
  81. package/dist/plugins/r/httr/index.d.ts.map +0 -1
  82. package/dist/plugins/r/httr/index.js +0 -1
@@ -0,0 +1,134 @@
1
+ import { accumulateRepeatedValue, buildQueryString } from '../../../libs/http.js';
2
+ import { objectToString } from '../../../libs/php.js';
3
+ const escapePhpString = (value) => value.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
4
+ const quotePhpString = (value) => `'${escapePhpString(value)}'`;
5
+ const escapePhpObjectKey = escapePhpString;
6
+ const escapeObjectKeys = (value) => {
7
+ if (Array.isArray(value)) {
8
+ return value.map((item) => escapeObjectKeys(item));
9
+ }
10
+ if (value && typeof value === 'object') {
11
+ return Object.entries(value).reduce((acc, [key, nestedValue]) => {
12
+ acc[escapePhpObjectKey(key)] = escapeObjectKeys(nestedValue);
13
+ return acc;
14
+ }, {});
15
+ }
16
+ return value;
17
+ };
18
+ const getCookieDomain = (url) => {
19
+ if (!url) {
20
+ return 'localhost';
21
+ }
22
+ try {
23
+ return new URL(url).hostname || 'localhost';
24
+ }
25
+ catch {
26
+ return 'localhost';
27
+ }
28
+ };
29
+ /**
30
+ * php/laravel
31
+ */
32
+ export const phpLaravel = {
33
+ target: 'php',
34
+ client: 'laravel',
35
+ title: 'Laravel HTTP Client',
36
+ generate(request, configuration) {
37
+ const normalizedRequest = {
38
+ method: 'GET',
39
+ ...request,
40
+ };
41
+ normalizedRequest.method = normalizedRequest.method.toUpperCase();
42
+ const queryString = buildQueryString(normalizedRequest.queryString);
43
+ const url = `${normalizedRequest.url ?? ''}${queryString}`;
44
+ const chain = [];
45
+ if (configuration?.auth?.username && configuration.auth.password) {
46
+ chain.push(`withBasicAuth(${quotePhpString(configuration.auth.username)}, ${quotePhpString(configuration.auth.password)})`);
47
+ }
48
+ if (normalizedRequest.headers?.length) {
49
+ const headers = {};
50
+ normalizedRequest.headers.forEach((header) => {
51
+ accumulateRepeatedValue(headers, header.name, header.value);
52
+ });
53
+ chain.push(`withHeaders(${objectToString(escapeObjectKeys(headers))})`);
54
+ }
55
+ if (normalizedRequest.cookies?.length) {
56
+ const cookies = {};
57
+ normalizedRequest.cookies.forEach((cookie) => {
58
+ accumulateRepeatedValue(cookies, cookie.name, cookie.value);
59
+ });
60
+ chain.push(`withCookies(${objectToString(escapeObjectKeys(cookies))}, ${quotePhpString(getCookieDomain(normalizedRequest.url ?? ''))})`);
61
+ }
62
+ let payload;
63
+ if (normalizedRequest.postData) {
64
+ if (normalizedRequest.postData.mimeType === 'application/json') {
65
+ if (normalizedRequest.postData.text) {
66
+ try {
67
+ payload = JSON.parse(normalizedRequest.postData.text);
68
+ }
69
+ catch {
70
+ chain.push(`withBody(${quotePhpString(normalizedRequest.postData.text)}, 'application/json')`);
71
+ }
72
+ }
73
+ }
74
+ else if (normalizedRequest.postData.mimeType === 'application/x-www-form-urlencoded' &&
75
+ normalizedRequest.postData.params) {
76
+ const formData = {};
77
+ normalizedRequest.postData.params.forEach((param) => {
78
+ accumulateRepeatedValue(formData, param.name, param.value ?? '');
79
+ });
80
+ chain.push('asForm()');
81
+ payload = formData;
82
+ }
83
+ else if (normalizedRequest.postData.mimeType === 'multipart/form-data' && normalizedRequest.postData.params) {
84
+ const multipartData = {};
85
+ normalizedRequest.postData.params.forEach((param) => {
86
+ if (param.fileName !== undefined) {
87
+ const args = [
88
+ quotePhpString(param.name),
89
+ `file_get_contents(${quotePhpString(param.fileName)})`,
90
+ quotePhpString(param.fileName),
91
+ ];
92
+ if (param.contentType) {
93
+ args.push(objectToString(escapeObjectKeys({ 'Content-Type': param.contentType })));
94
+ }
95
+ chain.push(`attach(${args.join(', ')})`);
96
+ }
97
+ else if (param.contentType) {
98
+ chain.push(`attach(${quotePhpString(param.name)}, ${quotePhpString(param.value ?? '')}, null, ${objectToString(escapeObjectKeys({ 'Content-Type': param.contentType }))})`);
99
+ }
100
+ else {
101
+ accumulateRepeatedValue(multipartData, param.name, param.value ?? '');
102
+ }
103
+ });
104
+ if (Object.keys(multipartData).length > 0) {
105
+ payload = multipartData;
106
+ }
107
+ }
108
+ else if (normalizedRequest.postData.mimeType === 'application/octet-stream') {
109
+ chain.push(`withBody(${quotePhpString(normalizedRequest.postData.text ?? '')}, 'application/octet-stream')`);
110
+ }
111
+ else if (normalizedRequest.postData.text) {
112
+ try {
113
+ payload = JSON.parse(normalizedRequest.postData.text);
114
+ }
115
+ catch {
116
+ chain.push(`withBody(${quotePhpString(normalizedRequest.postData.text)}, ${quotePhpString(normalizedRequest.postData.mimeType || 'text/plain')})`);
117
+ }
118
+ }
119
+ }
120
+ const requestMethod = normalizedRequest.method.toLowerCase();
121
+ const supportsDirectMethod = ['delete', 'get', 'head', 'patch', 'post', 'put'].includes(requestMethod);
122
+ const requestCall = supportsDirectMethod
123
+ ? payload !== undefined && requestMethod !== 'head'
124
+ ? `${requestMethod}(${quotePhpString(url)}, ${objectToString(escapeObjectKeys(payload), 1)})`
125
+ : `${requestMethod}(${quotePhpString(url)})`
126
+ : payload !== undefined
127
+ ? `send(${quotePhpString(normalizedRequest.method)}, ${quotePhpString(url)}, ${objectToString(escapeObjectKeys(payload), 1)})`
128
+ : `send(${quotePhpString(normalizedRequest.method)}, ${quotePhpString(url)})`;
129
+ const expression = chain.length > 0
130
+ ? [`Http::${chain[0]}`, ...chain.slice(1).map((method) => ` ->${method}`), ` ->${requestCall}`].join('\n')
131
+ : `Http::${requestCall}`;
132
+ return `use Illuminate\\Support\\Facades\\Http;\n\n$response = ${expression};`;
133
+ },
134
+ };
@@ -0,0 +1,6 @@
1
+ import type { Plugin } from '@scalar/types/snippetz';
2
+ /**
3
+ * python/aiohttp
4
+ */
5
+ export declare const pythonAiohttp: Plugin;
6
+ //# sourceMappingURL=aiohttp.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,107 @@
1
+ import { accumulateRepeatedValue, reduceQueryParams } from '../../../libs/http.js';
2
+ import { LENGTH_CONSIDERED_AS_SHORT, formatPythonValue } from '../../../plugins/python/requestsLike.js';
3
+ const indent = (value, prefix = ' ') => value
4
+ .split('\n')
5
+ .map((line) => (line.trim() === '' ? line : `${prefix}${line}`))
6
+ .join('\n');
7
+ const formatRequestCall = (clientVar, method, url, args) => {
8
+ const urlParam = JSON.stringify(url);
9
+ if (url.length > LENGTH_CONSIDERED_AS_SHORT) {
10
+ return `${clientVar}.${method}(\n ${[urlParam, ...args].join(',\n ')}\n)`;
11
+ }
12
+ if (args.length === 0) {
13
+ return `${clientVar}.${method}(${urlParam})`;
14
+ }
15
+ return `${clientVar}.${method}(${urlParam},\n ${args.join(',\n ')}\n)`;
16
+ };
17
+ /**
18
+ * python/aiohttp
19
+ */
20
+ export const pythonAiohttp = {
21
+ target: 'python',
22
+ client: 'aiohttp',
23
+ title: 'aiohttp',
24
+ generate(request, configuration) {
25
+ const normalizedRequest = {
26
+ url: 'https://example.com',
27
+ method: 'get',
28
+ ...request,
29
+ };
30
+ const method = normalizedRequest.method?.toLowerCase() ?? 'get';
31
+ const requestArgs = [];
32
+ const sessionArgs = [];
33
+ const setupLines = [];
34
+ if (normalizedRequest.headers?.length) {
35
+ const headers = normalizedRequest.headers.reduce((acc, header) => {
36
+ if (!(header.name in acc)) {
37
+ acc[header.name] = header.value;
38
+ }
39
+ return acc;
40
+ }, {});
41
+ requestArgs.push(`headers=${formatPythonValue(headers)}`);
42
+ }
43
+ if (normalizedRequest.queryString?.length) {
44
+ requestArgs.push(`params=${formatPythonValue(reduceQueryParams(normalizedRequest.queryString))}`);
45
+ }
46
+ if (normalizedRequest.cookies?.length) {
47
+ const cookies = Object.fromEntries(normalizedRequest.cookies.map((cookie) => [cookie.name, cookie.value]));
48
+ sessionArgs.push(`cookies=${formatPythonValue(cookies)}`);
49
+ }
50
+ if (configuration?.auth?.username && configuration?.auth?.password) {
51
+ sessionArgs.push(`auth=aiohttp.BasicAuth(${JSON.stringify(configuration.auth.username)}, ${JSON.stringify(configuration.auth.password)})`);
52
+ }
53
+ if (normalizedRequest.postData) {
54
+ const { mimeType, text, params } = normalizedRequest.postData;
55
+ if (mimeType === 'application/json' && text) {
56
+ try {
57
+ requestArgs.push(`json=${formatPythonValue(JSON.parse(text))}`);
58
+ }
59
+ catch {
60
+ requestArgs.push(`data=${JSON.stringify(text)}`);
61
+ }
62
+ }
63
+ else if (mimeType === 'application/octet-stream' && text) {
64
+ requestArgs.push(`data=b"${text}"`);
65
+ }
66
+ else if (mimeType === 'multipart/form-data' && params) {
67
+ setupLines.push('data = aiohttp.FormData()');
68
+ params.forEach((param) => {
69
+ if (param.fileName !== undefined) {
70
+ const addFieldArgs = [
71
+ JSON.stringify(param.name),
72
+ `open(${JSON.stringify(param.fileName)}, "rb")`,
73
+ `filename=${JSON.stringify(param.fileName)}`,
74
+ ];
75
+ if (param.contentType) {
76
+ addFieldArgs.push(`content_type=${JSON.stringify(param.contentType)}`);
77
+ }
78
+ setupLines.push(`data.add_field(${addFieldArgs.join(', ')})`);
79
+ return;
80
+ }
81
+ if (param.contentType) {
82
+ setupLines.push(`data.add_field(${JSON.stringify(param.name)}, ${JSON.stringify(param.value ?? '')}, content_type=${JSON.stringify(param.contentType)})`);
83
+ return;
84
+ }
85
+ setupLines.push(`data.add_field(${JSON.stringify(param.name)}, ${JSON.stringify(param.value ?? '')})`);
86
+ });
87
+ requestArgs.push('data=data');
88
+ }
89
+ else if (mimeType === 'application/x-www-form-urlencoded' && params) {
90
+ const formData = {};
91
+ params.forEach((param) => {
92
+ accumulateRepeatedValue(formData, param.name, param.value ?? '');
93
+ });
94
+ requestArgs.push(`data=${formatPythonValue(formData)}`);
95
+ }
96
+ else if (text) {
97
+ requestArgs.push(`data=${JSON.stringify(text)}`);
98
+ }
99
+ }
100
+ const sessionOpen = sessionArgs.length === 0
101
+ ? 'async with aiohttp.ClientSession() as session:'
102
+ : `async with aiohttp.ClientSession(\n ${sessionArgs.join(',\n ')}\n) as session:`;
103
+ const requestCall = formatRequestCall('await session', method, normalizedRequest.url ?? '', requestArgs);
104
+ const bodyLines = [...setupLines, requestCall];
105
+ return `${sessionOpen}\n${indent(bodyLines.join('\n'))}`;
106
+ },
107
+ };
@@ -0,0 +1,2 @@
1
+ export { pythonAiohttp } from './aiohttp.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/plugins/python/aiohttp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA"}
@@ -0,0 +1 @@
1
+ export { pythonAiohttp } from './aiohttp.js';
@@ -1 +1 @@
1
- {"version":3,"file":"python3.d.ts","sourceRoot":"","sources":["../../../../src/plugins/python/python3/python3.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAKpD;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,MAQ3B,CAAA"}
1
+ {"version":3,"file":"python3.d.ts","sourceRoot":"","sources":["../../../../src/plugins/python/python3/python3.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,MAAM,EAAE,MAAM,wBAAwB,CAAA;AA2KhE;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,MAiF3B,CAAA"}
@@ -1,5 +1,133 @@
1
- import { python3 } from '../../../httpsnippet-lite/targets/python/python3/client.js';
2
- import { convertWithHttpSnippetLite } from '../../../utils/convertWithHttpSnippetLite.js';
1
+ import { accumulateRepeatedValue, buildQueryString, normalizeRequest } from '../../../libs/http.js';
2
+ import { formatPythonValue } from '../../../plugins/python/requestsLike.js';
3
+ const createBasicAuthToken = (value) => {
4
+ if (typeof globalThis.btoa === 'function') {
5
+ return globalThis.btoa(value);
6
+ }
7
+ if (typeof Buffer !== 'undefined') {
8
+ return Buffer.from(value, 'utf-8').toString('base64');
9
+ }
10
+ throw new Error('Could not encode basic auth credentials');
11
+ };
12
+ const parseRequestUrl = (url) => {
13
+ if (!url) {
14
+ return new URL('https://example.com');
15
+ }
16
+ try {
17
+ return new URL(url);
18
+ }
19
+ catch {
20
+ return new URL(url, 'https://example.com');
21
+ }
22
+ };
23
+ const mergeQueryString = (url, queryString = []) => {
24
+ if (!queryString.length) {
25
+ return url.search;
26
+ }
27
+ const serializedQuery = buildQueryString(queryString);
28
+ if (!url.search) {
29
+ return serializedQuery;
30
+ }
31
+ return `${url.search}&${serializedQuery.slice(1)}`;
32
+ };
33
+ const formatBytesLiteral = (value) => {
34
+ const escaped = JSON.stringify(value).slice(1, -1);
35
+ return `b"${escaped}"`;
36
+ };
37
+ const buildRequestBody = (request, headers, imports) => {
38
+ const postData = request.postData;
39
+ if (!postData) {
40
+ return {
41
+ payloadLines: [],
42
+ };
43
+ }
44
+ const { mimeType, text, params } = postData;
45
+ if (mimeType === 'application/json' && text) {
46
+ try {
47
+ const parsed = JSON.parse(text);
48
+ imports.add('import json');
49
+ return {
50
+ payloadLines: [`payload = json.dumps(${formatPythonValue(parsed, 0)})`],
51
+ payloadVariable: 'payload',
52
+ };
53
+ }
54
+ catch {
55
+ return {
56
+ payloadLines: [`payload = ${JSON.stringify(text)}`],
57
+ payloadVariable: 'payload',
58
+ };
59
+ }
60
+ }
61
+ if (mimeType === 'application/octet-stream' && text) {
62
+ return {
63
+ payloadLines: [`payload = ${formatBytesLiteral(text)}`],
64
+ payloadVariable: 'payload',
65
+ };
66
+ }
67
+ if (mimeType === 'application/x-www-form-urlencoded' && params) {
68
+ imports.add('import urllib.parse');
69
+ const formData = {};
70
+ params.forEach((param) => {
71
+ accumulateRepeatedValue(formData, param.name, param.value ?? '');
72
+ });
73
+ if (!headers['Content-Type']) {
74
+ headers['Content-Type'] = 'application/x-www-form-urlencoded';
75
+ }
76
+ return {
77
+ payloadLines: [`payload = urllib.parse.urlencode(${formatPythonValue(formData, 0)}, doseq=True)`],
78
+ payloadVariable: 'payload',
79
+ };
80
+ }
81
+ if (mimeType === 'multipart/form-data' && params) {
82
+ const payloadLines = ['boundary = "----ScalarSnippetzBoundary"', 'data_list = []'];
83
+ params.forEach((param) => {
84
+ payloadLines.push('data_list.append("--" + boundary)');
85
+ if (param.fileName !== undefined) {
86
+ payloadLines.push(`data_list.append(${JSON.stringify(`Content-Disposition: form-data; name="${param.name}"; filename="${param.fileName}"`)})`);
87
+ }
88
+ else {
89
+ payloadLines.push(`data_list.append(${JSON.stringify(`Content-Disposition: form-data; name="${param.name}"`)})`);
90
+ }
91
+ if (param.contentType) {
92
+ payloadLines.push(`data_list.append(${JSON.stringify(`Content-Type: ${param.contentType}`)})`);
93
+ }
94
+ payloadLines.push('data_list.append("")');
95
+ if (param.fileName !== undefined) {
96
+ payloadLines.push(`data_list.append(open(${JSON.stringify(param.fileName)}, "rb").read().decode("latin-1"))`);
97
+ }
98
+ else {
99
+ payloadLines.push(`data_list.append(${JSON.stringify(param.value ?? '')})`);
100
+ }
101
+ });
102
+ payloadLines.push('data_list.append("--" + boundary + "--")');
103
+ payloadLines.push('data_list.append("")');
104
+ payloadLines.push('payload = "\\r\\n".join(data_list)');
105
+ headers['Content-Type'] = 'multipart/form-data; boundary=----ScalarSnippetzBoundary';
106
+ return {
107
+ payloadLines,
108
+ payloadVariable: 'payload',
109
+ };
110
+ }
111
+ if (text) {
112
+ try {
113
+ const parsed = JSON.parse(text);
114
+ imports.add('import json');
115
+ return {
116
+ payloadLines: [`payload = json.dumps(${formatPythonValue(parsed, 0)})`],
117
+ payloadVariable: 'payload',
118
+ };
119
+ }
120
+ catch {
121
+ return {
122
+ payloadLines: [`payload = ${JSON.stringify(text)}`],
123
+ payloadVariable: 'payload',
124
+ };
125
+ }
126
+ }
127
+ return {
128
+ payloadLines: [],
129
+ };
130
+ };
3
131
  /**
4
132
  * python/python3
5
133
  */
@@ -7,8 +135,67 @@ export const pythonPython3 = {
7
135
  target: 'python',
8
136
  client: 'python3',
9
137
  title: 'http.client',
10
- generate(request) {
11
- // TODO: Write an own converter
12
- return convertWithHttpSnippetLite(python3, request);
138
+ generate(request, configuration) {
139
+ const normalizedRequest = normalizeRequest({
140
+ url: 'https://example.com',
141
+ ...request,
142
+ });
143
+ const requestUrl = normalizedRequest.url ?? 'https://example.com';
144
+ const parsedUrl = parseRequestUrl(requestUrl);
145
+ const queryString = mergeQueryString(parsedUrl, normalizedRequest.queryString);
146
+ const path = `${parsedUrl.pathname || '/'}${queryString}`;
147
+ const headers = normalizedRequest.headers?.reduce((acc, header) => {
148
+ if (!(header.name in acc)) {
149
+ acc[header.name] = header.value;
150
+ }
151
+ return acc;
152
+ }, {});
153
+ const preparedHeaders = headers ?? {};
154
+ if (normalizedRequest.cookies?.length) {
155
+ const cookieHeader = normalizedRequest.cookies
156
+ .map((cookie) => `${encodeURIComponent(cookie.name)}=${encodeURIComponent(cookie.value)}`)
157
+ .join('; ');
158
+ if (preparedHeaders.Cookie) {
159
+ preparedHeaders.Cookie = `${preparedHeaders.Cookie}; ${cookieHeader}`;
160
+ }
161
+ else {
162
+ preparedHeaders.Cookie = cookieHeader;
163
+ }
164
+ }
165
+ if (configuration?.auth?.username && configuration.auth.password) {
166
+ const authValue = createBasicAuthToken(`${configuration.auth.username}:${configuration.auth.password}`);
167
+ preparedHeaders.Authorization = `Basic ${authValue}`;
168
+ }
169
+ const imports = new Set(['import http.client']);
170
+ const setupLines = [];
171
+ const bodyResult = buildRequestBody(normalizedRequest, preparedHeaders, imports);
172
+ setupLines.push(...bodyResult.payloadLines);
173
+ if (Object.keys(preparedHeaders).length) {
174
+ setupLines.push(`headers = ${formatPythonValue(preparedHeaders, 0)}`);
175
+ }
176
+ const requestArguments = [JSON.stringify(normalizedRequest.method), JSON.stringify(path)];
177
+ if (bodyResult.payloadVariable) {
178
+ requestArguments.push(`body=${bodyResult.payloadVariable}`);
179
+ }
180
+ if (Object.keys(preparedHeaders).length) {
181
+ requestArguments.push('headers=headers');
182
+ }
183
+ const requestCall = requestArguments.length <= 2
184
+ ? `conn.request(${requestArguments.join(', ')})`
185
+ : `conn.request(\n ${requestArguments.join(',\n ')},\n)`;
186
+ const lines = [
187
+ ...imports,
188
+ '',
189
+ `conn = http.client.${parsedUrl.protocol === 'https:' ? 'HTTPSConnection' : 'HTTPConnection'}(${JSON.stringify(parsedUrl.host)})`,
190
+ ...(setupLines.length ? ['', ...setupLines] : []),
191
+ '',
192
+ requestCall,
193
+ '',
194
+ 'response = conn.getresponse()',
195
+ 'print(response.read().decode())',
196
+ '',
197
+ 'conn.close()',
198
+ ];
199
+ return lines.join('\n');
13
200
  },
14
201
  };
@@ -1,3 +1,5 @@
1
1
  import type { HarRequest, PluginConfiguration } from '@scalar/types/snippetz';
2
+ export declare const LENGTH_CONSIDERED_AS_SHORT = 40;
3
+ export declare function formatPythonValue(value: unknown, indentation?: number): string;
2
4
  export declare function requestsLikeGenerate(clientVar: string, request?: Partial<HarRequest>, configuration?: PluginConfiguration): string;
3
5
  //# sourceMappingURL=requestsLike.d.ts.map
@@ -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;AA0B7E,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,EAC7B,aAAa,CAAC,EAAE,mBAAmB,UA2JpC"}
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,UAiJpC"}
@@ -1,5 +1,5 @@
1
1
  import { accumulateRepeatedValue, reduceQueryParams } from '../../libs/http.js';
2
- const LENGTH_CONSIDERED_AS_SHORT = 40;
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) {
5
5
  const replacements = [
@@ -16,6 +16,12 @@ function convertToPythonSyntax(str) {
16
16
  }
17
17
  return result;
18
18
  }
19
+ export function formatPythonValue(value, indentation = 4) {
20
+ return convertToPythonSyntax(JSON.stringify(value, null, 2)
21
+ .split('\n')
22
+ .map((line, index) => (index === 0 ? line : ' '.repeat(indentation) + line))
23
+ .join('\n'));
24
+ }
19
25
  export function requestsLikeGenerate(clientVar, request, configuration) {
20
26
  // Normalize request with defaults
21
27
  const normalizedRequest = {
@@ -127,10 +133,7 @@ export function requestsLikeGenerate(clientVar, request, configuration) {
127
133
  formattedParams.push(`${key}=${filesStr}`);
128
134
  }
129
135
  else if (key === 'json') {
130
- const jsonString = convertToPythonSyntax(JSON.stringify(value, null, 2)
131
- .split('\n')
132
- .map((line, i) => (i === 0 ? line : ' ' + line))
133
- .join('\n'));
136
+ const jsonString = formatPythonValue(value);
134
137
  formattedParams.push(`${key}=${jsonString}`);
135
138
  }
136
139
  else if (key === 'data' && normalizedRequest.postData?.mimeType === 'application/octet-stream') {
@@ -138,10 +141,7 @@ export function requestsLikeGenerate(clientVar, request, configuration) {
138
141
  formattedParams.push(`${key}=b"${value}"`);
139
142
  }
140
143
  else {
141
- const str = convertToPythonSyntax(JSON.stringify(value, null, 2)
142
- .split('\n')
143
- .map((line, i) => (i === 0 ? line : ' ' + line))
144
- .join('\n'));
144
+ const str = formatPythonValue(value);
145
145
  formattedParams.push(`${key}=${str}`);
146
146
  }
147
147
  }
@@ -0,0 +1,6 @@
1
+ import type { Plugin } from '@scalar/types/snippetz';
2
+ /**
3
+ * r/httr2
4
+ */
5
+ export declare const rHttr2: Plugin;
6
+ //# sourceMappingURL=httr2.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"httr2.d.ts","sourceRoot":"","sources":["../../../../src/plugins/r/httr2/httr2.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,MAAM,EAAuB,MAAM,wBAAwB,CAAA;AAkDrF;;GAEG;AACH,eAAO,MAAM,MAAM,EAAE,MAuHpB,CAAA"}