@usearazzo/runner 1.0.1-alpha.11 → 1.0.1-alpha.12
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/CHANGELOG.md +12 -0
- package/README.md +1 -3
- package/dist/arazzo-runner.browser.js +139 -112
- package/dist/arazzo-runner.browser.min.js +1 -1
- package/package.json +4 -4
- package/src/client/OpenAPIOperationResponse.cjs +37 -2
- package/src/client/OpenAPIOperationResponse.mjs +37 -2
- package/src/client/OpenAPIOperationResponseNormalizer.cjs +47 -3
- package/src/client/OpenAPIOperationResponseNormalizer.mjs +48 -3
- package/types/runner.d.ts +30 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usearazzo/runner",
|
|
3
|
-
"version": "1.0.1-alpha.
|
|
3
|
+
"version": "1.0.1-alpha.12",
|
|
4
4
|
"description": "Runner for Arazzo Workflows.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"arazzo",
|
|
@@ -72,8 +72,8 @@
|
|
|
72
72
|
"@swaggerexpert/json-pointer": "^3.0.2",
|
|
73
73
|
"@swaggerexpert/jsonpath": "^4.0.5",
|
|
74
74
|
"@swaggerexpert/media-types": "^1.0.1",
|
|
75
|
-
"@usearazzo/parser": "1.0.1-alpha.
|
|
76
|
-
"@usearazzo/resolver": "1.0.1-alpha.
|
|
75
|
+
"@usearazzo/parser": "1.0.1-alpha.12",
|
|
76
|
+
"@usearazzo/resolver": "1.0.1-alpha.12",
|
|
77
77
|
"@xmldom/xmldom": "^0.9.12",
|
|
78
78
|
"fontoxpath": "^3.34.0",
|
|
79
79
|
"ramda": "^0.32.0",
|
|
@@ -93,5 +93,5 @@
|
|
|
93
93
|
"devDependencies": {
|
|
94
94
|
"swagger-client": "^3.38.4"
|
|
95
95
|
},
|
|
96
|
-
"gitHead": "
|
|
96
|
+
"gitHead": "cc5d9b2fb744662650068a5993ebcdd19e8568c2"
|
|
97
97
|
}
|
|
@@ -17,6 +17,14 @@ exports.default = void 0;
|
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Response from an OpenAPI operation execution.
|
|
20
|
+
*
|
|
21
|
+
* `body` is the payload parsed by its content type, what `$response.body`
|
|
22
|
+
* reads. The body as received is read through `text()`, `blob()` and
|
|
23
|
+
* `bytes()`, named after the WHATWG `Response` methods but synchronous, and
|
|
24
|
+
* empty when the response carried no body (e.g. `204`, `304`). `bytes()` and
|
|
25
|
+
* `blob()` always return the bytes received. A body that is valid UTF-8 is held
|
|
26
|
+
* as its decoded string, which a plain-text or XML `body` shares rather than
|
|
27
|
+
* duplicates, and is encoded back on read; any other body is held as bytes.
|
|
20
28
|
* @public
|
|
21
29
|
*/
|
|
22
30
|
class OpenAPIOperationResponse {
|
|
@@ -25,18 +33,45 @@ class OpenAPIOperationResponse {
|
|
|
25
33
|
status;
|
|
26
34
|
statusText;
|
|
27
35
|
headers;
|
|
28
|
-
text;
|
|
29
36
|
body;
|
|
30
37
|
request;
|
|
38
|
+
#content;
|
|
31
39
|
constructor(raw) {
|
|
32
40
|
this.ok = raw.ok;
|
|
33
41
|
this.url = raw.url;
|
|
34
42
|
this.status = raw.status;
|
|
35
43
|
this.statusText = raw.statusText;
|
|
36
44
|
this.headers = raw.headers;
|
|
37
|
-
this.text = raw.text;
|
|
38
45
|
this.body = raw.body;
|
|
46
|
+
this.#content = raw.content;
|
|
39
47
|
this.request = raw.request;
|
|
40
48
|
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The body as text, like `Response.text()`; `''` when there is none.
|
|
52
|
+
*/
|
|
53
|
+
text() {
|
|
54
|
+
return typeof this.#content === 'string' ? this.#content : new TextDecoder().decode(this.#content);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* The body as a `Blob` typed by the response's `Content-Type`, like
|
|
59
|
+
* `Response.blob()`.
|
|
60
|
+
*/
|
|
61
|
+
blob() {
|
|
62
|
+
// the lib types only take ArrayBuffer-backed views; the normalizer never
|
|
63
|
+
// produces a shared one.
|
|
64
|
+
return new Blob([this.#content], {
|
|
65
|
+
type: this.headers['content-type'] ?? ''
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The body as bytes, like `Response.bytes()`; a fresh copy on every call, so
|
|
71
|
+
* the response stays immutable.
|
|
72
|
+
*/
|
|
73
|
+
bytes() {
|
|
74
|
+
return typeof this.#content === 'string' ? new TextEncoder().encode(this.#content) : this.#content.slice();
|
|
75
|
+
}
|
|
41
76
|
}
|
|
42
77
|
var _default = exports.default = OpenAPIOperationResponse;
|
|
@@ -11,6 +11,14 @@
|
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Response from an OpenAPI operation execution.
|
|
14
|
+
*
|
|
15
|
+
* `body` is the payload parsed by its content type, what `$response.body`
|
|
16
|
+
* reads. The body as received is read through `text()`, `blob()` and
|
|
17
|
+
* `bytes()`, named after the WHATWG `Response` methods but synchronous, and
|
|
18
|
+
* empty when the response carried no body (e.g. `204`, `304`). `bytes()` and
|
|
19
|
+
* `blob()` always return the bytes received. A body that is valid UTF-8 is held
|
|
20
|
+
* as its decoded string, which a plain-text or XML `body` shares rather than
|
|
21
|
+
* duplicates, and is encoded back on read; any other body is held as bytes.
|
|
14
22
|
* @public
|
|
15
23
|
*/
|
|
16
24
|
class OpenAPIOperationResponse {
|
|
@@ -19,18 +27,45 @@ class OpenAPIOperationResponse {
|
|
|
19
27
|
status;
|
|
20
28
|
statusText;
|
|
21
29
|
headers;
|
|
22
|
-
text;
|
|
23
30
|
body;
|
|
24
31
|
request;
|
|
32
|
+
#content;
|
|
25
33
|
constructor(raw) {
|
|
26
34
|
this.ok = raw.ok;
|
|
27
35
|
this.url = raw.url;
|
|
28
36
|
this.status = raw.status;
|
|
29
37
|
this.statusText = raw.statusText;
|
|
30
38
|
this.headers = raw.headers;
|
|
31
|
-
this.text = raw.text;
|
|
32
39
|
this.body = raw.body;
|
|
40
|
+
this.#content = raw.content;
|
|
33
41
|
this.request = raw.request;
|
|
34
42
|
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The body as text, like `Response.text()`; `''` when there is none.
|
|
46
|
+
*/
|
|
47
|
+
text() {
|
|
48
|
+
return typeof this.#content === 'string' ? this.#content : new TextDecoder().decode(this.#content);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The body as a `Blob` typed by the response's `Content-Type`, like
|
|
53
|
+
* `Response.blob()`.
|
|
54
|
+
*/
|
|
55
|
+
blob() {
|
|
56
|
+
// the lib types only take ArrayBuffer-backed views; the normalizer never
|
|
57
|
+
// produces a shared one.
|
|
58
|
+
return new Blob([this.#content], {
|
|
59
|
+
type: this.headers['content-type'] ?? ''
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The body as bytes, like `Response.bytes()`; a fresh copy on every call, so
|
|
65
|
+
* the response stays immutable.
|
|
66
|
+
*/
|
|
67
|
+
bytes() {
|
|
68
|
+
return typeof this.#content === 'string' ? new TextEncoder().encode(this.#content) : this.#content.slice();
|
|
69
|
+
}
|
|
35
70
|
}
|
|
36
71
|
export default OpenAPIOperationResponse;
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
7
|
exports.default = void 0;
|
|
8
|
+
var _mediaTypes = require("@swaggerexpert/media-types");
|
|
8
9
|
var _swaggerClient = require("../vendor/swagger-client.cjs");
|
|
9
10
|
var _OpenAPIOperationResponse = _interopRequireDefault(require("./OpenAPIOperationResponse.cjs"));
|
|
10
11
|
// @ts-expect-error vendored swagger-client bundle has no type declarations
|
|
@@ -20,7 +21,11 @@ var _OpenAPIOperationResponse = _interopRequireDefault(require("./OpenAPIOperati
|
|
|
20
21
|
* Headers are taken from the `Response` directly rather than from the
|
|
21
22
|
* deserializer, which splits every value containing `", "` into an array:
|
|
22
23
|
* values stay strings as sent, with repeated fields (`Set-Cookie` included)
|
|
23
|
-
* combined by `Headers.get`.
|
|
24
|
+
* combined by `Headers.get`. The body is read once, as bytes, and handed to the
|
|
25
|
+
* deserializer from memory. A body that decodes as UTF-8 without loss is kept
|
|
26
|
+
* as that one string, the same one the deserializer parses, so a plain-text or
|
|
27
|
+
* XML `body` shares it; any other body (binary, another charset, a leading
|
|
28
|
+
* byte-order mark) is kept as the bytes, so they are never re-encoded lossily.
|
|
24
29
|
* @public
|
|
25
30
|
*/
|
|
26
31
|
class OpenAPIOperationResponseNormalizer {
|
|
@@ -31,7 +36,30 @@ class OpenAPIOperationResponseNormalizer {
|
|
|
31
36
|
* carries none (e.g. a stubbed transport).
|
|
32
37
|
*/
|
|
33
38
|
async normalize(response, request) {
|
|
34
|
-
const
|
|
39
|
+
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
40
|
+
const text = this.#decodeLosslessly(bytes);
|
|
41
|
+
// the deserializer matches the raw Content-Type case-sensitively and against
|
|
42
|
+
// its parameters too, so it is handed only the parsed essence; the response's
|
|
43
|
+
// own `headers` below stay as sent.
|
|
44
|
+
const deserializerHeaders = new Headers(response.headers);
|
|
45
|
+
const contentType = response.headers.get('content-type');
|
|
46
|
+
const mediaType = contentType === null ? undefined : (0, _mediaTypes.parse)(contentType, {
|
|
47
|
+
type: 'media-type'
|
|
48
|
+
}).tree;
|
|
49
|
+
if (mediaType !== undefined) {
|
|
50
|
+
deserializerHeaders.set('content-type', `${mediaType.type}/${mediaType.subtype}`);
|
|
51
|
+
}
|
|
52
|
+
// the deserializer only reads the body through text() or blob(), by content
|
|
53
|
+
// type; answering from memory spares a second copy of the stream.
|
|
54
|
+
const deserialized = await (0, _swaggerClient.deserializeResponse)({
|
|
55
|
+
ok: response.ok,
|
|
56
|
+
url: response.url,
|
|
57
|
+
status: response.status,
|
|
58
|
+
statusText: response.statusText,
|
|
59
|
+
headers: deserializerHeaders,
|
|
60
|
+
text: async () => text ?? new TextDecoder().decode(bytes),
|
|
61
|
+
blob: async () => new Blob([bytes])
|
|
62
|
+
}, request?.url);
|
|
35
63
|
const headers = Object.fromEntries(Array.from(response.headers.keys(), name => [name, response.headers.get(name)]));
|
|
36
64
|
return new _OpenAPIOperationResponse.default({
|
|
37
65
|
ok: deserialized.ok,
|
|
@@ -39,10 +67,26 @@ class OpenAPIOperationResponseNormalizer {
|
|
|
39
67
|
status: deserialized.status,
|
|
40
68
|
statusText: deserialized.statusText,
|
|
41
69
|
headers,
|
|
42
|
-
text: deserialized.text,
|
|
43
70
|
body: deserialized.body,
|
|
71
|
+
content: text ?? bytes,
|
|
44
72
|
request
|
|
45
73
|
});
|
|
46
74
|
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* The bytes as a string that encodes back to exactly them, or `undefined`
|
|
78
|
+
* when there is none: invalid UTF-8, or a leading byte-order mark, which
|
|
79
|
+
* decoding strips.
|
|
80
|
+
*/
|
|
81
|
+
#decodeLosslessly(bytes) {
|
|
82
|
+
if (bytes[0] === 0xef && bytes[1] === 0xbb && bytes[2] === 0xbf) return undefined;
|
|
83
|
+
try {
|
|
84
|
+
return new TextDecoder('utf-8', {
|
|
85
|
+
fatal: true
|
|
86
|
+
}).decode(bytes);
|
|
87
|
+
} catch {
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
47
91
|
}
|
|
48
92
|
var _default = exports.default = OpenAPIOperationResponseNormalizer;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { parse } from '@swaggerexpert/media-types';
|
|
2
|
+
|
|
1
3
|
// @ts-expect-error vendored swagger-client bundle has no type declarations
|
|
2
4
|
import { deserializeResponse } from '../vendor/swagger-client.mjs';
|
|
3
5
|
import OpenAPIOperationResponse from "./OpenAPIOperationResponse.mjs";
|
|
@@ -12,7 +14,11 @@ import OpenAPIOperationResponse from "./OpenAPIOperationResponse.mjs";
|
|
|
12
14
|
* Headers are taken from the `Response` directly rather than from the
|
|
13
15
|
* deserializer, which splits every value containing `", "` into an array:
|
|
14
16
|
* values stay strings as sent, with repeated fields (`Set-Cookie` included)
|
|
15
|
-
* combined by `Headers.get`.
|
|
17
|
+
* combined by `Headers.get`. The body is read once, as bytes, and handed to the
|
|
18
|
+
* deserializer from memory. A body that decodes as UTF-8 without loss is kept
|
|
19
|
+
* as that one string, the same one the deserializer parses, so a plain-text or
|
|
20
|
+
* XML `body` shares it; any other body (binary, another charset, a leading
|
|
21
|
+
* byte-order mark) is kept as the bytes, so they are never re-encoded lossily.
|
|
16
22
|
* @public
|
|
17
23
|
*/
|
|
18
24
|
class OpenAPIOperationResponseNormalizer {
|
|
@@ -23,7 +29,30 @@ class OpenAPIOperationResponseNormalizer {
|
|
|
23
29
|
* carries none (e.g. a stubbed transport).
|
|
24
30
|
*/
|
|
25
31
|
async normalize(response, request) {
|
|
26
|
-
const
|
|
32
|
+
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
33
|
+
const text = this.#decodeLosslessly(bytes);
|
|
34
|
+
// the deserializer matches the raw Content-Type case-sensitively and against
|
|
35
|
+
// its parameters too, so it is handed only the parsed essence; the response's
|
|
36
|
+
// own `headers` below stay as sent.
|
|
37
|
+
const deserializerHeaders = new Headers(response.headers);
|
|
38
|
+
const contentType = response.headers.get('content-type');
|
|
39
|
+
const mediaType = contentType === null ? undefined : parse(contentType, {
|
|
40
|
+
type: 'media-type'
|
|
41
|
+
}).tree;
|
|
42
|
+
if (mediaType !== undefined) {
|
|
43
|
+
deserializerHeaders.set('content-type', `${mediaType.type}/${mediaType.subtype}`);
|
|
44
|
+
}
|
|
45
|
+
// the deserializer only reads the body through text() or blob(), by content
|
|
46
|
+
// type; answering from memory spares a second copy of the stream.
|
|
47
|
+
const deserialized = await deserializeResponse({
|
|
48
|
+
ok: response.ok,
|
|
49
|
+
url: response.url,
|
|
50
|
+
status: response.status,
|
|
51
|
+
statusText: response.statusText,
|
|
52
|
+
headers: deserializerHeaders,
|
|
53
|
+
text: async () => text ?? new TextDecoder().decode(bytes),
|
|
54
|
+
blob: async () => new Blob([bytes])
|
|
55
|
+
}, request?.url);
|
|
27
56
|
const headers = Object.fromEntries(Array.from(response.headers.keys(), name => [name, response.headers.get(name)]));
|
|
28
57
|
return new OpenAPIOperationResponse({
|
|
29
58
|
ok: deserialized.ok,
|
|
@@ -31,10 +60,26 @@ class OpenAPIOperationResponseNormalizer {
|
|
|
31
60
|
status: deserialized.status,
|
|
32
61
|
statusText: deserialized.statusText,
|
|
33
62
|
headers,
|
|
34
|
-
text: deserialized.text,
|
|
35
63
|
body: deserialized.body,
|
|
64
|
+
content: text ?? bytes,
|
|
36
65
|
request
|
|
37
66
|
});
|
|
38
67
|
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The bytes as a string that encodes back to exactly them, or `undefined`
|
|
71
|
+
* when there is none: invalid UTF-8, or a leading byte-order mark, which
|
|
72
|
+
* decoding strips.
|
|
73
|
+
*/
|
|
74
|
+
#decodeLosslessly(bytes) {
|
|
75
|
+
if (bytes[0] === 0xef && bytes[1] === 0xbb && bytes[2] === 0xbf) return undefined;
|
|
76
|
+
try {
|
|
77
|
+
return new TextDecoder('utf-8', {
|
|
78
|
+
fatal: true
|
|
79
|
+
}).decode(bytes);
|
|
80
|
+
} catch {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
39
84
|
}
|
|
40
85
|
export default OpenAPIOperationResponseNormalizer;
|
package/types/runner.d.ts
CHANGED
|
@@ -1261,15 +1261,23 @@ export declare interface OpenAPIOperationRequestInfo {
|
|
|
1261
1261
|
|
|
1262
1262
|
/**
|
|
1263
1263
|
* Response from an OpenAPI operation execution.
|
|
1264
|
+
*
|
|
1265
|
+
* `body` is the payload parsed by its content type, what `$response.body`
|
|
1266
|
+
* reads. The body as received is read through `text()`, `blob()` and
|
|
1267
|
+
* `bytes()`, named after the WHATWG `Response` methods but synchronous, and
|
|
1268
|
+
* empty when the response carried no body (e.g. `204`, `304`). `bytes()` and
|
|
1269
|
+
* `blob()` always return the bytes received. A body that is valid UTF-8 is held
|
|
1270
|
+
* as its decoded string, which a plain-text or XML `body` shares rather than
|
|
1271
|
+
* duplicates, and is encoded back on read; any other body is held as bytes.
|
|
1264
1272
|
* @public
|
|
1265
1273
|
*/
|
|
1266
1274
|
export declare class OpenAPIOperationResponse {
|
|
1275
|
+
#private;
|
|
1267
1276
|
readonly ok: boolean;
|
|
1268
1277
|
readonly url: string;
|
|
1269
1278
|
readonly status: number;
|
|
1270
1279
|
readonly statusText: string;
|
|
1271
1280
|
readonly headers: Record<string, string>;
|
|
1272
|
-
readonly text: string;
|
|
1273
1281
|
readonly body: unknown;
|
|
1274
1282
|
readonly request: OpenAPIOperationRequestInfo | undefined;
|
|
1275
1283
|
constructor(raw: {
|
|
@@ -1278,10 +1286,24 @@ export declare class OpenAPIOperationResponse {
|
|
|
1278
1286
|
status: number;
|
|
1279
1287
|
statusText: string;
|
|
1280
1288
|
headers: Record<string, string>;
|
|
1281
|
-
text: string;
|
|
1282
1289
|
body: unknown;
|
|
1290
|
+
content: string | Uint8Array;
|
|
1283
1291
|
request?: OpenAPIOperationRequestInfo;
|
|
1284
1292
|
});
|
|
1293
|
+
/**
|
|
1294
|
+
* The body as text, like `Response.text()`; `''` when there is none.
|
|
1295
|
+
*/
|
|
1296
|
+
text(): string;
|
|
1297
|
+
/**
|
|
1298
|
+
* The body as a `Blob` typed by the response's `Content-Type`, like
|
|
1299
|
+
* `Response.blob()`.
|
|
1300
|
+
*/
|
|
1301
|
+
blob(): Blob;
|
|
1302
|
+
/**
|
|
1303
|
+
* The body as bytes, like `Response.bytes()`; a fresh copy on every call, so
|
|
1304
|
+
* the response stays immutable.
|
|
1305
|
+
*/
|
|
1306
|
+
bytes(): Uint8Array;
|
|
1285
1307
|
}
|
|
1286
1308
|
|
|
1287
1309
|
/**
|
|
@@ -1295,10 +1317,15 @@ export declare class OpenAPIOperationResponse {
|
|
|
1295
1317
|
* Headers are taken from the `Response` directly rather than from the
|
|
1296
1318
|
* deserializer, which splits every value containing `", "` into an array:
|
|
1297
1319
|
* values stay strings as sent, with repeated fields (`Set-Cookie` included)
|
|
1298
|
-
* combined by `Headers.get`.
|
|
1320
|
+
* combined by `Headers.get`. The body is read once, as bytes, and handed to the
|
|
1321
|
+
* deserializer from memory. A body that decodes as UTF-8 without loss is kept
|
|
1322
|
+
* as that one string, the same one the deserializer parses, so a plain-text or
|
|
1323
|
+
* XML `body` shares it; any other body (binary, another charset, a leading
|
|
1324
|
+
* byte-order mark) is kept as the bytes, so they are never re-encoded lossily.
|
|
1299
1325
|
* @public
|
|
1300
1326
|
*/
|
|
1301
1327
|
export declare class OpenAPIOperationResponseNormalizer {
|
|
1328
|
+
#private;
|
|
1302
1329
|
/**
|
|
1303
1330
|
* Deserializes the response body by content type and maps the result into the
|
|
1304
1331
|
* runner's response model. `request` is the request the operation was
|