@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.
- package/dist/clients/index.d.ts.map +1 -1
- package/dist/clients/index.js +7 -5
- package/dist/libs/http.d.ts +29 -0
- package/dist/libs/http.d.ts.map +1 -1
- package/dist/libs/http.js +53 -0
- package/dist/libs/javascript.d.ts.map +1 -1
- package/dist/libs/javascript.js +6 -3
- package/dist/plugins/c/libcurl/libcurl.d.ts.map +1 -1
- package/dist/plugins/c/libcurl/libcurl.js +145 -5
- package/dist/plugins/go/native/native.d.ts.map +1 -1
- package/dist/plugins/go/native/native.js +150 -5
- package/dist/plugins/js/axios/axios.d.ts +1 -2
- package/dist/plugins/js/axios/axios.d.ts.map +1 -1
- package/dist/plugins/js/axios/axios.js +2 -11
- package/dist/plugins/node/axios/axios.d.ts +1 -2
- package/dist/plugins/node/axios/axios.d.ts.map +1 -1
- package/dist/plugins/node/axios/axios.js +2 -11
- package/dist/plugins/php/laravel/index.d.ts +2 -0
- package/dist/plugins/php/laravel/index.d.ts.map +1 -0
- package/dist/plugins/php/laravel/index.js +1 -0
- package/dist/plugins/php/laravel/laravel.d.ts +6 -0
- package/dist/plugins/php/laravel/laravel.d.ts.map +1 -0
- package/dist/plugins/php/laravel/laravel.js +134 -0
- package/dist/plugins/python/aiohttp/aiohttp.d.ts +6 -0
- package/dist/plugins/python/aiohttp/aiohttp.d.ts.map +1 -0
- package/dist/plugins/python/aiohttp/aiohttp.js +107 -0
- package/dist/plugins/python/aiohttp/index.d.ts +2 -0
- package/dist/plugins/python/aiohttp/index.d.ts.map +1 -0
- package/dist/plugins/python/aiohttp/index.js +1 -0
- package/dist/plugins/python/python3/python3.d.ts.map +1 -1
- package/dist/plugins/python/python3/python3.js +192 -5
- package/dist/plugins/python/requestsLike.d.ts +2 -0
- package/dist/plugins/python/requestsLike.d.ts.map +1 -1
- package/dist/plugins/python/requestsLike.js +9 -9
- package/dist/plugins/r/httr2/httr2.d.ts +6 -0
- package/dist/plugins/r/httr2/httr2.d.ts.map +1 -0
- package/dist/plugins/r/httr2/httr2.js +159 -0
- package/dist/plugins/r/httr2/index.d.ts +2 -0
- package/dist/plugins/r/httr2/index.d.ts.map +1 -0
- package/dist/plugins/r/httr2/index.js +1 -0
- package/dist/plugins/ruby/native/native.d.ts.map +1 -1
- package/dist/plugins/ruby/native/native.js +138 -5
- package/dist/plugins/shared/axios.d.ts +3 -0
- package/dist/plugins/shared/axios.d.ts.map +1 -0
- package/dist/plugins/shared/axios.js +148 -0
- package/dist/plugins/swift/nsurlsession/nsurlsession.d.ts.map +1 -1
- package/dist/plugins/swift/nsurlsession/nsurlsession.js +118 -5
- package/dist/snippetz.d.ts +2 -2
- package/package.json +17 -7
- package/dist/httpsnippet-lite/targets/c/libcurl/client.d.ts +0 -3
- package/dist/httpsnippet-lite/targets/c/libcurl/client.d.ts.map +0 -1
- package/dist/httpsnippet-lite/targets/c/libcurl/client.js +0 -74
- package/dist/httpsnippet-lite/targets/go/native/client.d.ts +0 -12
- package/dist/httpsnippet-lite/targets/go/native/client.d.ts.map +0 -1
- package/dist/httpsnippet-lite/targets/go/native/client.js +0 -157
- package/dist/httpsnippet-lite/targets/javascript/axios/client.d.ts +0 -12
- package/dist/httpsnippet-lite/targets/javascript/axios/client.d.ts.map +0 -1
- package/dist/httpsnippet-lite/targets/javascript/axios/client.js +0 -86
- package/dist/httpsnippet-lite/targets/node/axios/client.d.ts +0 -3
- package/dist/httpsnippet-lite/targets/node/axios/client.d.ts.map +0 -1
- package/dist/httpsnippet-lite/targets/node/axios/client.js +0 -78
- package/dist/httpsnippet-lite/targets/python/python3/client.d.ts +0 -12
- package/dist/httpsnippet-lite/targets/python/python3/client.d.ts.map +0 -1
- package/dist/httpsnippet-lite/targets/python/python3/client.js +0 -88
- package/dist/httpsnippet-lite/targets/r/httr/client.d.ts +0 -12
- package/dist/httpsnippet-lite/targets/r/httr/client.d.ts.map +0 -1
- package/dist/httpsnippet-lite/targets/r/httr/client.js +0 -115
- package/dist/httpsnippet-lite/targets/ruby/native/client.d.ts +0 -3
- package/dist/httpsnippet-lite/targets/ruby/native/client.d.ts.map +0 -1
- package/dist/httpsnippet-lite/targets/ruby/native/client.js +0 -67
- package/dist/httpsnippet-lite/targets/swift/helpers.d.ts +0 -15
- package/dist/httpsnippet-lite/targets/swift/helpers.d.ts.map +0 -1
- package/dist/httpsnippet-lite/targets/swift/helpers.js +0 -70
- package/dist/httpsnippet-lite/targets/swift/nsurlsession/client.d.ts +0 -12
- package/dist/httpsnippet-lite/targets/swift/nsurlsession/client.d.ts.map +0 -1
- package/dist/httpsnippet-lite/targets/swift/nsurlsession/client.js +0 -128
- package/dist/plugins/r/httr/httr.d.ts +0 -6
- package/dist/plugins/r/httr/httr.d.ts.map +0 -1
- package/dist/plugins/r/httr/httr.js +0 -14
- package/dist/plugins/r/httr/index.d.ts +0 -2
- package/dist/plugins/r/httr/index.d.ts.map +0 -1
- 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 @@
|
|
|
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 @@
|
|
|
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,
|
|
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 {
|
|
2
|
-
import {
|
|
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
|
-
|
|
12
|
-
|
|
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;
|
|
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 =
|
|
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 =
|
|
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 @@
|
|
|
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"}
|