1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | Object.defineProperty(exports, "__esModule", { value: true });
|
7 | exports.Trie = void 0;
|
8 | const path_to_regexp_1 = require("path-to-regexp");
|
9 | const openapi_path_1 = require("./openapi-path");
|
10 |
|
11 |
|
12 |
|
13 |
|
14 | class Trie {
|
15 | constructor() {
|
16 | this.root = { key: '', children: {} };
|
17 | }
|
18 | |
19 |
|
20 |
|
21 |
|
22 |
|
23 | create(routeTemplate, value) {
|
24 | const keys = routeTemplate.split('/').filter(Boolean);
|
25 | return createNode(keys, 0, value, this.root);
|
26 | }
|
27 | |
28 |
|
29 |
|
30 |
|
31 | match(path) {
|
32 | const keys = path.split('/').filter(Boolean);
|
33 | const params = {};
|
34 | const resolved = search(keys, 0, params, this.root);
|
35 | if (resolved == null || !isNodeWithValue(resolved.node))
|
36 | return undefined;
|
37 | return {
|
38 | node: resolved.node,
|
39 | params: resolved.params,
|
40 | };
|
41 | }
|
42 | |
43 |
|
44 |
|
45 | list() {
|
46 | const nodes = [];
|
47 | traverse(this.root, node => {
|
48 | nodes.push(node);
|
49 | });
|
50 | return nodes;
|
51 | }
|
52 | }
|
53 | exports.Trie = Trie;
|
54 | function isNodeWithValue(node) {
|
55 | return node.value != null;
|
56 | }
|
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 | function traverse(root, visitor) {
|
63 | if (isNodeWithValue(root))
|
64 | visitor(root);
|
65 | for (const k in root.children) {
|
66 | traverse(root.children[k], visitor);
|
67 | }
|
68 | }
|
69 |
|
70 |
|
71 |
|
72 |
|
73 |
|
74 | function matchChildren(key, parent) {
|
75 | const resolvedNodes = [];
|
76 |
|
77 | let child = parent.children[key];
|
78 | if (child) {
|
79 | resolvedNodes.push({
|
80 | node: child,
|
81 | });
|
82 | return resolvedNodes;
|
83 | }
|
84 |
|
85 | for (const k in parent.children) {
|
86 | child = parent.children[k];
|
87 | if (!child.names || !child.regexp)
|
88 | continue;
|
89 | const match = child.regexp.exec(key);
|
90 | if (match) {
|
91 | const resolved = { params: {}, node: child };
|
92 | let i = 0;
|
93 | for (const n of child.names) {
|
94 | const val = match[++i];
|
95 | resolved.params[n] = decodeURIComponent(val);
|
96 | }
|
97 | resolvedNodes.push(resolved);
|
98 | }
|
99 | }
|
100 | return resolvedNodes;
|
101 | }
|
102 |
|
103 |
|
104 |
|
105 |
|
106 |
|
107 |
|
108 |
|
109 | function search(keys, index,
|
110 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
111 | params, parent) {
|
112 | const key = keys[index];
|
113 | const resolved = { node: parent, params };
|
114 | if (key === undefined)
|
115 | return resolved;
|
116 | const children = matchChildren(key, parent);
|
117 | if (children.length === 0)
|
118 | return undefined;
|
119 |
|
120 | for (const child of children) {
|
121 | const result = search(keys, index + 1, params, child.node);
|
122 | if (result && isNodeWithValue(result.node)) {
|
123 | Object.assign(params, child.params);
|
124 | return result;
|
125 | }
|
126 | }
|
127 |
|
128 | return undefined;
|
129 | }
|
130 |
|
131 |
|
132 |
|
133 |
|
134 |
|
135 |
|
136 |
|
137 | function createNode(keys, index, value, parent) {
|
138 | const key = keys[index];
|
139 | if (key === undefined)
|
140 | return parent;
|
141 | const isLast = keys.length - 1 === index;
|
142 | let child = parent.children[key];
|
143 | if (child != null) {
|
144 |
|
145 | if (isLast) {
|
146 | if (child.value == null) {
|
147 | child.value = value;
|
148 | }
|
149 | else {
|
150 | if (child.value !== value) {
|
151 | throw new Error('Duplicate key found with different value: ' + keys.join('/'));
|
152 | }
|
153 | }
|
154 | }
|
155 | return createNode(keys, index + 1, value, child);
|
156 | }
|
157 | |
158 |
|
159 |
|
160 | child = {
|
161 | children: {},
|
162 | key: key,
|
163 | };
|
164 | if (isLast) {
|
165 | child.value = value;
|
166 | }
|
167 |
|
168 | const path = (0, openapi_path_1.toExpressPath)(key);
|
169 | const params = [];
|
170 | const re = (0, path_to_regexp_1.pathToRegexp)(path, params);
|
171 | if (params.length) {
|
172 | child.names = params.map(p => `${p.name}`);
|
173 | child.regexp = re;
|
174 | }
|
175 |
|
176 | parent.children[key] = child;
|
177 |
|
178 | return createNode(keys, index + 1, value, child);
|
179 | }
|
180 |
|
\ | No newline at end of file |