tsoa
This commit is contained in:
11
node_modules/@hapi/call/LICENSE.md
generated
vendored
Executable file
11
node_modules/@hapi/call/LICENSE.md
generated
vendored
Executable file
@@ -0,0 +1,11 @@
|
||||
Copyright (c) 2014-2022, Project contributors
|
||||
Copyright (c) 2014-2020, Sideway Inc
|
||||
Copyright (c) 2014, Walmart.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* The names of any contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS OFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
17
node_modules/@hapi/call/README.md
generated
vendored
Executable file
17
node_modules/@hapi/call/README.md
generated
vendored
Executable file
@@ -0,0 +1,17 @@
|
||||
<a href="https://hapi.dev"><img src="https://raw.githubusercontent.com/hapijs/assets/master/images/family.png" width="180px" align="right" /></a>
|
||||
|
||||
# @hapi/call
|
||||
|
||||
#### Simple HTTP Router.
|
||||
|
||||
**call** is part of the **hapi** ecosystem and was designed to work seamlessly with the [hapi web framework](https://hapi.dev) and its other components (but works great on its own or with other frameworks). If you are using a different web framework and find this module useful, check out [hapi](https://hapi.dev) – they work even better together.
|
||||
|
||||
### Visit the [hapi.dev](https://hapi.dev) Developer Portal for tutorials, documentation, and support
|
||||
|
||||
## Useful resources
|
||||
|
||||
- [Documentation and API](https://hapi.dev/family/call/)
|
||||
- [Version status](https://hapi.dev/resources/status/#call) (builds, dependencies, node versions, licenses, eol)
|
||||
- [Changelog](https://hapi.dev/family/call/changelog/)
|
||||
- [Project policies](https://hapi.dev/policies/)
|
||||
- [Free and commercial support options](https://hapi.dev/support/)
|
||||
120
node_modules/@hapi/call/lib/decode.js
generated
vendored
Normal file
120
node_modules/@hapi/call/lib/decode.js
generated
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
'use strict';
|
||||
|
||||
// Adapted from:
|
||||
// Copyright (c) 2017-2019 Justin Ridgewell, MIT Licensed, https://github.com/jridgewell/safe-decode-string-component
|
||||
// Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>, MIT Licensed, http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
|
||||
|
||||
|
||||
const internals = {};
|
||||
|
||||
|
||||
exports.decode = function (string) {
|
||||
|
||||
let percentPos = string.indexOf('%');
|
||||
if (percentPos === -1) {
|
||||
return string;
|
||||
}
|
||||
|
||||
let decoded = '';
|
||||
let last = 0;
|
||||
let codepoint = 0;
|
||||
let startOfOctets = percentPos;
|
||||
let state = internals.utf8.accept;
|
||||
|
||||
while (percentPos > -1 &&
|
||||
percentPos < string.length) {
|
||||
|
||||
const high = internals.resolveHex(string[percentPos + 1], 4);
|
||||
const low = internals.resolveHex(string[percentPos + 2], 0);
|
||||
const byte = high | low;
|
||||
const type = internals.utf8.data[byte];
|
||||
state = internals.utf8.data[256 + state + type];
|
||||
codepoint = (codepoint << 6) | (byte & internals.utf8.data[364 + type]);
|
||||
|
||||
if (state === internals.utf8.accept) {
|
||||
decoded += string.slice(last, startOfOctets);
|
||||
decoded += codepoint <= 0xFFFF
|
||||
? String.fromCharCode(codepoint)
|
||||
: String.fromCharCode(0xD7C0 + (codepoint >> 10), 0xDC00 + (codepoint & 0x3FF));
|
||||
|
||||
codepoint = 0;
|
||||
last = percentPos + 3;
|
||||
percentPos = string.indexOf('%', last);
|
||||
startOfOctets = percentPos;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (state === internals.utf8.reject) {
|
||||
return null;
|
||||
}
|
||||
|
||||
percentPos += 3;
|
||||
|
||||
if (percentPos >= string.length ||
|
||||
string[percentPos] !== '%') {
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return decoded + string.slice(last);
|
||||
};
|
||||
|
||||
|
||||
internals.resolveHex = function (char, shift) {
|
||||
|
||||
const i = internals.hex[char];
|
||||
return i === undefined ? 255 : i << shift;
|
||||
};
|
||||
|
||||
|
||||
internals.hex = {
|
||||
'0': 0, '1': 1, '2': 2, '3': 3, '4': 4,
|
||||
'5': 5, '6': 6, '7': 7, '8': 8, '9': 9,
|
||||
'a': 10, 'A': 10, 'b': 11, 'B': 11, 'c': 12,
|
||||
'C': 12, 'd': 13, 'D': 13, 'e': 14, 'E': 14,
|
||||
'f': 15, 'F': 15
|
||||
};
|
||||
|
||||
|
||||
internals.utf8 = {
|
||||
accept: 12,
|
||||
reject: 0,
|
||||
data: [
|
||||
|
||||
// Maps bytes to character to a transition
|
||||
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 7,
|
||||
10, 9, 9, 9, 11, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
|
||||
// Maps a state to a new state when adding a transition
|
||||
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
12, 0, 0, 0, 0, 24, 36, 48, 60, 72, 84, 96,
|
||||
0, 12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 24, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 48, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
// Maps the current transition to a mask that needs to apply to the byte
|
||||
|
||||
0x7F, 0x3F, 0x3F, 0x3F, 0x00, 0x1F, 0x0F, 0x0F, 0x0F, 0x07, 0x07, 0x07
|
||||
]
|
||||
};
|
||||
385
node_modules/@hapi/call/lib/index.js
generated
vendored
Executable file
385
node_modules/@hapi/call/lib/index.js
generated
vendored
Executable file
@@ -0,0 +1,385 @@
|
||||
'use strict';
|
||||
|
||||
const Boom = require('@hapi/boom');
|
||||
const Hoek = require('@hapi/hoek');
|
||||
|
||||
const Decode = require('./decode');
|
||||
const Regex = require('./regex');
|
||||
const Segment = require('./segment');
|
||||
|
||||
|
||||
const internals = {
|
||||
pathRegex: Regex.generate(),
|
||||
defaults: {
|
||||
isCaseSensitive: true
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
exports.Router = internals.Router = function (options) {
|
||||
|
||||
this.settings = Hoek.applyToDefaults(internals.defaults, options || {});
|
||||
|
||||
this.routes = new Map(); // Key: HTTP method or * for catch-all, value: sorted array of routes
|
||||
this.ids = new Map(); // Key: route id, value: record
|
||||
this.vhosts = null; // Map where Key: hostname, value: see this.routes
|
||||
|
||||
this.specials = {
|
||||
badRequest: null,
|
||||
notFound: null,
|
||||
options: null
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
internals.Router.prototype.add = function (config, route) {
|
||||
|
||||
const method = config.method.toLowerCase();
|
||||
|
||||
const vhost = config.vhost || '*';
|
||||
if (vhost !== '*') {
|
||||
this.vhosts = this.vhosts ?? new Map();
|
||||
if (!this.vhosts.has(vhost)) {
|
||||
this.vhosts.set(vhost, new Map());
|
||||
}
|
||||
}
|
||||
|
||||
const table = vhost === '*' ? this.routes : this.vhosts.get(vhost);
|
||||
if (!table.has(method)) {
|
||||
table.set(method, { routes: [], router: new Segment() });
|
||||
}
|
||||
|
||||
const analysis = config.analysis ?? this.analyze(config.path);
|
||||
const record = {
|
||||
path: config.path,
|
||||
route: route || config.path,
|
||||
segments: analysis.segments,
|
||||
params: analysis.params,
|
||||
fingerprint: analysis.fingerprint,
|
||||
settings: this.settings
|
||||
};
|
||||
|
||||
// Add route
|
||||
|
||||
const map = table.get(method);
|
||||
map.router.add(analysis.segments, record);
|
||||
map.routes.push(record);
|
||||
map.routes.sort(internals.sort);
|
||||
|
||||
const last = record.segments[record.segments.length - 1];
|
||||
if (last.empty) {
|
||||
map.router.add(analysis.segments.slice(0, -1), record);
|
||||
}
|
||||
|
||||
if (config.id) {
|
||||
Hoek.assert(!this.ids.has(config.id), 'Route id', config.id, 'for path', config.path, 'conflicts with existing path', this.ids.has(config.id) && this.ids.get(config.id).path);
|
||||
this.ids.set(config.id, record);
|
||||
}
|
||||
|
||||
return record;
|
||||
};
|
||||
|
||||
|
||||
internals.Router.prototype.special = function (type, route) {
|
||||
|
||||
Hoek.assert(Object.keys(this.specials).indexOf(type) !== -1, 'Unknown special route type:', type);
|
||||
|
||||
this.specials[type] = { route };
|
||||
};
|
||||
|
||||
|
||||
internals.Router.prototype.route = function (method, path, hostname) {
|
||||
|
||||
const segments = path.length === 1 ? [''] : path.split('/').slice(1);
|
||||
|
||||
const vhost = this.vhosts && hostname && this.vhosts.get(hostname);
|
||||
const route = vhost && this._lookup(path, segments, vhost, method) ||
|
||||
this._lookup(path, segments, this.routes, method) ||
|
||||
method === 'head' && vhost && this._lookup(path, segments, vhost, 'get') ||
|
||||
method === 'head' && this._lookup(path, segments, this.routes, 'get') ||
|
||||
method === 'options' && this.specials.options ||
|
||||
vhost && this._lookup(path, segments, vhost, '*') ||
|
||||
this._lookup(path, segments, this.routes, '*') ||
|
||||
this.specials.notFound || Boom.notFound();
|
||||
|
||||
return route;
|
||||
};
|
||||
|
||||
|
||||
internals.Router.prototype._lookup = function (path, segments, table, method) {
|
||||
|
||||
const set = table.get(method);
|
||||
if (!set) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const match = set.router.lookup(path, segments, this.settings);
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const assignments = {};
|
||||
const array = [];
|
||||
for (let i = 0; i < match.array.length; ++i) {
|
||||
const name = match.record.params[i];
|
||||
const value = Decode.decode(match.array[i]);
|
||||
if (value === null) {
|
||||
return this.specials.badRequest ?? Boom.badRequest('Invalid request path');
|
||||
}
|
||||
|
||||
if (assignments[name] !== undefined) {
|
||||
assignments[name] = assignments[name] + '/' + value;
|
||||
}
|
||||
else {
|
||||
assignments[name] = value;
|
||||
}
|
||||
|
||||
if (i + 1 === match.array.length || // Only include the last segment of a multi-segment param
|
||||
name !== match.record.params[i + 1]) {
|
||||
|
||||
array.push(assignments[name]);
|
||||
}
|
||||
}
|
||||
|
||||
return { params: assignments, paramsArray: array, route: match.record.route };
|
||||
};
|
||||
|
||||
|
||||
internals.Router.prototype.normalize = function (path) {
|
||||
|
||||
if (path &&
|
||||
path.indexOf('%') !== -1) {
|
||||
|
||||
// Uppercase %encoded values
|
||||
|
||||
const uppercase = path.replace(/%[0-9a-fA-F][0-9a-fA-F]/g, (encoded) => encoded.toUpperCase());
|
||||
|
||||
// Decode non-reserved path characters: a-z A-Z 0-9 _!$&'()*+,;=:@-.~
|
||||
// ! (%21) $ (%24) & (%26) ' (%27) ( (%28) ) (%29) * (%2A) + (%2B) , (%2C) - (%2D) . (%2E)
|
||||
// 0-9 (%30-39) : (%3A) ; (%3B) = (%3D)
|
||||
// @ (%40) A-Z (%41-5A) _ (%5F) a-z (%61-7A) ~ (%7E)
|
||||
|
||||
const decoded = uppercase.replace(/%(?:2[146-9A-E]|3[\dABD]|4[\dA-F]|5[\dAF]|6[1-9A-F]|7[\dAE])/g, (encoded) => String.fromCharCode(parseInt(encoded.substring(1), 16)));
|
||||
|
||||
path = decoded;
|
||||
}
|
||||
|
||||
// Normalize path segments
|
||||
|
||||
if (path &&
|
||||
(path.indexOf('/.') !== -1 || path[0] === '.')) {
|
||||
|
||||
const hasLeadingSlash = path[0] === '/';
|
||||
const segments = path.split('/');
|
||||
const normalized = [];
|
||||
let segment;
|
||||
|
||||
for (let i = 0; i < segments.length; ++i) {
|
||||
segment = segments[i];
|
||||
if (segment === '..') {
|
||||
normalized.pop();
|
||||
}
|
||||
else if (segment !== '.') {
|
||||
normalized.push(segment);
|
||||
}
|
||||
}
|
||||
|
||||
if (segment === '.' ||
|
||||
segment === '..') { // Add trailing slash when needed
|
||||
|
||||
normalized.push('');
|
||||
}
|
||||
|
||||
path = normalized.join('/');
|
||||
|
||||
if (path[0] !== '/' &&
|
||||
hasLeadingSlash) {
|
||||
|
||||
path = '/' + path;
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
};
|
||||
|
||||
|
||||
internals.Router.prototype.analyze = function (path) {
|
||||
|
||||
Hoek.assert(internals.pathRegex.validatePath.test(path), 'Invalid path:', path);
|
||||
Hoek.assert(!internals.pathRegex.validatePathEncoded.test(path), 'Path cannot contain encoded non-reserved path characters:', path);
|
||||
|
||||
const pathParts = path.split('/');
|
||||
const segments = [];
|
||||
const params = [];
|
||||
const fingers = [];
|
||||
|
||||
for (let i = 1; i < pathParts.length; ++i) { // Skip first empty segment
|
||||
let segment = pathParts[i];
|
||||
|
||||
// Literal
|
||||
|
||||
if (segment.indexOf('{') === -1) {
|
||||
segment = this.settings.isCaseSensitive ? segment : segment.toLowerCase();
|
||||
fingers.push(segment);
|
||||
segments.push({ literal: segment });
|
||||
continue;
|
||||
}
|
||||
|
||||
// Parameter
|
||||
|
||||
const parts = internals.parseParams(segment);
|
||||
if (parts.length === 1) {
|
||||
|
||||
// Simple parameter
|
||||
|
||||
const item = parts[0];
|
||||
Hoek.assert(params.indexOf(item.name) === -1, 'Cannot repeat the same parameter name:', item.name, 'in:', path);
|
||||
params.push(item.name);
|
||||
|
||||
if (item.wildcard) {
|
||||
if (item.count) {
|
||||
for (let j = 0; j < item.count; ++j) {
|
||||
fingers.push('?');
|
||||
segments.push({});
|
||||
if (j) {
|
||||
params.push(item.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
fingers.push('#');
|
||||
segments.push({ wildcard: true });
|
||||
}
|
||||
}
|
||||
else {
|
||||
fingers.push('?');
|
||||
segments.push({ empty: item.empty });
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
// Mixed parameter
|
||||
|
||||
const seg = {
|
||||
length: parts.length,
|
||||
first: typeof parts[0] !== 'string',
|
||||
segments: []
|
||||
};
|
||||
|
||||
let finger = '';
|
||||
let regex = '^';
|
||||
for (let j = 0; j < parts.length; ++j) {
|
||||
const part = parts[j];
|
||||
if (typeof part === 'string') {
|
||||
finger = finger + part;
|
||||
regex = regex + Hoek.escapeRegex(part);
|
||||
seg.segments.push(part);
|
||||
}
|
||||
else {
|
||||
Hoek.assert(params.indexOf(part.name) === -1, 'Cannot repeat the same parameter name:', part.name, 'in:', path);
|
||||
params.push(part.name);
|
||||
|
||||
finger = finger + '?';
|
||||
regex = regex + '(.' + (part.empty ? '*' : '+') + ')';
|
||||
}
|
||||
}
|
||||
|
||||
seg.mixed = new RegExp(regex + '$', !this.settings.isCaseSensitive ? 'i' : '');
|
||||
fingers.push(finger);
|
||||
segments.push(seg);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
segments,
|
||||
fingerprint: '/' + fingers.join('/'),
|
||||
params
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
internals.parseParams = function (segment) {
|
||||
|
||||
const parts = [];
|
||||
segment.replace(internals.pathRegex.parseParam, ($0, literal, name, wildcard, count, empty) => {
|
||||
|
||||
if (literal) {
|
||||
parts.push(literal);
|
||||
}
|
||||
else {
|
||||
parts.push({
|
||||
name,
|
||||
wildcard: !!wildcard,
|
||||
count: count && parseInt(count, 10),
|
||||
empty: !!empty
|
||||
});
|
||||
}
|
||||
|
||||
return '';
|
||||
});
|
||||
|
||||
return parts;
|
||||
};
|
||||
|
||||
|
||||
internals.Router.prototype.table = function (host) {
|
||||
|
||||
const result = [];
|
||||
const collect = (table) => {
|
||||
|
||||
if (!table) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const map of table.values()) {
|
||||
for (const record of map.routes) {
|
||||
result.push(record.route);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (this.vhosts) {
|
||||
const vhosts = host ? [].concat(host) : [...this.vhosts.keys()];
|
||||
for (const vhost of vhosts) {
|
||||
collect(this.vhosts.get(vhost));
|
||||
}
|
||||
}
|
||||
|
||||
collect(this.routes);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
internals.sort = function (a, b) {
|
||||
|
||||
const aFirst = -1;
|
||||
const bFirst = 1;
|
||||
|
||||
const as = a.segments;
|
||||
const bs = b.segments;
|
||||
|
||||
if (as.length !== bs.length) {
|
||||
return as.length > bs.length ? bFirst : aFirst;
|
||||
}
|
||||
|
||||
for (let i = 0; ; ++i) {
|
||||
if (as[i].literal) {
|
||||
if (bs[i].literal) {
|
||||
if (as[i].literal === bs[i].literal) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return as[i].literal > bs[i].literal ? bFirst : aFirst;
|
||||
}
|
||||
|
||||
return aFirst;
|
||||
}
|
||||
|
||||
if (bs[i].literal) {
|
||||
return bFirst;
|
||||
}
|
||||
|
||||
return as[i].wildcard ? bFirst : aFirst;
|
||||
}
|
||||
};
|
||||
47
node_modules/@hapi/call/lib/regex.js
generated
vendored
Executable file
47
node_modules/@hapi/call/lib/regex.js
generated
vendored
Executable file
@@ -0,0 +1,47 @@
|
||||
'use strict';
|
||||
|
||||
const internals = {};
|
||||
|
||||
|
||||
exports.generate = function () {
|
||||
|
||||
/*
|
||||
/path/{param}/path/{param?}
|
||||
/path/{param*2}/path
|
||||
/path/{param*2}
|
||||
/path/x{param}x
|
||||
/{param*}
|
||||
*/
|
||||
|
||||
const empty = '(?:^\\/$)';
|
||||
|
||||
const legalChars = '[\\w\\!\\$&\'\\(\\)\\*\\+\\,;\\=\\:@\\-\\.~]';
|
||||
const encoded = '%[A-F0-9]{2}';
|
||||
|
||||
const literalChar = '(?:' + legalChars + '|' + encoded + ')';
|
||||
const literal = literalChar + '+';
|
||||
const literalOptional = literalChar + '*';
|
||||
|
||||
const midParam = '(?:\\{\\w+(?:\\*[1-9]\\d*)?\\})'; // {p}, {p*2}
|
||||
const endParam = '(?:\\/(?:\\{\\w+(?:(?:\\*(?:[1-9]\\d*)?)|(?:\\?))?\\})?)?'; // {p}, {p*2}, {p*}, {p?}
|
||||
|
||||
const partialParam = '(?:\\{\\w+\\??\\})'; // {p}, {p?}
|
||||
const mixedParam = '(?:(?:' + literal + partialParam + ')+' + literalOptional + ')|(?:' + partialParam + '(?:' + literal + partialParam + ')+' + literalOptional + ')|(?:' + partialParam + literal + ')';
|
||||
|
||||
const segmentContent = '(?:' + literal + '|' + midParam + '|' + mixedParam + ')';
|
||||
const segment = '\\/' + segmentContent;
|
||||
const segments = '(?:' + segment + ')*';
|
||||
|
||||
const path = '(?:^' + segments + endParam + '$)';
|
||||
|
||||
// 1:literal 2:name 3:* 4:count 5:?
|
||||
const parseParam = '(' + literal + ')|(?:\\{(\\w+)(?:(\\*)(\\d+)?)?(\\?)?\\})';
|
||||
|
||||
const expressions = {
|
||||
parseParam: new RegExp(parseParam, 'g'),
|
||||
validatePath: new RegExp(empty + '|' + path),
|
||||
validatePathEncoded: /%(?:2[146-9A-E]|3[\dABD]|4[\dA-F]|5[\dAF]|6[1-9A-F]|7[\dAE])/g
|
||||
};
|
||||
|
||||
return expressions;
|
||||
};
|
||||
246
node_modules/@hapi/call/lib/segment.js
generated
vendored
Executable file
246
node_modules/@hapi/call/lib/segment.js
generated
vendored
Executable file
@@ -0,0 +1,246 @@
|
||||
'use strict';
|
||||
|
||||
const Hoek = require('@hapi/hoek');
|
||||
|
||||
|
||||
const internals = {};
|
||||
|
||||
|
||||
exports = module.exports = internals.Segment = function () {
|
||||
|
||||
this._edge = null; // { segment, record }
|
||||
this._fulls = null; // { path: { segment, record }
|
||||
this._literals = null; // { literal: { segment, <node> } }
|
||||
this._param = null; // <node>
|
||||
this._mixed = null; // [{ segment, <node> }]
|
||||
this._wildcard = null; // { segment, record }
|
||||
};
|
||||
|
||||
|
||||
internals.Segment.prototype.add = function (segments, record) {
|
||||
|
||||
/*
|
||||
{ literal: 'x' } -> x
|
||||
{ empty: false } -> {p}
|
||||
{ wildcard: true } -> {p*}
|
||||
{ mixed: /regex/ } -> a{p}b
|
||||
*/
|
||||
|
||||
const current = segments[0];
|
||||
const remaining = segments.slice(1);
|
||||
const isEdge = !remaining.length;
|
||||
|
||||
const literals = [];
|
||||
let isLiteral = true;
|
||||
for (let i = 0; i < segments.length && isLiteral; ++i) {
|
||||
isLiteral = segments[i].literal !== undefined;
|
||||
literals.push(segments[i].literal);
|
||||
}
|
||||
|
||||
if (isLiteral) {
|
||||
this._fulls = this._fulls ?? new Map();
|
||||
let literal = '/' + literals.join('/');
|
||||
if (!record.settings.isCaseSensitive) {
|
||||
literal = literal.toLowerCase();
|
||||
}
|
||||
|
||||
Hoek.assert(!this._fulls.has(literal), 'New route', record.path, 'conflicts with existing', this._fulls.get(literal)?.record.path);
|
||||
this._fulls.set(literal, { segment: current, record });
|
||||
}
|
||||
else if (current.literal !== undefined) { // Can be empty string
|
||||
|
||||
// Literal
|
||||
|
||||
this._literals = this._literals ?? new Map();
|
||||
const currentLiteral = record.settings.isCaseSensitive ? current.literal : current.literal.toLowerCase();
|
||||
if (!this._literals.has(currentLiteral)) {
|
||||
this._literals.set(currentLiteral, new internals.Segment());
|
||||
}
|
||||
|
||||
this._literals.get(currentLiteral).add(remaining, record);
|
||||
}
|
||||
else if (current.wildcard) {
|
||||
|
||||
// Wildcard
|
||||
|
||||
Hoek.assert(!this._wildcard, 'New route', record.path, 'conflicts with existing', this._wildcard?.record.path);
|
||||
Hoek.assert(!this._param || !this._param._wildcard, 'New route', record.path, 'conflicts with existing', this._param?._wildcard?.record.path);
|
||||
this._wildcard = { segment: current, record };
|
||||
}
|
||||
else if (current.mixed) {
|
||||
|
||||
// Mixed
|
||||
|
||||
this._mixed = this._mixed ?? [];
|
||||
|
||||
let mixed = this._mixedLookup(current);
|
||||
if (!mixed) {
|
||||
mixed = { segment: current, node: new internals.Segment() };
|
||||
this._mixed.push(mixed);
|
||||
this._mixed.sort(internals.mixed);
|
||||
}
|
||||
|
||||
if (isEdge) {
|
||||
Hoek.assert(!mixed.node._edge, 'New route', record.path, 'conflicts with existing', mixed.node._edge?.record.path);
|
||||
mixed.node._edge = { segment: current, record };
|
||||
}
|
||||
else {
|
||||
mixed.node.add(remaining, record);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
// Parameter
|
||||
|
||||
this._param = this._param ?? new internals.Segment();
|
||||
|
||||
if (isEdge) {
|
||||
Hoek.assert(!this._param._edge, 'New route', record.path, 'conflicts with existing', this._param._edge?.record.path);
|
||||
this._param._edge = { segment: current, record };
|
||||
}
|
||||
else {
|
||||
Hoek.assert(!this._wildcard || !remaining[0].wildcard, 'New route', record.path, 'conflicts with existing', this._wildcard?.record.path);
|
||||
this._param.add(remaining, record);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
internals.Segment.prototype._mixedLookup = function (segment) {
|
||||
|
||||
for (let i = 0; i < this._mixed.length; ++i) {
|
||||
if (internals.mixed({ segment }, this._mixed[i]) === 0) {
|
||||
return this._mixed[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
internals.mixed = function (a, b) {
|
||||
|
||||
const aFirst = -1;
|
||||
const bFirst = 1;
|
||||
|
||||
const as = a.segment;
|
||||
const bs = b.segment;
|
||||
|
||||
if (as.length !== bs.length) {
|
||||
return as.length > bs.length ? aFirst : bFirst;
|
||||
}
|
||||
|
||||
if (as.first !== bs.first) {
|
||||
return as.first ? bFirst : aFirst;
|
||||
}
|
||||
|
||||
for (let i = 0; i < as.segments.length; ++i) {
|
||||
const am = as.segments[i];
|
||||
const bm = bs.segments[i];
|
||||
|
||||
if (am === bm) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (am.length === bm.length) {
|
||||
return am > bm ? bFirst : aFirst;
|
||||
}
|
||||
|
||||
return am.length < bm.length ? bFirst : aFirst;
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
internals.Segment.prototype.lookup = function (path, segments, options) {
|
||||
|
||||
let match = null;
|
||||
|
||||
// Literal edge
|
||||
|
||||
if (this._fulls) {
|
||||
match = this._fulls.get(options.isCaseSensitive ? path : path.toLowerCase());
|
||||
if (match) {
|
||||
return { record: match.record, array: [] };
|
||||
}
|
||||
}
|
||||
|
||||
// Literal node
|
||||
|
||||
const current = segments[0];
|
||||
const nextPath = path.slice(current.length + 1);
|
||||
const remainder = segments.length > 1 ? segments.slice(1) : null;
|
||||
|
||||
if (this._literals) {
|
||||
const literal = options.isCaseSensitive ? current : current.toLowerCase();
|
||||
match = this._literals.get(literal);
|
||||
if (match) {
|
||||
const record = internals.deeper(match, nextPath, remainder, [], options);
|
||||
if (record) {
|
||||
return record;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mixed
|
||||
|
||||
if (this._mixed) {
|
||||
for (let i = 0; i < this._mixed.length; ++i) {
|
||||
match = this._mixed[i];
|
||||
const params = current.match(match.segment.mixed);
|
||||
if (params) {
|
||||
const array = [];
|
||||
for (let j = 1; j < params.length; ++j) {
|
||||
array.push(params[j]);
|
||||
}
|
||||
|
||||
const record = internals.deeper(match.node, nextPath, remainder, array, options);
|
||||
if (record) {
|
||||
return record;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Param
|
||||
|
||||
if (this._param) {
|
||||
if (current || this._param._edge?.segment.empty) {
|
||||
const record = internals.deeper(this._param, nextPath, remainder, [current], options);
|
||||
if (record) {
|
||||
return record;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wildcard
|
||||
|
||||
if (this._wildcard) {
|
||||
return { record: this._wildcard.record, array: [path.slice(1)] };
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
internals.deeper = function (match, path, segments, array, options) {
|
||||
|
||||
if (!segments) {
|
||||
if (match._edge) {
|
||||
return { record: match._edge.record, array };
|
||||
}
|
||||
|
||||
if (match._wildcard) {
|
||||
return { record: match._wildcard.record, array };
|
||||
}
|
||||
}
|
||||
else {
|
||||
const result = match.lookup(path, segments, options);
|
||||
if (result) {
|
||||
return { record: result.record, array: array.concat(result.array) };
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
33
node_modules/@hapi/call/package.json
generated
vendored
Executable file
33
node_modules/@hapi/call/package.json
generated
vendored
Executable file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "@hapi/call",
|
||||
"description": "HTTP Router",
|
||||
"version": "9.0.1",
|
||||
"repository": "git://github.com/hapijs/call",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"keywords": [
|
||||
"HTTP",
|
||||
"router"
|
||||
],
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"plugin:@hapi/module"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@hapi/boom": "^10.0.1",
|
||||
"@hapi/hoek": "^11.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@hapi/code": "^9.0.3",
|
||||
"@hapi/eslint-plugin": "*",
|
||||
"@hapi/lab": "^25.1.2"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "lab -a @hapi/code -t 100 -L",
|
||||
"test-cov-html": "lab -a @hapi/code -r html -o coverage.html"
|
||||
},
|
||||
"license": "BSD-3-Clause"
|
||||
}
|
||||
Reference in New Issue
Block a user