@opra/common 1.0.0-alpha.1 → 1.0.0-alpha.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/package.json +1 -1
- package/cjs/document/data-type/decorators/api-field-decorator.js +0 -26
- package/cjs/document/data-type/decorators/complex-type.decorator.js +0 -33
- package/cjs/document/data-type/decorators/simple-type.decorator.js +0 -67
- package/cjs/document/http/decorators/http-controller.decorator.js +0 -117
- package/cjs/document/http/decorators/http-operation-entity.decorator.js +0 -461
- package/cjs/document/http/decorators/http-operation.decorator.js +0 -183
- package/cjs/helpers/is-url-string.js +0 -12
- package/cjs/http/opra-url-path.js +0 -266
- package/cjs/http/opra-url.js +0 -253
- package/esm/document/data-type/decorators/api-field-decorator.js +0 -22
- package/esm/document/data-type/decorators/complex-type.decorator.js +0 -28
- package/esm/document/data-type/decorators/simple-type.decorator.js +0 -61
- package/esm/document/http/decorators/http-controller.decorator.js +0 -112
- package/esm/document/http/decorators/http-operation-entity.decorator.js +0 -459
- package/esm/document/http/decorators/http-operation.decorator.js +0 -178
- package/esm/helpers/is-url-string.js +0 -7
- package/esm/http/opra-url-path.js +0 -260
- package/esm/http/opra-url.js +0 -249
- package/types/document/data-type/decorators/api-field-decorator.d.ts +0 -5
- package/types/document/data-type/decorators/complex-type.decorator.d.ts +0 -2
- package/types/document/data-type/decorators/simple-type.decorator.d.ts +0 -20
- package/types/document/http/decorators/http-controller.decorator.d.ts +0 -14
- package/types/document/http/decorators/http-operation-entity.decorator.d.ts +0 -100
- package/types/document/http/decorators/http-operation.decorator.d.ts +0 -30
- package/types/helpers/is-url-string.d.ts +0 -2
- package/types/http/opra-url-path.d.ts +0 -55
- package/types/http/opra-url.d.ts +0 -66
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
import omit from 'lodash.omit';
|
|
2
|
-
import { MimeTypes } from '../../../http/index.js';
|
|
3
|
-
import { OpraSchema } from '../../../schema/index.js';
|
|
4
|
-
import { HTTP_CONTROLLER_METADATA } from '../../constants.js';
|
|
5
|
-
export function HttpOperationDecoratorFactory(decoratorChain, options) {
|
|
6
|
-
/**
|
|
7
|
-
*
|
|
8
|
-
*/
|
|
9
|
-
const decorator = ((target, propertyKey) => {
|
|
10
|
-
if (typeof propertyKey !== 'string')
|
|
11
|
-
throw new TypeError(`Symbol properties can not be decorated`);
|
|
12
|
-
const operationMetadata = {
|
|
13
|
-
kind: OpraSchema.HttpOperation.Kind,
|
|
14
|
-
...omit(options, ['kind']),
|
|
15
|
-
};
|
|
16
|
-
const resourceMetadata = (Reflect.getOwnMetadata(HTTP_CONTROLLER_METADATA, target.constructor) ||
|
|
17
|
-
{});
|
|
18
|
-
resourceMetadata.operations = resourceMetadata.operations || {};
|
|
19
|
-
resourceMetadata.operations[propertyKey] = operationMetadata;
|
|
20
|
-
for (const fn of decoratorChain)
|
|
21
|
-
fn(operationMetadata);
|
|
22
|
-
Reflect.defineMetadata(HTTP_CONTROLLER_METADATA, resourceMetadata, target.constructor);
|
|
23
|
-
});
|
|
24
|
-
/**
|
|
25
|
-
*
|
|
26
|
-
*/
|
|
27
|
-
decorator.Cookie = (name, arg1) => {
|
|
28
|
-
decoratorChain.push((meta) => {
|
|
29
|
-
const paramMeta = typeof arg1 === 'string' || typeof arg1 === 'function'
|
|
30
|
-
? {
|
|
31
|
-
name,
|
|
32
|
-
location: 'cookie',
|
|
33
|
-
type: arg1,
|
|
34
|
-
}
|
|
35
|
-
: { ...arg1, name, location: 'cookie' };
|
|
36
|
-
if (meta.parameters)
|
|
37
|
-
meta.parameters = meta.parameters.filter(p => !(p.location === 'cookie' && String(p.name) === String(name)));
|
|
38
|
-
else
|
|
39
|
-
meta.parameters = [];
|
|
40
|
-
meta.parameters.push(paramMeta);
|
|
41
|
-
});
|
|
42
|
-
return decorator;
|
|
43
|
-
};
|
|
44
|
-
/**
|
|
45
|
-
*
|
|
46
|
-
*/
|
|
47
|
-
decorator.Header = (name, arg1) => {
|
|
48
|
-
decoratorChain.push((meta) => {
|
|
49
|
-
const paramMeta = typeof arg1 === 'string' || typeof arg1 === 'function'
|
|
50
|
-
? {
|
|
51
|
-
name,
|
|
52
|
-
location: 'header',
|
|
53
|
-
type: arg1,
|
|
54
|
-
}
|
|
55
|
-
: { ...arg1, name, location: 'header' };
|
|
56
|
-
if (meta.parameters)
|
|
57
|
-
meta.parameters = meta.parameters.filter(p => !(p.location === 'header' && String(p.name) === String(name)));
|
|
58
|
-
else
|
|
59
|
-
meta.parameters = [];
|
|
60
|
-
meta.parameters.push(paramMeta);
|
|
61
|
-
});
|
|
62
|
-
return decorator;
|
|
63
|
-
};
|
|
64
|
-
/**
|
|
65
|
-
*
|
|
66
|
-
*/
|
|
67
|
-
decorator.QueryParam = (name, arg1) => {
|
|
68
|
-
decoratorChain.push((meta) => {
|
|
69
|
-
const paramMeta = typeof arg1 === 'string' || typeof arg1 === 'function'
|
|
70
|
-
? {
|
|
71
|
-
name,
|
|
72
|
-
location: 'query',
|
|
73
|
-
type: arg1,
|
|
74
|
-
}
|
|
75
|
-
: { ...arg1, name, location: 'query' };
|
|
76
|
-
if (meta.parameters)
|
|
77
|
-
meta.parameters = meta.parameters.filter(p => !(p.location === 'query' && String(p.name) === String(name)));
|
|
78
|
-
else
|
|
79
|
-
meta.parameters = [];
|
|
80
|
-
meta.parameters.push(paramMeta);
|
|
81
|
-
});
|
|
82
|
-
return decorator;
|
|
83
|
-
};
|
|
84
|
-
/**
|
|
85
|
-
*
|
|
86
|
-
*/
|
|
87
|
-
decorator.PathParam = (name, arg1) => {
|
|
88
|
-
decoratorChain.push((meta) => {
|
|
89
|
-
const paramMeta = typeof arg1 === 'string' || typeof arg1 === 'function'
|
|
90
|
-
? {
|
|
91
|
-
name,
|
|
92
|
-
location: 'path',
|
|
93
|
-
type: arg1,
|
|
94
|
-
}
|
|
95
|
-
: { ...arg1, name, location: 'path' };
|
|
96
|
-
if (meta.parameters)
|
|
97
|
-
meta.parameters = meta.parameters.filter(p => !(p.location === 'path' && String(p.name) === String(name)));
|
|
98
|
-
else
|
|
99
|
-
meta.parameters = [];
|
|
100
|
-
meta.parameters.push(paramMeta);
|
|
101
|
-
});
|
|
102
|
-
return decorator;
|
|
103
|
-
};
|
|
104
|
-
/**
|
|
105
|
-
*
|
|
106
|
-
*/
|
|
107
|
-
decorator.Response = (statusCode, responseOptions) => {
|
|
108
|
-
const responseMeta = { ...responseOptions, statusCode };
|
|
109
|
-
if (responseMeta.type) {
|
|
110
|
-
responseMeta.contentType = responseMeta.contentType || MimeTypes.opra_response_json;
|
|
111
|
-
responseMeta.contentEncoding = responseMeta.contentEncoding || 'utf-8';
|
|
112
|
-
}
|
|
113
|
-
decoratorChain.push((meta) => {
|
|
114
|
-
meta.responses = meta.responses || [];
|
|
115
|
-
meta.responses.push(responseMeta);
|
|
116
|
-
});
|
|
117
|
-
return decorator;
|
|
118
|
-
};
|
|
119
|
-
decorator.RequestContent = function (arg0) {
|
|
120
|
-
const contentMeta = typeof arg0 === 'object' ? arg0 : { type: arg0 };
|
|
121
|
-
if (contentMeta.type) {
|
|
122
|
-
contentMeta.contentType = contentMeta.contentType || MimeTypes.json;
|
|
123
|
-
contentMeta.contentEncoding = contentMeta.contentEncoding || 'utf-8';
|
|
124
|
-
}
|
|
125
|
-
decoratorChain.push((operationMetadata) => {
|
|
126
|
-
operationMetadata.requestBody = operationMetadata.requestBody || { required: true, content: [] };
|
|
127
|
-
operationMetadata.requestBody.content = operationMetadata.requestBody.content || [];
|
|
128
|
-
operationMetadata.requestBody.content.push(contentMeta);
|
|
129
|
-
});
|
|
130
|
-
return decorator;
|
|
131
|
-
};
|
|
132
|
-
decorator.MultipartContent = function (contentOpts, subInit) {
|
|
133
|
-
const contentMetadata = {
|
|
134
|
-
...contentOpts,
|
|
135
|
-
contentType: contentOpts?.contentType || 'multipart/form-data',
|
|
136
|
-
};
|
|
137
|
-
decoratorChain.push((operationMetadata) => {
|
|
138
|
-
operationMetadata.requestBody = operationMetadata.requestBody || { required: true, content: [] };
|
|
139
|
-
operationMetadata.requestBody.content = operationMetadata.requestBody.content || [];
|
|
140
|
-
operationMetadata.requestBody.content.push(contentMetadata);
|
|
141
|
-
});
|
|
142
|
-
if (subInit) {
|
|
143
|
-
const configScope = {
|
|
144
|
-
Field(fieldName, opts) {
|
|
145
|
-
contentMetadata.multipartFields = contentMetadata.multipartFields || [];
|
|
146
|
-
contentMetadata.multipartFields.push({
|
|
147
|
-
fieldName,
|
|
148
|
-
fieldType: 'field',
|
|
149
|
-
...opts,
|
|
150
|
-
});
|
|
151
|
-
return configScope;
|
|
152
|
-
},
|
|
153
|
-
File(fieldName, opts) {
|
|
154
|
-
contentMetadata.multipartFields = contentMetadata.multipartFields || [];
|
|
155
|
-
contentMetadata.multipartFields.push({
|
|
156
|
-
fieldName,
|
|
157
|
-
fieldType: 'file',
|
|
158
|
-
...opts,
|
|
159
|
-
});
|
|
160
|
-
return configScope;
|
|
161
|
-
},
|
|
162
|
-
};
|
|
163
|
-
subInit(configScope);
|
|
164
|
-
}
|
|
165
|
-
return decorator;
|
|
166
|
-
};
|
|
167
|
-
/**
|
|
168
|
-
*
|
|
169
|
-
*/
|
|
170
|
-
decorator.UseType = (...type) => {
|
|
171
|
-
decoratorChain.push((meta) => {
|
|
172
|
-
meta.types = meta.types || [];
|
|
173
|
-
meta.types.push(...type);
|
|
174
|
-
});
|
|
175
|
-
return decorator;
|
|
176
|
-
};
|
|
177
|
-
return decorator;
|
|
178
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
const URL_PATTERN = /^(https?:\/\/.)[-a-zA-Z0-9@:%._+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_+.~#?&/=]*)$/i;
|
|
2
|
-
export function isUrlString(url) {
|
|
3
|
-
return URL_PATTERN.test(url);
|
|
4
|
-
}
|
|
5
|
-
export const isAbsoluteUrl = (urlString) => {
|
|
6
|
-
return !urlString.includes('://') && new URL(urlString, 'http://tempuri.org/').host !== 'tempuri.org';
|
|
7
|
-
};
|
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
var _a;
|
|
2
|
-
import { splitString, tokenize } from 'fast-tokenizer';
|
|
3
|
-
import isPlainObject from 'putil-isplainobject';
|
|
4
|
-
const nodeInspectCustom = Symbol.for('nodejs.util.inspect.custom');
|
|
5
|
-
const kLength = Symbol.for('kLength');
|
|
6
|
-
const pathComponentRegEx = /^([^/?#:@]+)(?:@([^/?#:]*))?(?:::(.*))?$/;
|
|
7
|
-
const decimalPattern = /^[+-]?\d+(\.\d+)?$/;
|
|
8
|
-
const booleanPattern = /^true|false$/;
|
|
9
|
-
/**
|
|
10
|
-
* @class OpraURLPath
|
|
11
|
-
*/
|
|
12
|
-
export class OpraURLPath {
|
|
13
|
-
constructor(...init) {
|
|
14
|
-
this[_a] = 0;
|
|
15
|
-
this._resolve(init.filter(x => x));
|
|
16
|
-
}
|
|
17
|
-
get length() {
|
|
18
|
-
return this[kLength];
|
|
19
|
-
}
|
|
20
|
-
slice(start, end) {
|
|
21
|
-
return new OpraURLPath(...[...this].slice(start, end));
|
|
22
|
-
}
|
|
23
|
-
resolve(...items) {
|
|
24
|
-
this._resolve(items);
|
|
25
|
-
return this;
|
|
26
|
-
}
|
|
27
|
-
join(...items) {
|
|
28
|
-
this._resolve(items, true);
|
|
29
|
-
return this;
|
|
30
|
-
}
|
|
31
|
-
isRelativeTo(basePath) {
|
|
32
|
-
basePath = basePath instanceof OpraURLPath ? basePath : new OpraURLPath(basePath);
|
|
33
|
-
let i;
|
|
34
|
-
for (i = 0; i < basePath.length; i++) {
|
|
35
|
-
if (String(this[i]) !== String(basePath[i]))
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
return true;
|
|
39
|
-
}
|
|
40
|
-
forEach(callback) {
|
|
41
|
-
let i = 0;
|
|
42
|
-
for (const item of this.values()) {
|
|
43
|
-
callback.call(this, item, i++, this);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
values() {
|
|
47
|
-
const arr = new Array(this.length);
|
|
48
|
-
for (let i = 0; i < this.length; i++)
|
|
49
|
-
arr[i] = this[i];
|
|
50
|
-
return arr.values();
|
|
51
|
-
}
|
|
52
|
-
toString() {
|
|
53
|
-
const v = Array.from(this).join('/');
|
|
54
|
-
return v ? '/' + v : '';
|
|
55
|
-
}
|
|
56
|
-
/* istanbul ignore next */
|
|
57
|
-
[(_a = kLength, nodeInspectCustom)]() {
|
|
58
|
-
return `(UrlPath [${this.toString()}])`;
|
|
59
|
-
}
|
|
60
|
-
[Symbol.iterator]() {
|
|
61
|
-
return this.values();
|
|
62
|
-
}
|
|
63
|
-
_resolve(items, join) {
|
|
64
|
-
let paths = (Array.isArray(items) ? items : [items]).map(item => {
|
|
65
|
-
if (typeof item === 'object' && !(item instanceof OpraURLPath || item instanceof OpraURLPathComponent)) {
|
|
66
|
-
item = new OpraURLPathComponent(item);
|
|
67
|
-
if (item.resource.includes('/')) {
|
|
68
|
-
const subPath = new OpraURLPath(item.resource);
|
|
69
|
-
subPath[subPath.length - 1].key = item.key;
|
|
70
|
-
return String(subPath);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
item = String(item);
|
|
74
|
-
// Remove url parts coming after path (query, hash parts)
|
|
75
|
-
if (item.includes('?'))
|
|
76
|
-
item = splitString(item, {
|
|
77
|
-
delimiters: '?',
|
|
78
|
-
quotes: true,
|
|
79
|
-
brackets: true,
|
|
80
|
-
keepBrackets: true,
|
|
81
|
-
keepQuotes: true,
|
|
82
|
-
})[0];
|
|
83
|
-
if (item.includes('#'))
|
|
84
|
-
item = splitString(item, {
|
|
85
|
-
delimiters: '#',
|
|
86
|
-
quotes: true,
|
|
87
|
-
brackets: true,
|
|
88
|
-
keepBrackets: true,
|
|
89
|
-
keepQuotes: true,
|
|
90
|
-
})[0];
|
|
91
|
-
return join ? removeLeadingSeparator(item) : item;
|
|
92
|
-
});
|
|
93
|
-
const oldLength = this.length;
|
|
94
|
-
let n = 0;
|
|
95
|
-
if (!join) {
|
|
96
|
-
for (n = paths.length - 1; n >= 0; n--) {
|
|
97
|
-
if (String(items[n]).startsWith('/'))
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
if (n > 0)
|
|
101
|
-
paths = paths.slice(n);
|
|
102
|
-
}
|
|
103
|
-
const newPath = paths[0]?.startsWith('/') ? [] : Array.from(this).map(String);
|
|
104
|
-
for (let i = 0; i < paths.length; i++) {
|
|
105
|
-
const pathTokenizer = tokenize(paths[i], { delimiters: '/', quotes: true, brackets: true });
|
|
106
|
-
for (const x of pathTokenizer) {
|
|
107
|
-
if (!x)
|
|
108
|
-
continue;
|
|
109
|
-
if (x.startsWith('.')) {
|
|
110
|
-
if (x === '.')
|
|
111
|
-
continue;
|
|
112
|
-
if (x === '..') {
|
|
113
|
-
newPath.pop();
|
|
114
|
-
continue;
|
|
115
|
-
}
|
|
116
|
-
throw new TypeError('Invalid path string');
|
|
117
|
-
}
|
|
118
|
-
newPath.push(x);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
for (let i = 0; i < newPath.length; i++) {
|
|
122
|
-
this[i] = OpraURLPathComponent.parse(newPath[i]);
|
|
123
|
-
}
|
|
124
|
-
for (let i = newPath.length; i < oldLength; i++) {
|
|
125
|
-
delete this[i];
|
|
126
|
-
}
|
|
127
|
-
this[kLength] = newPath.length;
|
|
128
|
-
}
|
|
129
|
-
static join(...items) {
|
|
130
|
-
const instance = new OpraURLPath();
|
|
131
|
-
instance.join(...items);
|
|
132
|
-
return instance;
|
|
133
|
-
}
|
|
134
|
-
static resolve(...items) {
|
|
135
|
-
return new OpraURLPath(...items);
|
|
136
|
-
}
|
|
137
|
-
static relative(source, basePath) {
|
|
138
|
-
source = source instanceof OpraURLPath ? source : new OpraURLPath(source);
|
|
139
|
-
basePath = basePath instanceof OpraURLPath ? basePath : new OpraURLPath(basePath);
|
|
140
|
-
let i;
|
|
141
|
-
for (i = 0; i < basePath.length; i++) {
|
|
142
|
-
if (String(source[i]) !== String(basePath[i]))
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
return new OpraURLPath(Array.from(source).slice(i).join('/'));
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
*
|
|
150
|
-
* @class OpraURLPathComponent
|
|
151
|
-
*/
|
|
152
|
-
export class OpraURLPathComponent {
|
|
153
|
-
constructor(init) {
|
|
154
|
-
this.resource = init.resource;
|
|
155
|
-
this.key = init.key;
|
|
156
|
-
this.args = init.args;
|
|
157
|
-
this.typeCast = init.typeCast;
|
|
158
|
-
}
|
|
159
|
-
toString() {
|
|
160
|
-
let out = encodeURIComponent(this.resource).replace(/%24/, '$');
|
|
161
|
-
if (this.key) {
|
|
162
|
-
if (typeof this.key === 'object' && isPlainObject(this.key)) {
|
|
163
|
-
const arr = [];
|
|
164
|
-
for (const k of Object.keys(this.key)) {
|
|
165
|
-
let v = this.key[k];
|
|
166
|
-
if (typeof v === 'number' || typeof v === 'boolean')
|
|
167
|
-
v = String(v);
|
|
168
|
-
else
|
|
169
|
-
v = '"' + encodeURIComponent(String(v)) + '"';
|
|
170
|
-
arr.push(encodeURIComponent(k) + '=' + v);
|
|
171
|
-
}
|
|
172
|
-
out += '@' + arr.join(';');
|
|
173
|
-
}
|
|
174
|
-
else
|
|
175
|
-
out += '@' + encodeURIComponent(String(this.key));
|
|
176
|
-
}
|
|
177
|
-
if (this.args) {
|
|
178
|
-
const arr = [];
|
|
179
|
-
for (const k of Object.keys(this.args)) {
|
|
180
|
-
arr.push(encodeURIComponent(k) + '=' + encodeURIComponent(String(this.args[k])));
|
|
181
|
-
}
|
|
182
|
-
out += '(' + arr.join(';') + ')';
|
|
183
|
-
}
|
|
184
|
-
if (this.typeCast)
|
|
185
|
-
out += '::' + encodeURIComponent(this.typeCast);
|
|
186
|
-
return out;
|
|
187
|
-
}
|
|
188
|
-
/* istanbul ignore next */
|
|
189
|
-
[nodeInspectCustom]() {
|
|
190
|
-
return this.toString();
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* Factory method.
|
|
194
|
-
* @param input
|
|
195
|
-
*/
|
|
196
|
-
static parse(input) {
|
|
197
|
-
const m = pathComponentRegEx.exec(input);
|
|
198
|
-
if (!m)
|
|
199
|
-
throw Object.assign(new TypeError('Invalid Opra URL'), {
|
|
200
|
-
code: 'ERR_INVALID_OPRA_URL',
|
|
201
|
-
input,
|
|
202
|
-
});
|
|
203
|
-
let key;
|
|
204
|
-
if (m[2]) {
|
|
205
|
-
const s = decodeURIComponent(m[2]);
|
|
206
|
-
const b = splitString(s, { delimiters: ';', quotes: true, escape: false, keepQuotes: true, keepBrackets: true });
|
|
207
|
-
for (const n of b) {
|
|
208
|
-
const c = splitString(n, {
|
|
209
|
-
delimiters: '=',
|
|
210
|
-
quotes: true,
|
|
211
|
-
escape: false,
|
|
212
|
-
keepQuotes: true,
|
|
213
|
-
keepBrackets: true,
|
|
214
|
-
});
|
|
215
|
-
if ((b.length > 1 && c.length < 2) ||
|
|
216
|
-
(key && c.length >= 2 && typeof key !== 'object') ||
|
|
217
|
-
(c.length < 2 && typeof key === 'object'))
|
|
218
|
-
throw Object.assign(new TypeError('Invalid Opra URL. name:value pair required for multiple key format'), {
|
|
219
|
-
pathComponent: input,
|
|
220
|
-
code: 'ERR_INVALID_OPRA_URL',
|
|
221
|
-
});
|
|
222
|
-
if (c.length >= 2) {
|
|
223
|
-
key = key || {};
|
|
224
|
-
const k = c.shift() || '';
|
|
225
|
-
let v = c.join('=');
|
|
226
|
-
if (decimalPattern.test(v))
|
|
227
|
-
v = Number(v);
|
|
228
|
-
else if (booleanPattern.test(v))
|
|
229
|
-
v = Boolean(v);
|
|
230
|
-
else if (v.startsWith('"') && v.endsWith('"'))
|
|
231
|
-
v = v.substring(1, v.length - 1);
|
|
232
|
-
else if (v.startsWith("'") && v.endsWith("'"))
|
|
233
|
-
v = v.substring(1, v.length - 1);
|
|
234
|
-
key[k] = v;
|
|
235
|
-
}
|
|
236
|
-
else {
|
|
237
|
-
if (decimalPattern.test(c[0]))
|
|
238
|
-
key = Number(c[0]);
|
|
239
|
-
else if (booleanPattern.test(c[0]))
|
|
240
|
-
key = Boolean(c[0]);
|
|
241
|
-
else
|
|
242
|
-
key = c[0];
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
return new OpraURLPathComponent({
|
|
246
|
-
resource: decodeURIComponent(m[1]),
|
|
247
|
-
key,
|
|
248
|
-
typeCast: m[3] ? decodeURIComponent(m[3]) : undefined,
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
return new OpraURLPathComponent({
|
|
252
|
-
resource: decodeURIComponent(m[1]),
|
|
253
|
-
typeCast: m[3] ? decodeURIComponent(m[3]) : undefined,
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
function removeLeadingSeparator(s) {
|
|
258
|
-
const m = /^\/*(.*)/.exec(s);
|
|
259
|
-
return m?.[1] || s;
|
|
260
|
-
}
|
package/esm/http/opra-url.js
DELETED
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
var _a;
|
|
2
|
-
import { splitString, tokenize } from 'fast-tokenizer';
|
|
3
|
-
import { OpraURLPath } from './opra-url-path.js';
|
|
4
|
-
const nodeInspectCustom = Symbol.for('nodejs.util.inspect.custom');
|
|
5
|
-
const urlRegEx = /^(?:((?:[A-Z][A-Z+-.]+:)+)\/\/([^/?]+))?(.*)?$/i;
|
|
6
|
-
const schemeRegEx = /^([A-Z][A-Z+-.]+:?)+$/i;
|
|
7
|
-
const hostRegEx = /^([^/:]+)(?::(\d+))?$/;
|
|
8
|
-
const hostnameRegEx = /^([^/:]+)$/;
|
|
9
|
-
const kContext = Symbol.for('kContext');
|
|
10
|
-
const kPath = Symbol.for('kPath');
|
|
11
|
-
const kSearchParams = Symbol.for('kSearchParams');
|
|
12
|
-
export class OpraURL {
|
|
13
|
-
constructor(input, base) {
|
|
14
|
-
this[_a] = {
|
|
15
|
-
protocol: '',
|
|
16
|
-
username: '',
|
|
17
|
-
hostname: '',
|
|
18
|
-
port: '',
|
|
19
|
-
hash: '',
|
|
20
|
-
password: '',
|
|
21
|
-
};
|
|
22
|
-
this[kSearchParams] = new URLSearchParams();
|
|
23
|
-
this[kPath] = new OpraURLPath();
|
|
24
|
-
if (input)
|
|
25
|
-
this._parse(String(input));
|
|
26
|
-
if (base && !this.host) {
|
|
27
|
-
const baseUrl = base instanceof OpraURL ? base : new OpraURL(base);
|
|
28
|
-
this[kContext].protocol = baseUrl.protocol;
|
|
29
|
-
this[kContext].hostname = baseUrl.hostname;
|
|
30
|
-
this[kContext].username = baseUrl.username;
|
|
31
|
-
this[kContext].password = baseUrl.password;
|
|
32
|
-
this[kContext].port = baseUrl.port;
|
|
33
|
-
this.path = OpraURLPath.join(baseUrl.path, this.path);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
get address() {
|
|
37
|
-
if (this[kContext].address == null) {
|
|
38
|
-
let address = '';
|
|
39
|
-
if (this[kContext].hostname) {
|
|
40
|
-
address +=
|
|
41
|
-
(this[kContext].protocol || 'http:') +
|
|
42
|
-
'//' +
|
|
43
|
-
(this[kContext].username || this[kContext].password
|
|
44
|
-
? (this[kContext].username ? encodeURIComponent(this[kContext].username) : '') +
|
|
45
|
-
(this[kContext].password ? ':' + encodeURIComponent(this[kContext].password) : '') +
|
|
46
|
-
'@'
|
|
47
|
-
: '') +
|
|
48
|
-
this.host;
|
|
49
|
-
}
|
|
50
|
-
this[kContext].address = address + (this.pathname !== '/' ? this.pathname : '');
|
|
51
|
-
}
|
|
52
|
-
return this[kContext].address;
|
|
53
|
-
}
|
|
54
|
-
get host() {
|
|
55
|
-
return this.hostname ? this.hostname + (this.port ? ':' + this.port : '') : '';
|
|
56
|
-
}
|
|
57
|
-
set host(v) {
|
|
58
|
-
if (v) {
|
|
59
|
-
const m = hostRegEx.exec(v);
|
|
60
|
-
if (!m)
|
|
61
|
-
throw Object.assign(new TypeError('Invalid host'), {
|
|
62
|
-
host: v,
|
|
63
|
-
code: 'ERR_INVALID_URL',
|
|
64
|
-
});
|
|
65
|
-
this.hostname = m[1];
|
|
66
|
-
this.port = m[2] || '';
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
this.hostname = '';
|
|
70
|
-
this.port = '';
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
get hostname() {
|
|
74
|
-
return this[kContext].hostname;
|
|
75
|
-
}
|
|
76
|
-
set hostname(v) {
|
|
77
|
-
if (v) {
|
|
78
|
-
if (!hostnameRegEx.test(v))
|
|
79
|
-
throw Object.assign(new TypeError('Invalid hostname'), {
|
|
80
|
-
hostname: v,
|
|
81
|
-
code: 'ERR_INVALID_URL',
|
|
82
|
-
});
|
|
83
|
-
this[kContext].hostname = v;
|
|
84
|
-
}
|
|
85
|
-
else
|
|
86
|
-
this[kContext].hostname = '';
|
|
87
|
-
this.invalidate();
|
|
88
|
-
}
|
|
89
|
-
get href() {
|
|
90
|
-
return this.address + this.search + this.hash;
|
|
91
|
-
}
|
|
92
|
-
get password() {
|
|
93
|
-
return this[kContext].password;
|
|
94
|
-
}
|
|
95
|
-
set password(v) {
|
|
96
|
-
this[kContext].password = v ?? '';
|
|
97
|
-
this.invalidate();
|
|
98
|
-
}
|
|
99
|
-
get port() {
|
|
100
|
-
return this[kContext].port;
|
|
101
|
-
}
|
|
102
|
-
set port(value) {
|
|
103
|
-
if (value) {
|
|
104
|
-
// noinspection SuspiciousTypeOfGuard
|
|
105
|
-
const v = typeof value === 'number' ? value : parseInt(value, 10);
|
|
106
|
-
if (isNaN(v) || v < 1 || v > 65535 || v % 1 > 0)
|
|
107
|
-
throw Object.assign(new TypeError(`Invalid port number (${value})`), {
|
|
108
|
-
hostname: v,
|
|
109
|
-
code: 'ERR_INVALID_URL',
|
|
110
|
-
});
|
|
111
|
-
this[kContext].port = String(v);
|
|
112
|
-
}
|
|
113
|
-
else
|
|
114
|
-
this[kContext].port = '';
|
|
115
|
-
this.invalidate();
|
|
116
|
-
}
|
|
117
|
-
get protocol() {
|
|
118
|
-
return this[kContext].protocol;
|
|
119
|
-
}
|
|
120
|
-
set protocol(v) {
|
|
121
|
-
if (v) {
|
|
122
|
-
if (!schemeRegEx.test(v))
|
|
123
|
-
throw Object.assign(new TypeError('Invalid protocol'), {
|
|
124
|
-
protocol: v,
|
|
125
|
-
code: 'ERR_INVALID_URL',
|
|
126
|
-
});
|
|
127
|
-
this[kContext].protocol = v + (v.endsWith(':') ? '' : ':');
|
|
128
|
-
}
|
|
129
|
-
else
|
|
130
|
-
this[kContext].protocol = '';
|
|
131
|
-
this.invalidate();
|
|
132
|
-
}
|
|
133
|
-
get username() {
|
|
134
|
-
return this[kContext].username;
|
|
135
|
-
}
|
|
136
|
-
set username(v) {
|
|
137
|
-
this[kContext].username = v ?? '';
|
|
138
|
-
this.invalidate();
|
|
139
|
-
}
|
|
140
|
-
get origin() {
|
|
141
|
-
return this.hostname ? this.protocol + '//' + this.hostname : '';
|
|
142
|
-
}
|
|
143
|
-
get path() {
|
|
144
|
-
return this[kPath];
|
|
145
|
-
}
|
|
146
|
-
set path(path) {
|
|
147
|
-
// noinspection SuspiciousTypeOfGuard
|
|
148
|
-
this[kPath] = path instanceof OpraURLPath ? path : new OpraURLPath(path);
|
|
149
|
-
this[kContext].pathname = String(this[kPath]);
|
|
150
|
-
this.invalidate();
|
|
151
|
-
}
|
|
152
|
-
get pathname() {
|
|
153
|
-
if (this[kContext].pathname == null)
|
|
154
|
-
this[kContext].pathname = this.path.toString() || '/';
|
|
155
|
-
return this[kContext].pathname;
|
|
156
|
-
}
|
|
157
|
-
set pathname(v) {
|
|
158
|
-
this[kPath] = new OpraURLPath(v);
|
|
159
|
-
this.invalidate();
|
|
160
|
-
}
|
|
161
|
-
get hash() {
|
|
162
|
-
return this[kContext].hash;
|
|
163
|
-
}
|
|
164
|
-
set hash(v) {
|
|
165
|
-
this[kContext].hash = v ? (v.startsWith('#') ? v : '#' + v) : '';
|
|
166
|
-
}
|
|
167
|
-
get search() {
|
|
168
|
-
const s = this[kSearchParams].toString();
|
|
169
|
-
return s ? '?' + s : '';
|
|
170
|
-
}
|
|
171
|
-
set search(v) {
|
|
172
|
-
this[kSearchParams] = new URLSearchParams(v);
|
|
173
|
-
}
|
|
174
|
-
get searchParams() {
|
|
175
|
-
return this[kSearchParams];
|
|
176
|
-
}
|
|
177
|
-
set setSearchParams(v) {
|
|
178
|
-
this[kSearchParams] = v;
|
|
179
|
-
}
|
|
180
|
-
invalidate() {
|
|
181
|
-
this[kContext].address = undefined;
|
|
182
|
-
this[kContext].pathname = undefined;
|
|
183
|
-
}
|
|
184
|
-
join(...items) {
|
|
185
|
-
this.path = this.path.join(...items);
|
|
186
|
-
this.invalidate();
|
|
187
|
-
return this;
|
|
188
|
-
}
|
|
189
|
-
resolve(...items) {
|
|
190
|
-
this.path = this.path.resolve(...items);
|
|
191
|
-
this.invalidate();
|
|
192
|
-
return this;
|
|
193
|
-
}
|
|
194
|
-
toString() {
|
|
195
|
-
return this.href;
|
|
196
|
-
}
|
|
197
|
-
_parse(input) {
|
|
198
|
-
const m = urlRegEx.exec(input);
|
|
199
|
-
if (!m)
|
|
200
|
-
throw Object.assign(new TypeError('Invalid URL'), {
|
|
201
|
-
input,
|
|
202
|
-
code: 'ERR_INVALID_URL',
|
|
203
|
-
});
|
|
204
|
-
this.protocol = m[1];
|
|
205
|
-
const isAbsolute = !!m[2];
|
|
206
|
-
if (isAbsolute) {
|
|
207
|
-
let tokens = splitString(m[2], { delimiters: '@' });
|
|
208
|
-
if (tokens.length > 1) {
|
|
209
|
-
this.host = tokens[1];
|
|
210
|
-
tokens = splitString(tokens[0], { delimiters: ':' });
|
|
211
|
-
this.username = tokens[0] ? decodeURIComponent(tokens[0]) : '';
|
|
212
|
-
this.password = tokens[1] ? decodeURIComponent(tokens[1]) : '';
|
|
213
|
-
}
|
|
214
|
-
else
|
|
215
|
-
this.host = tokens[0];
|
|
216
|
-
}
|
|
217
|
-
else {
|
|
218
|
-
this.host = '';
|
|
219
|
-
this.username = '';
|
|
220
|
-
this.password = '';
|
|
221
|
-
}
|
|
222
|
-
input = m[3] || '';
|
|
223
|
-
let tokenizer = tokenize(input, { delimiters: '#', quotes: true, brackets: true });
|
|
224
|
-
input = tokenizer.next() || '';
|
|
225
|
-
this.hash = tokenizer.join('#');
|
|
226
|
-
tokenizer = tokenize(input, { delimiters: '?', quotes: true, brackets: true });
|
|
227
|
-
this.path = new OpraURLPath(tokenizer.next());
|
|
228
|
-
this.search = tokenizer.join('&');
|
|
229
|
-
}
|
|
230
|
-
/* istanbul ignore next */
|
|
231
|
-
[(_a = kContext, nodeInspectCustom)]() {
|
|
232
|
-
// this._update();
|
|
233
|
-
return {
|
|
234
|
-
protocol: this.protocol,
|
|
235
|
-
username: this.username,
|
|
236
|
-
password: this.password,
|
|
237
|
-
host: this.host,
|
|
238
|
-
hostname: this.hostname,
|
|
239
|
-
origin: this.origin,
|
|
240
|
-
path: this.path,
|
|
241
|
-
pathname: this.pathname,
|
|
242
|
-
search: this.search,
|
|
243
|
-
hash: this.hash,
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
OpraURL.kContext = kContext;
|
|
248
|
-
OpraURL.kPath = kPath;
|
|
249
|
-
OpraURL.kParams = kSearchParams;
|