@opra/common 1.0.0-alpha.12 → 1.0.0-alpha.13
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/browser.js +167 -166
- package/cjs/document/api-document.js +10 -0
- package/cjs/document/decorators/http-operation-entity.decorator.js +4 -15
- package/cjs/document/decorators/http-operation.decorator.js +3 -0
- package/cjs/document/factory/api-document.factory.js +4 -6
- package/cjs/document/http/http-controller.js +3 -2
- package/cjs/document/http/http-operation.js +11 -1
- package/cjs/document/http/http-status-range.js +5 -2
- package/esm/document/api-document.js +9 -0
- package/esm/document/decorators/http-operation-entity.decorator.js +4 -15
- package/esm/document/decorators/http-operation.decorator.js +3 -0
- package/esm/document/factory/api-document.factory.js +4 -5
- package/esm/document/http/http-controller.js +2 -2
- package/esm/document/http/http-operation.js +11 -1
- package/esm/document/http/http-status-range.js +5 -2
- package/package.json +1 -1
- package/types/document/api-document.d.ts +1 -0
- package/types/document/http/http-operation.d.ts +3 -2
- package/types/document/http/http-status-range.d.ts +2 -1
- package/types/schema/http/http-operation.interface.d.ts +4 -0
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
var _a;
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.ApiDocument = void 0;
|
|
5
|
+
const tslib_1 = require("tslib");
|
|
6
|
+
const node_crypto_1 = tslib_1.__importDefault(require("node:crypto"));
|
|
5
7
|
const index_js_1 = require("../helpers/index.js");
|
|
6
8
|
const index_js_2 = require("../schema/index.js");
|
|
7
9
|
const data_type_map_js_1 = require("./common/data-type-map.js");
|
|
@@ -80,6 +82,14 @@ class ApiDocument extends document_element_js_1.DocumentElement {
|
|
|
80
82
|
out.api = this.api.toJSON();
|
|
81
83
|
return out;
|
|
82
84
|
}
|
|
85
|
+
invalidate() {
|
|
86
|
+
/** Generate id */
|
|
87
|
+
const x = this.export();
|
|
88
|
+
delete x.id;
|
|
89
|
+
this.id = node_crypto_1.default.createHash('md5').update(JSON.stringify(x)).digest('base64url');
|
|
90
|
+
/** Clear [kTypeNSMap] */
|
|
91
|
+
this[constants_js_1.kTypeNSMap] = new WeakMap();
|
|
92
|
+
}
|
|
83
93
|
_findDataType(nameOrCtor, visitedRefs) {
|
|
84
94
|
let result = this.types.get(nameOrCtor);
|
|
85
95
|
if (result || !this.references.size)
|
|
@@ -53,8 +53,6 @@ http_operation_js_1.HttpOperation.Entity.Create = function (arg0, arg1) {
|
|
|
53
53
|
description: 'The request was well-formed but was unable to process operation due to one or many errors.',
|
|
54
54
|
contentType: index_js_2.MimeTypes.opra_response_json,
|
|
55
55
|
});
|
|
56
|
-
if (typeof args.type === 'function')
|
|
57
|
-
decorator.UseType(args.type);
|
|
58
56
|
decoratorChain.push((operationMeta) => {
|
|
59
57
|
const compositionOptions = (operationMeta.compositionOptions = operationMeta.compositionOptions || {});
|
|
60
58
|
compositionOptions.type = getDataTypeName(args.type);
|
|
@@ -87,8 +85,6 @@ http_operation_js_1.HttpOperation.Entity.Delete = function (arg0, arg1) {
|
|
|
87
85
|
description: 'The request was well-formed but was unable to process operation due to one or many errors.',
|
|
88
86
|
contentType: index_js_2.MimeTypes.opra_response_json,
|
|
89
87
|
});
|
|
90
|
-
if (typeof args.type === 'function')
|
|
91
|
-
decorator.UseType(args.type);
|
|
92
88
|
/**
|
|
93
89
|
*
|
|
94
90
|
*/
|
|
@@ -110,6 +106,7 @@ http_operation_js_1.HttpOperation.Entity.Delete = function (arg0, arg1) {
|
|
|
110
106
|
decoratorChain.push((meta) => {
|
|
111
107
|
if (!meta.path?.includes(':' + name))
|
|
112
108
|
meta.path = (meta.path || '') + '@:' + name;
|
|
109
|
+
meta.mergePath = true;
|
|
113
110
|
});
|
|
114
111
|
return decorator;
|
|
115
112
|
};
|
|
@@ -152,8 +149,6 @@ http_operation_js_1.HttpOperation.Entity.DeleteMany = function (arg0, arg1) {
|
|
|
152
149
|
type: filterType,
|
|
153
150
|
description: 'Determines filter fields',
|
|
154
151
|
});
|
|
155
|
-
if (typeof args.type === 'function')
|
|
156
|
-
decorator.UseType(args.type);
|
|
157
152
|
decoratorChain.push((operationMeta) => {
|
|
158
153
|
const compositionOptions = (operationMeta.compositionOptions = operationMeta.compositionOptions || {});
|
|
159
154
|
compositionOptions.type = getDataTypeName(args.type);
|
|
@@ -233,8 +228,6 @@ http_operation_js_1.HttpOperation.Entity.FindMany = function (arg0, arg1) {
|
|
|
233
228
|
isArray: true,
|
|
234
229
|
arraySeparator: ',',
|
|
235
230
|
});
|
|
236
|
-
if (typeof args.type === 'function')
|
|
237
|
-
decorator.UseType(args.type);
|
|
238
231
|
decoratorChain.push((operationMeta) => {
|
|
239
232
|
const compositionOptions = (operationMeta.compositionOptions = operationMeta.compositionOptions || {});
|
|
240
233
|
compositionOptions.type = getDataTypeName(args.type);
|
|
@@ -302,8 +295,6 @@ http_operation_js_1.HttpOperation.Entity.Get = function (arg0, arg1) {
|
|
|
302
295
|
description: 'The request was well-formed but was unable to process operation due to one or many errors.',
|
|
303
296
|
contentType: index_js_2.MimeTypes.opra_response_json,
|
|
304
297
|
});
|
|
305
|
-
if (typeof args.type === 'function')
|
|
306
|
-
decorator.UseType(args.type);
|
|
307
298
|
/**
|
|
308
299
|
*
|
|
309
300
|
*/
|
|
@@ -325,6 +316,7 @@ http_operation_js_1.HttpOperation.Entity.Get = function (arg0, arg1) {
|
|
|
325
316
|
decoratorChain.push((meta) => {
|
|
326
317
|
if (!meta.path?.includes(':' + name))
|
|
327
318
|
meta.path = (meta.path || '') + '@:' + name;
|
|
319
|
+
meta.mergePath = true;
|
|
328
320
|
});
|
|
329
321
|
return decorator;
|
|
330
322
|
};
|
|
@@ -360,10 +352,8 @@ http_operation_js_1.HttpOperation.Entity.UpdateMany = function (arg0, arg1) {
|
|
|
360
352
|
required: true,
|
|
361
353
|
},
|
|
362
354
|
}));
|
|
363
|
-
decorator.RequestContent(args.requestBody?.type || args.type);
|
|
364
|
-
if (typeof args.type === 'function')
|
|
365
|
-
decorator.UseType(args.type);
|
|
366
355
|
decorator
|
|
356
|
+
.RequestContent(args.requestBody?.type || args.type)
|
|
367
357
|
.Response(index_js_2.HttpStatusCode.OK, {
|
|
368
358
|
description: 'Operation is successful. Returns OperationResult with "affected" field.',
|
|
369
359
|
contentType: index_js_2.MimeTypes.opra_response_json,
|
|
@@ -443,8 +433,6 @@ http_operation_js_1.HttpOperation.Entity.Update = function (arg0, arg1) {
|
|
|
443
433
|
description: 'The request was well-formed but was unable to process operation due to one or many errors.',
|
|
444
434
|
contentType: index_js_2.MimeTypes.opra_response_json,
|
|
445
435
|
});
|
|
446
|
-
if (typeof args.type === 'function')
|
|
447
|
-
decorator.UseType(args.type);
|
|
448
436
|
/**
|
|
449
437
|
*
|
|
450
438
|
*/
|
|
@@ -466,6 +454,7 @@ http_operation_js_1.HttpOperation.Entity.Update = function (arg0, arg1) {
|
|
|
466
454
|
decoratorChain.push((meta) => {
|
|
467
455
|
if (!meta.path?.includes(':' + name))
|
|
468
456
|
meta.path = (meta.path || '') + '@:' + name;
|
|
457
|
+
meta.mergePath = true;
|
|
469
458
|
});
|
|
470
459
|
return decorator;
|
|
471
460
|
};
|
|
@@ -118,6 +118,9 @@ function HttpOperationDecoratorFactory(decoratorChain, options) {
|
|
|
118
118
|
responseMeta.contentType = responseMeta.contentType || index_js_1.MimeTypes.opra_response_json;
|
|
119
119
|
responseMeta.contentEncoding = responseMeta.contentEncoding || 'utf-8';
|
|
120
120
|
}
|
|
121
|
+
if (responseMeta.contentType === index_js_1.MimeTypes.opra_response_json) {
|
|
122
|
+
responseMeta.contentEncoding = responseMeta.contentEncoding || 'utf-8';
|
|
123
|
+
}
|
|
121
124
|
decoratorChain.push((meta) => {
|
|
122
125
|
meta.responses = meta.responses || [];
|
|
123
126
|
meta.responses.push(responseMeta);
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ApiDocumentFactory = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
const node_crypto_1 = tslib_1.__importDefault(require("node:crypto"));
|
|
6
|
-
const ts_gems_1 = require("ts-gems");
|
|
7
4
|
const index_js_1 = require("../../helpers/index.js");
|
|
8
5
|
const index_js_2 = require("../../schema/index.js");
|
|
9
6
|
const api_document_js_1 = require("../api-document.js");
|
|
@@ -99,7 +96,9 @@ class ApiDocumentFactory {
|
|
|
99
96
|
if (builtinDocument)
|
|
100
97
|
refDoc.references.set('opra', builtinDocument);
|
|
101
98
|
await this.initDocument(refDoc, context, r);
|
|
102
|
-
document
|
|
99
|
+
/** If same document already exists in document tree, we use it except the new one */
|
|
100
|
+
const preDoc = document.findDocument(refDoc.id);
|
|
101
|
+
document.references.set(ns, preDoc || refDoc);
|
|
103
102
|
});
|
|
104
103
|
}
|
|
105
104
|
});
|
|
@@ -120,8 +119,7 @@ class ApiDocumentFactory {
|
|
|
120
119
|
context.addError(`Unknown service protocol (${init.api.protocol})`);
|
|
121
120
|
});
|
|
122
121
|
}
|
|
123
|
-
|
|
124
|
-
(0, ts_gems_1.asMutable)(document).id = node_crypto_1.default.createHash('md5').update(JSON.stringify(x)).digest('base64url');
|
|
122
|
+
document.invalidate();
|
|
125
123
|
}
|
|
126
124
|
/**
|
|
127
125
|
*
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.HttpController = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const node_path_1 = tslib_1.__importDefault(require("node:path"));
|
|
4
6
|
const ts_gems_1 = require("ts-gems");
|
|
5
7
|
const index_js_1 = require("../../helpers/index.js");
|
|
6
8
|
const index_js_2 = require("../../schema/index.js");
|
|
@@ -100,8 +102,7 @@ class HttpControllerClass extends document_element_js_1.DocumentElement {
|
|
|
100
102
|
}
|
|
101
103
|
}
|
|
102
104
|
getFullUrl() {
|
|
103
|
-
|
|
104
|
-
return out + this.path;
|
|
105
|
+
return node_path_1.default.posix.join(this.owner instanceof exports.HttpController ? this.owner.getFullUrl() : '/', this.path);
|
|
105
106
|
}
|
|
106
107
|
/**
|
|
107
108
|
*
|
|
@@ -31,6 +31,7 @@ exports.HttpOperation = function (...args) {
|
|
|
31
31
|
_this.types = _this.node[constants_js_1.kDataTypeMap] = new data_type_map_js_1.DataTypeMap();
|
|
32
32
|
_this.name = initArgs.name;
|
|
33
33
|
_this.path = initArgs.path;
|
|
34
|
+
_this.mergePath = initArgs.mergePath;
|
|
34
35
|
_this.method = initArgs.method || 'GET';
|
|
35
36
|
_this.description = initArgs.description;
|
|
36
37
|
_this.composition = initArgs.composition;
|
|
@@ -57,7 +58,15 @@ class HttpOperationClass extends document_element_js_1.DocumentElement {
|
|
|
57
58
|
}
|
|
58
59
|
getFullUrl() {
|
|
59
60
|
const out = this.owner.getFullUrl();
|
|
60
|
-
|
|
61
|
+
if (out) {
|
|
62
|
+
if (this.path) {
|
|
63
|
+
if (this.mergePath)
|
|
64
|
+
return out + this.path;
|
|
65
|
+
return node_path_1.default.posix.join(out, this.path);
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
return this.path || '/';
|
|
61
70
|
}
|
|
62
71
|
toJSON() {
|
|
63
72
|
const out = (0, index_js_1.omitUndefined)({
|
|
@@ -65,6 +74,7 @@ class HttpOperationClass extends document_element_js_1.DocumentElement {
|
|
|
65
74
|
description: this.description,
|
|
66
75
|
method: this.method,
|
|
67
76
|
path: this.path,
|
|
77
|
+
mergePath: this.mergePath,
|
|
68
78
|
composition: this.composition,
|
|
69
79
|
requestBody: this.requestBody?.toJSON(),
|
|
70
80
|
});
|
|
@@ -25,8 +25,11 @@ class HttpStatusRange {
|
|
|
25
25
|
this.end = m[2] ? parseInt(m[2], 10) : this.start;
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
-
|
|
29
|
-
return this.
|
|
28
|
+
includes(statusCode) {
|
|
29
|
+
return statusCode >= this.start && statusCode <= this.end;
|
|
30
|
+
}
|
|
31
|
+
intersects(start, end) {
|
|
32
|
+
return end >= this.start && start <= this.end;
|
|
30
33
|
}
|
|
31
34
|
toString() {
|
|
32
35
|
if (this.start === this.end)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
var _a;
|
|
2
|
+
import crypto from 'node:crypto';
|
|
2
3
|
import { cloneObject, omitUndefined, ResponsiveMap } from '../helpers/index.js';
|
|
3
4
|
import { OpraSchema } from '../schema/index.js';
|
|
4
5
|
import { DataTypeMap } from './common/data-type-map.js';
|
|
@@ -77,6 +78,14 @@ export class ApiDocument extends DocumentElement {
|
|
|
77
78
|
out.api = this.api.toJSON();
|
|
78
79
|
return out;
|
|
79
80
|
}
|
|
81
|
+
invalidate() {
|
|
82
|
+
/** Generate id */
|
|
83
|
+
const x = this.export();
|
|
84
|
+
delete x.id;
|
|
85
|
+
this.id = crypto.createHash('md5').update(JSON.stringify(x)).digest('base64url');
|
|
86
|
+
/** Clear [kTypeNSMap] */
|
|
87
|
+
this[kTypeNSMap] = new WeakMap();
|
|
88
|
+
}
|
|
80
89
|
_findDataType(nameOrCtor, visitedRefs) {
|
|
81
90
|
let result = this.types.get(nameOrCtor);
|
|
82
91
|
if (result || !this.references.size)
|
|
@@ -51,8 +51,6 @@ HttpOperation.Entity.Create = function (arg0, arg1) {
|
|
|
51
51
|
description: 'The request was well-formed but was unable to process operation due to one or many errors.',
|
|
52
52
|
contentType: MimeTypes.opra_response_json,
|
|
53
53
|
});
|
|
54
|
-
if (typeof args.type === 'function')
|
|
55
|
-
decorator.UseType(args.type);
|
|
56
54
|
decoratorChain.push((operationMeta) => {
|
|
57
55
|
const compositionOptions = (operationMeta.compositionOptions = operationMeta.compositionOptions || {});
|
|
58
56
|
compositionOptions.type = getDataTypeName(args.type);
|
|
@@ -85,8 +83,6 @@ HttpOperation.Entity.Delete = function (arg0, arg1) {
|
|
|
85
83
|
description: 'The request was well-formed but was unable to process operation due to one or many errors.',
|
|
86
84
|
contentType: MimeTypes.opra_response_json,
|
|
87
85
|
});
|
|
88
|
-
if (typeof args.type === 'function')
|
|
89
|
-
decorator.UseType(args.type);
|
|
90
86
|
/**
|
|
91
87
|
*
|
|
92
88
|
*/
|
|
@@ -108,6 +104,7 @@ HttpOperation.Entity.Delete = function (arg0, arg1) {
|
|
|
108
104
|
decoratorChain.push((meta) => {
|
|
109
105
|
if (!meta.path?.includes(':' + name))
|
|
110
106
|
meta.path = (meta.path || '') + '@:' + name;
|
|
107
|
+
meta.mergePath = true;
|
|
111
108
|
});
|
|
112
109
|
return decorator;
|
|
113
110
|
};
|
|
@@ -150,8 +147,6 @@ HttpOperation.Entity.DeleteMany = function (arg0, arg1) {
|
|
|
150
147
|
type: filterType,
|
|
151
148
|
description: 'Determines filter fields',
|
|
152
149
|
});
|
|
153
|
-
if (typeof args.type === 'function')
|
|
154
|
-
decorator.UseType(args.type);
|
|
155
150
|
decoratorChain.push((operationMeta) => {
|
|
156
151
|
const compositionOptions = (operationMeta.compositionOptions = operationMeta.compositionOptions || {});
|
|
157
152
|
compositionOptions.type = getDataTypeName(args.type);
|
|
@@ -231,8 +226,6 @@ HttpOperation.Entity.FindMany = function (arg0, arg1) {
|
|
|
231
226
|
isArray: true,
|
|
232
227
|
arraySeparator: ',',
|
|
233
228
|
});
|
|
234
|
-
if (typeof args.type === 'function')
|
|
235
|
-
decorator.UseType(args.type);
|
|
236
229
|
decoratorChain.push((operationMeta) => {
|
|
237
230
|
const compositionOptions = (operationMeta.compositionOptions = operationMeta.compositionOptions || {});
|
|
238
231
|
compositionOptions.type = getDataTypeName(args.type);
|
|
@@ -300,8 +293,6 @@ HttpOperation.Entity.Get = function (arg0, arg1) {
|
|
|
300
293
|
description: 'The request was well-formed but was unable to process operation due to one or many errors.',
|
|
301
294
|
contentType: MimeTypes.opra_response_json,
|
|
302
295
|
});
|
|
303
|
-
if (typeof args.type === 'function')
|
|
304
|
-
decorator.UseType(args.type);
|
|
305
296
|
/**
|
|
306
297
|
*
|
|
307
298
|
*/
|
|
@@ -323,6 +314,7 @@ HttpOperation.Entity.Get = function (arg0, arg1) {
|
|
|
323
314
|
decoratorChain.push((meta) => {
|
|
324
315
|
if (!meta.path?.includes(':' + name))
|
|
325
316
|
meta.path = (meta.path || '') + '@:' + name;
|
|
317
|
+
meta.mergePath = true;
|
|
326
318
|
});
|
|
327
319
|
return decorator;
|
|
328
320
|
};
|
|
@@ -358,10 +350,8 @@ HttpOperation.Entity.UpdateMany = function (arg0, arg1) {
|
|
|
358
350
|
required: true,
|
|
359
351
|
},
|
|
360
352
|
}));
|
|
361
|
-
decorator.RequestContent(args.requestBody?.type || args.type);
|
|
362
|
-
if (typeof args.type === 'function')
|
|
363
|
-
decorator.UseType(args.type);
|
|
364
353
|
decorator
|
|
354
|
+
.RequestContent(args.requestBody?.type || args.type)
|
|
365
355
|
.Response(HttpStatusCode.OK, {
|
|
366
356
|
description: 'Operation is successful. Returns OperationResult with "affected" field.',
|
|
367
357
|
contentType: MimeTypes.opra_response_json,
|
|
@@ -441,8 +431,6 @@ HttpOperation.Entity.Update = function (arg0, arg1) {
|
|
|
441
431
|
description: 'The request was well-formed but was unable to process operation due to one or many errors.',
|
|
442
432
|
contentType: MimeTypes.opra_response_json,
|
|
443
433
|
});
|
|
444
|
-
if (typeof args.type === 'function')
|
|
445
|
-
decorator.UseType(args.type);
|
|
446
434
|
/**
|
|
447
435
|
*
|
|
448
436
|
*/
|
|
@@ -464,6 +452,7 @@ HttpOperation.Entity.Update = function (arg0, arg1) {
|
|
|
464
452
|
decoratorChain.push((meta) => {
|
|
465
453
|
if (!meta.path?.includes(':' + name))
|
|
466
454
|
meta.path = (meta.path || '') + '@:' + name;
|
|
455
|
+
meta.mergePath = true;
|
|
467
456
|
});
|
|
468
457
|
return decorator;
|
|
469
458
|
};
|
|
@@ -114,6 +114,9 @@ export function HttpOperationDecoratorFactory(decoratorChain, options) {
|
|
|
114
114
|
responseMeta.contentType = responseMeta.contentType || MimeTypes.opra_response_json;
|
|
115
115
|
responseMeta.contentEncoding = responseMeta.contentEncoding || 'utf-8';
|
|
116
116
|
}
|
|
117
|
+
if (responseMeta.contentType === MimeTypes.opra_response_json) {
|
|
118
|
+
responseMeta.contentEncoding = responseMeta.contentEncoding || 'utf-8';
|
|
119
|
+
}
|
|
117
120
|
decoratorChain.push((meta) => {
|
|
118
121
|
meta.responses = meta.responses || [];
|
|
119
122
|
meta.responses.push(responseMeta);
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import crypto from 'node:crypto';
|
|
2
|
-
import { asMutable } from 'ts-gems';
|
|
3
1
|
import { resolveThunk } from '../../helpers/index.js';
|
|
4
2
|
import { OpraSchema } from '../../schema/index.js';
|
|
5
3
|
import { ApiDocument } from '../api-document.js';
|
|
@@ -95,7 +93,9 @@ export class ApiDocumentFactory {
|
|
|
95
93
|
if (builtinDocument)
|
|
96
94
|
refDoc.references.set('opra', builtinDocument);
|
|
97
95
|
await this.initDocument(refDoc, context, r);
|
|
98
|
-
document
|
|
96
|
+
/** If same document already exists in document tree, we use it except the new one */
|
|
97
|
+
const preDoc = document.findDocument(refDoc.id);
|
|
98
|
+
document.references.set(ns, preDoc || refDoc);
|
|
99
99
|
});
|
|
100
100
|
}
|
|
101
101
|
});
|
|
@@ -116,8 +116,7 @@ export class ApiDocumentFactory {
|
|
|
116
116
|
context.addError(`Unknown service protocol (${init.api.protocol})`);
|
|
117
117
|
});
|
|
118
118
|
}
|
|
119
|
-
|
|
120
|
-
asMutable(document).id = crypto.createHash('md5').update(JSON.stringify(x)).digest('base64url');
|
|
119
|
+
document.invalidate();
|
|
121
120
|
}
|
|
122
121
|
/**
|
|
123
122
|
*
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import nodePath from 'node:path';
|
|
1
2
|
import { asMutable } from 'ts-gems';
|
|
2
3
|
import { omitUndefined, ResponsiveMap } from '../../helpers/index.js';
|
|
3
4
|
import { OpraSchema } from '../../schema/index.js';
|
|
@@ -97,8 +98,7 @@ class HttpControllerClass extends DocumentElement {
|
|
|
97
98
|
}
|
|
98
99
|
}
|
|
99
100
|
getFullUrl() {
|
|
100
|
-
|
|
101
|
-
return out + this.path;
|
|
101
|
+
return nodePath.posix.join(this.owner instanceof HttpController ? this.owner.getFullUrl() : '/', this.path);
|
|
102
102
|
}
|
|
103
103
|
/**
|
|
104
104
|
*
|
|
@@ -27,6 +27,7 @@ export const HttpOperation = function (...args) {
|
|
|
27
27
|
_this.types = _this.node[kDataTypeMap] = new DataTypeMap();
|
|
28
28
|
_this.name = initArgs.name;
|
|
29
29
|
_this.path = initArgs.path;
|
|
30
|
+
_this.mergePath = initArgs.mergePath;
|
|
30
31
|
_this.method = initArgs.method || 'GET';
|
|
31
32
|
_this.description = initArgs.description;
|
|
32
33
|
_this.composition = initArgs.composition;
|
|
@@ -53,7 +54,15 @@ class HttpOperationClass extends DocumentElement {
|
|
|
53
54
|
}
|
|
54
55
|
getFullUrl() {
|
|
55
56
|
const out = this.owner.getFullUrl();
|
|
56
|
-
|
|
57
|
+
if (out) {
|
|
58
|
+
if (this.path) {
|
|
59
|
+
if (this.mergePath)
|
|
60
|
+
return out + this.path;
|
|
61
|
+
return nodePath.posix.join(out, this.path);
|
|
62
|
+
}
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
65
|
+
return this.path || '/';
|
|
57
66
|
}
|
|
58
67
|
toJSON() {
|
|
59
68
|
const out = omitUndefined({
|
|
@@ -61,6 +70,7 @@ class HttpOperationClass extends DocumentElement {
|
|
|
61
70
|
description: this.description,
|
|
62
71
|
method: this.method,
|
|
63
72
|
path: this.path,
|
|
73
|
+
mergePath: this.mergePath,
|
|
64
74
|
composition: this.composition,
|
|
65
75
|
requestBody: this.requestBody?.toJSON(),
|
|
66
76
|
});
|
|
@@ -22,8 +22,11 @@ export class HttpStatusRange {
|
|
|
22
22
|
this.end = m[2] ? parseInt(m[2], 10) : this.start;
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
-
|
|
26
|
-
return this.
|
|
25
|
+
includes(statusCode) {
|
|
26
|
+
return statusCode >= this.start && statusCode <= this.end;
|
|
27
|
+
}
|
|
28
|
+
intersects(start, end) {
|
|
29
|
+
return end >= this.start && start <= this.end;
|
|
27
30
|
}
|
|
28
31
|
toString() {
|
|
29
32
|
if (this.start === this.end)
|
package/package.json
CHANGED
|
@@ -31,5 +31,6 @@ export declare class ApiDocument extends DocumentElement {
|
|
|
31
31
|
* Export as Opra schema definition object
|
|
32
32
|
*/
|
|
33
33
|
export(): OpraSchema.ApiDocument;
|
|
34
|
+
invalidate(): void;
|
|
34
35
|
protected _findDataType(nameOrCtor: string | Type | Function | EnumType.EnumArray | EnumType.EnumObject, visitedRefs?: WeakMap<ApiDocument, boolean>): DataType | undefined;
|
|
35
36
|
}
|
|
@@ -13,7 +13,7 @@ import type { HttpRequestBody } from './http-request-body.js';
|
|
|
13
13
|
* @namespace HttpOperation
|
|
14
14
|
*/
|
|
15
15
|
export declare namespace HttpOperation {
|
|
16
|
-
interface Metadata extends Pick<OpraSchema.HttpOperation, 'description' | 'path' | '
|
|
16
|
+
interface Metadata extends Pick<OpraSchema.HttpOperation, 'description' | 'method' | 'path' | 'mergePath' | 'composition' | 'compositionOptions'> {
|
|
17
17
|
types?: ThunkAsync<Type | EnumType.EnumObject | EnumType.EnumArray>[];
|
|
18
18
|
parameters?: HttpParameter.Metadata[];
|
|
19
19
|
responses?: HttpOperationResponse.Metadata[];
|
|
@@ -26,7 +26,7 @@ export declare namespace HttpOperation {
|
|
|
26
26
|
interface InitArguments extends Combine<{
|
|
27
27
|
name: string;
|
|
28
28
|
types?: DataType[];
|
|
29
|
-
}, Pick<Metadata, 'description' | 'path' | '
|
|
29
|
+
}, Pick<Metadata, 'description' | 'method' | 'path' | 'mergePath' | 'composition' | 'compositionOptions' | 'immediateFetch'>> {
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
@@ -72,6 +72,7 @@ declare class HttpOperationClass extends DocumentElement {
|
|
|
72
72
|
method: OpraSchema.HttpMethod;
|
|
73
73
|
description?: string;
|
|
74
74
|
path?: string;
|
|
75
|
+
mergePath?: boolean;
|
|
75
76
|
types: DataTypeMap;
|
|
76
77
|
parameters: HttpParameter[];
|
|
77
78
|
responses: HttpOperationResponse[];
|
|
@@ -8,7 +8,8 @@ export declare class HttpStatusRange {
|
|
|
8
8
|
constructor(value: string);
|
|
9
9
|
constructor(start: number, end?: number);
|
|
10
10
|
constructor(init: Pick<HttpStatusRange, 'start' | 'end'>);
|
|
11
|
-
|
|
11
|
+
includes(statusCode: number): boolean;
|
|
12
|
+
intersects(start: number, end: number): boolean;
|
|
12
13
|
toString(): string;
|
|
13
14
|
toJSON(): OpraSchema.HttpStatusRange | number;
|
|
14
15
|
}
|
|
@@ -11,6 +11,10 @@ export interface HttpOperation extends DataTypeContainer {
|
|
|
11
11
|
method: HttpMethod;
|
|
12
12
|
description?: string;
|
|
13
13
|
path?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Determines if the `path` will be joined or merged to parent path.
|
|
16
|
+
*/
|
|
17
|
+
mergePath?: boolean;
|
|
14
18
|
parameters?: HttpParameter[];
|
|
15
19
|
responses?: HttpOperationResponse[];
|
|
16
20
|
requestBody?: HttpRequestBody;
|