@esportsplus/routing 0.0.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.
- package/.editorconfig +9 -0
- package/.gitattributes +2 -0
- package/build/group.d.ts +3 -0
- package/build/group.js +8 -0
- package/build/index.d.ts +85 -0
- package/build/index.js +7 -0
- package/build/listener.d.ts +4 -0
- package/build/listener.js +13 -0
- package/build/middleware/dispatch.d.ts +3 -0
- package/build/middleware/dispatch.js +11 -0
- package/build/middleware/index.d.ts +31 -0
- package/build/middleware/index.js +3 -0
- package/build/middleware/match.d.ts +4 -0
- package/build/middleware/match.js +12 -0
- package/build/redirect.d.ts +2 -0
- package/build/redirect.js +10 -0
- package/build/request/index.d.ts +34 -0
- package/build/request/index.js +4 -0
- package/build/request/middleware.d.ts +3 -0
- package/build/request/middleware.js +12 -0
- package/build/request/parse.d.ts +15 -0
- package/build/request/parse.js +18 -0
- package/build/request/types.d.ts +6 -0
- package/build/request/types.js +1 -0
- package/build/routes.d.ts +13 -0
- package/build/routes.js +46 -0
- package/build/types.d.ts +16 -0
- package/build/types.js +2 -0
- package/package.json +26 -0
- package/src/group.ts +11 -0
- package/src/index.ts +9 -0
- package/src/listener.ts +24 -0
- package/src/middleware/dispatch.ts +17 -0
- package/src/middleware/index.ts +5 -0
- package/src/middleware/match.ts +26 -0
- package/src/redirect.ts +16 -0
- package/src/request/index.ts +6 -0
- package/src/request/middleware.ts +20 -0
- package/src/request/parse.ts +21 -0
- package/src/request/types.ts +13 -0
- package/src/routes.ts +63 -0
- package/src/types.ts +21 -0
- package/tsconfig.json +24 -0
package/.editorconfig
ADDED
package/.gitattributes
ADDED
package/build/group.d.ts
ADDED
package/build/group.js
ADDED
package/build/index.d.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import middleware from './middleware';
|
|
2
|
+
import redirect from './redirect';
|
|
3
|
+
import listener from './listener';
|
|
4
|
+
import request from './request';
|
|
5
|
+
import routes from './routes';
|
|
6
|
+
declare const _default: {
|
|
7
|
+
listener: (d: Record<string, any>, f: (url?: string) => {
|
|
8
|
+
data: Record<string, any>;
|
|
9
|
+
href: string;
|
|
10
|
+
hostname: string;
|
|
11
|
+
uri: string;
|
|
12
|
+
origin: string;
|
|
13
|
+
pathname: string;
|
|
14
|
+
port: string;
|
|
15
|
+
protocol: string;
|
|
16
|
+
query: {
|
|
17
|
+
[k: string]: string;
|
|
18
|
+
};
|
|
19
|
+
subdomain: string;
|
|
20
|
+
}) => void;
|
|
21
|
+
middleware: {
|
|
22
|
+
dispatch: (request: {
|
|
23
|
+
data: Record<string, any>;
|
|
24
|
+
href: string;
|
|
25
|
+
hostname: string;
|
|
26
|
+
uri: string;
|
|
27
|
+
origin: string;
|
|
28
|
+
pathname: string;
|
|
29
|
+
port: string;
|
|
30
|
+
protocol: string;
|
|
31
|
+
query: {
|
|
32
|
+
[k: string]: string;
|
|
33
|
+
};
|
|
34
|
+
subdomain: string;
|
|
35
|
+
}) => any;
|
|
36
|
+
match: (routes: import("./routes").Routes) => (request: {
|
|
37
|
+
data: Record<string, any>;
|
|
38
|
+
href: string;
|
|
39
|
+
hostname: string;
|
|
40
|
+
uri: string;
|
|
41
|
+
origin: string;
|
|
42
|
+
pathname: string;
|
|
43
|
+
port: string;
|
|
44
|
+
protocol: string;
|
|
45
|
+
query: {
|
|
46
|
+
[k: string]: string;
|
|
47
|
+
};
|
|
48
|
+
subdomain: string;
|
|
49
|
+
}, next: import("./request/types").Next) => unknown;
|
|
50
|
+
};
|
|
51
|
+
redirect: (key: string, _?: Record<string, any>) => void;
|
|
52
|
+
request: {
|
|
53
|
+
middleware: (...middleware: import("./request/types").Middleware[]) => (request: {
|
|
54
|
+
data: Record<string, any>;
|
|
55
|
+
href: string;
|
|
56
|
+
hostname: string;
|
|
57
|
+
uri: string;
|
|
58
|
+
origin: string;
|
|
59
|
+
pathname: string;
|
|
60
|
+
port: string;
|
|
61
|
+
protocol: string;
|
|
62
|
+
query: {
|
|
63
|
+
[k: string]: string;
|
|
64
|
+
};
|
|
65
|
+
subdomain: string;
|
|
66
|
+
}) => Promise<unknown>;
|
|
67
|
+
parse: (url?: string) => {
|
|
68
|
+
data: Record<string, any>;
|
|
69
|
+
href: string;
|
|
70
|
+
hostname: string;
|
|
71
|
+
uri: string;
|
|
72
|
+
origin: string;
|
|
73
|
+
pathname: string;
|
|
74
|
+
port: string;
|
|
75
|
+
protocol: string;
|
|
76
|
+
query: {
|
|
77
|
+
[k: string]: string;
|
|
78
|
+
};
|
|
79
|
+
subdomain: string;
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
routes: import("./routes").Routes;
|
|
83
|
+
};
|
|
84
|
+
export default _default;
|
|
85
|
+
export { listener, middleware, redirect, request, routes };
|
package/build/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import middleware from './middleware';
|
|
2
|
+
import redirect from './redirect';
|
|
3
|
+
import listener from './listener';
|
|
4
|
+
import request from './request';
|
|
5
|
+
import routes from './routes';
|
|
6
|
+
export default { listener, middleware, redirect, request, routes };
|
|
7
|
+
export { listener, middleware, redirect, request, routes };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
let data, factory, registered = false;
|
|
2
|
+
function update() {
|
|
3
|
+
data.request = factory();
|
|
4
|
+
}
|
|
5
|
+
export default (d, f) => {
|
|
6
|
+
data = d;
|
|
7
|
+
factory = f;
|
|
8
|
+
if (!registered) {
|
|
9
|
+
registered = true;
|
|
10
|
+
update();
|
|
11
|
+
window.addEventListener('popstate', update);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { middleware } from '../request';
|
|
2
|
+
export default (request) => {
|
|
3
|
+
let route = request.data.route;
|
|
4
|
+
if (!route) {
|
|
5
|
+
throw new Error(`Route dispatching failed, route was not defined!`);
|
|
6
|
+
}
|
|
7
|
+
if (!route.middleware.length) {
|
|
8
|
+
return route.responder(request);
|
|
9
|
+
}
|
|
10
|
+
return middleware(...route.middleware, (request => route.responder(request)))(request);
|
|
11
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
dispatch: (request: {
|
|
3
|
+
data: Record<string, any>;
|
|
4
|
+
href: string;
|
|
5
|
+
hostname: string;
|
|
6
|
+
uri: string;
|
|
7
|
+
origin: string;
|
|
8
|
+
pathname: string;
|
|
9
|
+
port: string;
|
|
10
|
+
protocol: string;
|
|
11
|
+
query: {
|
|
12
|
+
[k: string]: string;
|
|
13
|
+
};
|
|
14
|
+
subdomain: string;
|
|
15
|
+
}) => any;
|
|
16
|
+
match: (routes: import("../routes").Routes) => (request: {
|
|
17
|
+
data: Record<string, any>;
|
|
18
|
+
href: string;
|
|
19
|
+
hostname: string;
|
|
20
|
+
uri: string;
|
|
21
|
+
origin: string;
|
|
22
|
+
pathname: string;
|
|
23
|
+
port: string;
|
|
24
|
+
protocol: string;
|
|
25
|
+
query: {
|
|
26
|
+
[k: string]: string;
|
|
27
|
+
};
|
|
28
|
+
subdomain: string;
|
|
29
|
+
}, next: import("../request/types").Next) => unknown;
|
|
30
|
+
};
|
|
31
|
+
export default _default;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export default (routes) => {
|
|
2
|
+
return (request, next) => {
|
|
3
|
+
let name = (routes.subdomains[request.subdomain] || {})[request.uri], route = routes.static[name];
|
|
4
|
+
if (!route) {
|
|
5
|
+
}
|
|
6
|
+
if (!route && routes.fallback) {
|
|
7
|
+
route = routes.static[routes.fallback];
|
|
8
|
+
}
|
|
9
|
+
request.data.route = route;
|
|
10
|
+
return next(request);
|
|
11
|
+
};
|
|
12
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import routes from './routes';
|
|
2
|
+
export default (key, _ = {}) => {
|
|
3
|
+
if (key.startsWith('http://') || key.startsWith('https://')) {
|
|
4
|
+
window.location.replace(key);
|
|
5
|
+
}
|
|
6
|
+
if (!routes.static[key]) {
|
|
7
|
+
throw new Error(`Route '${key}' does not exist`);
|
|
8
|
+
}
|
|
9
|
+
window.location.hash = `#${routes.static[key].pattern}`;
|
|
10
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import middleware from './middleware';
|
|
2
|
+
import parse from './parse';
|
|
3
|
+
declare const _default: {
|
|
4
|
+
middleware: (...middleware: import("./types").Middleware[]) => (request: {
|
|
5
|
+
data: Record<string, any>;
|
|
6
|
+
href: string;
|
|
7
|
+
hostname: string;
|
|
8
|
+
uri: string;
|
|
9
|
+
origin: string;
|
|
10
|
+
pathname: string;
|
|
11
|
+
port: string;
|
|
12
|
+
protocol: string;
|
|
13
|
+
query: {
|
|
14
|
+
[k: string]: string;
|
|
15
|
+
};
|
|
16
|
+
subdomain: string;
|
|
17
|
+
}) => Promise<unknown>;
|
|
18
|
+
parse: (url?: string) => {
|
|
19
|
+
data: Record<string, any>;
|
|
20
|
+
href: string;
|
|
21
|
+
hostname: string;
|
|
22
|
+
uri: string;
|
|
23
|
+
origin: string;
|
|
24
|
+
pathname: string;
|
|
25
|
+
port: string;
|
|
26
|
+
protocol: string;
|
|
27
|
+
query: {
|
|
28
|
+
[k: string]: string;
|
|
29
|
+
};
|
|
30
|
+
subdomain: string;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
export default _default;
|
|
34
|
+
export { middleware, parse };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export default (...middleware) => {
|
|
2
|
+
let i = -1, n = middleware.length, next = (request) => middleware[++i](request, (i < n ? next : () => {
|
|
3
|
+
throw new Error('Request middleware did not return a responder');
|
|
4
|
+
}));
|
|
5
|
+
return async (request) => {
|
|
6
|
+
if (!middleware.length) {
|
|
7
|
+
throw new Error('Request middleware has not been defined');
|
|
8
|
+
}
|
|
9
|
+
i = -1;
|
|
10
|
+
return await next(request);
|
|
11
|
+
};
|
|
12
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
declare const _default: (url?: string) => {
|
|
2
|
+
data: Record<string, any>;
|
|
3
|
+
href: string;
|
|
4
|
+
hostname: string;
|
|
5
|
+
uri: string;
|
|
6
|
+
origin: string;
|
|
7
|
+
pathname: string;
|
|
8
|
+
port: string;
|
|
9
|
+
protocol: string;
|
|
10
|
+
query: {
|
|
11
|
+
[k: string]: string;
|
|
12
|
+
};
|
|
13
|
+
subdomain: string;
|
|
14
|
+
};
|
|
15
|
+
export default _default;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export default (url = window.location.href) => {
|
|
2
|
+
let data = new URL(url), subdomain = data.host.split('.')[0] || '';
|
|
3
|
+
if (['127', 'www'].includes(`${subdomain}`)) {
|
|
4
|
+
subdomain = '';
|
|
5
|
+
}
|
|
6
|
+
return {
|
|
7
|
+
data: {},
|
|
8
|
+
href: data.href,
|
|
9
|
+
hostname: data.hostname,
|
|
10
|
+
uri: data.hash.replace('#/', '/') || '/',
|
|
11
|
+
origin: data.origin,
|
|
12
|
+
pathname: data.pathname,
|
|
13
|
+
port: data.port,
|
|
14
|
+
protocol: data.protocol,
|
|
15
|
+
query: Object.fromEntries(data.searchParams.entries()),
|
|
16
|
+
subdomain
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import parse from './parse';
|
|
2
|
+
type Middleware = (request: Request, next: Next) => unknown;
|
|
3
|
+
type Next = (request: Request) => unknown;
|
|
4
|
+
type Request = ReturnType<typeof parse>;
|
|
5
|
+
type Responder = (request: Request) => Promise<unknown> | unknown;
|
|
6
|
+
export { Middleware, Next, Request, Responder };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Group, Responder, Route } from './types';
|
|
2
|
+
declare class Routes {
|
|
3
|
+
dynamic: Record<Route['name'], Route>;
|
|
4
|
+
fallback?: string;
|
|
5
|
+
groups: Group[];
|
|
6
|
+
static: Record<Route['name'], Route>;
|
|
7
|
+
subdomains: Record<Route['subdomain'], Record<Route['pattern'], Route['name']>>;
|
|
8
|
+
add(name: string, pattern: string, responder: Responder): Route;
|
|
9
|
+
group(group: any, routes: (routes: Routes) => void): void;
|
|
10
|
+
}
|
|
11
|
+
declare const _default: Routes;
|
|
12
|
+
export default _default;
|
|
13
|
+
export { Routes };
|
package/build/routes.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
class Routes {
|
|
2
|
+
dynamic = {};
|
|
3
|
+
fallback;
|
|
4
|
+
groups = [];
|
|
5
|
+
static = {};
|
|
6
|
+
subdomains = {};
|
|
7
|
+
add(name, pattern, responder) {
|
|
8
|
+
let route = {
|
|
9
|
+
middleware: [],
|
|
10
|
+
name: '',
|
|
11
|
+
pattern: '',
|
|
12
|
+
responder,
|
|
13
|
+
subdomain: ''
|
|
14
|
+
};
|
|
15
|
+
for (let i = 0, n = this.groups.length; i < n; i++) {
|
|
16
|
+
let group = this.groups[i];
|
|
17
|
+
route.name += group.name;
|
|
18
|
+
route.pattern += group.pattern;
|
|
19
|
+
route.subdomain = group.subdomain + route.subdomain;
|
|
20
|
+
if (group.middleware.length) {
|
|
21
|
+
route.middleware.push(...group.middleware);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
route.name += name;
|
|
25
|
+
route.pattern += pattern;
|
|
26
|
+
if (route.pattern[0] !== '/') {
|
|
27
|
+
route.pattern = `/${route.pattern}`;
|
|
28
|
+
}
|
|
29
|
+
if (route.subdomain === 'www') {
|
|
30
|
+
route.subdomain = '';
|
|
31
|
+
}
|
|
32
|
+
if (!this.subdomains[route.subdomain]) {
|
|
33
|
+
this.subdomains[route.subdomain] = {};
|
|
34
|
+
}
|
|
35
|
+
this.static[route.name] = route;
|
|
36
|
+
this.subdomains[route.subdomain][route.pattern] = route.name;
|
|
37
|
+
return route;
|
|
38
|
+
}
|
|
39
|
+
group(group, routes) {
|
|
40
|
+
this.groups.push(group);
|
|
41
|
+
routes(this);
|
|
42
|
+
this.groups.pop();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export default new Routes();
|
|
46
|
+
export { Routes };
|
package/build/types.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Middleware, Next, Request, Responder } from "./request/types";
|
|
2
|
+
import { Routes } from './routes';
|
|
3
|
+
type Group = {
|
|
4
|
+
middleware: Middleware[];
|
|
5
|
+
name: string;
|
|
6
|
+
pattern: string;
|
|
7
|
+
subdomain: string;
|
|
8
|
+
};
|
|
9
|
+
type Route = {
|
|
10
|
+
middleware: Middleware[];
|
|
11
|
+
name: string;
|
|
12
|
+
pattern: string;
|
|
13
|
+
responder: Responder;
|
|
14
|
+
subdomain: string;
|
|
15
|
+
};
|
|
16
|
+
export { Group, Middleware, Next, Request, Responder, Route, Routes };
|
package/build/types.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"author": "ICJR",
|
|
3
|
+
"description": "Routing",
|
|
4
|
+
"devDependencies": {
|
|
5
|
+
"tsc-alias": "^1.8.1",
|
|
6
|
+
"typescript": "^4.9.3"
|
|
7
|
+
},
|
|
8
|
+
"main": "./build/index.js",
|
|
9
|
+
"name": "@esportsplus/routing",
|
|
10
|
+
"private": false,
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc && tsc-alias",
|
|
13
|
+
"-": "-",
|
|
14
|
+
"prepare": "npm run build",
|
|
15
|
+
"prepublishOnly": "npm run build"
|
|
16
|
+
},
|
|
17
|
+
"types": "./build/index.d.ts",
|
|
18
|
+
"typesVersions": {
|
|
19
|
+
"*": {
|
|
20
|
+
"types": [
|
|
21
|
+
"build/types"
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"version": "0.0.1"
|
|
26
|
+
}
|
package/src/group.ts
ADDED
package/src/index.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import middleware from './middleware';
|
|
2
|
+
import redirect from './redirect';
|
|
3
|
+
import listener from './listener';
|
|
4
|
+
import request from './request';
|
|
5
|
+
import routes from './routes';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
export default { listener, middleware, redirect, request, routes };
|
|
9
|
+
export { listener, middleware, redirect, request, routes };
|
package/src/listener.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { parse } from './request';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
let data: Record<string, any>,
|
|
5
|
+
factory: typeof parse,
|
|
6
|
+
registered: boolean = false;
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
function update() {
|
|
10
|
+
data.request = factory();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
export default (d: typeof data, f: typeof factory) => {
|
|
15
|
+
data = d;
|
|
16
|
+
factory = f;
|
|
17
|
+
|
|
18
|
+
if (!registered) {
|
|
19
|
+
registered = true;
|
|
20
|
+
update();
|
|
21
|
+
|
|
22
|
+
window.addEventListener('popstate', update);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { middleware } from '~/request';
|
|
2
|
+
import { Request } from '~/types';
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export default (request: Request) => {
|
|
6
|
+
let route = request.data.route;
|
|
7
|
+
|
|
8
|
+
if (!route) {
|
|
9
|
+
throw new Error(`Route dispatching failed, route was not defined!`);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (!route.middleware.length) {
|
|
13
|
+
return route.responder(request);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return middleware(...route.middleware, (request => route.responder(request)))(request);
|
|
17
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Routes } from '~/routes';
|
|
2
|
+
import { Next, Request } from '~/types';
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export default (routes: Routes) => {
|
|
6
|
+
return (request: Request, next: Next) => {
|
|
7
|
+
let name = (routes.subdomains[request.subdomain] || {})[request.uri],
|
|
8
|
+
route = routes.static[name];
|
|
9
|
+
|
|
10
|
+
// Dynamic routing
|
|
11
|
+
if (!route) {
|
|
12
|
+
// TODO:
|
|
13
|
+
// - Trie based routing
|
|
14
|
+
// - Bind variables to request
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Fallback route
|
|
18
|
+
if (!route && routes.fallback) {
|
|
19
|
+
route = routes.static[routes.fallback];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
request.data.route = route;
|
|
23
|
+
|
|
24
|
+
return next(request);
|
|
25
|
+
};
|
|
26
|
+
};
|
package/src/redirect.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import routes from './routes';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export default (key: string, _: Record<string, any> = {}) => {
|
|
5
|
+
// External redirect
|
|
6
|
+
if (key.startsWith('http://') || key.startsWith('https://')) {
|
|
7
|
+
window.location.replace(key);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Internal route based redirect
|
|
11
|
+
if (!routes.static[key]) {
|
|
12
|
+
throw new Error(`Route '${key}' does not exist`);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
window.location.hash = `#${routes.static[key].pattern}`;
|
|
16
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Middleware, Request } from './types';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export default (...middleware: Middleware[]) => {
|
|
5
|
+
let i = -1,
|
|
6
|
+
n = middleware.length,
|
|
7
|
+
next = (request: Request) => middleware[++i](request, (i < n ? next : () => {
|
|
8
|
+
throw new Error('Request middleware did not return a responder');
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
return async (request: Request) => {
|
|
12
|
+
if (!middleware.length) {
|
|
13
|
+
throw new Error('Request middleware has not been defined');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
i = -1;
|
|
17
|
+
|
|
18
|
+
return await next(request);
|
|
19
|
+
};
|
|
20
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export default (url: string = window.location.href) => {
|
|
2
|
+
let data = new URL( url ),
|
|
3
|
+
subdomain = data.host.split('.')[0] || '';
|
|
4
|
+
|
|
5
|
+
if (['127', 'www'].includes(`${subdomain}`)) {
|
|
6
|
+
subdomain = '';
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
data: {} as Record<string, any>,
|
|
11
|
+
href: data.href,
|
|
12
|
+
hostname: data.hostname,
|
|
13
|
+
uri: data.hash.replace('#/', '/') || '/',
|
|
14
|
+
origin: data.origin,
|
|
15
|
+
pathname: data.pathname,
|
|
16
|
+
port: data.port,
|
|
17
|
+
protocol: data.protocol,
|
|
18
|
+
query: Object.fromEntries( data.searchParams.entries() ),
|
|
19
|
+
subdomain
|
|
20
|
+
};
|
|
21
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import parse from './parse';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
type Middleware = (request: Request, next: Next) => unknown;
|
|
5
|
+
|
|
6
|
+
type Next = (request: Request) => unknown;
|
|
7
|
+
|
|
8
|
+
type Request = ReturnType<typeof parse>;
|
|
9
|
+
|
|
10
|
+
type Responder = (request: Request) => Promise<unknown> | unknown;
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
export { Middleware, Next, Request, Responder };
|
package/src/routes.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Group, Responder, Route } from './types';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Routes {
|
|
5
|
+
dynamic: Record<Route['name'], Route> = {};
|
|
6
|
+
fallback?: string;
|
|
7
|
+
groups: Group[] = [];
|
|
8
|
+
static: Record<Route['name'], Route> = {};
|
|
9
|
+
subdomains: Record<Route['subdomain'], Record<Route['pattern'], Route['name']>> = {};
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
add(name: string, pattern: string, responder: Responder) {
|
|
13
|
+
let route: Route = {
|
|
14
|
+
middleware: [],
|
|
15
|
+
name: '',
|
|
16
|
+
pattern: '',
|
|
17
|
+
responder,
|
|
18
|
+
subdomain: ''
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
for (let i = 0, n = this.groups.length; i < n; i++) {
|
|
22
|
+
let group = this.groups[i];
|
|
23
|
+
|
|
24
|
+
route.name += group.name;
|
|
25
|
+
route.pattern += group.pattern;
|
|
26
|
+
route.subdomain = group.subdomain + route.subdomain;
|
|
27
|
+
|
|
28
|
+
if (group.middleware.length) {
|
|
29
|
+
route.middleware.push(...group.middleware);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
route.name += name;
|
|
34
|
+
route.pattern += pattern;
|
|
35
|
+
|
|
36
|
+
if (route.pattern[0] !== '/') {
|
|
37
|
+
route.pattern = `/${route.pattern}`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (route.subdomain === 'www') {
|
|
41
|
+
route.subdomain = '';
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!this.subdomains[route.subdomain]) {
|
|
45
|
+
this.subdomains[route.subdomain] = {};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
this.static[route.name] = route;
|
|
49
|
+
this.subdomains[route.subdomain][route.pattern] = route.name;
|
|
50
|
+
|
|
51
|
+
return route;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
group(group: any, routes: (routes: Routes) => void) {
|
|
55
|
+
this.groups.push(group);
|
|
56
|
+
routes(this);
|
|
57
|
+
this.groups.pop();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
export default new Routes();
|
|
63
|
+
export { Routes };
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Middleware, Next, Request, Responder } from "./request/types";
|
|
2
|
+
import { Routes } from './routes';
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
type Group = {
|
|
6
|
+
middleware: Middleware[];
|
|
7
|
+
name: string;
|
|
8
|
+
pattern: string;
|
|
9
|
+
subdomain: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
type Route = {
|
|
13
|
+
middleware: Middleware[];
|
|
14
|
+
name: string;
|
|
15
|
+
pattern: string;
|
|
16
|
+
responder: Responder;
|
|
17
|
+
subdomain: string;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
export { Group, Middleware, Next, Request, Responder, Route, Routes };
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"allowJs": true,
|
|
4
|
+
"alwaysStrict": true,
|
|
5
|
+
"baseUrl": "src",
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"declarationDir": "./build",
|
|
8
|
+
"lib": ["dom", "dom.iterable", "esnext"],
|
|
9
|
+
"module": "esnext",
|
|
10
|
+
"moduleResolution": "nodenext",
|
|
11
|
+
"noUnusedLocals": true,
|
|
12
|
+
"noUnusedParameters": true,
|
|
13
|
+
"outDir": "./build",
|
|
14
|
+
"paths": {
|
|
15
|
+
"~/*": ["*"]
|
|
16
|
+
},
|
|
17
|
+
"removeComments": true,
|
|
18
|
+
"resolveJsonModule": true,
|
|
19
|
+
"strict": true,
|
|
20
|
+
"target": "esnext"
|
|
21
|
+
},
|
|
22
|
+
"exclude": ["node_modules"],
|
|
23
|
+
"include": ["src"]
|
|
24
|
+
}
|