hono 2.1.4 → 2.2.1

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.
Files changed (145) hide show
  1. package/README.md +13 -14
  2. package/dist/cjs/compose.js +48 -0
  3. package/dist/cjs/context.js +147 -0
  4. package/dist/cjs/hono.js +152 -0
  5. package/dist/cjs/index.js +13 -0
  6. package/dist/cjs/middleware/basic-auth/index.js +48 -0
  7. package/dist/cjs/middleware/bearer-auth/index.js +57 -0
  8. package/dist/cjs/middleware/cache/index.js +32 -0
  9. package/dist/cjs/middleware/compress/index.js +19 -0
  10. package/dist/cjs/middleware/cors/index.js +75 -0
  11. package/dist/cjs/middleware/etag/index.js +27 -0
  12. package/dist/cjs/middleware/html/index.js +36 -0
  13. package/dist/cjs/middleware/jsx/index.js +193 -0
  14. package/dist/cjs/middleware/jsx/jsx-dev-runtime.js +10 -0
  15. package/dist/cjs/middleware/jsx/jsx-runtime.js +7 -0
  16. package/dist/cjs/middleware/jwt/index.js +63 -0
  17. package/dist/cjs/middleware/logger/index.js +49 -0
  18. package/dist/cjs/middleware/powered-by/index.js +10 -0
  19. package/dist/cjs/middleware/pretty-json/index.js +11 -0
  20. package/dist/cjs/middleware/serve-static/bun.js +41 -0
  21. package/dist/cjs/middleware/serve-static/index.js +5 -0
  22. package/dist/cjs/middleware/serve-static/serve-static.js +40 -0
  23. package/dist/cjs/middleware/validator/index.js +5 -0
  24. package/dist/cjs/middleware/validator/middleware.js +56 -0
  25. package/dist/cjs/middleware/validator/rule.js +66 -0
  26. package/dist/cjs/middleware/validator/sanitizer.js +6 -0
  27. package/dist/cjs/middleware/validator/validator.js +195 -0
  28. package/dist/cjs/request.js +120 -0
  29. package/dist/cjs/router/reg-exp-router/index.js +5 -0
  30. package/dist/cjs/router/reg-exp-router/node.js +108 -0
  31. package/dist/cjs/router/reg-exp-router/router.js +161 -0
  32. package/dist/cjs/router/reg-exp-router/trie.js +42 -0
  33. package/dist/cjs/router/smart-router/index.js +5 -0
  34. package/dist/cjs/router/smart-router/router.js +57 -0
  35. package/dist/cjs/router/static-router/index.js +5 -0
  36. package/dist/cjs/router/static-router/router.js +72 -0
  37. package/dist/cjs/router/trie-router/index.js +5 -0
  38. package/dist/cjs/router/trie-router/node.js +175 -0
  39. package/dist/cjs/router/trie-router/router.js +24 -0
  40. package/dist/cjs/router.js +9 -0
  41. package/dist/cjs/utils/body.js +18 -0
  42. package/dist/cjs/utils/buffer.js +39 -0
  43. package/dist/cjs/utils/cloudflare.js +39 -0
  44. package/dist/cjs/utils/cookie.js +40 -0
  45. package/dist/cjs/utils/crypto.js +53 -0
  46. package/dist/cjs/utils/encode.js +80 -0
  47. package/dist/cjs/utils/filepath.js +25 -0
  48. package/dist/cjs/utils/html.js +38 -0
  49. package/dist/cjs/utils/http-status.js +50 -0
  50. package/dist/cjs/utils/json.js +22 -0
  51. package/dist/cjs/utils/jwt/index.js +27 -0
  52. package/dist/cjs/utils/jwt/jwt.js +101 -0
  53. package/dist/cjs/utils/jwt/types.js +49 -0
  54. package/dist/cjs/utils/mime.js +92 -0
  55. package/dist/cjs/utils/url.js +94 -0
  56. package/dist/compose.d.ts +2 -2
  57. package/dist/compose.js +3 -7
  58. package/dist/context.d.ts +14 -9
  59. package/dist/context.js +55 -25
  60. package/dist/hono.d.ts +28 -27
  61. package/dist/hono.js +22 -23
  62. package/dist/index.js +3 -6
  63. package/dist/middleware/basic-auth/index.d.ts +2 -3
  64. package/dist/middleware/basic-auth/index.js +7 -11
  65. package/dist/middleware/bearer-auth/index.d.ts +2 -3
  66. package/dist/middleware/bearer-auth/index.js +4 -12
  67. package/dist/middleware/cache/index.d.ts +2 -3
  68. package/dist/middleware/cache/index.js +1 -5
  69. package/dist/middleware/compress/index.d.ts +2 -3
  70. package/dist/middleware/compress/index.js +1 -5
  71. package/dist/middleware/cors/index.d.ts +3 -4
  72. package/dist/middleware/cors/index.js +16 -6
  73. package/dist/middleware/etag/index.d.ts +2 -3
  74. package/dist/middleware/etag/index.js +3 -7
  75. package/dist/middleware/html/index.js +6 -11
  76. package/dist/middleware/jsx/index.js +9 -15
  77. package/dist/middleware/jsx/jsx-dev-runtime.js +3 -7
  78. package/dist/middleware/jsx/jsx-runtime.js +2 -7
  79. package/dist/middleware/jwt/index.d.ts +2 -3
  80. package/dist/middleware/jwt/index.js +3 -7
  81. package/dist/middleware/logger/index.d.ts +2 -3
  82. package/dist/middleware/logger/index.js +3 -7
  83. package/dist/middleware/powered-by/index.d.ts +2 -3
  84. package/dist/middleware/powered-by/index.js +1 -5
  85. package/dist/middleware/pretty-json/index.d.ts +2 -3
  86. package/dist/middleware/pretty-json/index.js +1 -5
  87. package/dist/middleware/serve-static/bun.d.ts +2 -3
  88. package/dist/middleware/serve-static/bun.js +18 -19
  89. package/dist/middleware/serve-static/index.js +1 -5
  90. package/dist/middleware/serve-static/module.d.mts +1 -1
  91. package/dist/middleware/serve-static/serve-static.d.ts +2 -3
  92. package/dist/middleware/serve-static/serve-static.js +7 -11
  93. package/dist/middleware/validator/index.d.ts +2 -0
  94. package/dist/middleware/validator/index.js +2 -0
  95. package/dist/middleware/validator/middleware.d.ts +21 -0
  96. package/dist/middleware/validator/middleware.js +52 -0
  97. package/dist/middleware/validator/rule.d.ts +21 -0
  98. package/dist/middleware/validator/rule.js +63 -0
  99. package/dist/middleware/validator/sanitizer.d.ts +3 -0
  100. package/dist/middleware/validator/sanitizer.js +3 -0
  101. package/dist/middleware/validator/validator.d.ts +75 -0
  102. package/dist/middleware/validator/validator.js +186 -0
  103. package/dist/request.d.ts +15 -5
  104. package/dist/request.js +58 -28
  105. package/dist/router/reg-exp-router/index.js +1 -5
  106. package/dist/router/reg-exp-router/node.d.ts +1 -3
  107. package/dist/router/reg-exp-router/node.js +21 -17
  108. package/dist/router/reg-exp-router/router.d.ts +3 -27
  109. package/dist/router/reg-exp-router/router.js +105 -315
  110. package/dist/router/reg-exp-router/trie.d.ts +0 -4
  111. package/dist/router/reg-exp-router/trie.js +4 -8
  112. package/dist/router/smart-router/index.d.ts +1 -0
  113. package/dist/router/smart-router/index.js +1 -0
  114. package/dist/router/smart-router/router.d.ts +9 -0
  115. package/dist/router/smart-router/router.js +53 -0
  116. package/dist/router/static-router/index.d.ts +1 -0
  117. package/dist/router/static-router/index.js +1 -0
  118. package/dist/router/static-router/router.d.ts +8 -0
  119. package/dist/router/static-router/router.js +68 -0
  120. package/dist/router/trie-router/index.js +1 -5
  121. package/dist/router/trie-router/node.js +7 -11
  122. package/dist/router/trie-router/router.js +11 -7
  123. package/dist/router.d.ts +3 -0
  124. package/dist/router.js +5 -5
  125. package/dist/utils/body.d.ts +2 -1
  126. package/dist/utils/body.js +1 -5
  127. package/dist/utils/buffer.d.ts +1 -1
  128. package/dist/utils/buffer.js +5 -11
  129. package/dist/utils/cloudflare.d.ts +1 -1
  130. package/dist/utils/cloudflare.js +1 -5
  131. package/dist/utils/cookie.js +2 -7
  132. package/dist/utils/crypto.js +8 -15
  133. package/dist/utils/encode.js +10 -20
  134. package/dist/utils/filepath.js +1 -5
  135. package/dist/utils/html.js +1 -5
  136. package/dist/utils/http-status.js +1 -5
  137. package/dist/utils/json.d.ts +1 -0
  138. package/dist/utils/json.js +18 -0
  139. package/dist/utils/jwt/index.js +1 -27
  140. package/dist/utils/jwt/jwt.js +22 -28
  141. package/dist/utils/jwt/types.js +8 -16
  142. package/dist/utils/mime.js +1 -5
  143. package/dist/utils/url.d.ts +1 -1
  144. package/dist/utils/url.js +18 -22
  145. package/package.json +122 -35
@@ -0,0 +1,195 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VObject = exports.VBoolean = exports.VNumber = exports.VString = exports.VBase = exports.Validator = void 0;
4
+ const json_1 = require("../../utils/json");
5
+ const rule_1 = require("./rule");
6
+ const sanitizer_1 = require("./sanitizer");
7
+ class Validator {
8
+ constructor() {
9
+ this.query = (key) => new VString({ target: 'query', key: key });
10
+ this.header = (key) => new VString({ target: 'header', key: key });
11
+ this.body = (key) => new VString({ target: 'body', key: key });
12
+ this.json = (key) => new VString({ target: 'json', key: key });
13
+ }
14
+ }
15
+ exports.Validator = Validator;
16
+ class VBase {
17
+ constructor(options) {
18
+ this.addRule = (rule) => {
19
+ this.rules.push(rule);
20
+ return this;
21
+ };
22
+ this.addSanitizer = (sanitizer) => {
23
+ this.sanitizers.push(sanitizer);
24
+ return this;
25
+ };
26
+ this.isRequired = () => {
27
+ return this.addRule((value) => {
28
+ if (value)
29
+ return true;
30
+ return false;
31
+ });
32
+ };
33
+ this.isOptional = () => {
34
+ return this.addRule(() => true);
35
+ };
36
+ this.isEqual = (comparison) => {
37
+ return this.addRule((value) => {
38
+ return value === comparison;
39
+ });
40
+ };
41
+ this.asNumber = () => {
42
+ const newVNumber = new VNumber(this);
43
+ return newVNumber;
44
+ };
45
+ this.asBoolean = () => {
46
+ const newVBoolean = new VBoolean(this);
47
+ return newVBoolean;
48
+ };
49
+ this.asObject = () => {
50
+ const newVObject = new VObject(this);
51
+ return newVObject;
52
+ };
53
+ this.validate = async (req) => {
54
+ const result = {
55
+ isValid: true,
56
+ message: undefined,
57
+ target: this.target,
58
+ key: this.key,
59
+ value: undefined,
60
+ };
61
+ let value = undefined;
62
+ if (this.target === 'query') {
63
+ value = req.query(this.key);
64
+ }
65
+ if (this.target === 'header') {
66
+ value = req.header(this.key);
67
+ }
68
+ if (this.target === 'body') {
69
+ const body = await req.parseBody();
70
+ value = body[this.key];
71
+ }
72
+ if (this.target === 'json') {
73
+ const obj = await req.json();
74
+ value = (0, json_1.JSONPath)(obj, this.key);
75
+ }
76
+ result.value = value;
77
+ result.isValid = this.validateValue(value);
78
+ if (result.isValid == false) {
79
+ if (this._message) {
80
+ result.message = this._message;
81
+ }
82
+ else {
83
+ switch (this.target) {
84
+ case 'query':
85
+ result.message = `Invalid Value: the query parameter "${this.key}" is invalid - ${value}`;
86
+ break;
87
+ case 'header':
88
+ result.message = `Invalid Value: the request header "${this.key}" is invalid - ${value}`;
89
+ break;
90
+ case 'body':
91
+ result.message = `Invalid Value: the request body "${this.key}" is invalid - ${value}`;
92
+ break;
93
+ case 'json':
94
+ result.message = `Invalid Value: the JSON body "${this.key}" is invalid - ${value}`;
95
+ break;
96
+ }
97
+ }
98
+ }
99
+ return result;
100
+ };
101
+ this.validateValue = (value) => {
102
+ // Check type
103
+ if (typeof value !== this.type) {
104
+ return false;
105
+ }
106
+ // Sanitize
107
+ for (const sanitizer of this.sanitizers) {
108
+ value = sanitizer(value);
109
+ }
110
+ for (const rule of this.rules) {
111
+ if (!rule(value)) {
112
+ return false;
113
+ }
114
+ }
115
+ return true;
116
+ };
117
+ this.target = options.target;
118
+ this.key = options.key;
119
+ this.type = options.type || 'string';
120
+ this.rules = [];
121
+ this.sanitizers = [];
122
+ }
123
+ message(value) {
124
+ this._message = value;
125
+ return this;
126
+ }
127
+ }
128
+ exports.VBase = VBase;
129
+ class VString extends VBase {
130
+ constructor(options) {
131
+ super(options);
132
+ this.isEmpty = (options = { ignore_whitespace: false }) => {
133
+ return this.addRule((value) => rule_1.rule.isEmpty(value, options));
134
+ };
135
+ this.isLength = (options, arg2) => {
136
+ return this.addRule((value) => rule_1.rule.isLength(value, options, arg2));
137
+ };
138
+ this.isAlpha = () => {
139
+ return this.addRule((value) => rule_1.rule.isAlpha(value));
140
+ };
141
+ this.isNumeric = () => {
142
+ return this.addRule((value) => rule_1.rule.isNumeric(value));
143
+ };
144
+ this.contains = (elem, options = {
145
+ ignoreCase: false,
146
+ minOccurrences: 1,
147
+ }) => {
148
+ return this.addRule((value) => rule_1.rule.contains(value, elem, options));
149
+ };
150
+ this.isIn = (options) => {
151
+ return this.addRule((value) => rule_1.rule.isIn(value, options));
152
+ };
153
+ this.match = (regExp) => {
154
+ return this.addRule((value) => rule_1.rule.match(value, regExp));
155
+ };
156
+ this.trim = () => {
157
+ return this.addSanitizer((value) => sanitizer_1.sanitizer.trim(value));
158
+ };
159
+ this.type = 'string';
160
+ }
161
+ }
162
+ exports.VString = VString;
163
+ class VNumber extends VBase {
164
+ constructor(options) {
165
+ super(options);
166
+ this.isGte = (min) => {
167
+ return this.addRule((value) => rule_1.rule.isGte(value, min));
168
+ };
169
+ this.isLte = (min) => {
170
+ return this.addRule((value) => rule_1.rule.isLte(value, min));
171
+ };
172
+ this.type = 'number';
173
+ }
174
+ }
175
+ exports.VNumber = VNumber;
176
+ class VBoolean extends VBase {
177
+ constructor(options) {
178
+ super(options);
179
+ this.isTrue = () => {
180
+ return this.addRule((value) => rule_1.rule.isTrue(value));
181
+ };
182
+ this.isFalse = () => {
183
+ return this.addRule((value) => rule_1.rule.isFalse(value));
184
+ };
185
+ this.type = 'boolean';
186
+ }
187
+ }
188
+ exports.VBoolean = VBoolean;
189
+ class VObject extends VBase {
190
+ constructor(options) {
191
+ super(options);
192
+ this.type = 'object';
193
+ }
194
+ }
195
+ exports.VObject = VObject;
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extendRequestPrototype = void 0;
4
+ const body_1 = require("./utils/body");
5
+ const cookie_1 = require("./utils/cookie");
6
+ const url_1 = require("./utils/url");
7
+ function extendRequestPrototype() {
8
+ if (!!Request.prototype.param) {
9
+ // already extended
10
+ return;
11
+ }
12
+ Request.prototype.param = function (key) {
13
+ if (this.paramData) {
14
+ if (key) {
15
+ return this.paramData[key];
16
+ }
17
+ else {
18
+ return this.paramData;
19
+ }
20
+ }
21
+ return null;
22
+ };
23
+ Request.prototype.header = function (name) {
24
+ if (!this.headerData) {
25
+ this.headerData = {};
26
+ for (const [key, value] of this.headers) {
27
+ this.headerData[key] = value;
28
+ }
29
+ }
30
+ if (name) {
31
+ return this.headerData[name.toLowerCase()];
32
+ }
33
+ else {
34
+ return this.headerData;
35
+ }
36
+ };
37
+ Request.prototype.query = function (key) {
38
+ const queryString = (0, url_1.getQueryStringFromURL)(this.url);
39
+ const searchParams = new URLSearchParams(queryString);
40
+ if (!this.queryData) {
41
+ this.queryData = {};
42
+ for (const key of searchParams.keys()) {
43
+ this.queryData[key] = searchParams.get(key) || '';
44
+ }
45
+ }
46
+ if (key) {
47
+ return this.queryData[key];
48
+ }
49
+ else {
50
+ return this.queryData;
51
+ }
52
+ };
53
+ Request.prototype.queries = function (key) {
54
+ const queryString = (0, url_1.getQueryStringFromURL)(this.url);
55
+ const searchParams = new URLSearchParams(queryString);
56
+ if (key) {
57
+ return searchParams.getAll(key);
58
+ }
59
+ else {
60
+ const result = {};
61
+ for (const key of searchParams.keys()) {
62
+ result[key] = searchParams.getAll(key);
63
+ }
64
+ return result;
65
+ }
66
+ };
67
+ Request.prototype.cookie = function (key) {
68
+ const cookie = this.headers.get('Cookie') || '';
69
+ const obj = (0, cookie_1.parse)(cookie);
70
+ if (key) {
71
+ const value = obj[key];
72
+ return value;
73
+ }
74
+ else {
75
+ return obj;
76
+ }
77
+ };
78
+ Request.prototype.parseBody = async function () {
79
+ // Cache the parsed body
80
+ let body;
81
+ if (!this.bodyData) {
82
+ body = await (0, body_1.parseBody)(this);
83
+ this.bodyData = body;
84
+ }
85
+ else {
86
+ body = this.bodyData;
87
+ }
88
+ return body;
89
+ };
90
+ Request.prototype.json = async function () {
91
+ // Cache the JSON body
92
+ let jsonData;
93
+ if (!this.jsonData) {
94
+ jsonData = JSON.parse(await this.text());
95
+ this.jsonData = jsonData;
96
+ }
97
+ else {
98
+ jsonData = this.jsonData;
99
+ }
100
+ return jsonData;
101
+ };
102
+ Request.prototype.valid = function (keys, value) {
103
+ var _a;
104
+ if (!this.data) {
105
+ this.data = {};
106
+ }
107
+ if (keys !== undefined) {
108
+ if (typeof keys === 'string') {
109
+ keys = [keys];
110
+ }
111
+ let data = this.data;
112
+ for (let i = 0; i < keys.length - 1; i++) {
113
+ data = data[_a = keys[i]] || (data[_a] = {});
114
+ }
115
+ data[keys[keys.length - 1]] = value;
116
+ }
117
+ return this.data;
118
+ };
119
+ }
120
+ exports.extendRequestPrototype = extendRequestPrototype;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RegExpRouter = void 0;
4
+ var router_1 = require("./router");
5
+ Object.defineProperty(exports, "RegExpRouter", { enumerable: true, get: function () { return router_1.RegExpRouter; } });
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Node = exports.PATH_ERROR = void 0;
4
+ const LABEL_REG_EXP_STR = '[^/]+';
5
+ const ONLY_WILDCARD_REG_EXP_STR = '.*';
6
+ const TAIL_WILDCARD_REG_EXP_STR = '(?:|/.*)';
7
+ exports.PATH_ERROR = Symbol();
8
+ /**
9
+ * Sort order:
10
+ * 1. literal
11
+ * 2. special pattern (e.g. :label{[0-9]+})
12
+ * 3. common label pattern (e.g. :label)
13
+ * 4. wildcard
14
+ */
15
+ function compareKey(a, b) {
16
+ if (a.length === 1) {
17
+ return b.length === 1 ? (a < b ? -1 : 1) : -1;
18
+ }
19
+ if (b.length === 1) {
20
+ return 1;
21
+ }
22
+ // wildcard
23
+ if (a === ONLY_WILDCARD_REG_EXP_STR || a === TAIL_WILDCARD_REG_EXP_STR) {
24
+ return 1;
25
+ }
26
+ else if (b === ONLY_WILDCARD_REG_EXP_STR || b === TAIL_WILDCARD_REG_EXP_STR) {
27
+ return -1;
28
+ }
29
+ // label
30
+ if (a === LABEL_REG_EXP_STR) {
31
+ return 1;
32
+ }
33
+ else if (b === LABEL_REG_EXP_STR) {
34
+ return -1;
35
+ }
36
+ return a.length === b.length ? (a < b ? -1 : 1) : b.length - a.length;
37
+ }
38
+ class Node {
39
+ constructor() {
40
+ this.children = {};
41
+ }
42
+ insert(tokens, index, paramMap, context) {
43
+ if (tokens.length === 0) {
44
+ if (this.index !== undefined) {
45
+ throw exports.PATH_ERROR;
46
+ }
47
+ this.index = index;
48
+ return;
49
+ }
50
+ const [token, ...restTokens] = tokens;
51
+ const pattern = token === '*'
52
+ ? restTokens.length === 0
53
+ ? ['', '', ONLY_WILDCARD_REG_EXP_STR] // '*' matches to all the trailing paths
54
+ : ['', '', LABEL_REG_EXP_STR]
55
+ : token === '/*'
56
+ ? ['', '', TAIL_WILDCARD_REG_EXP_STR] // '/path/to/*' is /\/path\/to(?:|/.*)$
57
+ : token.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
58
+ let node;
59
+ if (pattern) {
60
+ const name = pattern[1];
61
+ const regexpStr = pattern[2] || LABEL_REG_EXP_STR;
62
+ node = this.children[regexpStr];
63
+ if (!node) {
64
+ if (Object.keys(this.children).some((k) => k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR)) {
65
+ throw exports.PATH_ERROR;
66
+ }
67
+ node = this.children[regexpStr] = new Node();
68
+ if (name !== '') {
69
+ node.varIndex = context.varIndex++;
70
+ }
71
+ }
72
+ if (name !== '') {
73
+ if (paramMap.some((p) => p[0] === name)) {
74
+ throw new Error('Duplicate param name');
75
+ }
76
+ paramMap.push([name, node.varIndex]);
77
+ }
78
+ }
79
+ else {
80
+ node = this.children[token];
81
+ if (!node) {
82
+ if (Object.keys(this.children).some((k) => k.length > 1 && k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR)) {
83
+ throw exports.PATH_ERROR;
84
+ }
85
+ node = this.children[token] = new Node();
86
+ }
87
+ }
88
+ node.insert(restTokens, index, paramMap, context);
89
+ }
90
+ buildRegExpStr() {
91
+ const childKeys = Object.keys(this.children).sort(compareKey);
92
+ const strList = childKeys.map((k) => {
93
+ const c = this.children[k];
94
+ return (typeof c.varIndex === 'number' ? `(${k})@${c.varIndex}` : k) + c.buildRegExpStr();
95
+ });
96
+ if (typeof this.index === 'number') {
97
+ strList.unshift(`#${this.index}`);
98
+ }
99
+ if (strList.length === 0) {
100
+ return '';
101
+ }
102
+ if (strList.length === 1) {
103
+ return strList[0];
104
+ }
105
+ return '(?:' + strList.join('|') + ')';
106
+ }
107
+ }
108
+ exports.Node = Node;
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RegExpRouter = void 0;
4
+ const router_1 = require("../../router");
5
+ const url_1 = require("../../utils/url");
6
+ const node_1 = require("./node");
7
+ const trie_1 = require("./trie");
8
+ const METHOD_NAMES = [router_1.METHOD_NAME_ALL, ...router_1.METHODS].map((method) => method.toUpperCase());
9
+ const emptyParam = {};
10
+ const nullMatcher = [/^$/, []];
11
+ function buildWildcardRegExp(path) {
12
+ return new RegExp(path === '*' ? '' : `^${path.replace(/\/\*/, '(?:|/.*)')}$`);
13
+ }
14
+ function buildMatcherFromPreprocessedRoutes(routes) {
15
+ const trie = new trie_1.Trie();
16
+ const handlers = [];
17
+ if (routes.length === 0) {
18
+ return nullMatcher;
19
+ }
20
+ for (let i = 0, len = routes.length; i < len; i++) {
21
+ let paramMap;
22
+ try {
23
+ paramMap = trie.insert(routes[i][0], i);
24
+ }
25
+ catch (e) {
26
+ throw e === node_1.PATH_ERROR ? new router_1.UnsupportedPathError(routes[i][0]) : e;
27
+ }
28
+ handlers[i] = [routes[i][1], paramMap.length !== 0 ? paramMap : null];
29
+ }
30
+ const [regexp, indexReplacementMap, paramReplacementMap] = trie.buildRegExp();
31
+ for (let i = 0, len = handlers.length; i < len; i++) {
32
+ const paramMap = handlers[i][1];
33
+ if (paramMap) {
34
+ for (let j = 0, len = paramMap.length; j < len; j++) {
35
+ paramMap[j][1] = paramReplacementMap[paramMap[j][1]];
36
+ }
37
+ }
38
+ }
39
+ const handlerMap = [];
40
+ // using `in` because indexReplacementMap is a sparse array
41
+ for (const i in indexReplacementMap) {
42
+ handlerMap[i] = handlers[indexReplacementMap[i]];
43
+ }
44
+ return [regexp, handlerMap];
45
+ }
46
+ function findMiddleware(middleware, path) {
47
+ if (!middleware) {
48
+ return undefined;
49
+ }
50
+ for (const k of Object.keys(middleware).sort((a, b) => b.length - a.length)) {
51
+ if (buildWildcardRegExp(k).test(path)) {
52
+ return [...middleware[k]];
53
+ }
54
+ }
55
+ return undefined;
56
+ }
57
+ class RegExpRouter {
58
+ constructor() {
59
+ this.middleware = { [router_1.METHOD_NAME_ALL]: {} };
60
+ this.routes = { [router_1.METHOD_NAME_ALL]: {} };
61
+ }
62
+ add(method, path, handler) {
63
+ var _a, _b;
64
+ const { middleware, routes } = this;
65
+ if (!middleware || !routes) {
66
+ throw new Error('Can not add a route since the matcher is already built.');
67
+ }
68
+ if (path === '/*') {
69
+ path = '*';
70
+ }
71
+ if (/\*$/.test(path)) {
72
+ middleware[method] || (middleware[method] = {});
73
+ const re = buildWildcardRegExp(path);
74
+ (_a = middleware[method])[path] || (_a[path] = findMiddleware(middleware[router_1.METHOD_NAME_ALL], path) || []);
75
+ Object.keys(middleware).forEach((m) => {
76
+ if (method === router_1.METHOD_NAME_ALL || method === m) {
77
+ Object.keys(middleware[m]).forEach((p) => {
78
+ ;
79
+ (path === '*' || path === p) && middleware[m][p].push(handler);
80
+ });
81
+ }
82
+ });
83
+ Object.keys(routes).forEach((m) => {
84
+ if (method === router_1.METHOD_NAME_ALL || method === m) {
85
+ Object.keys(routes[m]).forEach((p) => (path === '*' || re.test(p)) && routes[m][p].push(handler));
86
+ }
87
+ });
88
+ return;
89
+ }
90
+ const paths = (0, url_1.checkOptionalParameter)(path) || [path];
91
+ for (let i = 0, len = paths.length; i < len; i++) {
92
+ const path = paths[i];
93
+ routes[method] || (routes[method] = {});
94
+ (_b = routes[method])[path] || (_b[path] = [
95
+ ...(routes[router_1.METHOD_NAME_ALL][path] ||
96
+ findMiddleware(middleware[method], path) ||
97
+ findMiddleware(middleware[router_1.METHOD_NAME_ALL], path) ||
98
+ []),
99
+ ]);
100
+ Object.keys(routes).forEach((m) => {
101
+ ;
102
+ (method === router_1.METHOD_NAME_ALL || method === m) &&
103
+ routes[m][path] &&
104
+ routes[m][path].push(handler);
105
+ });
106
+ }
107
+ }
108
+ match(method, path) {
109
+ const matchers = this.buildAllMatchers();
110
+ this.match = (method, path) => {
111
+ const matcher = matchers[method];
112
+ const match = path.match(matcher[0]);
113
+ if (!match) {
114
+ return null;
115
+ }
116
+ const index = match.indexOf('', 1);
117
+ const [handlers, paramMap] = matcher[1][index];
118
+ if (!paramMap) {
119
+ return { handlers, params: emptyParam };
120
+ }
121
+ const params = {};
122
+ for (let i = 0, len = paramMap.length; i < len; i++) {
123
+ params[paramMap[i][0]] = match[paramMap[i][1]];
124
+ }
125
+ return { handlers, params };
126
+ };
127
+ return this.match(method, path);
128
+ }
129
+ buildAllMatchers() {
130
+ const matchers = {};
131
+ METHOD_NAMES.forEach((method) => {
132
+ matchers[method] = this.buildMatcher(method) || matchers[router_1.METHOD_NAME_ALL];
133
+ });
134
+ // Release cache
135
+ this.middleware = this.routes = undefined;
136
+ return matchers;
137
+ }
138
+ buildMatcher(method) {
139
+ const routes = [];
140
+ let hasOwnRoute = method === router_1.METHOD_NAME_ALL;
141
+ [this.middleware, this.routes].forEach((r) => {
142
+ const ownRoute = r[method]
143
+ ? Object.keys(r[method]).map((path) => [path, r[method][path]])
144
+ : [];
145
+ if (ownRoute.length !== 0) {
146
+ hasOwnRoute || (hasOwnRoute = true);
147
+ routes.push(...ownRoute);
148
+ }
149
+ else if (method !== router_1.METHOD_NAME_ALL) {
150
+ routes.push(...Object.keys(r[router_1.METHOD_NAME_ALL]).map((path) => [path, r[router_1.METHOD_NAME_ALL][path]]));
151
+ }
152
+ });
153
+ if (!hasOwnRoute) {
154
+ return null;
155
+ }
156
+ else {
157
+ return buildMatcherFromPreprocessedRoutes(routes);
158
+ }
159
+ }
160
+ }
161
+ exports.RegExpRouter = RegExpRouter;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Trie = void 0;
4
+ const node_1 = require("./node");
5
+ class Trie {
6
+ constructor() {
7
+ this.context = { varIndex: 0 };
8
+ this.root = new node_1.Node();
9
+ }
10
+ insert(path, index) {
11
+ const paramMap = [];
12
+ /**
13
+ * - pattern (:label, :label{0-9]+}, ...)
14
+ * - /* wildcard
15
+ * - character
16
+ */
17
+ const tokens = path.match(/(?::[^\/]+)|(?:\/\*$)|./g);
18
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
19
+ // @ts-ignore
20
+ this.root.insert(tokens, index, paramMap, this.context);
21
+ return paramMap;
22
+ }
23
+ buildRegExp() {
24
+ let regexp = this.root.buildRegExpStr();
25
+ let captureIndex = 0;
26
+ const indexReplacementMap = [];
27
+ const paramReplacementMap = [];
28
+ regexp = regexp.replace(/#(\d+)|@(\d+)|\.\*\$/g, (_, handlerIndex, paramIndex) => {
29
+ if (typeof handlerIndex !== 'undefined') {
30
+ indexReplacementMap[++captureIndex] = Number(handlerIndex);
31
+ return '$()';
32
+ }
33
+ if (typeof paramIndex !== 'undefined') {
34
+ paramReplacementMap[Number(paramIndex)] = ++captureIndex;
35
+ return '';
36
+ }
37
+ return '';
38
+ });
39
+ return [new RegExp(`^${regexp}`), indexReplacementMap, paramReplacementMap];
40
+ }
41
+ }
42
+ exports.Trie = Trie;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SmartRouter = void 0;
4
+ var router_1 = require("./router");
5
+ Object.defineProperty(exports, "SmartRouter", { enumerable: true, get: function () { return router_1.SmartRouter; } });
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SmartRouter = void 0;
4
+ const router_1 = require("../../router");
5
+ class SmartRouter {
6
+ constructor(init) {
7
+ this.routers = [];
8
+ this.routes = [];
9
+ Object.assign(this, init);
10
+ }
11
+ add(method, path, handler) {
12
+ if (!this.routes) {
13
+ throw new Error('Can not add a route since the matcher is already built.');
14
+ }
15
+ this.routes.push([method, path, handler]);
16
+ }
17
+ match(method, path) {
18
+ if (!this.routes) {
19
+ throw new Error('Fatal error');
20
+ }
21
+ const { routers, routes } = this;
22
+ const len = routers.length;
23
+ let i = 0;
24
+ let res;
25
+ for (; i < len; i++) {
26
+ const router = routers[i];
27
+ try {
28
+ routes.forEach((args) => {
29
+ router.add(...args);
30
+ });
31
+ res = router.match(method, path);
32
+ }
33
+ catch (e) {
34
+ if (e instanceof router_1.UnsupportedPathError) {
35
+ continue;
36
+ }
37
+ throw e;
38
+ }
39
+ this.match = router.match.bind(router);
40
+ this.routers = [router];
41
+ this.routes = undefined;
42
+ break;
43
+ }
44
+ if (i === len) {
45
+ // not found
46
+ throw new Error('Fatal error');
47
+ }
48
+ return res || null;
49
+ }
50
+ get activeRouter() {
51
+ if (this.routes || this.routers.length !== 1) {
52
+ throw new Error('No active router has been determined yet.');
53
+ }
54
+ return this.routers[0];
55
+ }
56
+ }
57
+ exports.SmartRouter = SmartRouter;