@readme/httpsnippet 8.1.3 → 9.0.0

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/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import 'har-format';
2
2
  import './helpers/reducer.cjs';
3
- export { n as HTTPSnippet, m as HTTPSnippetOptions, H as HarRequest, l as Request, R as RequestExtras, j as addClientPlugin, g as addTarget, k as addTargetClient, o as availableTargets, p as extname } from './index-d5b13104.js';
3
+ export { n as HTTPSnippet, m as HTTPSnippetOptions, H as HarRequest, l as Request, R as RequestExtras, j as addClientPlugin, g as addTarget, k as addTargetClient, o as availableTargets, p as extname } from './index-BRpINGne.cjs';
4
4
  import 'node:url';
5
5
  import './helpers/code-builder.cjs';
6
6
  import 'type-fest';
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import 'har-format';
2
2
  import './helpers/reducer.js';
3
- export { n as HTTPSnippet, m as HTTPSnippetOptions, H as HarRequest, l as Request, R as RequestExtras, j as addClientPlugin, g as addTarget, k as addTargetClient, o as availableTargets, p as extname } from './index-09744b29.js';
3
+ export { n as HTTPSnippet, m as HTTPSnippetOptions, H as HarRequest, l as Request, R as RequestExtras, j as addClientPlugin, g as addTarget, k as addTargetClient, o as availableTargets, p as extname } from './index-D_ySc8Oi.js';
4
4
  import 'node:url';
5
5
  import './helpers/code-builder.js';
6
6
  import 'type-fest';
package/dist/index.js CHANGED
@@ -1,9 +1,8 @@
1
1
  import { reducer } from './chunk-KT7MO6Z4.js';
2
- import { targets, getHeaderName } from './chunk-ENNB4GTT.js';
3
- export { addClientPlugin, addTarget, addTargetClient } from './chunk-ENNB4GTT.js';
2
+ import { targets, getHeaderName } from './chunk-R65NNSSK.js';
3
+ export { addClientPlugin, addTarget, addTargetClient } from './chunk-R65NNSSK.js';
4
4
  import './chunk-Y7NI4MMY.js';
5
5
  import { parse, format } from 'url';
6
- import formDataToString from 'formdata-to-string';
7
6
  import { stringify } from 'qs';
8
7
 
9
8
  // src/helpers/utils.ts
@@ -44,10 +43,9 @@ var HTTPSnippet = class {
44
43
  ];
45
44
  }
46
45
  }
47
- async init() {
46
+ init() {
48
47
  this.initCalled = true;
49
- const promises = [];
50
- this.entries.forEach(({ request }) => {
48
+ this.requests = this.entries.map(({ request }) => {
51
49
  const req = {
52
50
  bodySize: 0,
53
51
  headersSize: 0,
@@ -63,12 +61,11 @@ var HTTPSnippet = class {
63
61
  if (req.postData && !req.postData.mimeType) {
64
62
  req.postData.mimeType = "application/octet-stream";
65
63
  }
66
- promises.push(this.prepare(req, this.options));
64
+ return this.prepare(req, this.options);
67
65
  });
68
- this.requests = await Promise.all(promises);
69
66
  return this;
70
67
  }
71
- async prepare(harRequest, options) {
68
+ prepare(harRequest, options) {
72
69
  const request = {
73
70
  ...harRequest,
74
71
  fullUrl: "",
@@ -117,21 +114,34 @@ var HTTPSnippet = class {
117
114
  request.postData.text = "";
118
115
  request.postData.mimeType = "multipart/form-data";
119
116
  if (request.postData?.params) {
120
- const form = new FormData();
121
- request.postData?.params.forEach((param) => {
117
+ const boundary = "---011000010111000001101001";
118
+ const carriage = `${boundary}--`;
119
+ const rn = "\r\n";
120
+ const escape = (str) => str.replace(/\n/g, "%0A").replace(/\r/g, "%0D").replace(/"/g, "%22");
121
+ const normalizeLinefeeds = (value) => value.replace(/\r?\n|\r/g, "\r\n");
122
+ const payload = [`--${boundary}`];
123
+ request.postData?.params.forEach((param, i) => {
122
124
  const name = param.name;
123
125
  const value = param.value || "";
124
126
  const filename = param.fileName || null;
125
- const contentType = param.contentType || "";
127
+ const contentType = param.contentType || "application/octet-stream";
126
128
  if (filename) {
127
- form.append(name, new Blob([value], { type: contentType }), filename);
129
+ payload.push(
130
+ `Content-Disposition: form-data; name="${escape(normalizeLinefeeds(name))}"; filename="${filename}"`
131
+ );
132
+ payload.push(`Content-Type: ${contentType}`);
128
133
  } else {
129
- form.append(name, value);
134
+ payload.push(`Content-Disposition: form-data; name="${escape(normalizeLinefeeds(name))}"`);
135
+ }
136
+ payload.push("");
137
+ payload.push(normalizeLinefeeds(value));
138
+ if (i !== request.postData.params.length - 1) {
139
+ payload.push(`--${boundary}`);
130
140
  }
131
141
  });
132
- const boundary = "---011000010111000001101001";
142
+ payload.push(`--${carriage}`);
133
143
  request.postData.boundary = boundary;
134
- request.postData.text = await formDataToString(form, { boundary });
144
+ request.postData.text = payload.join(rn);
135
145
  const contentTypeHeader = getHeaderName(request.headersObj, "content-type") || "content-type";
136
146
  request.headersObj[contentTypeHeader] = `multipart/form-data; boundary=${boundary}`;
137
147
  }
@@ -201,9 +211,9 @@ var HTTPSnippet = class {
201
211
  uriObj
202
212
  };
203
213
  }
204
- async convert(targetId, clientId, options) {
214
+ convert(targetId, clientId, options) {
205
215
  if (!this.initCalled) {
206
- await this.init();
216
+ this.init();
207
217
  }
208
218
  if (!options && clientId) {
209
219
  options = clientId;
@@ -217,6 +227,7 @@ var HTTPSnippet = class {
217
227
  return results.length === 1 ? results[0] : results;
218
228
  }
219
229
  };
230
+ /*! formdata-polyfill. MIT License. Jimmy Wärting <https://jimmy.warting.se/opensource> */
220
231
 
221
232
  export { HTTPSnippet, availableTargets, extname };
222
233
  //# sourceMappingURL=out.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/helpers/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReducedHelperObject } from './helpers/reducer.js';\nimport type { ClientId, TargetId } from './targets/index.js';\nimport type { Param, PostDataCommon, Request as NpmHarRequest } from 'har-format';\nimport type { UrlWithParsedQuery } from 'node:url';\n\nimport { format as urlFormat, parse as urlParse } from 'node:url';\n\nimport formDataToString from 'formdata-to-string';\nimport { stringify as queryStringify } from 'qs';\n\nimport { getHeaderName } from './helpers/headers.js';\nimport { reducer } from './helpers/reducer.js';\nimport { targets } from './targets/index.js';\n\nexport { availableTargets, extname } from './helpers/utils.js';\nexport { addTarget, addTargetClient, addClientPlugin } from './targets/index.js';\n\n/** is this wrong? yes. according to the spec (http://www.softwareishard.com/blog/har-12-spec/#postData) it's technically wrong since `params` and `text` are (by the spec) mutually exclusive. However, in practice, this is not what is often the case.\n *\n * In general, this library takes a _descriptive_ rather than _perscriptive_ approach (see https://amyrey.web.unc.edu/classes/ling-101-online/tutorials/understanding-prescriptive-vs-descriptive-grammar/).\n *\n * Then, in addition to that, it really adds to complexity with TypeScript (TypeScript takes this constraint very very seriously) in a way that's not actually super useful. So, we treat this object as though it could have both or either of `params` and/or `text`.\n */\ntype PostDataBase = PostDataCommon & {\n params?: Param[];\n text?: string;\n};\n\nexport type HarRequest = Omit<NpmHarRequest, 'postData'> & { postData: PostDataBase };\n\nexport interface RequestExtras {\n allHeaders: ReducedHelperObject;\n cookiesObj: ReducedHelperObject;\n fullUrl: string;\n headersObj: ReducedHelperObject;\n postData: PostDataBase & {\n boundary?: string;\n jsonObj?: ReducedHelperObject;\n paramsObj?: ReducedHelperObject;\n };\n queryObj: ReducedHelperObject;\n uriObj: UrlWithParsedQuery;\n}\n\nexport type Request = HarRequest & RequestExtras;\n\ninterface Entry {\n request: Partial<HarRequest>;\n}\n\ninterface HarEntry {\n log: {\n creator: {\n name: string;\n version: string;\n };\n entries: Entry[];\n version: string;\n };\n}\n\nexport interface HTTPSnippetOptions {\n harIsAlreadyEncoded?: boolean;\n}\n\nconst isHarEntry = (value: any): value is HarEntry =>\n typeof value === 'object' &&\n 'log' in value &&\n typeof value.log === 'object' &&\n 'entries' in value.log &&\n Array.isArray(value.log.entries);\n\nexport class HTTPSnippet {\n initCalled = false;\n\n entries: Entry[] = [];\n\n requests: Request[] = [];\n\n options: HTTPSnippetOptions = {};\n\n constructor(input: HarEntry | HarRequest, opts: HTTPSnippetOptions = {}) {\n this.options = {\n harIsAlreadyEncoded: false,\n ...opts,\n };\n\n // prep the main container\n this.requests = [];\n\n // is it har?\n if (isHarEntry(input)) {\n this.entries = input.log.entries;\n } else {\n this.entries = [\n {\n request: input,\n },\n ];\n }\n }\n\n async init() {\n this.initCalled = true;\n\n const promises: Promise<Request>[] = [];\n\n this.entries.forEach(({ request }) => {\n // add optional properties to make validation successful\n const req = {\n bodySize: 0,\n headersSize: 0,\n headers: [],\n cookies: [],\n httpVersion: 'HTTP/1.1',\n queryString: [],\n postData: {\n mimeType: request.postData?.mimeType || 'application/octet-stream',\n },\n ...request,\n };\n\n // Per the HAR spec `mimeType` needs to always be present if we have a `postData` object.\n if (req.postData && !req.postData.mimeType) {\n req.postData.mimeType = 'application/octet-stream';\n }\n\n promises.push(this.prepare(req as HarRequest, this.options));\n });\n\n this.requests = await Promise.all(promises);\n\n return this;\n }\n\n async prepare(harRequest: HarRequest, options: HTTPSnippetOptions) {\n const request: Request = {\n ...harRequest,\n fullUrl: '',\n uriObj: {} as UrlWithParsedQuery,\n queryObj: {},\n headersObj: {},\n cookiesObj: {},\n allHeaders: {},\n };\n\n // construct query objects\n if (request.queryString && request.queryString.length) {\n request.queryObj = request.queryString.reduce(reducer, {});\n }\n\n // construct headers objects\n if (request.headers && request.headers.length) {\n const http2VersionRegex = /^HTTP\\/2/;\n request.headersObj = request.headers.reduce((accumulator, { name, value }) => {\n const headerName = http2VersionRegex.exec(request.httpVersion) ? name.toLocaleLowerCase() : name;\n return {\n ...accumulator,\n [headerName]: value,\n };\n }, {});\n }\n\n // construct headers objects\n if (request.cookies && request.cookies.length) {\n request.cookiesObj = request.cookies.reduceRight(\n (accumulator, { name, value }) => ({\n ...accumulator,\n [name]: value,\n }),\n {},\n );\n }\n\n // construct Cookie header\n const cookies = request.cookies?.map(({ name, value }) => {\n if (options.harIsAlreadyEncoded) {\n return `${name}=${value}`;\n }\n\n return `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;\n });\n\n if (cookies?.length) {\n request.allHeaders.cookie = cookies.join('; ');\n }\n\n switch (request.postData.mimeType) {\n case 'multipart/mixed':\n case 'multipart/related':\n case 'multipart/form-data':\n case 'multipart/alternative':\n // reset values\n request.postData.text = '';\n request.postData.mimeType = 'multipart/form-data';\n\n if (request.postData?.params) {\n const form = new FormData();\n\n request.postData?.params.forEach(param => {\n const name = param.name;\n const value = param.value || '';\n const filename = param.fileName || null;\n const contentType = param.contentType || '';\n\n if (filename) {\n form.append(name, new Blob([value], { type: contentType }), filename);\n } else {\n form.append(name, value);\n }\n });\n\n const boundary = '---011000010111000001101001'; // this is binary for \"api\" (easter egg)\n request.postData.boundary = boundary;\n request.postData.text = await formDataToString(form, { boundary });\n\n // Since headers are case-sensitive we need to see if there's an existing `Content-Type` header that we can override.\n const contentTypeHeader = getHeaderName(request.headersObj, 'content-type') || 'content-type';\n\n request.headersObj[contentTypeHeader] = `multipart/form-data; boundary=${boundary}`;\n }\n break;\n\n case 'application/x-www-form-urlencoded':\n if (!request.postData.params) {\n request.postData.text = '';\n } else {\n // @ts-expect-error the `har-format` types make this challenging\n request.postData.paramsObj = request.postData.params.reduce(reducer, {});\n\n // always overwrite\n request.postData.text = queryStringify(request.postData.paramsObj);\n }\n break;\n\n case 'text/json':\n case 'text/x-json':\n case 'application/json':\n case 'application/x-json':\n request.postData.mimeType = 'application/json';\n\n if (request.postData.text) {\n try {\n request.postData.jsonObj = JSON.parse(request.postData.text);\n } catch (e) {\n // force back to `text/plain` if headers have proper content-type value, then this should also work\n request.postData.mimeType = 'text/plain';\n }\n }\n break;\n }\n\n // create allHeaders object\n const allHeaders = {\n ...request.allHeaders,\n ...request.headersObj,\n };\n\n const urlWithParsedQuery = urlParse(request.url, true, true); //?\n\n // query string key/value pairs in with literal querystrings containd within the url\n request.queryObj = {\n ...request.queryObj,\n ...(urlWithParsedQuery.query as ReducedHelperObject),\n }; //?\n\n // reset uriObj values for a clean url\n let search;\n if (options.harIsAlreadyEncoded) {\n search = queryStringify(request.queryObj, {\n encode: false,\n indices: false,\n });\n } else {\n search = queryStringify(request.queryObj, {\n indices: false,\n });\n }\n\n const uriObj = {\n ...urlWithParsedQuery,\n query: request.queryObj,\n search,\n path: search ? `${urlWithParsedQuery.pathname}?${search}` : urlWithParsedQuery.pathname,\n };\n\n // keep the base url clean of queryString\n const url = urlFormat({\n ...urlWithParsedQuery,\n query: null,\n search: null,\n }); //?\n\n const fullUrl = urlFormat({\n ...urlWithParsedQuery,\n ...uriObj,\n }); //?\n\n return {\n ...request,\n allHeaders,\n fullUrl,\n url,\n uriObj,\n };\n }\n\n async convert(targetId: TargetId, clientId?: ClientId, options?: any) {\n if (!this.initCalled) {\n await this.init();\n }\n\n if (!options && clientId) {\n options = clientId;\n }\n\n const target = targets[targetId];\n if (!target) {\n return false;\n }\n\n const { convert } = target.clientsById[clientId || target.info.default];\n const results = this.requests.map(request => convert(request, options));\n return results.length === 1 ? results[0] : results;\n }\n}\n","import type { ClientId, ClientInfo, TargetId, TargetInfo } from '../targets/index.js';\n\nimport { targets } from '../targets/index.js';\n\nexport interface AvailableTarget extends TargetInfo {\n clients: ClientInfo[];\n}\n\nexport const availableTargets = () =>\n Object.keys(targets).map<AvailableTarget>(targetId => ({\n ...targets[targetId as TargetId].info,\n clients: Object.keys(targets[targetId as TargetId].clientsById).map(\n clientId => targets[targetId as TargetId].clientsById[clientId].info,\n ),\n }));\n\nexport const extname = (targetId: TargetId, clientId: ClientId) => {\n const target = targets[targetId];\n if (!target) {\n return '';\n }\n\n return target.clientsById[clientId]?.info.extname || '';\n};\n"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/helpers/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReducedHelperObject } from './helpers/reducer.js';\nimport type { ClientId, TargetId } from './targets/index.js';\nimport type { Param, PostDataCommon, Request as NpmHarRequest } from 'har-format';\nimport type { UrlWithParsedQuery } from 'node:url';\n\nimport { format as urlFormat, parse as urlParse } from 'node:url';\n\nimport { stringify as queryStringify } from 'qs';\n\nimport { getHeaderName } from './helpers/headers.js';\nimport { reducer } from './helpers/reducer.js';\nimport { targets } from './targets/index.js';\n\nexport { availableTargets, extname } from './helpers/utils.js';\nexport { addTarget, addTargetClient, addClientPlugin } from './targets/index.js';\n\n/** is this wrong? yes. according to the spec (http://www.softwareishard.com/blog/har-12-spec/#postData) it's technically wrong since `params` and `text` are (by the spec) mutually exclusive. However, in practice, this is not what is often the case.\n *\n * In general, this library takes a _descriptive_ rather than _perscriptive_ approach (see https://amyrey.web.unc.edu/classes/ling-101-online/tutorials/understanding-prescriptive-vs-descriptive-grammar/).\n *\n * Then, in addition to that, it really adds to complexity with TypeScript (TypeScript takes this constraint very very seriously) in a way that's not actually super useful. So, we treat this object as though it could have both or either of `params` and/or `text`.\n */\ntype PostDataBase = PostDataCommon & {\n params?: Param[];\n text?: string;\n};\n\nexport type HarRequest = Omit<NpmHarRequest, 'postData'> & { postData: PostDataBase };\n\nexport interface RequestExtras {\n allHeaders: ReducedHelperObject;\n cookiesObj: ReducedHelperObject;\n fullUrl: string;\n headersObj: ReducedHelperObject;\n postData: PostDataBase & {\n boundary?: string;\n jsonObj?: ReducedHelperObject;\n paramsObj?: ReducedHelperObject;\n };\n queryObj: ReducedHelperObject;\n uriObj: UrlWithParsedQuery;\n}\n\nexport type Request = HarRequest & RequestExtras;\n\ninterface Entry {\n request: Partial<HarRequest>;\n}\n\ninterface HarEntry {\n log: {\n creator: {\n name: string;\n version: string;\n };\n entries: Entry[];\n version: string;\n };\n}\n\nexport interface HTTPSnippetOptions {\n harIsAlreadyEncoded?: boolean;\n}\n\nconst isHarEntry = (value: any): value is HarEntry =>\n typeof value === 'object' &&\n 'log' in value &&\n typeof value.log === 'object' &&\n 'entries' in value.log &&\n Array.isArray(value.log.entries);\n\nexport class HTTPSnippet {\n initCalled = false;\n\n entries: Entry[] = [];\n\n requests: Request[] = [];\n\n options: HTTPSnippetOptions = {};\n\n constructor(input: HarEntry | HarRequest, opts: HTTPSnippetOptions = {}) {\n this.options = {\n harIsAlreadyEncoded: false,\n ...opts,\n };\n\n // prep the main container\n this.requests = [];\n\n // is it har?\n if (isHarEntry(input)) {\n this.entries = input.log.entries;\n } else {\n this.entries = [\n {\n request: input,\n },\n ];\n }\n }\n\n init() {\n this.initCalled = true;\n\n this.requests = this.entries.map(({ request }) => {\n // add optional properties to make validation successful\n const req = {\n bodySize: 0,\n headersSize: 0,\n headers: [],\n cookies: [],\n httpVersion: 'HTTP/1.1',\n queryString: [],\n postData: {\n mimeType: request.postData?.mimeType || 'application/octet-stream',\n },\n ...request,\n };\n\n // Per the HAR spec `mimeType` needs to always be present if we have a `postData` object.\n if (req.postData && !req.postData.mimeType) {\n req.postData.mimeType = 'application/octet-stream';\n }\n\n return this.prepare(req as HarRequest, this.options);\n });\n\n return this;\n }\n\n prepare(harRequest: HarRequest, options: HTTPSnippetOptions) {\n const request: Request = {\n ...harRequest,\n fullUrl: '',\n uriObj: {} as UrlWithParsedQuery,\n queryObj: {},\n headersObj: {},\n cookiesObj: {},\n allHeaders: {},\n };\n\n // construct query objects\n if (request.queryString && request.queryString.length) {\n request.queryObj = request.queryString.reduce(reducer, {});\n }\n\n // construct headers objects\n if (request.headers && request.headers.length) {\n const http2VersionRegex = /^HTTP\\/2/;\n request.headersObj = request.headers.reduce((accumulator, { name, value }) => {\n const headerName = http2VersionRegex.exec(request.httpVersion) ? name.toLocaleLowerCase() : name;\n return {\n ...accumulator,\n [headerName]: value,\n };\n }, {});\n }\n\n // construct headers objects\n if (request.cookies && request.cookies.length) {\n request.cookiesObj = request.cookies.reduceRight(\n (accumulator, { name, value }) => ({\n ...accumulator,\n [name]: value,\n }),\n {},\n );\n }\n\n // construct Cookie header\n const cookies = request.cookies?.map(({ name, value }) => {\n if (options.harIsAlreadyEncoded) {\n return `${name}=${value}`;\n }\n\n return `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;\n });\n\n if (cookies?.length) {\n request.allHeaders.cookie = cookies.join('; ');\n }\n\n switch (request.postData.mimeType) {\n case 'multipart/mixed':\n case 'multipart/related':\n case 'multipart/form-data':\n case 'multipart/alternative':\n // reset values\n request.postData.text = '';\n request.postData.mimeType = 'multipart/form-data';\n\n if (request.postData?.params) {\n const boundary = '---011000010111000001101001'; // this is binary for \"api\" (easter egg)\n const carriage = `${boundary}--`;\n const rn = '\\r\\n';\n\n /*! formdata-polyfill. MIT License. Jimmy Wärting <https://jimmy.warting.se/opensource> */\n const escape = (str: string) => str.replace(/\\n/g, '%0A').replace(/\\r/g, '%0D').replace(/\"/g, '%22');\n const normalizeLinefeeds = (value: string) => value.replace(/\\r?\\n|\\r/g, '\\r\\n');\n\n const payload = [`--${boundary}`];\n request.postData?.params.forEach((param, i) => {\n const name = param.name;\n const value = param.value || '';\n const filename = param.fileName || null;\n const contentType = param.contentType || 'application/octet-stream';\n\n if (filename) {\n payload.push(\n `Content-Disposition: form-data; name=\"${escape(normalizeLinefeeds(name))}\"; filename=\"${filename}\"`,\n );\n payload.push(`Content-Type: ${contentType}`);\n } else {\n payload.push(`Content-Disposition: form-data; name=\"${escape(normalizeLinefeeds(name))}\"`);\n }\n\n payload.push('');\n payload.push(normalizeLinefeeds(value));\n\n if (i !== (request.postData.params as Param[]).length - 1) {\n payload.push(`--${boundary}`);\n }\n });\n\n payload.push(`--${carriage}`);\n\n request.postData.boundary = boundary;\n request.postData.text = payload.join(rn);\n\n // Since headers are case-sensitive we need to see if there's an existing `Content-Type` header that we can override.\n const contentTypeHeader = getHeaderName(request.headersObj, 'content-type') || 'content-type';\n\n request.headersObj[contentTypeHeader] = `multipart/form-data; boundary=${boundary}`;\n }\n break;\n\n case 'application/x-www-form-urlencoded':\n if (!request.postData.params) {\n request.postData.text = '';\n } else {\n // @ts-expect-error the `har-format` types make this challenging\n request.postData.paramsObj = request.postData.params.reduce(reducer, {});\n\n // always overwrite\n request.postData.text = queryStringify(request.postData.paramsObj);\n }\n break;\n\n case 'text/json':\n case 'text/x-json':\n case 'application/json':\n case 'application/x-json':\n request.postData.mimeType = 'application/json';\n\n if (request.postData.text) {\n try {\n request.postData.jsonObj = JSON.parse(request.postData.text);\n } catch (e) {\n // force back to `text/plain` if headers have proper content-type value, then this should also work\n request.postData.mimeType = 'text/plain';\n }\n }\n break;\n }\n\n // create allHeaders object\n const allHeaders = {\n ...request.allHeaders,\n ...request.headersObj,\n };\n\n const urlWithParsedQuery = urlParse(request.url, true, true); //?\n\n // query string key/value pairs in with literal querystrings containd within the url\n request.queryObj = {\n ...request.queryObj,\n ...(urlWithParsedQuery.query as ReducedHelperObject),\n }; //?\n\n // reset uriObj values for a clean url\n let search;\n if (options.harIsAlreadyEncoded) {\n search = queryStringify(request.queryObj, {\n encode: false,\n indices: false,\n });\n } else {\n search = queryStringify(request.queryObj, {\n indices: false,\n });\n }\n\n const uriObj = {\n ...urlWithParsedQuery,\n query: request.queryObj,\n search,\n path: search ? `${urlWithParsedQuery.pathname}?${search}` : urlWithParsedQuery.pathname,\n };\n\n // keep the base url clean of queryString\n const url = urlFormat({\n ...urlWithParsedQuery,\n query: null,\n search: null,\n }); //?\n\n const fullUrl = urlFormat({\n ...urlWithParsedQuery,\n ...uriObj,\n }); //?\n\n return {\n ...request,\n allHeaders,\n fullUrl,\n url,\n uriObj,\n };\n }\n\n convert(targetId: TargetId, clientId?: ClientId, options?: any) {\n if (!this.initCalled) {\n this.init();\n }\n\n if (!options && clientId) {\n options = clientId;\n }\n\n const target = targets[targetId];\n if (!target) {\n return false;\n }\n\n const { convert } = target.clientsById[clientId || target.info.default];\n const results = this.requests.map(request => convert(request, options));\n return results.length === 1 ? results[0] : results;\n }\n}\n","import type { ClientId, ClientInfo, TargetId, TargetInfo } from '../targets/index.js';\n\nimport { targets } from '../targets/index.js';\n\nexport interface AvailableTarget extends TargetInfo {\n clients: ClientInfo[];\n}\n\nexport const availableTargets = () =>\n Object.keys(targets).map<AvailableTarget>(targetId => ({\n ...targets[targetId as TargetId].info,\n clients: Object.keys(targets[targetId as TargetId].clientsById).map(\n clientId => targets[targetId as TargetId].clientsById[clientId].info,\n ),\n }));\n\nexport const extname = (targetId: TargetId, clientId: ClientId) => {\n const target = targets[targetId];\n if (!target) {\n return '';\n }\n\n return target.clientsById[clientId]?.info.extname || '';\n};\n"]}
@@ -3013,11 +3013,11 @@ ${indent}` : " "
3013
3013
  postData.params?.forEach((param) => {
3014
3014
  let post = "";
3015
3015
  if (param.fileName) {
3016
- post = `${param.name}=@${param.fileName}`;
3016
+ post = `${param.name}='@${param.fileName}'`;
3017
3017
  } else {
3018
- post = `${param.name}=${param.value}`;
3018
+ post = quote(`${param.name}=${param.value}`);
3019
3019
  }
3020
- push(`${arg("form")} ${quote(post)}`);
3020
+ push(`${arg("form")} ${post}`);
3021
3021
  });
3022
3022
  break;
3023
3023
  case "application/x-www-form-urlencoded":
@@ -3027,7 +3027,7 @@ ${indent}` : " "
3027
3027
  const encoded = encodeURIComponent(param.name);
3028
3028
  const needsEncoding = encoded !== unencoded;
3029
3029
  const name = needsEncoding ? encoded : unencoded;
3030
- const flag = binary ? "--data-binary" : `--data${needsEncoding ? "-urlencode" : ""}`;
3030
+ const flag = binary ? "--data-binary" : needsEncoding ? "--data-urlencode" : arg("data");
3031
3031
  push(`${flag} ${quote(`${name}=${param.value}`)}`);
3032
3032
  });
3033
3033
  } else {