@opra/common 0.21.0 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/browser.js +810 -1427
- package/cjs/document/api-document.js +8 -4
- package/cjs/document/data-type/api-field.js +2 -2
- package/cjs/document/data-type/complex-type.js +17 -63
- package/cjs/document/data-type/data-type.js +0 -9
- package/cjs/document/data-type/enum-type.js +2 -8
- package/cjs/document/data-type/mapped-type.js +0 -36
- package/cjs/document/data-type/simple-type.js +2 -8
- package/cjs/document/data-type/union-type.js +0 -36
- package/cjs/document/index.js +2 -0
- package/cjs/document/resource/collection.js +75 -32
- package/cjs/document/resource/singleton.js +31 -20
- package/cjs/document/resource/storage.js +6 -20
- package/cjs/document/utils/generate-codec.js +39 -0
- package/cjs/exception/resource-errors/resource-not-found.error.js +1 -1
- package/cjs/helpers/index.js +1 -1
- package/cjs/helpers/is-url-string.js +14 -0
- package/cjs/helpers/object-utils.js +2 -2
- package/cjs/helpers/responsive-map.js +4 -4
- package/cjs/helpers/type-guards.js +15 -3
- package/cjs/http/enums/http-headers-codes.enum.js +3 -5
- package/cjs/http/enums/http-status-codes.enum.js +1 -1
- package/cjs/http/index.js +2 -9
- package/cjs/http/opra-url-path.js +251 -0
- package/cjs/{url → http}/opra-url.js +53 -109
- package/cjs/i18n/i18n.js +3 -3
- package/cjs/index.js +0 -2
- package/cjs/schema/opra-schema.ns.js +1 -1
- package/cjs/schema/resource/operation.interface.js +2 -0
- package/esm/document/api-document.js +10 -6
- package/esm/document/data-type/api-field.js +2 -2
- package/esm/document/data-type/complex-type.js +13 -59
- package/esm/document/data-type/data-type.js +0 -9
- package/esm/document/data-type/enum-type.js +2 -8
- package/esm/document/data-type/mapped-type.js +0 -36
- package/esm/document/data-type/simple-type.js +2 -8
- package/esm/document/data-type/union-type.js +0 -36
- package/esm/document/index.js +2 -0
- package/esm/document/resource/collection.js +75 -32
- package/esm/document/resource/singleton.js +31 -20
- package/esm/document/resource/storage.js +6 -20
- package/esm/document/utils/generate-codec.js +33 -0
- package/esm/exception/resource-errors/resource-not-found.error.js +1 -1
- package/esm/helpers/index.js +1 -1
- package/esm/helpers/is-url-string.js +9 -0
- package/esm/helpers/object-utils.js +2 -2
- package/esm/helpers/responsive-map.js +4 -4
- package/esm/helpers/type-guards.js +11 -2
- package/esm/http/enums/http-headers-codes.enum.js +3 -5
- package/esm/http/enums/http-status-codes.enum.js +1 -1
- package/esm/http/index.js +2 -9
- package/esm/http/opra-url-path.js +246 -0
- package/esm/{url → http}/opra-url.js +53 -109
- package/esm/i18n/i18n.js +4 -4
- package/esm/index.js +0 -2
- package/esm/schema/opra-schema.ns.js +1 -1
- package/esm/schema/resource/operation.interface.js +1 -0
- package/package.json +1 -1
- package/types/document/api-document.d.ts +4 -1
- package/types/document/data-type/complex-type.d.ts +6 -11
- package/types/document/data-type/data-type.d.ts +0 -6
- package/types/document/data-type/enum-type.d.ts +2 -4
- package/types/document/data-type/mapped-type.d.ts +0 -4
- package/types/document/data-type/simple-type.d.ts +2 -4
- package/types/document/data-type/union-type.d.ts +0 -5
- package/types/document/index.d.ts +2 -0
- package/types/document/interfaces/collection-resource.interface.d.ts +10 -0
- package/types/document/interfaces/singleton-resource.interface.d.ts +7 -0
- package/types/document/interfaces/storage-resource.interface.d.ts +8 -0
- package/types/document/resource/collection.d.ts +42 -36
- package/types/document/resource/resource.d.ts +2 -1
- package/types/document/resource/singleton.d.ts +24 -21
- package/types/document/resource/storage.d.ts +14 -17
- package/types/document/utils/generate-codec.d.ts +10 -0
- package/types/filter/errors.d.ts +2 -2
- package/types/helpers/index.d.ts +1 -1
- package/types/helpers/is-url-string.d.ts +2 -0
- package/types/helpers/object-utils.d.ts +1 -1
- package/types/helpers/type-guards.d.ts +3 -0
- package/types/http/enums/http-headers-codes.enum.d.ts +2 -4
- package/types/http/enums/http-status-codes.enum.d.ts +1 -1
- package/types/http/index.d.ts +2 -9
- package/types/http/opra-url-path.d.ts +54 -0
- package/types/{url → http}/opra-url.d.ts +9 -13
- package/types/index.d.ts +0 -2
- package/types/schema/opra-schema.ns.d.ts +1 -1
- package/types/schema/resource/collection.interface.d.ts +29 -8
- package/types/schema/resource/operation.interface.d.ts +3 -0
- package/types/schema/resource/resource.interface.d.ts +1 -0
- package/types/schema/resource/singleton.interface.d.ts +5 -5
- package/types/schema/resource/storage.interface.d.ts +42 -5
- package/cjs/helpers/is-url.js +0 -8
- package/cjs/http/codecs/boolean-codec.js +0 -24
- package/cjs/http/codecs/date-codec.js +0 -41
- package/cjs/http/codecs/filter-codec.js +0 -17
- package/cjs/http/codecs/integer-codec.js +0 -19
- package/cjs/http/codecs/number-codec.js +0 -24
- package/cjs/http/codecs/string-codec.js +0 -23
- package/cjs/http/http-params.js +0 -353
- package/cjs/http/multipart/batch-multipart.js +0 -170
- package/cjs/http/multipart/http-request-content.js +0 -17
- package/cjs/http/multipart/http-response-content.js +0 -14
- package/cjs/http/multipart/index.js +0 -2
- package/cjs/url/index.js +0 -8
- package/cjs/url/opra-url-path-component.js +0 -30
- package/cjs/url/opra-url-path.js +0 -155
- package/cjs/url/utils/decode-path-component.js +0 -41
- package/cjs/url/utils/encode-path-component.js +0 -27
- package/cjs/utils/path-utils.js +0 -24
- package/esm/helpers/is-url.js +0 -4
- package/esm/http/codecs/boolean-codec.js +0 -20
- package/esm/http/codecs/date-codec.js +0 -37
- package/esm/http/codecs/filter-codec.js +0 -13
- package/esm/http/codecs/integer-codec.js +0 -15
- package/esm/http/codecs/number-codec.js +0 -20
- package/esm/http/codecs/string-codec.js +0 -19
- package/esm/http/http-params.js +0 -348
- package/esm/http/multipart/batch-multipart.js +0 -170
- package/esm/http/multipart/http-request-content.js +0 -17
- package/esm/http/multipart/http-response-content.js +0 -14
- package/esm/http/multipart/index.js +0 -2
- package/esm/url/index.js +0 -5
- package/esm/url/opra-url-path-component.js +0 -26
- package/esm/url/opra-url-path.js +0 -151
- package/esm/url/utils/decode-path-component.js +0 -37
- package/esm/url/utils/encode-path-component.js +0 -22
- package/esm/utils/path-utils.js +0 -19
- package/types/helpers/is-url.d.ts +0 -1
- package/types/http/codecs/boolean-codec.d.ts +0 -5
- package/types/http/codecs/date-codec.d.ts +0 -16
- package/types/http/codecs/filter-codec.d.ts +0 -6
- package/types/http/codecs/integer-codec.d.ts +0 -11
- package/types/http/codecs/number-codec.d.ts +0 -14
- package/types/http/codecs/string-codec.d.ts +0 -16
- package/types/http/http-params.d.ts +0 -114
- package/types/http/interfaces/client-http-headers.interface.d.ts +0 -65
- package/types/http/interfaces/server-http-headers.interface.d.ts +0 -1
- package/types/http/multipart/batch-multipart.d.ts +0 -0
- package/types/http/multipart/http-request-content.d.ts +0 -0
- package/types/http/multipart/http-response-content.d.ts +0 -0
- package/types/http/multipart/index.d.ts +0 -0
- package/types/schema/resource/endpoint.interface.d.ts +0 -29
- package/types/url/index.d.ts +0 -5
- package/types/url/opra-url-path-component.d.ts +0 -15
- package/types/url/opra-url-path.d.ts +0 -36
- package/types/url/utils/decode-path-component.d.ts +0 -5
- package/types/url/utils/encode-path-component.d.ts +0 -1
- package/types/utils/path-utils.d.ts +0 -2
- /package/cjs/{http/interfaces/client-http-headers.interface.js → document/interfaces/collection-resource.interface.js} +0 -0
- /package/cjs/{http/interfaces/server-http-headers.interface.js → document/interfaces/singleton-resource.interface.js} +0 -0
- /package/cjs/{schema/resource/endpoint.interface.js → document/interfaces/storage-resource.interface.js} +0 -0
- /package/esm/{http/interfaces/client-http-headers.interface.js → document/interfaces/collection-resource.interface.js} +0 -0
- /package/esm/{http/interfaces/server-http-headers.interface.js → document/interfaces/singleton-resource.interface.js} +0 -0
- /package/esm/{schema/resource/endpoint.interface.js → document/interfaces/storage-resource.interface.js} +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import omit from 'lodash.omit';
|
|
2
2
|
import merge from 'putil-merge';
|
|
3
|
+
import * as vg from 'valgen';
|
|
3
4
|
import { BadRequestError } from '../../exception/index.js';
|
|
4
5
|
import { OpraFilter } from '../../filter/index.js';
|
|
5
6
|
import { omitUndefined } from '../../helpers/index.js';
|
|
@@ -7,15 +8,18 @@ import { translate } from '../../i18n/index.js';
|
|
|
7
8
|
import { OpraSchema } from '../../schema/index.js';
|
|
8
9
|
import { METADATA_KEY } from '../constants.js';
|
|
9
10
|
import { SimpleType } from '../data-type/simple-type.js';
|
|
11
|
+
import { generateCodec } from '../utils/generate-codec.js';
|
|
10
12
|
import { Resource } from './resource.js';
|
|
11
|
-
const NESTJS_INJECTABLE_WATERMARK = '__injectable__';
|
|
13
|
+
const NESTJS_INJECTABLE_WATERMARK = '__injectable__'; // todo, put this in nextjs package wia augmentation
|
|
12
14
|
const NAME_PATTERN = /^(.*)(Resource|Collection)$/;
|
|
13
15
|
class CollectionClass extends Resource {
|
|
14
16
|
constructor(document, init) {
|
|
15
17
|
super(document, init);
|
|
18
|
+
this._decoders = {};
|
|
19
|
+
this._encoders = {};
|
|
16
20
|
this.kind = OpraSchema.Collection.Kind;
|
|
17
21
|
this.controller = init.controller;
|
|
18
|
-
|
|
22
|
+
this.operations = { ...init.operations };
|
|
19
23
|
const dataType = this.type = init.type;
|
|
20
24
|
// Validate key fields
|
|
21
25
|
this.primaryKey = init.primaryKey
|
|
@@ -28,19 +32,6 @@ class CollectionClass extends Resource {
|
|
|
28
32
|
if (!(field?.type instanceof SimpleType))
|
|
29
33
|
throw new TypeError(`Only Simple type allowed for primary keys but "${f}" is a ${field.type.kind}`);
|
|
30
34
|
});
|
|
31
|
-
if (this.controller) {
|
|
32
|
-
const instance = typeof this.controller == 'function'
|
|
33
|
-
? new this.controller()
|
|
34
|
-
: this.controller;
|
|
35
|
-
for (const operation of Object.values(operations)) {
|
|
36
|
-
if (!operation.handler && operation.handlerName) {
|
|
37
|
-
const fn = instance[operation.handlerName];
|
|
38
|
-
if (!fn)
|
|
39
|
-
throw new TypeError(`No such operation handler (${operation.handlerName}) found`);
|
|
40
|
-
operation.handler = fn.bind(instance);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
35
|
}
|
|
45
36
|
exportSchema() {
|
|
46
37
|
const out = Resource.prototype.exportSchema.call(this);
|
|
@@ -66,7 +57,8 @@ class CollectionClass extends Resource {
|
|
|
66
57
|
// decode values
|
|
67
58
|
for (const [k, v] of Object.entries(obj)) {
|
|
68
59
|
const el = dataType.getField(k);
|
|
69
|
-
|
|
60
|
+
if (el.type instanceof SimpleType)
|
|
61
|
+
obj[k] = el.type.decode(v);
|
|
70
62
|
if (obj[k] == null)
|
|
71
63
|
throw new TypeError(`You must provide value of primary field(s) (${k})`);
|
|
72
64
|
}
|
|
@@ -76,7 +68,9 @@ class CollectionClass extends Resource {
|
|
|
76
68
|
if (typeof value === 'object')
|
|
77
69
|
value = value[primaryKey];
|
|
78
70
|
const el = dataType.getField(primaryKey);
|
|
79
|
-
|
|
71
|
+
let result;
|
|
72
|
+
if (el.type instanceof SimpleType)
|
|
73
|
+
result = el.type.decode(value);
|
|
80
74
|
if (result == null)
|
|
81
75
|
throw new TypeError(`You must provide value of primary field(s) (${primaryKey})`);
|
|
82
76
|
return result;
|
|
@@ -87,12 +81,14 @@ class CollectionClass extends Resource {
|
|
|
87
81
|
}
|
|
88
82
|
normalizeSortFields(fields) {
|
|
89
83
|
const normalized = this.type.normalizeFieldPath(fields);
|
|
90
|
-
|
|
91
|
-
|
|
84
|
+
if (!normalized)
|
|
85
|
+
return;
|
|
86
|
+
const findManyOp = this.operations.findMany;
|
|
87
|
+
const sortFields = findManyOp && findManyOp.sortFields;
|
|
92
88
|
(Array.isArray(normalized) ? normalized : [normalized]).forEach(field => {
|
|
93
89
|
if (!sortFields?.find(x => x === field))
|
|
94
90
|
throw new BadRequestError({
|
|
95
|
-
message: translate('error:UNACCEPTED_SORT_FIELD', { field }
|
|
91
|
+
message: translate('error:UNACCEPTED_SORT_FIELD', { field }),
|
|
96
92
|
});
|
|
97
93
|
});
|
|
98
94
|
return normalized;
|
|
@@ -105,27 +101,75 @@ class CollectionClass extends Resource {
|
|
|
105
101
|
this.normalizeFilter(ast.left);
|
|
106
102
|
if (!(ast.left instanceof OpraFilter.QualifiedIdentifier && ast.left.field))
|
|
107
103
|
throw new TypeError(`Invalid filter query. Left side should be a data field.`);
|
|
104
|
+
// Check if filtering accepted for given field
|
|
105
|
+
const findManyOp = this.operations.findMany;
|
|
106
|
+
const fieldLower = ast.left.value.toLowerCase();
|
|
107
|
+
const filterDef = (findManyOp && findManyOp.filters || [])
|
|
108
|
+
.find(f => f.field.toLowerCase() === fieldLower);
|
|
109
|
+
if (!filterDef) {
|
|
110
|
+
throw new BadRequestError({
|
|
111
|
+
message: translate('error:UNACCEPTED_FILTER_FIELD', { field: ast.left.value }),
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
// Check if filtering operation accepted for given field
|
|
115
|
+
if (!filterDef.operators?.includes(ast.op))
|
|
116
|
+
throw new BadRequestError({
|
|
117
|
+
message: translate('error:UNACCEPTED_FILTER_OPERATION', { field: ast.left.value }),
|
|
118
|
+
});
|
|
108
119
|
this.normalizeFilter(ast.right);
|
|
120
|
+
return ast;
|
|
109
121
|
}
|
|
110
|
-
|
|
122
|
+
if (ast instanceof OpraFilter.LogicalExpression) {
|
|
111
123
|
ast.items.forEach(item => this.normalizeFilter(item));
|
|
124
|
+
return ast;
|
|
112
125
|
}
|
|
113
|
-
|
|
126
|
+
if (ast instanceof OpraFilter.ArithmeticExpression) {
|
|
114
127
|
ast.items.forEach(item => this.normalizeFilter(item.expression));
|
|
128
|
+
return ast;
|
|
115
129
|
}
|
|
116
|
-
|
|
130
|
+
if (ast instanceof OpraFilter.ArrayExpression) {
|
|
117
131
|
ast.items.forEach(item => this.normalizeFilter(item));
|
|
132
|
+
return ast;
|
|
118
133
|
}
|
|
119
|
-
|
|
134
|
+
if (ast instanceof OpraFilter.ParenthesizedExpression) {
|
|
120
135
|
this.normalizeFilter(ast.expression);
|
|
136
|
+
return ast;
|
|
121
137
|
}
|
|
122
|
-
|
|
123
|
-
|
|
138
|
+
if (ast instanceof OpraFilter.QualifiedIdentifier) {
|
|
139
|
+
const normalizedFieldPath = this.type.normalizeFieldPath(ast.value)?.join('.');
|
|
140
|
+
ast.field = this.type.getField(normalizedFieldPath);
|
|
124
141
|
ast.dataType = ast.field?.type || this.document.getDataType('any');
|
|
125
|
-
ast.value =
|
|
142
|
+
ast.value = normalizedFieldPath;
|
|
143
|
+
return ast;
|
|
126
144
|
}
|
|
127
145
|
return ast;
|
|
128
146
|
}
|
|
147
|
+
getDecoder(operation) {
|
|
148
|
+
let decoder = this._decoders[operation];
|
|
149
|
+
if (decoder)
|
|
150
|
+
return decoder;
|
|
151
|
+
const options = {
|
|
152
|
+
partial: operation !== 'create'
|
|
153
|
+
};
|
|
154
|
+
if (operation !== 'create')
|
|
155
|
+
options.omit = [...this.primaryKey];
|
|
156
|
+
decoder = generateCodec(this.type, 'decode', options);
|
|
157
|
+
this._decoders[operation] = decoder;
|
|
158
|
+
return decoder;
|
|
159
|
+
}
|
|
160
|
+
getEncoder(operation) {
|
|
161
|
+
let encoder = this._encoders[operation];
|
|
162
|
+
if (encoder)
|
|
163
|
+
return encoder;
|
|
164
|
+
const options = {
|
|
165
|
+
partial: true
|
|
166
|
+
};
|
|
167
|
+
encoder = generateCodec(this.type, 'encode', options);
|
|
168
|
+
if (operation === 'findMany')
|
|
169
|
+
return vg.isArray(encoder);
|
|
170
|
+
this._encoders[operation] = encoder;
|
|
171
|
+
return encoder;
|
|
172
|
+
}
|
|
129
173
|
}
|
|
130
174
|
/**
|
|
131
175
|
*
|
|
@@ -163,13 +207,12 @@ export const Collection = function (...args) {
|
|
|
163
207
|
Collection.prototype = CollectionClass.prototype;
|
|
164
208
|
function createOperationDecorator(operation) {
|
|
165
209
|
return (options) => ((target, propertyKey) => {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
};
|
|
210
|
+
if (propertyKey !== operation)
|
|
211
|
+
throw new TypeError(`Name of the handler name should be '${operation}'`);
|
|
212
|
+
const operationMeta = { ...options };
|
|
170
213
|
const resourceMetadata = (Reflect.getOwnMetadata(METADATA_KEY, target.constructor) || {});
|
|
171
214
|
resourceMetadata.operations = resourceMetadata.operations || {};
|
|
172
|
-
resourceMetadata.operations[operation] =
|
|
215
|
+
resourceMetadata.operations[operation] = operationMeta;
|
|
173
216
|
Reflect.defineMetadata(METADATA_KEY, resourceMetadata, target.constructor);
|
|
174
217
|
});
|
|
175
218
|
}
|
|
@@ -3,29 +3,19 @@ import merge from 'putil-merge';
|
|
|
3
3
|
import { omitUndefined } from '../../helpers/index.js';
|
|
4
4
|
import { OpraSchema } from '../../schema/index.js';
|
|
5
5
|
import { METADATA_KEY } from '../constants.js';
|
|
6
|
+
import { generateCodec } from '../utils/generate-codec.js';
|
|
6
7
|
import { Resource } from './resource.js';
|
|
7
|
-
const NESTJS_INJECTABLE_WATERMARK = '__injectable__';
|
|
8
|
+
const NESTJS_INJECTABLE_WATERMARK = '__injectable__'; // todo, put this in nextjs package wia augmentation
|
|
8
9
|
const NAME_PATTERN = /^(.*)(Resource|Singleton)$/;
|
|
9
10
|
class SingletonClass extends Resource {
|
|
10
11
|
constructor(document, init) {
|
|
11
12
|
super(document, init);
|
|
13
|
+
this._decoders = {};
|
|
14
|
+
this._encoders = {};
|
|
12
15
|
this.kind = OpraSchema.Singleton.Kind;
|
|
13
16
|
this.controller = init.controller;
|
|
14
|
-
|
|
17
|
+
this.operations = { ...init.operations };
|
|
15
18
|
this.type = init.type;
|
|
16
|
-
if (this.controller) {
|
|
17
|
-
const instance = typeof this.controller == 'function'
|
|
18
|
-
? new this.controller()
|
|
19
|
-
: this.controller;
|
|
20
|
-
for (const operation of Object.values(operations)) {
|
|
21
|
-
if (!operation.handler && operation.handlerName) {
|
|
22
|
-
const fn = instance[operation.handlerName];
|
|
23
|
-
if (!fn)
|
|
24
|
-
throw new TypeError(`No such operation handler (${operation.handlerName}) found`);
|
|
25
|
-
operation.handler = fn.bind(instance);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
19
|
}
|
|
30
20
|
exportSchema() {
|
|
31
21
|
const out = Resource.prototype.exportSchema.call(this);
|
|
@@ -38,6 +28,28 @@ class SingletonClass extends Resource {
|
|
|
38
28
|
normalizeFieldPath(path) {
|
|
39
29
|
return this.type.normalizeFieldPath(path);
|
|
40
30
|
}
|
|
31
|
+
getDecoder(operation) {
|
|
32
|
+
let decoder = this._decoders[operation];
|
|
33
|
+
if (decoder)
|
|
34
|
+
return decoder;
|
|
35
|
+
const options = {
|
|
36
|
+
partial: operation !== 'create'
|
|
37
|
+
};
|
|
38
|
+
decoder = generateCodec(this.type, 'decode', options);
|
|
39
|
+
this._decoders[operation] = decoder;
|
|
40
|
+
return decoder;
|
|
41
|
+
}
|
|
42
|
+
getEncoder(operation) {
|
|
43
|
+
let encoder = this._encoders[operation];
|
|
44
|
+
if (encoder)
|
|
45
|
+
return encoder;
|
|
46
|
+
const options = {
|
|
47
|
+
partial: true
|
|
48
|
+
};
|
|
49
|
+
encoder = generateCodec(this.type, 'encode', options);
|
|
50
|
+
this._encoders[operation] = encoder;
|
|
51
|
+
return encoder;
|
|
52
|
+
}
|
|
41
53
|
}
|
|
42
54
|
export const Singleton = function (...args) {
|
|
43
55
|
// ClassDecorator
|
|
@@ -68,13 +80,12 @@ export const Singleton = function (...args) {
|
|
|
68
80
|
Singleton.prototype = SingletonClass.prototype;
|
|
69
81
|
function createOperationDecorator(operation) {
|
|
70
82
|
return (options) => ((target, propertyKey) => {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
};
|
|
83
|
+
if (propertyKey !== operation)
|
|
84
|
+
throw new TypeError(`Name of the handler name should be '${operation}'`);
|
|
85
|
+
const operationMeta = { ...options };
|
|
75
86
|
const resourceMetadata = (Reflect.getOwnMetadata(METADATA_KEY, target.constructor) || {});
|
|
76
87
|
resourceMetadata.operations = resourceMetadata.operations || {};
|
|
77
|
-
resourceMetadata.operations[operation] =
|
|
88
|
+
resourceMetadata.operations[operation] = operationMeta;
|
|
78
89
|
Reflect.defineMetadata(METADATA_KEY, resourceMetadata, target.constructor);
|
|
79
90
|
});
|
|
80
91
|
}
|
|
@@ -11,20 +11,7 @@ class StorageClass extends Resource {
|
|
|
11
11
|
super(document, init);
|
|
12
12
|
this.kind = OpraSchema.Storage.Kind;
|
|
13
13
|
this.controller = init.controller;
|
|
14
|
-
|
|
15
|
-
if (this.controller) {
|
|
16
|
-
const instance = typeof this.controller == 'function'
|
|
17
|
-
? new this.controller()
|
|
18
|
-
: this.controller;
|
|
19
|
-
for (const operation of Object.values(operations)) {
|
|
20
|
-
if (!operation.handler && operation.handlerName) {
|
|
21
|
-
const fn = instance[operation.handlerName];
|
|
22
|
-
if (!fn)
|
|
23
|
-
throw new TypeError(`No such operation handler (${operation.handlerName}) found`);
|
|
24
|
-
operation.handler = fn.bind(instance);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
14
|
+
this.operations = { ...init.operations };
|
|
28
15
|
}
|
|
29
16
|
exportSchema() {
|
|
30
17
|
const out = Resource.prototype.exportSchema.call(this);
|
|
@@ -62,16 +49,15 @@ export const Storage = function (...args) {
|
|
|
62
49
|
Storage.prototype = StorageClass.prototype;
|
|
63
50
|
function createOperationDecorator(operation) {
|
|
64
51
|
return (options) => ((target, propertyKey) => {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
};
|
|
52
|
+
if (propertyKey !== operation)
|
|
53
|
+
throw new TypeError(`Name of the handler name should be '${operation}'`);
|
|
54
|
+
const operationMeta = { ...options };
|
|
69
55
|
const resourceMetadata = (Reflect.getOwnMetadata(METADATA_KEY, target.constructor) || {});
|
|
70
56
|
resourceMetadata.operations = resourceMetadata.operations || {};
|
|
71
|
-
resourceMetadata.operations[operation] =
|
|
57
|
+
resourceMetadata.operations[operation] = operationMeta;
|
|
72
58
|
Reflect.defineMetadata(METADATA_KEY, resourceMetadata, target.constructor);
|
|
73
59
|
});
|
|
74
60
|
}
|
|
75
61
|
Storage.Delete = createOperationDecorator('delete');
|
|
76
62
|
Storage.Get = createOperationDecorator('get');
|
|
77
|
-
Storage.
|
|
63
|
+
Storage.Post = createOperationDecorator('post');
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as vg from 'valgen';
|
|
2
|
+
import { ComplexType } from '../data-type/complex-type.js';
|
|
3
|
+
import { EnumType } from '../data-type/enum-type.js';
|
|
4
|
+
import { MappedType } from '../data-type/mapped-type.js';
|
|
5
|
+
import { SimpleType } from '../data-type/simple-type.js';
|
|
6
|
+
import { UnionType } from '../data-type/union-type.js';
|
|
7
|
+
export function generateCodec(type, codec, options) {
|
|
8
|
+
return _generateDecoder(type, codec, options);
|
|
9
|
+
}
|
|
10
|
+
export function _generateDecoder(type, codec, options) {
|
|
11
|
+
const schema = {};
|
|
12
|
+
for (const f of type.fields.values()) {
|
|
13
|
+
let fn;
|
|
14
|
+
if (f.type instanceof SimpleType || f.type instanceof EnumType) {
|
|
15
|
+
fn = f.type[codec];
|
|
16
|
+
}
|
|
17
|
+
else if (f.type instanceof ComplexType || f.type instanceof MappedType || f.type instanceof UnionType) {
|
|
18
|
+
fn = _generateDecoder(f.type, codec, options);
|
|
19
|
+
}
|
|
20
|
+
/* istanbul ignore next */
|
|
21
|
+
if (!fn)
|
|
22
|
+
throw new TypeError(`Can't generate codec for (${f.type})`);
|
|
23
|
+
if (f.isArray)
|
|
24
|
+
fn = vg.isArray(fn);
|
|
25
|
+
schema[f.name] = !options.partial && f.required ? vg.required(fn) : vg.optional(fn);
|
|
26
|
+
}
|
|
27
|
+
return vg.isObject(schema, {
|
|
28
|
+
ctor: type.ctor,
|
|
29
|
+
additionalFields: type.additionalFields ?? 'ignore',
|
|
30
|
+
name: type.name,
|
|
31
|
+
caseInSensitive: true,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
@@ -7,7 +7,7 @@ import { OpraException } from '../opra-exception.js';
|
|
|
7
7
|
export class ResourceNotFoundError extends OpraException {
|
|
8
8
|
constructor(resource, keyValue, cause) {
|
|
9
9
|
super({
|
|
10
|
-
message: translate(`error:RESOURCE_NOT_FOUND`, { resource: resource + (keyValue ? '@' + keyValue : '') }, `The resource '{{resource}}'
|
|
10
|
+
message: translate(`error:RESOURCE_NOT_FOUND`, { resource: resource + (keyValue ? '@' + keyValue : '') }, `The resource '{{resource}}' not found`),
|
|
11
11
|
severity: 'error',
|
|
12
12
|
code: 'RESOURCE_NOT_FOUND',
|
|
13
13
|
details: {
|
package/esm/helpers/index.js
CHANGED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { URL } from 'url';
|
|
2
|
+
const URL_PATTERN = /^(https?:\/\/.)[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_+.~#?&/=]*)$/i;
|
|
3
|
+
export function isUrlString(url) {
|
|
4
|
+
return URL_PATTERN.test(url);
|
|
5
|
+
}
|
|
6
|
+
export const isAbsoluteUrl = (urlString) => {
|
|
7
|
+
return !urlString.includes('://') &&
|
|
8
|
+
(new URL(urlString, 'http://tempuri.org/')).host !== 'tempuri.org';
|
|
9
|
+
};
|
|
@@ -12,13 +12,13 @@ export function cloneObject(obj, jsonOnly) {
|
|
|
12
12
|
}
|
|
13
13
|
});
|
|
14
14
|
}
|
|
15
|
-
export function omitUndefined(obj) {
|
|
15
|
+
export function omitUndefined(obj, recursive) {
|
|
16
16
|
if (!(obj && typeof obj === 'object'))
|
|
17
17
|
return obj;
|
|
18
18
|
for (const k of Object.keys(obj)) {
|
|
19
19
|
if (obj[k] === undefined)
|
|
20
20
|
delete obj[k];
|
|
21
|
-
else if (typeof obj[k] === 'object')
|
|
21
|
+
else if (recursive && typeof obj[k] === 'object')
|
|
22
22
|
omitUndefined(obj[k]);
|
|
23
23
|
}
|
|
24
24
|
return obj;
|
|
@@ -2,10 +2,10 @@ var _a, _b, _c, _d;
|
|
|
2
2
|
function isMap(v) {
|
|
3
3
|
return v && typeof v.forEach === 'function';
|
|
4
4
|
}
|
|
5
|
-
const kKeyMap = Symbol('kKeyMap');
|
|
6
|
-
const kKeyOrder = Symbol('kKeyOrder');
|
|
7
|
-
const kWellKnownKeys = Symbol('kWellKnownKeys');
|
|
8
|
-
const kOptions = Symbol('kOptions');
|
|
5
|
+
const kKeyMap = Symbol.for('kKeyMap');
|
|
6
|
+
const kKeyOrder = Symbol.for('kKeyOrder');
|
|
7
|
+
const kWellKnownKeys = Symbol.for('kWellKnownKeys');
|
|
8
|
+
const kOptions = Symbol.for('kOptions');
|
|
9
9
|
/**
|
|
10
10
|
* A Map implementation that supports case-insensitivity and ordered keys
|
|
11
11
|
*/
|
|
@@ -11,13 +11,15 @@ export function isStream(stream) {
|
|
|
11
11
|
}
|
|
12
12
|
export function isReadable(x) {
|
|
13
13
|
return isStream(x)
|
|
14
|
-
&& x.readable !== false
|
|
15
14
|
&& typeof x._read === 'function'
|
|
16
15
|
&& typeof x._readableState === 'object';
|
|
17
16
|
}
|
|
17
|
+
export function isWritable(x) {
|
|
18
|
+
return isStream(x)
|
|
19
|
+
&& typeof x._write === 'function';
|
|
20
|
+
}
|
|
18
21
|
export function isReadableStream(x) {
|
|
19
22
|
return isStream(x)
|
|
20
|
-
&& x.readable !== false
|
|
21
23
|
&& typeof x.getReader === 'function'
|
|
22
24
|
&& typeof x.pipeThrough === 'function'
|
|
23
25
|
&& typeof x.pipeTo === 'function';
|
|
@@ -38,6 +40,13 @@ export function isFormData(x) {
|
|
|
38
40
|
}
|
|
39
41
|
export function isURL(x) {
|
|
40
42
|
return x !== null
|
|
43
|
+
&& typeof x == 'object'
|
|
41
44
|
&& typeof x.host === 'string'
|
|
42
45
|
&& typeof x.href === 'string';
|
|
43
46
|
}
|
|
47
|
+
export function isIterable(x) {
|
|
48
|
+
return Symbol.iterator in x;
|
|
49
|
+
}
|
|
50
|
+
export function isAsyncIterable(x) {
|
|
51
|
+
return Symbol.asyncIterator in x;
|
|
52
|
+
}
|
|
@@ -4,11 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export var HttpHeaderCodes;
|
|
6
6
|
(function (HttpHeaderCodes) {
|
|
7
|
-
/* *** Opra Headers *** */
|
|
8
|
-
HttpHeaderCodes["X_Opra_Version"] = "X-
|
|
9
|
-
HttpHeaderCodes["
|
|
10
|
-
HttpHeaderCodes["X_Opra_Operation"] = "X-OPRA-Operation";
|
|
11
|
-
HttpHeaderCodes["X_Opra_Total_Matches"] = "X-OPRA-Total-Matches";
|
|
7
|
+
/* *** Opra Custom Headers *** */
|
|
8
|
+
HttpHeaderCodes["X_Opra_Version"] = "X-Opra-Version";
|
|
9
|
+
HttpHeaderCodes["X_Total_Count"] = "X-Total-Count";
|
|
12
10
|
/* *** Authentication *** */
|
|
13
11
|
/**
|
|
14
12
|
* Defines the authentication method that should be used to access a resource.
|
|
@@ -225,7 +225,7 @@ export var HttpStatusCodes;
|
|
|
225
225
|
* to do so after the client upgrades to a different protocol. The server sends an Upgrade
|
|
226
226
|
* header in a 426 response to indicate the required protocol(s).
|
|
227
227
|
*/
|
|
228
|
-
HttpStatusCodes[HttpStatusCodes["UPGRADE_REQUIRED"] =
|
|
228
|
+
HttpStatusCodes[HttpStatusCodes["UPGRADE_REQUIRED"] = 426] = "UPGRADE_REQUIRED";
|
|
229
229
|
/**
|
|
230
230
|
* The origin server requires the request to be conditional. This response is intended to prevent
|
|
231
231
|
* the 'lost update' problem, where a client GETs a resource's state, modifies it and PUTs
|
package/esm/http/index.js
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
|
-
export * from './
|
|
1
|
+
export * from './opra-url.js';
|
|
2
|
+
export * from './opra-url-path.js';
|
|
2
3
|
export * from './enums/http-headers-codes.enum.js';
|
|
3
4
|
export * from './enums/http-status-codes.enum.js';
|
|
4
5
|
export * from './enums/http-status-messages.js';
|
|
5
|
-
export * from './interfaces/client-http-headers.interface.js';
|
|
6
|
-
export * from './interfaces/server-http-headers.interface.js';
|
|
7
|
-
export * from './codecs/date-codec.js';
|
|
8
|
-
export * from './codecs/boolean-codec.js';
|
|
9
|
-
export * from './codecs/filter-codec.js';
|
|
10
|
-
export * from './codecs/integer-codec.js';
|
|
11
|
-
export * from './codecs/number-codec.js';
|
|
12
|
-
export * from './codecs/string-codec.js';
|