@opra/client 0.17.1 → 0.17.2
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/cjs/client-error.js +17 -0
- package/cjs/constants.js +7 -0
- package/cjs/http/batch-request.js +90 -0
- package/cjs/http/http-client.js +232 -0
- package/cjs/http/http-collection-node.js +110 -0
- package/cjs/http/http-request-observable.js +36 -0
- package/cjs/http/http-request.js +88 -0
- package/cjs/http/http-response.js +24 -0
- package/cjs/http/http-service-base.js +9 -0
- package/cjs/http/http-singleton-node.js +63 -0
- package/cjs/http/http-types.js +2 -0
- package/cjs/index.js +12 -0
- package/cjs/package.json +3 -0
- package/esm/client-error.js +13 -0
- package/esm/constants.js +4 -0
- package/esm/http/batch-request.js +90 -0
- package/esm/http/http-client.js +228 -0
- package/esm/http/http-collection-node.js +106 -0
- package/esm/http/http-request-observable.js +32 -0
- package/esm/http/http-request.js +84 -0
- package/esm/http/http-response.js +20 -0
- package/esm/http/http-service-base.js +5 -0
- package/esm/http/http-singleton-node.js +59 -0
- package/esm/http/http-types.js +1 -0
- package/esm/index.js +9 -0
- package/package.json +32 -12
- package/types/client-error.d.ts +1 -1
- package/types/http/http-client.d.ts +1 -1
- package/types/http/http-collection-node.d.ts +5 -5
- package/types/http/http-request-observable.d.ts +1 -1
- package/types/http/http-request.d.ts +1 -1
- package/types/http/http-response.d.ts +3 -1
- package/types/http/http-singleton-node.d.ts +1 -1
- package/types/http/http-types.d.ts +1 -1
- package/types/index.d.ts +0 -6
- package/cjs/content-disposition-d575fee5.js +0 -473
- package/cjs/cookie-signature-3e974173.js +0 -64
- package/cjs/index.min.mjs +0 -9295
- package/cjs/mime-db-49f150d0.js +0 -10719
- package/cjs/mime-types-6e2bdb57.js +0 -201
- package/cjs/safe-buffer-8acd60c7.js +0 -78
- package/esm/content-disposition-65f281a9.js +0 -470
- package/esm/cookie-signature-bf274b6b.js +0 -62
- package/esm/index.min.mjs +0 -9174
- package/esm/mime-db-d0f15d8f.js +0 -10717
- package/esm/mime-types-79c091fd.js +0 -199
- package/esm/safe-buffer-63383356.js +0 -76
- package/types/common/document/api-document.d.ts +0 -102
- package/types/common/document/constants.d.ts +0 -3
- package/types/common/document/data-type/api-field.d.ts +0 -41
- package/types/common/document/data-type/builtin/any.type.d.ts +0 -2
- package/types/common/document/data-type/builtin/base64.type.d.ts +0 -6
- package/types/common/document/data-type/builtin/bigint.type.d.ts +0 -6
- package/types/common/document/data-type/builtin/boolean.type.d.ts +0 -5
- package/types/common/document/data-type/builtin/date.type.d.ts +0 -4
- package/types/common/document/data-type/builtin/guid.type.d.ts +0 -7
- package/types/common/document/data-type/builtin/index.d.ts +0 -10
- package/types/common/document/data-type/builtin/integer.type.d.ts +0 -6
- package/types/common/document/data-type/builtin/number.type.d.ts +0 -6
- package/types/common/document/data-type/builtin/object.type.d.ts +0 -3
- package/types/common/document/data-type/builtin/string.type.d.ts +0 -5
- package/types/common/document/data-type/builtin/time.type.d.ts +0 -7
- package/types/common/document/data-type/builtin/timestamp.type.d.ts +0 -5
- package/types/common/document/data-type/complex-type.d.ts +0 -56
- package/types/common/document/data-type/data-type.d.ts +0 -33
- package/types/common/document/data-type/enum-type.d.ts +0 -32
- package/types/common/document/data-type/mapped-type.d.ts +0 -53
- package/types/common/document/data-type/simple-type.d.ts +0 -33
- package/types/common/document/data-type/union-type.d.ts +0 -42
- package/types/common/document/factory/add-references.d.ts +0 -4
- package/types/common/document/factory/create-document.d.ts +0 -12
- package/types/common/document/factory/factory.d.ts +0 -61
- package/types/common/document/factory/import-resource-class.d.ts +0 -10
- package/types/common/document/factory/import-type-class.d.ts +0 -17
- package/types/common/document/factory/index.d.ts +0 -1
- package/types/common/document/factory/process-resources.d.ts +0 -7
- package/types/common/document/factory/process-types.d.ts +0 -6
- package/types/common/document/index.d.ts +0 -14
- package/types/common/document/resource/collection.d.ts +0 -69
- package/types/common/document/resource/resource.d.ts +0 -29
- package/types/common/document/resource/singleton.d.ts +0 -51
- package/types/common/document/utils/inspect.util.d.ts +0 -4
- package/types/common/document/utils/string-compare.util.d.ts +0 -1
- package/types/common/exception/enums/issue-severity.enum.d.ts +0 -13
- package/types/common/exception/error-issue.d.ts +0 -9
- package/types/common/exception/http-errors/bad-request.error.d.ts +0 -10
- package/types/common/exception/http-errors/failed-dependency.error.d.ts +0 -9
- package/types/common/exception/http-errors/forbidden.error.d.ts +0 -11
- package/types/common/exception/http-errors/internal-server.error.d.ts +0 -9
- package/types/common/exception/http-errors/method-not-allowed.error.d.ts +0 -10
- package/types/common/exception/http-errors/not-acceptable.error.d.ts +0 -10
- package/types/common/exception/http-errors/not-found.error.d.ts +0 -13
- package/types/common/exception/http-errors/unauthorized.error.d.ts +0 -10
- package/types/common/exception/http-errors/unprocessable-entity.error.d.ts +0 -9
- package/types/common/exception/index.d.ts +0 -15
- package/types/common/exception/opra-exception.d.ts +0 -15
- package/types/common/exception/resource-errors/resource-conflict.error.d.ts +0 -5
- package/types/common/exception/resource-errors/resource-not-found.error.d.ts +0 -8
- package/types/common/exception/wrap-exception.d.ts +0 -2
- package/types/common/filter/antlr/OpraFilterLexer.d.ts +0 -77
- package/types/common/filter/antlr/OpraFilterListener.d.ts +0 -430
- package/types/common/filter/antlr/OpraFilterParser.d.ts +0 -437
- package/types/common/filter/antlr/OpraFilterVisitor.d.ts +0 -260
- package/types/common/filter/ast/abstract/ast.d.ts +0 -5
- package/types/common/filter/ast/abstract/expression.d.ts +0 -3
- package/types/common/filter/ast/abstract/literal.d.ts +0 -6
- package/types/common/filter/ast/abstract/term.d.ts +0 -3
- package/types/common/filter/ast/expressions/arithmetic-expression.d.ts +0 -13
- package/types/common/filter/ast/expressions/array-expression.d.ts +0 -7
- package/types/common/filter/ast/expressions/comparison-expression.d.ts +0 -10
- package/types/common/filter/ast/expressions/logical-expression.d.ts +0 -8
- package/types/common/filter/ast/expressions/parentheses-expression.d.ts +0 -6
- package/types/common/filter/ast/index.d.ts +0 -16
- package/types/common/filter/ast/terms/boolean-literal.d.ts +0 -5
- package/types/common/filter/ast/terms/date-literal.d.ts +0 -6
- package/types/common/filter/ast/terms/external-constant.d.ts +0 -5
- package/types/common/filter/ast/terms/null-literal.d.ts +0 -5
- package/types/common/filter/ast/terms/number-literal.d.ts +0 -6
- package/types/common/filter/ast/terms/qualified-identifier.d.ts +0 -8
- package/types/common/filter/ast/terms/string-literal.d.ts +0 -5
- package/types/common/filter/ast/terms/time-literal.d.ts +0 -6
- package/types/common/filter/build.d.ts +0 -31
- package/types/common/filter/errors.d.ts +0 -20
- package/types/common/filter/filter-tree-visitor.d.ts +0 -33
- package/types/common/filter/index.d.ts +0 -5
- package/types/common/filter/opra-error-listener.d.ts +0 -8
- package/types/common/filter/parse.d.ts +0 -2
- package/types/common/filter/utils.d.ts +0 -2
- package/types/common/helpers/function-utils.d.ts +0 -4
- package/types/common/helpers/get-stack-filename.d.ts +0 -1
- package/types/common/helpers/index.d.ts +0 -8
- package/types/common/helpers/is-url.d.ts +0 -1
- package/types/common/helpers/mixin-utils.d.ts +0 -3
- package/types/common/helpers/object-utils.d.ts +0 -2
- package/types/common/helpers/path-to-object-tree.d.ts +0 -4
- package/types/common/helpers/responsive-map.d.ts +0 -34
- package/types/common/helpers/type-guards.d.ts +0 -11
- package/types/common/http/codecs/boolean-codec.d.ts +0 -5
- package/types/common/http/codecs/date-codec.d.ts +0 -16
- package/types/common/http/codecs/filter-codec.d.ts +0 -6
- package/types/common/http/codecs/integer-codec.d.ts +0 -11
- package/types/common/http/codecs/number-codec.d.ts +0 -14
- package/types/common/http/codecs/string-codec.d.ts +0 -16
- package/types/common/http/enums/http-headers-codes.enum.d.ts +0 -388
- package/types/common/http/enums/http-status-codes.enum.d.ts +0 -290
- package/types/common/http/enums/http-status-messages.d.ts +0 -65
- package/types/common/http/http-headers.d.ts +0 -86
- package/types/common/http/http-message.host.d.ts +0 -122
- package/types/common/http/http-params.d.ts +0 -114
- package/types/common/http/http-request-message.d.ts +0 -213
- package/types/common/http/http-response-message.d.ts +0 -318
- package/types/common/http/index.d.ts +0 -14
- package/types/common/http/interfaces/client-http-headers.interface.d.ts +0 -65
- package/types/common/http/interfaces/cookie-options.interface.d.ts +0 -4
- package/types/common/http/interfaces/server-http-headers.interface.d.ts +0 -1
- package/types/common/http/multipart/batch-multipart.d.ts +0 -0
- package/types/common/http/multipart/http-request-content.d.ts +0 -0
- package/types/common/http/multipart/http-response-content.d.ts +0 -0
- package/types/common/http/multipart/index.d.ts +0 -0
- package/types/common/i18n/i18n.d.ts +0 -28
- package/types/common/i18n/index.d.ts +0 -5
- package/types/common/i18n/string-utils.d.ts +0 -2
- package/types/common/i18n/translate.d.ts +0 -4
- package/types/common/index.d.ts +0 -11
- package/types/common/schema/constants.d.ts +0 -2
- package/types/common/schema/data-type/complex-type.interface.d.ts +0 -16
- package/types/common/schema/data-type/data-type.interface.d.ts +0 -14
- package/types/common/schema/data-type/enum-type.interface.d.ts +0 -15
- package/types/common/schema/data-type/field.interface.d.ts +0 -21
- package/types/common/schema/data-type/mapped-type.interface.d.ts +0 -11
- package/types/common/schema/data-type/simple-type.interface.d.ts +0 -18
- package/types/common/schema/data-type/union-type.interface.d.ts +0 -10
- package/types/common/schema/document.interface.d.ts +0 -34
- package/types/common/schema/index.d.ts +0 -51
- package/types/common/schema/resource/collection.interface.d.ts +0 -33
- package/types/common/schema/resource/container.interface.d.ts +0 -9
- package/types/common/schema/resource/endpoint.interface.d.ts +0 -29
- package/types/common/schema/resource/resource.interface.d.ts +0 -12
- package/types/common/schema/resource/singleton.interface.d.ts +0 -22
- package/types/common/schema/type-guards.d.ts +0 -20
- package/types/common/types.d.ts +0 -11
- package/types/common/url/index.d.ts +0 -5
- package/types/common/url/opra-url-path-component.d.ts +0 -15
- package/types/common/url/opra-url-path.d.ts +0 -36
- package/types/common/url/opra-url.d.ts +0 -70
- package/types/common/url/utils/decode-path-component.d.ts +0 -5
- package/types/common/url/utils/encode-path-component.d.ts +0 -1
- package/types/common/utils/path-utils.d.ts +0 -2
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HttpSingletonNode = void 0;
|
|
4
|
+
const constants_js_1 = require("../constants.js");
|
|
5
|
+
const http_request_observable_js_1 = require("./http-request-observable.js");
|
|
6
|
+
class HttpSingletonNode {
|
|
7
|
+
constructor(context) {
|
|
8
|
+
this[constants_js_1.kHttpClientContext] = context;
|
|
9
|
+
}
|
|
10
|
+
create(data, options) {
|
|
11
|
+
const context = this[constants_js_1.kHttpClientContext];
|
|
12
|
+
const requestHost = new http_request_observable_js_1.HttpRequestObservable(context, options);
|
|
13
|
+
const request = requestHost[http_request_observable_js_1.HttpRequestObservable.kRequest];
|
|
14
|
+
request.method = 'POST';
|
|
15
|
+
request.url = context.resourceName;
|
|
16
|
+
request.body = data;
|
|
17
|
+
if (options?.include)
|
|
18
|
+
request.params.set('$include', options.include);
|
|
19
|
+
if (options?.pick)
|
|
20
|
+
request.params.set('$pick', options.pick);
|
|
21
|
+
if (options?.omit)
|
|
22
|
+
request.params.set('$omit', options.omit);
|
|
23
|
+
return requestHost;
|
|
24
|
+
}
|
|
25
|
+
delete(options) {
|
|
26
|
+
const context = this[constants_js_1.kHttpClientContext];
|
|
27
|
+
const requestHost = new http_request_observable_js_1.HttpRequestObservable(context, options);
|
|
28
|
+
const request = requestHost[http_request_observable_js_1.HttpRequestObservable.kRequest];
|
|
29
|
+
request.method = 'DELETE';
|
|
30
|
+
request.path.join({ resource: context.resourceName });
|
|
31
|
+
return requestHost;
|
|
32
|
+
}
|
|
33
|
+
get(options) {
|
|
34
|
+
const context = this[constants_js_1.kHttpClientContext];
|
|
35
|
+
const requestHost = new http_request_observable_js_1.HttpRequestObservable(context, options);
|
|
36
|
+
const request = requestHost[http_request_observable_js_1.HttpRequestObservable.kRequest];
|
|
37
|
+
request.method = 'GET';
|
|
38
|
+
request.path.join({ resource: context.resourceName });
|
|
39
|
+
if (options?.include)
|
|
40
|
+
request.params.set('$include', options.include);
|
|
41
|
+
if (options?.pick)
|
|
42
|
+
request.params.set('$pick', options.pick);
|
|
43
|
+
if (options?.omit)
|
|
44
|
+
request.params.set('$omit', options.omit);
|
|
45
|
+
return requestHost;
|
|
46
|
+
}
|
|
47
|
+
update(data, options) {
|
|
48
|
+
const context = this[constants_js_1.kHttpClientContext];
|
|
49
|
+
const requestHost = new http_request_observable_js_1.HttpRequestObservable(context, options);
|
|
50
|
+
const request = requestHost[http_request_observable_js_1.HttpRequestObservable.kRequest];
|
|
51
|
+
request.method = 'PATCH';
|
|
52
|
+
request.path.join({ resource: context.resourceName });
|
|
53
|
+
request.body = data;
|
|
54
|
+
if (options?.include)
|
|
55
|
+
request.params.set('$include', options.include);
|
|
56
|
+
if (options?.pick)
|
|
57
|
+
request.params.set('$pick', options.pick);
|
|
58
|
+
if (options?.omit)
|
|
59
|
+
request.params.set('$omit', options.omit);
|
|
60
|
+
return requestHost;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.HttpSingletonNode = HttpSingletonNode;
|
package/cjs/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
tslib_1.__exportStar(require("./client-error.js"), exports);
|
|
5
|
+
tslib_1.__exportStar(require("./http/http-client.js"), exports);
|
|
6
|
+
tslib_1.__exportStar(require("./http/http-collection-node.js"), exports);
|
|
7
|
+
tslib_1.__exportStar(require("./http/http-request.js"), exports);
|
|
8
|
+
tslib_1.__exportStar(require("./http/http-request-observable.js"), exports);
|
|
9
|
+
tslib_1.__exportStar(require("./http/http-response.js"), exports);
|
|
10
|
+
tslib_1.__exportStar(require("./http/http-service-base.js"), exports);
|
|
11
|
+
tslib_1.__exportStar(require("./http/http-singleton-node.js"), exports);
|
|
12
|
+
tslib_1.__exportStar(require("./http/http-types.js"), exports);
|
package/cjs/package.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export class ClientError extends Error {
|
|
2
|
+
constructor(init, cause) {
|
|
3
|
+
super(init.message);
|
|
4
|
+
this.cause = cause;
|
|
5
|
+
this.issues = init.issues || [];
|
|
6
|
+
this.status = init.status;
|
|
7
|
+
if (cause) {
|
|
8
|
+
this.cause = cause;
|
|
9
|
+
if (cause.stack)
|
|
10
|
+
this.stack = cause.stack;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
package/esm/constants.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// import { BatchMultipart } from '@opra/common';
|
|
3
|
+
// import { HttpRequestHost } from '../http-request-host.js';
|
|
4
|
+
// import { HttpResponse } from '../http-response.js';
|
|
5
|
+
// import { CommonHttpRequestOptions, HttpRequestHandler, RawHttpRequest } from '../http-types.js';
|
|
6
|
+
//
|
|
7
|
+
// export class BatchRequest extends HttpRequestHost {
|
|
8
|
+
//
|
|
9
|
+
// protected _results = new WeakMap<HttpRequestHost, { error?: Error, response?: HttpResponse }>();
|
|
10
|
+
// protected _listeners = new Set<((error: Error | undefined, response?: HttpResponse) => void)>();
|
|
11
|
+
//
|
|
12
|
+
// constructor(
|
|
13
|
+
// protected _handler: HttpRequestHandler,
|
|
14
|
+
// readonly requests: HttpRequestHost[],
|
|
15
|
+
// public options: CommonHttpRequestOptions = {}
|
|
16
|
+
// ) {
|
|
17
|
+
// super(_handler, options);
|
|
18
|
+
//
|
|
19
|
+
// requests.forEach(request => {
|
|
20
|
+
// // Overwrite the _execute method
|
|
21
|
+
// Object.defineProperty(request, '_execute', {
|
|
22
|
+
// writable: true,
|
|
23
|
+
// enumerable: false,
|
|
24
|
+
// configurable: true,
|
|
25
|
+
// value: () => {
|
|
26
|
+
// return new Promise((resolve, reject) => {
|
|
27
|
+
// const x = this._results.get(request);
|
|
28
|
+
// if (x) {
|
|
29
|
+
// if (x.error)
|
|
30
|
+
// return reject(x.error);
|
|
31
|
+
// return resolve(x.response);
|
|
32
|
+
// }
|
|
33
|
+
// const callback = (error, response) => {
|
|
34
|
+
// this._listeners.delete(callback);
|
|
35
|
+
// if (error)
|
|
36
|
+
// return reject(error);
|
|
37
|
+
// resolve(response);
|
|
38
|
+
// };
|
|
39
|
+
// this._listeners.add(callback);
|
|
40
|
+
// })
|
|
41
|
+
// }
|
|
42
|
+
// })
|
|
43
|
+
// });
|
|
44
|
+
// }
|
|
45
|
+
//
|
|
46
|
+
// prepare(): RawHttpRequest {
|
|
47
|
+
// const batch = this._buildBatchMultipart(this);
|
|
48
|
+
// const headers = {
|
|
49
|
+
// 'content-type': 'multipart/mixed;boundary=' + batch.boundary
|
|
50
|
+
// }
|
|
51
|
+
// return mergeRawHttpRequests({
|
|
52
|
+
// method: 'POST',
|
|
53
|
+
// path: '/$batch',
|
|
54
|
+
// headers,
|
|
55
|
+
// body: batch.stream()
|
|
56
|
+
// },
|
|
57
|
+
// this.options.http
|
|
58
|
+
// );
|
|
59
|
+
// }
|
|
60
|
+
//
|
|
61
|
+
// protected _buildBatchMultipart(batch: BatchRequest): BatchMultipart {
|
|
62
|
+
// const multipart = new BatchMultipart();
|
|
63
|
+
//
|
|
64
|
+
// for (const req of batch.requests) {
|
|
65
|
+
// const prepared = req.prepare();
|
|
66
|
+
//
|
|
67
|
+
// if (req instanceof BatchRequest) {
|
|
68
|
+
// const subMultipart = this._buildBatchMultipart(req);
|
|
69
|
+
// multipart.addBatch(subMultipart);
|
|
70
|
+
// continue;
|
|
71
|
+
// }
|
|
72
|
+
//
|
|
73
|
+
// multipart.addRequestPart({
|
|
74
|
+
// method: prepared.method,
|
|
75
|
+
// url: prepared.path,
|
|
76
|
+
// headers: prepared.headers,
|
|
77
|
+
// data: prepared.body
|
|
78
|
+
// });
|
|
79
|
+
// }
|
|
80
|
+
//
|
|
81
|
+
// return multipart;
|
|
82
|
+
// }
|
|
83
|
+
//
|
|
84
|
+
// protected async _execute(): Promise<HttpResponse> {
|
|
85
|
+
// const req = this.prepare();
|
|
86
|
+
// const resp = await this._handler(req) as HttpResponse;
|
|
87
|
+
// return resp;
|
|
88
|
+
// }
|
|
89
|
+
//
|
|
90
|
+
// }
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { lastValueFrom, Observable } from 'rxjs';
|
|
2
|
+
import { isReadableStreamLike } from 'rxjs/internal/util/isReadableStreamLike';
|
|
3
|
+
import { DocumentFactory, HttpHeaderCodes, HttpHeaders, HttpParams, isBlob, joinPath, } from '@opra/common';
|
|
4
|
+
import { ClientError } from '../client-error.js';
|
|
5
|
+
import { FORMDATA_CONTENT_TYPE_PATTERN, JSON_CONTENT_TYPE_PATTERN, TEXT_CONTENT_TYPE_PATTERN } from '../constants.js';
|
|
6
|
+
import { HttpCollectionNode } from './http-collection-node.js';
|
|
7
|
+
import { HttpRequest } from './http-request.js';
|
|
8
|
+
import { HttpResponse } from './http-response.js';
|
|
9
|
+
import { HttpSingletonNode } from './http-singleton-node.js';
|
|
10
|
+
const kAssets = Symbol('kAssets');
|
|
11
|
+
export class OpraHttpClient {
|
|
12
|
+
constructor(serviceUrl, options) {
|
|
13
|
+
Object.defineProperty(this, kAssets, {
|
|
14
|
+
enumerable: false,
|
|
15
|
+
value: {
|
|
16
|
+
serviceUrl,
|
|
17
|
+
api: options?.api,
|
|
18
|
+
requestInterceptors: options?.requestInterceptors || [],
|
|
19
|
+
responseInterceptors: options?.responseInterceptors || []
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
this.defaults = {
|
|
23
|
+
...options?.defaults,
|
|
24
|
+
headers: options?.defaults?.headers instanceof HttpHeaders
|
|
25
|
+
? options?.defaults?.headers : new HttpHeaders(options?.defaults?.headers),
|
|
26
|
+
params: options?.defaults?.params instanceof HttpParams
|
|
27
|
+
? options?.defaults?.params : new HttpParams(options?.defaults?.params)
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
get serviceUrl() {
|
|
31
|
+
return this[kAssets].serviceUrl;
|
|
32
|
+
}
|
|
33
|
+
async getMetadata() {
|
|
34
|
+
if (this[kAssets].api)
|
|
35
|
+
return this[kAssets].api;
|
|
36
|
+
let promise = this[kAssets].metadataPromise;
|
|
37
|
+
if (promise) {
|
|
38
|
+
return promise;
|
|
39
|
+
}
|
|
40
|
+
this[kAssets].metadataPromise = promise = lastValueFrom(this._sendRequest('body', new HttpRequest({
|
|
41
|
+
method: 'GET',
|
|
42
|
+
url: '$metadata',
|
|
43
|
+
headers: new HttpHeaders({ 'accept': 'application/json' })
|
|
44
|
+
})));
|
|
45
|
+
return await promise
|
|
46
|
+
.then(body => DocumentFactory.createDocument(body))
|
|
47
|
+
.then(api => this[kAssets].api = api)
|
|
48
|
+
.catch((e) => {
|
|
49
|
+
e.message = 'Unable to fetch metadata from ' + this.serviceUrl + '. ' + e.message;
|
|
50
|
+
throw e;
|
|
51
|
+
})
|
|
52
|
+
.finally(() => delete this[kAssets].metadataPromise);
|
|
53
|
+
}
|
|
54
|
+
// batch(requests: HttpRequestHost<any>[]): BatchRequest {
|
|
55
|
+
// this._assertMetadata();
|
|
56
|
+
// return new BatchRequest(request => this._sendRequest('response', request, requests);
|
|
57
|
+
// }
|
|
58
|
+
collection(resourceName) {
|
|
59
|
+
// If name argument is a class, we extract name from the class
|
|
60
|
+
if (typeof resourceName === 'function')
|
|
61
|
+
resourceName = resourceName.name;
|
|
62
|
+
const ctx = {
|
|
63
|
+
client: this,
|
|
64
|
+
resourceName,
|
|
65
|
+
send: (observe, request) => this._sendRequest(observe, request, ctx),
|
|
66
|
+
requestInterceptors: [
|
|
67
|
+
// Validate resource exists and is a collection resource
|
|
68
|
+
async () => {
|
|
69
|
+
const metadata = await this.getMetadata();
|
|
70
|
+
metadata.getCollection(ctx.resourceName);
|
|
71
|
+
}
|
|
72
|
+
],
|
|
73
|
+
responseInterceptors: []
|
|
74
|
+
};
|
|
75
|
+
return new HttpCollectionNode(ctx);
|
|
76
|
+
}
|
|
77
|
+
singleton(resourceName) {
|
|
78
|
+
// If name argument is a class, we extract name from the class
|
|
79
|
+
if (typeof resourceName === 'function')
|
|
80
|
+
resourceName = resourceName.name;
|
|
81
|
+
const ctx = {
|
|
82
|
+
client: this,
|
|
83
|
+
resourceName,
|
|
84
|
+
send: (observe, request) => this._sendRequest(observe, request, ctx),
|
|
85
|
+
requestInterceptors: [
|
|
86
|
+
// Validate resource exists and is a singleton resource
|
|
87
|
+
async () => {
|
|
88
|
+
const metadata = await this.getMetadata();
|
|
89
|
+
metadata.getSingleton(ctx.resourceName);
|
|
90
|
+
}
|
|
91
|
+
],
|
|
92
|
+
responseInterceptors: []
|
|
93
|
+
};
|
|
94
|
+
return new HttpSingletonNode(ctx);
|
|
95
|
+
}
|
|
96
|
+
_sendRequest(observe, request, ctx) {
|
|
97
|
+
return new Observable(subscriber => {
|
|
98
|
+
(async () => {
|
|
99
|
+
request.inset(this.defaults);
|
|
100
|
+
const url = request.url.includes('://') ? request.url : joinPath(this.serviceUrl, request.url);
|
|
101
|
+
let body;
|
|
102
|
+
if (request.body) {
|
|
103
|
+
let contentType;
|
|
104
|
+
if (typeof request.body === 'string' || typeof request.body === 'number' || typeof request.body === 'boolean') {
|
|
105
|
+
contentType = 'text/plain;charset=UTF-8"';
|
|
106
|
+
body = String(request.body);
|
|
107
|
+
request.headers.delete('Content-Size');
|
|
108
|
+
delete request.duplex;
|
|
109
|
+
}
|
|
110
|
+
else if (isReadableStreamLike(request.body)) {
|
|
111
|
+
contentType = 'application/octet-stream';
|
|
112
|
+
body = request.body;
|
|
113
|
+
request.duplex = 'half';
|
|
114
|
+
}
|
|
115
|
+
else if (Buffer.isBuffer(request.body)) {
|
|
116
|
+
contentType = 'application/octet-stream';
|
|
117
|
+
body = request.body;
|
|
118
|
+
request.headers.set('Content-Size', request.body.length);
|
|
119
|
+
delete request.duplex;
|
|
120
|
+
}
|
|
121
|
+
else if (isBlob(request.body)) {
|
|
122
|
+
contentType = request.body.type || 'application/octet-stream';
|
|
123
|
+
body = request.body;
|
|
124
|
+
request.headers.set('Content-Size', request.body.length);
|
|
125
|
+
delete request.duplex;
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
contentType = 'application/json';
|
|
129
|
+
body = JSON.stringify(request.body);
|
|
130
|
+
request.headers.delete('Content-Size');
|
|
131
|
+
delete request.duplex;
|
|
132
|
+
}
|
|
133
|
+
if (!request.headers.has('Content-Type') && contentType)
|
|
134
|
+
request.headers.set('Content-Type', contentType);
|
|
135
|
+
request.body = body;
|
|
136
|
+
}
|
|
137
|
+
if (ctx) {
|
|
138
|
+
const requestInterceptors = [
|
|
139
|
+
...this[kAssets].requestInterceptors,
|
|
140
|
+
...ctx.requestInterceptors
|
|
141
|
+
];
|
|
142
|
+
for (const interceptor of requestInterceptors) {
|
|
143
|
+
await interceptor(ctx, request);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (observe === 'events')
|
|
147
|
+
subscriber.next({ event: 'sent', request });
|
|
148
|
+
const response = await this._fetch(url, { ...request, headers: request.headers.toObject() });
|
|
149
|
+
await this._handleResponse(observe, subscriber, request, response);
|
|
150
|
+
})().catch(error => subscriber.error(error));
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
_fetch(url, init = {}) {
|
|
154
|
+
return fetch(url, init);
|
|
155
|
+
}
|
|
156
|
+
_createResponse(init) {
|
|
157
|
+
return new HttpResponse(init);
|
|
158
|
+
}
|
|
159
|
+
async _handleResponse(observe, subscriber, request, fetchResponse, ctx) {
|
|
160
|
+
const headers = new HttpHeaders(fetchResponse.headers);
|
|
161
|
+
if (observe === 'events') {
|
|
162
|
+
const response = this._createResponse({
|
|
163
|
+
url: fetchResponse.url,
|
|
164
|
+
headers,
|
|
165
|
+
status: fetchResponse.status,
|
|
166
|
+
statusText: fetchResponse.statusText,
|
|
167
|
+
hasBody: !!fetchResponse.body
|
|
168
|
+
});
|
|
169
|
+
subscriber.next({ event: 'headers-received', request, response });
|
|
170
|
+
}
|
|
171
|
+
let body;
|
|
172
|
+
if (fetchResponse.body) {
|
|
173
|
+
if (JSON_CONTENT_TYPE_PATTERN.test(fetchResponse.headers.get('Content-Type') || '')) {
|
|
174
|
+
body = await fetchResponse.json();
|
|
175
|
+
if (typeof body === 'string')
|
|
176
|
+
body = JSON.parse(body);
|
|
177
|
+
}
|
|
178
|
+
else if (TEXT_CONTENT_TYPE_PATTERN.test(fetchResponse.headers.get('Content-Type') || ''))
|
|
179
|
+
body = await fetchResponse.text();
|
|
180
|
+
else if (FORMDATA_CONTENT_TYPE_PATTERN.test(fetchResponse.headers.get('Content-Type') || ''))
|
|
181
|
+
body = await fetchResponse.formData();
|
|
182
|
+
else {
|
|
183
|
+
const buf = await fetchResponse.arrayBuffer();
|
|
184
|
+
if (buf.byteLength)
|
|
185
|
+
body = buf;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (observe === 'body' && fetchResponse.status >= 400 && fetchResponse.status < 600) {
|
|
189
|
+
subscriber.error(new ClientError({
|
|
190
|
+
message: fetchResponse.status + ' ' + fetchResponse.statusText,
|
|
191
|
+
status: fetchResponse.status,
|
|
192
|
+
issues: body?.errors
|
|
193
|
+
}));
|
|
194
|
+
subscriber.complete();
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
const responseInit = {
|
|
198
|
+
url: fetchResponse.url,
|
|
199
|
+
headers,
|
|
200
|
+
status: fetchResponse.status,
|
|
201
|
+
statusText: fetchResponse.statusText,
|
|
202
|
+
body
|
|
203
|
+
};
|
|
204
|
+
if (fetchResponse.headers.has(HttpHeaderCodes.X_Opra_Total_Matches))
|
|
205
|
+
responseInit.totalMatches = parseInt(fetchResponse.headers.get(HttpHeaderCodes.X_Opra_Total_Matches), 10);
|
|
206
|
+
const response = this._createResponse(responseInit);
|
|
207
|
+
if (ctx) {
|
|
208
|
+
const responseInterceptors = [
|
|
209
|
+
...this[kAssets].responseInterceptors,
|
|
210
|
+
...ctx.responseInterceptors
|
|
211
|
+
];
|
|
212
|
+
for (const interceptor of responseInterceptors) {
|
|
213
|
+
await interceptor(ctx, observe, request);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (observe === 'body') {
|
|
217
|
+
subscriber.next(body);
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
if (observe === 'events')
|
|
221
|
+
subscriber.next({ event: 'response', request, response });
|
|
222
|
+
else
|
|
223
|
+
subscriber.next(response);
|
|
224
|
+
}
|
|
225
|
+
subscriber.complete();
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
OpraHttpClient.kAssets = kAssets;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { kHttpClientContext } from '../constants.js';
|
|
2
|
+
import { HttpRequestObservable } from './http-request-observable.js';
|
|
3
|
+
export class HttpCollectionNode {
|
|
4
|
+
constructor(context) {
|
|
5
|
+
this[kHttpClientContext] = context;
|
|
6
|
+
}
|
|
7
|
+
create(data, options) {
|
|
8
|
+
const context = this[kHttpClientContext];
|
|
9
|
+
const requestHost = new HttpRequestObservable(context, options);
|
|
10
|
+
const request = requestHost[HttpRequestObservable.kRequest];
|
|
11
|
+
request.method = 'POST';
|
|
12
|
+
request.url = context.resourceName;
|
|
13
|
+
request.body = data;
|
|
14
|
+
if (options?.include)
|
|
15
|
+
request.params.set('$include', options.include);
|
|
16
|
+
if (options?.pick)
|
|
17
|
+
request.params.set('$pick', options.pick);
|
|
18
|
+
if (options?.omit)
|
|
19
|
+
request.params.set('$omit', options.omit);
|
|
20
|
+
return requestHost;
|
|
21
|
+
}
|
|
22
|
+
delete(id, options) {
|
|
23
|
+
const context = this[kHttpClientContext];
|
|
24
|
+
const requestHost = new HttpRequestObservable(context, options);
|
|
25
|
+
const request = requestHost[HttpRequestObservable.kRequest];
|
|
26
|
+
request.method = 'DELETE';
|
|
27
|
+
request.path.join({ resource: context.resourceName, key: id });
|
|
28
|
+
return requestHost;
|
|
29
|
+
}
|
|
30
|
+
deleteMany(options) {
|
|
31
|
+
const context = this[kHttpClientContext];
|
|
32
|
+
const requestHost = new HttpRequestObservable(context, options);
|
|
33
|
+
const request = requestHost[HttpRequestObservable.kRequest];
|
|
34
|
+
request.method = 'DELETE';
|
|
35
|
+
request.url = context.resourceName;
|
|
36
|
+
if (options?.filter)
|
|
37
|
+
request.params.set('$filter', options.filter);
|
|
38
|
+
return requestHost;
|
|
39
|
+
}
|
|
40
|
+
get(id, options) {
|
|
41
|
+
const context = this[kHttpClientContext];
|
|
42
|
+
const requestHost = new HttpRequestObservable(context, options);
|
|
43
|
+
const request = requestHost[HttpRequestObservable.kRequest];
|
|
44
|
+
request.method = 'GET';
|
|
45
|
+
request.path.join({ resource: context.resourceName, key: id });
|
|
46
|
+
if (options?.include)
|
|
47
|
+
request.params.set('$include', options.include);
|
|
48
|
+
if (options?.pick)
|
|
49
|
+
request.params.set('$pick', options.pick);
|
|
50
|
+
if (options?.omit)
|
|
51
|
+
request.params.set('$omit', options.omit);
|
|
52
|
+
return requestHost;
|
|
53
|
+
}
|
|
54
|
+
findMany(options) {
|
|
55
|
+
const context = this[kHttpClientContext];
|
|
56
|
+
const requestHost = new HttpRequestObservable(context, options);
|
|
57
|
+
const request = requestHost[HttpRequestObservable.kRequest];
|
|
58
|
+
request.method = 'GET';
|
|
59
|
+
request.url = context.resourceName;
|
|
60
|
+
if (options?.include)
|
|
61
|
+
request.params.set('$include', options.include);
|
|
62
|
+
if (options?.pick)
|
|
63
|
+
request.params.set('$pick', options.pick);
|
|
64
|
+
if (options?.omit)
|
|
65
|
+
request.params.set('$omit', options.omit);
|
|
66
|
+
if (options?.sort)
|
|
67
|
+
request.params.set('$sort', options.sort);
|
|
68
|
+
if (options?.filter)
|
|
69
|
+
request.params.set('$filter', options.filter);
|
|
70
|
+
if (options?.limit != null)
|
|
71
|
+
request.params.set('$limit', options.limit);
|
|
72
|
+
if (options?.skip != null)
|
|
73
|
+
request.params.set('$skip', options.skip);
|
|
74
|
+
if (options?.count != null)
|
|
75
|
+
request.params.set('$count', options.count);
|
|
76
|
+
if (options?.distinct != null)
|
|
77
|
+
request.params.set('$distinct', options.distinct);
|
|
78
|
+
return requestHost;
|
|
79
|
+
}
|
|
80
|
+
update(id, data, options) {
|
|
81
|
+
const context = this[kHttpClientContext];
|
|
82
|
+
const requestHost = new HttpRequestObservable(context, options);
|
|
83
|
+
const request = requestHost[HttpRequestObservable.kRequest];
|
|
84
|
+
request.method = 'PATCH';
|
|
85
|
+
request.path.join({ resource: context.resourceName, key: id });
|
|
86
|
+
request.body = data;
|
|
87
|
+
if (options?.include)
|
|
88
|
+
request.params.set('$include', options.include);
|
|
89
|
+
if (options?.pick)
|
|
90
|
+
request.params.set('$pick', options.pick);
|
|
91
|
+
if (options?.omit)
|
|
92
|
+
request.params.set('$omit', options.omit);
|
|
93
|
+
return requestHost;
|
|
94
|
+
}
|
|
95
|
+
updateMany(data, options) {
|
|
96
|
+
const context = this[kHttpClientContext];
|
|
97
|
+
const requestHost = new HttpRequestObservable(context, options);
|
|
98
|
+
const request = requestHost[HttpRequestObservable.kRequest];
|
|
99
|
+
request.method = 'PATCH';
|
|
100
|
+
request.url = context.resourceName;
|
|
101
|
+
request.body = data;
|
|
102
|
+
if (options?.filter)
|
|
103
|
+
request.params.set('$filter', options.filter);
|
|
104
|
+
return requestHost;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { lastValueFrom, Observable } from 'rxjs';
|
|
2
|
+
import { uid } from '@opra/common';
|
|
3
|
+
import { kHttpClientContext } from '../constants.js';
|
|
4
|
+
import { HttpRequest } from './http-request.js';
|
|
5
|
+
const kRequest = Symbol('kRequest');
|
|
6
|
+
export class HttpRequestObservable extends Observable {
|
|
7
|
+
constructor(context, options) {
|
|
8
|
+
super((subscriber) => {
|
|
9
|
+
context.send(options?.observe || 'body', this[kRequest]).subscribe((subscriber));
|
|
10
|
+
});
|
|
11
|
+
this[kHttpClientContext] = context;
|
|
12
|
+
this[kRequest] = new HttpRequest(options?.http);
|
|
13
|
+
this.contentId = uid(6);
|
|
14
|
+
}
|
|
15
|
+
header(name, value) {
|
|
16
|
+
this[kRequest].headers.append(name, value);
|
|
17
|
+
return this;
|
|
18
|
+
}
|
|
19
|
+
param(name, value) {
|
|
20
|
+
this[kRequest].params.append(name, value);
|
|
21
|
+
return this;
|
|
22
|
+
}
|
|
23
|
+
async fetch(observe) {
|
|
24
|
+
return lastValueFrom(this[kHttpClientContext].send(observe || 'body', this[kRequest]));
|
|
25
|
+
}
|
|
26
|
+
with(cb) {
|
|
27
|
+
cb(this);
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
HttpRequestObservable.kContext = kHttpClientContext;
|
|
32
|
+
HttpRequestObservable.kRequest = kRequest;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
2
|
+
import { HttpHeaders, OpraURL } from '@opra/common';
|
|
3
|
+
const directCopyProperties = ['cache', 'credentials', 'destination', 'headers', 'integrity',
|
|
4
|
+
'keepalive', 'mode', 'redirect', 'referrer', 'referrerPolicy'];
|
|
5
|
+
export class HttpRequest {
|
|
6
|
+
constructor(init) {
|
|
7
|
+
this.cache = init?.cache || 'default';
|
|
8
|
+
this.credentials = init?.credentials || 'same-origin';
|
|
9
|
+
this.destination = init?.destination || '';
|
|
10
|
+
this.headers = new HttpHeaders(init?.headers);
|
|
11
|
+
this.integrity = init?.integrity || '';
|
|
12
|
+
this.keepalive = init?.keepalive ?? false;
|
|
13
|
+
this.method = (init?.method || 'GET').toUpperCase();
|
|
14
|
+
this.mode = init?.mode || 'cors';
|
|
15
|
+
this.redirect = init?.redirect || 'follow';
|
|
16
|
+
this.mode = init?.mode || 'cors';
|
|
17
|
+
this.referrer = init?.referrer || '';
|
|
18
|
+
this.referrerPolicy = init?.referrerPolicy || '';
|
|
19
|
+
this.signal = init?.signal || new AbortController().signal;
|
|
20
|
+
this.body = init?.body;
|
|
21
|
+
this.urlInstance = new OpraURL(init?.url);
|
|
22
|
+
if (init?.params)
|
|
23
|
+
this.params.appendAll(init.params);
|
|
24
|
+
}
|
|
25
|
+
/** Returns the URL of request as a string. */
|
|
26
|
+
get url() {
|
|
27
|
+
return this.urlInstance.href;
|
|
28
|
+
}
|
|
29
|
+
set url(value) {
|
|
30
|
+
this.urlInstance.parse(value);
|
|
31
|
+
}
|
|
32
|
+
/** Returns the searchParams of the URL as OpraURLSearchParams */
|
|
33
|
+
get params() {
|
|
34
|
+
return this.urlInstance.searchParams;
|
|
35
|
+
}
|
|
36
|
+
/** Returns the path part of URL as OpraURLPath */
|
|
37
|
+
get path() {
|
|
38
|
+
return this.urlInstance.path;
|
|
39
|
+
}
|
|
40
|
+
clone(...update) {
|
|
41
|
+
const out = new HttpRequest();
|
|
42
|
+
out.merge(this);
|
|
43
|
+
for (const upd of update) {
|
|
44
|
+
out.merge(upd);
|
|
45
|
+
}
|
|
46
|
+
return out;
|
|
47
|
+
}
|
|
48
|
+
merge(update) {
|
|
49
|
+
directCopyProperties.forEach(k => {
|
|
50
|
+
if (update[k] != null)
|
|
51
|
+
this[k] = update[k];
|
|
52
|
+
});
|
|
53
|
+
if (update.headers) {
|
|
54
|
+
const h = update.headers instanceof HttpHeaders
|
|
55
|
+
? update.headers
|
|
56
|
+
: new HttpHeaders(update.headers);
|
|
57
|
+
h.forEach((v, k) => {
|
|
58
|
+
if (k.toLowerCase() === 'set-cookie') {
|
|
59
|
+
this.headers.append(k, v);
|
|
60
|
+
}
|
|
61
|
+
else
|
|
62
|
+
this.headers.set(k, v);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
inset(src) {
|
|
67
|
+
directCopyProperties.forEach(k => {
|
|
68
|
+
if (this[k] == null && src[k] != null)
|
|
69
|
+
this[k] = src[k];
|
|
70
|
+
});
|
|
71
|
+
if (src.headers) {
|
|
72
|
+
const h = src.headers instanceof HttpHeaders
|
|
73
|
+
? src.headers
|
|
74
|
+
: new HttpHeaders(src.headers);
|
|
75
|
+
h.forEach((v, k) => {
|
|
76
|
+
if (k.toLowerCase() === 'set-cookie') {
|
|
77
|
+
this.headers.append(k, v);
|
|
78
|
+
}
|
|
79
|
+
else if (!this.headers.has(k))
|
|
80
|
+
this.headers.set(k, v);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { HttpHeaders } from '@opra/common';
|
|
2
|
+
export class HttpResponse {
|
|
3
|
+
constructor(init) {
|
|
4
|
+
/**
|
|
5
|
+
* Returns true if response has body to be received
|
|
6
|
+
*/
|
|
7
|
+
this.hasBody = false;
|
|
8
|
+
this.headers = new HttpHeaders(init?.headers);
|
|
9
|
+
this.status = init?.status || 200;
|
|
10
|
+
this.statusText = init?.statusText || 'OK';
|
|
11
|
+
this.url = init?.url || null;
|
|
12
|
+
this.ok = this.status >= 200 && this.status < 300;
|
|
13
|
+
this.body = init?.body;
|
|
14
|
+
this.hasBody = init?.body != null || !!init?.hasBody;
|
|
15
|
+
this.totalMatches = init?.totalMatches;
|
|
16
|
+
}
|
|
17
|
+
clone(update) {
|
|
18
|
+
return new HttpResponse({ ...this, ...update });
|
|
19
|
+
}
|
|
20
|
+
}
|