vanilla-jet 1.1.6 → 1.1.8
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/docs/router.md +84 -0
- package/framework/router.js +32 -12
- package/package.json +1 -1
package/docs/router.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Router Documentation
|
|
2
|
+
|
|
3
|
+
## routeToRegExp Method
|
|
4
|
+
|
|
5
|
+
The `routeToRegExp` method converts URL route patterns into regular expressions for route matching. This method is inspired by Backbone's router implementation and supports various parameter types.
|
|
6
|
+
|
|
7
|
+
### Syntax
|
|
8
|
+
```javascript
|
|
9
|
+
router.routeToRegExp(route)
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
### Parameters
|
|
13
|
+
- `route` (String): The route pattern to convert to a regular expression
|
|
14
|
+
|
|
15
|
+
### Return Value
|
|
16
|
+
Returns a RegExp object that can be used to match URLs against the route pattern.
|
|
17
|
+
|
|
18
|
+
### Supported Pattern Types
|
|
19
|
+
|
|
20
|
+
1. **Optional Parameters**: `(param)`
|
|
21
|
+
- Matches optional segments in the URL
|
|
22
|
+
- Example: `/items(/:id)` matches both `/items` and `/items/123`
|
|
23
|
+
|
|
24
|
+
2. **Named Parameters**: `:param`
|
|
25
|
+
- Matches any segment in the URL and captures it as a parameter
|
|
26
|
+
- Example: `/users/:id` matches `/users/123`
|
|
27
|
+
|
|
28
|
+
3. **Splat Parameters**: `*param`
|
|
29
|
+
- Matches any number of URL segments
|
|
30
|
+
- Example: `/files/*path` matches `/files/folder/subfolder/file.txt`
|
|
31
|
+
|
|
32
|
+
### Examples
|
|
33
|
+
|
|
34
|
+
```javascript
|
|
35
|
+
const router = new Router();
|
|
36
|
+
|
|
37
|
+
// Example 1: Simple route
|
|
38
|
+
router.routeToRegExp('/users')
|
|
39
|
+
// Matches: /users
|
|
40
|
+
// Does not match: /users/123, /user
|
|
41
|
+
|
|
42
|
+
// Example 2: Route with named parameter
|
|
43
|
+
router.routeToRegExp('/users/:id')
|
|
44
|
+
// Matches: /users/123, /users/abc
|
|
45
|
+
// Does not match: /users, /users/123/edit
|
|
46
|
+
|
|
47
|
+
// Example 3: Route with optional parameter
|
|
48
|
+
router.routeToRegExp('/items(/:id)')
|
|
49
|
+
// Matches: /items, /items/123
|
|
50
|
+
// Does not match: /items/123/edit
|
|
51
|
+
|
|
52
|
+
// Example 4: Route with splat parameter
|
|
53
|
+
router.routeToRegExp('/files/*path')
|
|
54
|
+
// Matches: /files/document.pdf, /files/images/photo.jpg
|
|
55
|
+
// Matches any number of segments after /files/
|
|
56
|
+
|
|
57
|
+
// Example 5: Route with query parameters
|
|
58
|
+
router.routeToRegExp('/search')
|
|
59
|
+
// Matches: /search, /search?q=test
|
|
60
|
+
// The query parameters are captured in the regex
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Regular Expression Components
|
|
64
|
+
|
|
65
|
+
The method uses several regex patterns to handle different URL components:
|
|
66
|
+
|
|
67
|
+
1. `escapeRegExp`: `/[\-{}\[\]+?.,\\\^$|#\s]/g`
|
|
68
|
+
- Escapes special regex characters in the route
|
|
69
|
+
|
|
70
|
+
2. `optionalParam`: `/\((.*?)\)/g`
|
|
71
|
+
- Matches optional parameters in parentheses
|
|
72
|
+
|
|
73
|
+
3. `namedParam`: `/(\(\?)?:\w+/g`
|
|
74
|
+
- Matches named parameters starting with ':'
|
|
75
|
+
|
|
76
|
+
4. `splatParam`: `/\*\w+/g`
|
|
77
|
+
- Matches splat parameters starting with '*'
|
|
78
|
+
|
|
79
|
+
### Notes
|
|
80
|
+
|
|
81
|
+
- The method automatically handles query strings in URLs
|
|
82
|
+
- All routes are anchored to the start of the string with `^`
|
|
83
|
+
- The method is case-sensitive
|
|
84
|
+
- Special characters in routes should be escaped properly
|
package/framework/router.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
let Request = require('./request.js');
|
|
2
2
|
let Response = require('./response.js');
|
|
3
3
|
let _ = require('underscore');
|
|
4
|
+
let path = require('path');
|
|
5
|
+
let fs = require('fs');
|
|
4
6
|
|
|
5
7
|
class Router {
|
|
6
8
|
|
|
@@ -14,11 +16,33 @@ class Router {
|
|
|
14
16
|
this.defaultRoute = '';
|
|
15
17
|
this.server = server;
|
|
16
18
|
this.cwd = process.cwd();
|
|
19
|
+
this.mimes = {
|
|
20
|
+
'png': 'image/png',
|
|
21
|
+
'webp': 'image/webp',
|
|
22
|
+
'jpg': 'image/jpg',
|
|
23
|
+
'css': 'text/css',
|
|
24
|
+
'gz': 'application/x-gzip',
|
|
25
|
+
'gif': 'image/gif',
|
|
26
|
+
'js': 'text/javascript',
|
|
27
|
+
'svg': 'image/svg+xml',
|
|
28
|
+
'ttf': 'application/x-font-ttf',
|
|
29
|
+
'otf': 'application/x-font-opentype',
|
|
30
|
+
'pdf': 'application/pdf',
|
|
31
|
+
'json': 'application/json'
|
|
32
|
+
};
|
|
33
|
+
this.compressionMimes = {
|
|
34
|
+
'css': 'text/css',
|
|
35
|
+
'js': 'text/javascript',
|
|
36
|
+
'gz': 'application/x-gzip'
|
|
37
|
+
};
|
|
17
38
|
}
|
|
18
39
|
|
|
19
40
|
routeToRegExp(route) {
|
|
20
41
|
|
|
21
|
-
|
|
42
|
+
let optionalParam = /\((.*?)\)/g,
|
|
43
|
+
namedParam = /(\(\?)?:\w+/g,
|
|
44
|
+
splatParam = /\*\w+/g,
|
|
45
|
+
escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g;
|
|
22
46
|
// Convert route to regular expression, this was taken from Backbone's router
|
|
23
47
|
route = route.replace(escapeRegExp, '\\$&')
|
|
24
48
|
.replace(optionalParam, '(?:$1)?')
|
|
@@ -93,21 +117,18 @@ class Router {
|
|
|
93
117
|
return obj.onNotFound(response);
|
|
94
118
|
}
|
|
95
119
|
|
|
96
|
-
const acceptEncoding = req.headers['accept-encoding'] || '';
|
|
120
|
+
// -- const acceptEncoding = req.headers['accept-encoding'] || '';
|
|
97
121
|
const fileStream = fs.createReadStream(filename);
|
|
98
122
|
fileStream.on('error', (streamErr) => {
|
|
99
|
-
|
|
123
|
+
console.error("Error reading file:", streamErr);
|
|
100
124
|
res.writeHead(500);
|
|
101
|
-
res.end('Error
|
|
125
|
+
res.end('Server Error');
|
|
102
126
|
});
|
|
103
127
|
|
|
104
128
|
extHeader['Content-Length'] = stats.size;
|
|
105
129
|
res.writeHead(200, extHeader);
|
|
106
130
|
fileStream.pipe(res);
|
|
107
|
-
|
|
108
|
-
res.on('close', () => {
|
|
109
|
-
//console.log("✅ Archivo servido y cerrado:", filename);
|
|
110
|
-
});
|
|
131
|
+
res.on('close', () => {});
|
|
111
132
|
});
|
|
112
133
|
}
|
|
113
134
|
}
|
|
@@ -119,7 +140,7 @@ class Router {
|
|
|
119
140
|
isProtectedFile(route) {
|
|
120
141
|
|
|
121
142
|
let protectedDirs = ['framework', 'external', 'node_mudules'];
|
|
122
|
-
|
|
143
|
+
let routeParts = route.split('/');
|
|
123
144
|
if (routeParts[1] != undefined && routeParts.length > 2) {
|
|
124
145
|
return protectedDirs.includes(routeParts[1]);
|
|
125
146
|
}
|
|
@@ -128,12 +149,11 @@ class Router {
|
|
|
128
149
|
|
|
129
150
|
validateCallback(clazz, method) {
|
|
130
151
|
|
|
131
|
-
|
|
152
|
+
let obj = this,
|
|
153
|
+
endpoints = obj.server.endpoints;
|
|
132
154
|
|
|
133
155
|
if (endpoints[clazz] != undefined) {
|
|
134
|
-
|
|
135
156
|
clazz = endpoints[clazz];
|
|
136
|
-
|
|
137
157
|
if (typeof clazz[method] === 'function') {
|
|
138
158
|
return clazz[method];
|
|
139
159
|
}
|