@api-client/core 0.6.2 → 0.6.3
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/build/browser.d.ts +0 -1
- package/build/browser.js +0 -1
- package/build/browser.js.map +1 -1
- package/build/index.d.ts +0 -1
- package/build/index.js +0 -1
- package/build/index.js.map +1 -1
- package/build/src/lib/transformers/PayloadSerializer.d.ts +79 -16
- package/build/src/lib/transformers/PayloadSerializer.js +167 -61
- package/build/src/lib/transformers/PayloadSerializer.js.map +1 -1
- package/build/src/runtime/http-engine/CoreEngine.js +3 -6
- package/build/src/runtime/http-engine/CoreEngine.js.map +1 -1
- package/build/src/runtime/http-engine/FormData.d.ts +36 -2
- package/build/src/runtime/http-engine/FormData.js +156 -55
- package/build/src/runtime/http-engine/FormData.js.map +1 -1
- package/build/src/runtime/http-engine/PayloadSupport.d.ts +4 -5
- package/build/src/runtime/http-engine/PayloadSupport.js +19 -12
- package/build/src/runtime/http-engine/PayloadSupport.js.map +1 -1
- package/package.json +1 -3
- package/src/lib/transformers/PayloadSerializer.ts +206 -70
- package/src/runtime/http-engine/CoreEngine.ts +3 -6
- package/src/runtime/http-engine/FormData.ts +184 -63
- package/src/runtime/http-engine/PayloadSupport.ts +23 -15
- package/build/src/lib/transformers/Utils.d.ts +0 -7
- package/build/src/lib/transformers/Utils.js +0 -19
- package/build/src/lib/transformers/Utils.js.map +0 -1
- package/src/lib/transformers/Utils.ts +0 -18
|
@@ -1,85 +1,206 @@
|
|
|
1
|
-
|
|
2
|
-
import _FormData from 'form-data';
|
|
3
|
-
import { IMultipartBody, PayloadSerializer } from '../../lib/transformers/PayloadSerializer.js';
|
|
1
|
+
import { IMultipartBody, PayloadSerializer, IBlobMeta, IFileMeta } from '../../lib/transformers/PayloadSerializer.js';
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
export interface FormDataResult {
|
|
4
|
+
/**
|
|
5
|
+
* The contents of the form data
|
|
6
|
+
*/
|
|
7
|
+
buffer: Buffer;
|
|
8
|
+
/**
|
|
9
|
+
* Content type for the form data.
|
|
10
|
+
*/
|
|
11
|
+
type: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface IPart {
|
|
15
|
+
name: string;
|
|
16
|
+
type: 'file' | 'string';
|
|
17
|
+
meta?: IBlobMeta | IFileMeta;
|
|
18
|
+
contents: Buffer;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const DefaultContentType = 'application/octet-stream';
|
|
22
|
+
const LineBreak = '\r\n';
|
|
6
23
|
|
|
7
24
|
/**
|
|
8
|
-
*
|
|
25
|
+
* In API Client (old old version of ARC) multipart data is encoded
|
|
26
|
+
* as serializable array of buffer views. This class transforms these data
|
|
27
|
+
* into a valid form data contents as a Buffer and generates content type header with the proper boundary.
|
|
9
28
|
*/
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
if (enabled === false) {
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
29
|
+
export class FormDataNode {
|
|
30
|
+
protected _boundary?: string;
|
|
15
31
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
if (
|
|
20
|
-
|
|
21
|
-
filename: fileName,
|
|
22
|
-
knownLength: blob.length,
|
|
23
|
-
contentType: type,
|
|
24
|
-
});
|
|
32
|
+
protected _parts: IPart[] = [];
|
|
33
|
+
|
|
34
|
+
get boundary(): string {
|
|
35
|
+
if (!this._boundary) {
|
|
36
|
+
this._boundary = this._generateBoundary();
|
|
25
37
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
38
|
+
return this._boundary;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
protected _generateBoundary(): string {
|
|
42
|
+
let boundary = '--------------------------';
|
|
43
|
+
for (let i = 0; i < 24; i++) {
|
|
44
|
+
boundary += Math.floor(Math.random() * 10).toString(16);
|
|
30
45
|
}
|
|
31
|
-
|
|
32
|
-
target.append(name, value);
|
|
46
|
+
return boundary;
|
|
33
47
|
}
|
|
34
|
-
}
|
|
35
48
|
|
|
36
|
-
export interface FormDataResult {
|
|
37
49
|
/**
|
|
38
|
-
*
|
|
50
|
+
*
|
|
51
|
+
* @param parts The serialized FormData body
|
|
52
|
+
* @returns
|
|
39
53
|
*/
|
|
40
|
-
|
|
54
|
+
getBody(parts: IMultipartBody[]): FormDataResult {
|
|
55
|
+
parts.forEach(part => this._append(part));
|
|
56
|
+
const buffer = this._generate();
|
|
57
|
+
return {
|
|
58
|
+
buffer,
|
|
59
|
+
type: this.getContentType(),
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
41
63
|
/**
|
|
42
|
-
*
|
|
64
|
+
* @returns The value of the content type header with the generate boundary.
|
|
43
65
|
*/
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
66
|
+
getContentType(): string {
|
|
67
|
+
return `multipart/form-data; boundary=${this.boundary}`;
|
|
68
|
+
}
|
|
47
69
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
target.on('error', (err) => reject(err));
|
|
63
|
-
target.on('end', () => {
|
|
64
|
-
const ct = target.getHeaders()['content-type'];
|
|
65
|
-
resolve({
|
|
66
|
-
buffer: result,
|
|
67
|
-
type: ct,
|
|
70
|
+
protected _append(part: IMultipartBody): void {
|
|
71
|
+
if (part.enabled === false) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (typeof part.isFile === 'boolean') {
|
|
75
|
+
this._appendLegacy(part);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const { name, value } = part;
|
|
79
|
+
if (typeof value === 'string') {
|
|
80
|
+
this._parts.push({
|
|
81
|
+
name,
|
|
82
|
+
type: 'string',
|
|
83
|
+
contents: Buffer.from(value),
|
|
68
84
|
});
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
let buffer: Buffer
|
|
88
|
+
if (value.type === 'file') {
|
|
89
|
+
buffer = PayloadSerializer.deserializeFileBuffer(value);
|
|
90
|
+
} else {
|
|
91
|
+
buffer = PayloadSerializer.deserializeBlobBuffer(value);
|
|
92
|
+
}
|
|
93
|
+
this._parts.push({
|
|
94
|
+
name,
|
|
95
|
+
type: 'file',
|
|
96
|
+
contents: buffer,
|
|
97
|
+
meta: value.meta,
|
|
69
98
|
});
|
|
70
|
-
|
|
71
|
-
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
protected _appendLegacy(part: IMultipartBody): void {
|
|
102
|
+
if (part.isFile) {
|
|
103
|
+
const buffer = PayloadSerializer.deserializeBlobBufferLegacy(part.value as string);
|
|
104
|
+
this._parts.push({
|
|
105
|
+
name: part.name,
|
|
106
|
+
type: 'file',
|
|
107
|
+
contents: buffer,
|
|
108
|
+
meta: {
|
|
109
|
+
mime: this._readDataUrlMime(part.value as string) || DefaultContentType,
|
|
110
|
+
name: part.fileName,
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
} else if (part.type) {
|
|
114
|
+
const buffer = PayloadSerializer.deserializeBlobBufferLegacy(part.value as string);
|
|
115
|
+
this._parts.push({
|
|
116
|
+
name: part.name,
|
|
117
|
+
type: 'file',
|
|
118
|
+
contents: buffer,
|
|
119
|
+
meta: {
|
|
120
|
+
mime: part.type || DefaultContentType,
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
} else {
|
|
124
|
+
const buffer = Buffer.from(part.value as string);
|
|
125
|
+
this._parts.push({
|
|
126
|
+
name: part.name,
|
|
127
|
+
type: 'string',
|
|
128
|
+
contents: buffer,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
protected _readDataUrlMime(dataUrl: string): string | undefined {
|
|
134
|
+
const arr = dataUrl.split(',');
|
|
135
|
+
const matchedMime = arr[0].match(/:(.*?);/);
|
|
136
|
+
if (!matchedMime) {
|
|
137
|
+
return undefined;
|
|
138
|
+
}
|
|
139
|
+
return matchedMime[1];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
protected _generate(): Buffer {
|
|
143
|
+
const result: Buffer[] = [];
|
|
144
|
+
for (const part of this._parts) {
|
|
145
|
+
result.push(this._getHeader(part));
|
|
146
|
+
result.push(part.contents);
|
|
147
|
+
result.push(Buffer.from(LineBreak));
|
|
148
|
+
}
|
|
149
|
+
result.push(this._getFooter());
|
|
150
|
+
return Buffer.concat(result);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
protected _getHeader(part: IPart): Buffer {
|
|
154
|
+
const disposition: string[] = [
|
|
155
|
+
'Content-Disposition: form-data',
|
|
156
|
+
`name="${part.name}"`,
|
|
157
|
+
];
|
|
158
|
+
let mime: string | undefined;
|
|
159
|
+
if (part.type === 'file') {
|
|
160
|
+
const meta = part.meta as IFileMeta;
|
|
161
|
+
if (meta) {
|
|
162
|
+
// "blob" is added by browsers by default.
|
|
163
|
+
disposition.push(`filename="${meta.name || 'blob'}"`);
|
|
164
|
+
mime = meta.mime || DefaultContentType;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const headers: string[] = [
|
|
169
|
+
`--${this.boundary}`,
|
|
170
|
+
disposition.join('; '),
|
|
171
|
+
];
|
|
172
|
+
if (mime) {
|
|
173
|
+
headers.push(`Content-Type: ${mime}`);
|
|
174
|
+
}
|
|
175
|
+
headers.push(LineBreak);
|
|
176
|
+
return Buffer.from(headers.join(LineBreak));
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
protected _getFooter(): Buffer {
|
|
180
|
+
return Buffer.from(`--${this.boundary}--`);
|
|
181
|
+
}
|
|
72
182
|
}
|
|
73
183
|
|
|
184
|
+
// --7MA4YWxkTrZu0gW
|
|
185
|
+
// Content-Disposition: form-data; name="a"; filename="kubectrl-apimodeling.sh"
|
|
186
|
+
// Content-Type: application/x-shellscript
|
|
187
|
+
|
|
188
|
+
// {…file content…}
|
|
189
|
+
// --7MA4YWxkTrZu0gW
|
|
190
|
+
// Content-Disposition: form-data; name="t1"
|
|
191
|
+
|
|
192
|
+
// v1
|
|
193
|
+
// --7MA4YWxkTrZu0gW
|
|
194
|
+
// Content-Disposition: form-data; name="t2"; filename="blob"
|
|
195
|
+
// Content-Type: plain/text
|
|
196
|
+
|
|
197
|
+
// {…file content…}
|
|
198
|
+
// --7MA4YWxkTrZu0gW--
|
|
199
|
+
|
|
74
200
|
/**
|
|
75
201
|
* Processes the form data.
|
|
76
202
|
*/
|
|
77
|
-
export default
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
parts.forEach((part) => {
|
|
81
|
-
promises.push(_append(part));
|
|
82
|
-
});
|
|
83
|
-
await Promise.all(promises);
|
|
84
|
-
return _getData();
|
|
203
|
+
export default function (parts: IMultipartBody[]): FormDataResult {
|
|
204
|
+
const factory = new FormDataNode();
|
|
205
|
+
return factory.getBody(parts);
|
|
85
206
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import formDataConverter from './FormData.js';
|
|
2
2
|
import { Headers } from '../../lib/headers/Headers.js';
|
|
3
|
-
import { Payload, PayloadSerializer, IMultipartBody } from '../../lib/transformers/PayloadSerializer.js';
|
|
3
|
+
import { Payload, PayloadSerializer, IMultipartBody, IFileMeta, IBlobMeta } from '../../lib/transformers/PayloadSerializer.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* A class containing static helper methods to deal with Payload
|
|
@@ -8,9 +8,8 @@ import { Payload, PayloadSerializer, IMultipartBody } from '../../lib/transforme
|
|
|
8
8
|
*/
|
|
9
9
|
export class PayloadSupport {
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
12
|
-
* https://
|
|
13
|
-
* platform/text/LineEnding.cpp&rcl=1458041387&l=101
|
|
11
|
+
* Normalizes line endings to CRLF
|
|
12
|
+
* https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/platform/wtf/text/line_ending.cc;l=68
|
|
14
13
|
*
|
|
15
14
|
* @param string A string to be normalized.
|
|
16
15
|
* @return normalized string
|
|
@@ -41,28 +40,37 @@ export class PayloadSupport {
|
|
|
41
40
|
/**
|
|
42
41
|
* Transforms the request payload into a `Buffer`
|
|
43
42
|
*
|
|
44
|
-
* @param payload A payload message
|
|
45
43
|
* @param headers A headers object where to append headers when needed
|
|
44
|
+
* @param payload A payload message
|
|
46
45
|
* @returns A promise resolved to a `Buffer`.
|
|
47
46
|
*/
|
|
48
|
-
static
|
|
47
|
+
static payloadToBuffer(headers: Headers, payload?: Payload): Buffer | undefined {
|
|
49
48
|
if (!payload) {
|
|
50
|
-
return;
|
|
49
|
+
return undefined;
|
|
51
50
|
}
|
|
52
51
|
if (typeof payload === 'string') {
|
|
53
52
|
payload = PayloadSupport.normalizeString(payload);
|
|
54
53
|
return Buffer.from(payload, 'utf8');
|
|
55
54
|
}
|
|
56
|
-
|
|
55
|
+
|
|
57
56
|
if (payload.type === 'string') {
|
|
58
|
-
return PayloadSupport.payloadToBuffer(payload.data as string
|
|
57
|
+
return PayloadSupport.payloadToBuffer(headers, payload.data as string);
|
|
59
58
|
}
|
|
60
59
|
|
|
61
|
-
if (
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
if (payload.type === 'file') {
|
|
61
|
+
const meta = payload.meta as IFileMeta;
|
|
62
|
+
if (!headers.has('content-type') && meta.mime) {
|
|
63
|
+
headers.set('content-type', meta.mime);
|
|
64
64
|
}
|
|
65
|
-
return PayloadSerializer.
|
|
65
|
+
return PayloadSerializer.deserializeFileBuffer(payload);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (payload.type === 'blob') {
|
|
69
|
+
const meta = payload.meta as IBlobMeta;
|
|
70
|
+
if (!headers.has('content-type') && meta.mime) {
|
|
71
|
+
headers.set('content-type', meta.mime);
|
|
72
|
+
}
|
|
73
|
+
return PayloadSerializer.deserializeBlobBuffer(payload);
|
|
66
74
|
}
|
|
67
75
|
|
|
68
76
|
if (payload.type === 'buffer') {
|
|
@@ -74,11 +82,11 @@ export class PayloadSupport {
|
|
|
74
82
|
}
|
|
75
83
|
|
|
76
84
|
if (payload.type === 'formdata') {
|
|
77
|
-
const result =
|
|
85
|
+
const result = formDataConverter(payload.data as IMultipartBody[]);
|
|
78
86
|
headers.set('Content-Type', result.type);
|
|
79
87
|
return result.buffer;
|
|
80
88
|
}
|
|
81
|
-
|
|
89
|
+
|
|
82
90
|
throw new Error('Unsupported payload message');
|
|
83
91
|
}
|
|
84
92
|
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Converts blob data to base64 string.
|
|
3
|
-
*
|
|
4
|
-
* @param blob File or blob object to be translated to string
|
|
5
|
-
* @return Promise resolved to a base64 string data from the file.
|
|
6
|
-
*/
|
|
7
|
-
export function blobToDataUrl(blob) {
|
|
8
|
-
return new Promise((resolve, reject) => {
|
|
9
|
-
const reader = new FileReader();
|
|
10
|
-
reader.onloadend = () => {
|
|
11
|
-
resolve(String(reader.result));
|
|
12
|
-
};
|
|
13
|
-
reader.onerror = () => {
|
|
14
|
-
reject(new Error('Unable to convert blob to string.'));
|
|
15
|
-
};
|
|
16
|
-
reader.readAsDataURL(blob);
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
//# sourceMappingURL=Utils.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Utils.js","sourceRoot":"","sources":["../../../../src/lib/transformers/Utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,IAAU;IACtC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAChC,MAAM,CAAC,SAAS,GAAG,GAAS,EAAE;YAC5B,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QACjC,CAAC,CAAC;QACF,MAAM,CAAC,OAAO,GAAG,GAAS,EAAE;YAC1B,MAAM,CAAC,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC,CAAC;QACzD,CAAC,CAAC;QACF,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Converts blob data to base64 string.
|
|
3
|
-
*
|
|
4
|
-
* @param blob File or blob object to be translated to string
|
|
5
|
-
* @return Promise resolved to a base64 string data from the file.
|
|
6
|
-
*/
|
|
7
|
-
export function blobToDataUrl(blob: Blob): Promise<string> {
|
|
8
|
-
return new Promise((resolve, reject) => {
|
|
9
|
-
const reader = new FileReader();
|
|
10
|
-
reader.onloadend = (): void => {
|
|
11
|
-
resolve(String(reader.result));
|
|
12
|
-
};
|
|
13
|
-
reader.onerror = (): void => {
|
|
14
|
-
reject(new Error('Unable to convert blob to string.'));
|
|
15
|
-
};
|
|
16
|
-
reader.readAsDataURL(blob);
|
|
17
|
-
});
|
|
18
|
-
}
|