@esportsplus/routing 0.0.8 → 0.0.10

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 (65) hide show
  1. package/build/hash.d.ts +70 -0
  2. package/build/hash.js +75 -0
  3. package/build/index.d.ts +6 -92
  4. package/build/index.js +6 -8
  5. package/build/middleware/dispatch.d.ts +5 -0
  6. package/build/middleware/dispatch.js +7 -0
  7. package/build/middleware/factory.d.ts +3 -3
  8. package/build/middleware/factory.js +13 -13
  9. package/build/middleware/index.d.ts +24 -47
  10. package/build/middleware/index.js +5 -4
  11. package/build/middleware/match.d.ts +10 -0
  12. package/build/middleware/match.js +23 -0
  13. package/build/router/index.d.ts +36 -0
  14. package/build/router/index.js +182 -0
  15. package/build/router/node.d.ts +17 -0
  16. package/build/router/node.js +93 -0
  17. package/build/router/path.d.ts +14 -0
  18. package/build/router/path.js +21 -0
  19. package/build/slugify.d.ts +2 -0
  20. package/build/slugify.js +3 -0
  21. package/build/symbols.d.ts +4 -0
  22. package/build/symbols.js +4 -0
  23. package/build/types.d.ts +12 -26
  24. package/build/types.js +2 -1
  25. package/package.json +2 -3
  26. package/readme.md +1 -0
  27. package/src/hash.ts +106 -0
  28. package/src/index.ts +4 -6
  29. package/src/middleware/dispatch.ts +12 -0
  30. package/src/middleware/factory.ts +10 -9
  31. package/src/middleware/index.ts +4 -3
  32. package/src/middleware/match.ts +41 -0
  33. package/src/router/index.ts +237 -0
  34. package/src/router/node.ts +141 -0
  35. package/src/router/path.ts +29 -0
  36. package/src/slugify.ts +4 -0
  37. package/src/symbols.ts +8 -0
  38. package/src/types.ts +9 -26
  39. package/tsconfig.json +5 -19
  40. package/build/group.d.ts +0 -3
  41. package/build/group.js +0 -8
  42. package/build/listener.d.ts +0 -4
  43. package/build/listener.js +0 -13
  44. package/build/middleware/common/dispatch.d.ts +0 -3
  45. package/build/middleware/common/dispatch.js +0 -11
  46. package/build/middleware/common/index.d.ts +0 -29
  47. package/build/middleware/common/index.js +0 -3
  48. package/build/middleware/common/match.d.ts +0 -3
  49. package/build/middleware/common/match.js +0 -12
  50. package/build/middleware/factory-backup.d.ts +0 -3
  51. package/build/middleware/factory-backup.js +0 -11
  52. package/build/redirect.d.ts +0 -2
  53. package/build/redirect.js +0 -10
  54. package/build/routes.d.ts +0 -20
  55. package/build/routes.js +0 -45
  56. package/build/url.d.ts +0 -30
  57. package/build/url.js +0 -22
  58. package/src/group.ts +0 -11
  59. package/src/listener.ts +0 -24
  60. package/src/middleware/common/dispatch.ts +0 -17
  61. package/src/middleware/common/index.ts +0 -5
  62. package/src/middleware/common/match.ts +0 -24
  63. package/src/redirect.ts +0 -16
  64. package/src/routes.ts +0 -68
  65. package/src/url.ts +0 -30
@@ -0,0 +1,70 @@
1
+ import { Router } from './types';
2
+ declare let cache: {
3
+ factory: typeof request;
4
+ state: Record<PropertyKey, unknown>;
5
+ }[];
6
+ declare const back: () => void;
7
+ declare const forward: () => void;
8
+ declare const listener: {
9
+ register: (factory: (typeof cache)[0]['factory'], state: (typeof cache)[0]['state']) => () => void;
10
+ remove: (state: (typeof cache)[0]['state']) => void;
11
+ };
12
+ declare const factory: {
13
+ redirect: (router: Router) => (path: string, { state, values }: {
14
+ state?: Record<PropertyKey, unknown> | undefined;
15
+ values?: unknown[] | undefined;
16
+ }) => void;
17
+ uri: (router: Router) => (path: string, values?: unknown[]) => string;
18
+ };
19
+ declare const request: (url?: string) => {
20
+ href: string;
21
+ hostname: string;
22
+ method: string;
23
+ origin: string;
24
+ path: string;
25
+ port: string;
26
+ protocol: string;
27
+ query: {
28
+ [k: string]: string;
29
+ };
30
+ };
31
+ declare const _default: {
32
+ back: () => void;
33
+ factory: {
34
+ redirect: (router: Router) => (path: string, { state, values }: {
35
+ state?: Record<PropertyKey, unknown> | undefined;
36
+ values?: unknown[] | undefined;
37
+ }) => void;
38
+ uri: (router: Router) => (path: string, values?: unknown[]) => string;
39
+ };
40
+ forward: () => void;
41
+ listener: {
42
+ register: (factory: (url?: string) => {
43
+ href: string;
44
+ hostname: string;
45
+ method: string;
46
+ origin: string;
47
+ path: string;
48
+ port: string;
49
+ protocol: string;
50
+ query: {
51
+ [k: string]: string;
52
+ };
53
+ }, state: Record<PropertyKey, unknown>) => () => void;
54
+ remove: (state: Record<PropertyKey, unknown>) => void;
55
+ };
56
+ request: (url?: string) => {
57
+ href: string;
58
+ hostname: string;
59
+ method: string;
60
+ origin: string;
61
+ path: string;
62
+ port: string;
63
+ protocol: string;
64
+ query: {
65
+ [k: string]: string;
66
+ };
67
+ };
68
+ };
69
+ export default _default;
70
+ export { back, factory, forward, listener, request };
package/build/hash.js ADDED
@@ -0,0 +1,75 @@
1
+ let cache = [], registered = false;
2
+ function update() {
3
+ for (let i = 0, n = cache.length; i < n; i++) {
4
+ let { factory, state } = cache[i], values = factory();
5
+ for (let key in values) {
6
+ state[key] = values[key];
7
+ }
8
+ }
9
+ }
10
+ const back = () => window.history.back();
11
+ const forward = () => window.history.forward();
12
+ const listener = {
13
+ register: (factory, state) => {
14
+ cache.push({ factory, state });
15
+ if (!registered) {
16
+ registered = true;
17
+ update();
18
+ window.addEventListener('popstate', update);
19
+ }
20
+ return () => {
21
+ listener.remove(state);
22
+ };
23
+ },
24
+ remove: (state) => {
25
+ for (let i = 0, n = cache.length; i < n; i++) {
26
+ if (cache[i].state !== state) {
27
+ continue;
28
+ }
29
+ cache[i] = cache[n - 1];
30
+ cache.pop();
31
+ if (cache.length === 0) {
32
+ window.removeEventListener('popstate', update);
33
+ }
34
+ return;
35
+ }
36
+ }
37
+ };
38
+ const factory = {
39
+ redirect: (router) => {
40
+ return (path, { state, values }) => {
41
+ if (path.startsWith('http://') || path.startsWith('https://')) {
42
+ return window.location.replace(path);
43
+ }
44
+ let uri = router.uri(path, values || []);
45
+ if (uri[0] === '/') {
46
+ uri = '#' + uri;
47
+ }
48
+ window.history.pushState(state || {}, '', uri);
49
+ };
50
+ },
51
+ uri: (router) => {
52
+ return (path, values = []) => {
53
+ let uri = router.uri(path, values || []);
54
+ if (uri[0] === '/') {
55
+ uri = '#' + uri;
56
+ }
57
+ return uri;
58
+ };
59
+ }
60
+ };
61
+ const request = (url = window?.location?.href || '') => {
62
+ let { hash, hostname, href, origin, port, protocol } = new URL(url), path = hash?.replace('#/', '/')?.split('?') || ['/', ''];
63
+ return {
64
+ href,
65
+ hostname,
66
+ method: 'GET',
67
+ origin,
68
+ path: path[0],
69
+ port,
70
+ protocol,
71
+ query: Object.fromEntries((new URLSearchParams(path[1])).entries())
72
+ };
73
+ };
74
+ export default { back, factory, forward, listener, request };
75
+ export { back, factory, forward, listener, request };
package/build/index.d.ts CHANGED
@@ -1,92 +1,6 @@
1
- import middleware from './middleware';
2
- import redirect from './redirect';
3
- import listener from './listener';
4
- import routes from './routes';
5
- import url from './url';
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
- origin: string;
12
- path: string;
13
- port: string;
14
- protocol: string;
15
- query: {
16
- [k: string]: string;
17
- };
18
- subdomain: string;
19
- }) => void;
20
- middleware: {
21
- common: {
22
- dispatch: (request: {
23
- data: Record<string, any>;
24
- href: string;
25
- hostname: string;
26
- origin: string;
27
- path: string;
28
- port: string;
29
- protocol: string;
30
- query: {
31
- [k: string]: string;
32
- };
33
- subdomain: string;
34
- }) => any;
35
- match: ({ routes, subdomains }: import("./types").Routes) => (request: {
36
- data: Record<string, any>;
37
- href: string;
38
- hostname: string;
39
- origin: string;
40
- path: string;
41
- port: string;
42
- protocol: string;
43
- query: {
44
- [k: string]: string;
45
- };
46
- subdomain: string;
47
- }, next: import("./types").Next) => unknown;
48
- };
49
- factory: (...m: import("./types").Middleware[]) => (request: {
50
- data: Record<string, any>;
51
- href: string;
52
- hostname: string;
53
- origin: string;
54
- path: string;
55
- port: string;
56
- protocol: string;
57
- query: {
58
- [k: string]: string;
59
- };
60
- subdomain: string;
61
- }) => Promise<unknown>;
62
- };
63
- redirect: (key: string, _?: Record<string, any>) => void;
64
- routes: {
65
- add: ({ name, path, responder }: {
66
- name: string;
67
- path?: string | undefined;
68
- responder: import("./types").Responder;
69
- }) => import("./types").Route;
70
- group: (group: any, fn: (routes: import("./types").Routes) => void) => void;
71
- routes: Record<string, import("./types").Route>;
72
- subdomains: Record<string, Record<string, string>>;
73
- };
74
- url: {
75
- parse: (url?: string) => {
76
- data: Record<string, any>;
77
- href: string;
78
- hostname: string;
79
- origin: string;
80
- path: string;
81
- port: string;
82
- protocol: string;
83
- query: {
84
- [k: string]: string;
85
- };
86
- subdomain: string;
87
- };
88
- };
89
- };
90
- export default _default;
91
- export { listener, middleware, redirect, routes, url };
92
- export * from './types';
1
+ import hash from './hash';
2
+ import middleware from './middleware';
3
+ import router from './router';
4
+ import slugify from './slugify';
5
+ export { hash, middleware, router, slugify };
6
+ export * from './types';
package/build/index.js CHANGED
@@ -1,8 +1,6 @@
1
- import middleware from './middleware';
2
- import redirect from './redirect';
3
- import listener from './listener';
4
- import routes from './routes';
5
- import url from './url';
6
- export default { listener, middleware, redirect, routes, url };
7
- export { listener, middleware, redirect, routes, url };
8
- export * from './types';
1
+ import hash from './hash';
2
+ import middleware from './middleware';
3
+ import router from './router';
4
+ import slugify from './slugify';
5
+ export { hash, middleware, router, slugify };
6
+ export * from './types';
@@ -0,0 +1,5 @@
1
+ import { Router } from '../types';
2
+ declare const _default: (request: {
3
+ data: ReturnType<Router['match']>;
4
+ }) => unknown;
5
+ export default _default;
@@ -0,0 +1,7 @@
1
+ export default (request) => {
2
+ let { route } = request.data;
3
+ if (!route) {
4
+ throw new Error(`Routing: route dispatching failed, route is undefined!`);
5
+ }
6
+ return route.dispatcher(request);
7
+ };
@@ -1,3 +1,3 @@
1
- import { Middleware, Request } from '../types';
2
- declare const _default: (...m: Middleware[]) => (request: Request) => Promise<unknown>;
3
- export default _default;
1
+ import { Middleware } from '../types';
2
+ declare const _default: (...middleware: Middleware[]) => <T>(request: T) => unknown;
3
+ export default _default;
@@ -1,13 +1,13 @@
1
- function error() {
2
- throw new Error('Request middleware did not return a responder');
3
- }
4
- export default (...m) => {
5
- let middleware = [];
6
- for (let i = 0, n = m.length; i < n; i++) {
7
- middleware[i] = (request) => m[i](request, middleware[i + 1] || error);
8
- }
9
- if (!middleware.length) {
10
- throw new Error('Request middleware has not been defined');
11
- }
12
- return async (request) => await middleware[0](request);
13
- };
1
+ function error() {
2
+ throw new Error('Routing: request middleware did not return a responder');
3
+ }
4
+ export default (...middleware) => {
5
+ let stack = [];
6
+ for (let i = 0, n = middleware.length; i < n; i++) {
7
+ stack[i] = (request) => middleware[i](request, stack[i + 1] || error);
8
+ }
9
+ if (!stack.length) {
10
+ throw new Error('Routing: request middleware has not been defined');
11
+ }
12
+ return (request) => stack[0](request);
13
+ };
@@ -1,47 +1,24 @@
1
- import common from './common';
2
- import factory from './factory';
3
- declare const _default: {
4
- common: {
5
- dispatch: (request: {
6
- data: Record<string, any>;
7
- href: string;
8
- hostname: string;
9
- origin: string;
10
- path: string;
11
- port: string;
12
- protocol: string;
13
- query: {
14
- [k: string]: string;
15
- };
16
- subdomain: string;
17
- }) => any;
18
- match: ({ routes, subdomains }: import("../types").Routes) => (request: {
19
- data: Record<string, any>;
20
- href: string;
21
- hostname: string;
22
- origin: string;
23
- path: string;
24
- port: string;
25
- protocol: string;
26
- query: {
27
- [k: string]: string;
28
- };
29
- subdomain: string;
30
- }, next: import("../types").Next) => unknown;
31
- };
32
- factory: (...m: import("../types").Middleware[]) => (request: {
33
- data: Record<string, any>;
34
- href: string;
35
- hostname: string;
36
- origin: string;
37
- path: string;
38
- port: string;
39
- protocol: string;
40
- query: {
41
- [k: string]: string;
42
- };
43
- subdomain: string;
44
- }) => Promise<unknown>;
45
- };
46
- export default _default;
47
- export { common, factory };
1
+ import dispatch from './dispatch';
2
+ import factory from './factory';
3
+ import match from './match';
4
+ declare const _default: {
5
+ dispatch: (request: {
6
+ data: {
7
+ parameters?: Record<PropertyKey, unknown> | undefined;
8
+ route?: import("../router").Route | undefined;
9
+ };
10
+ }) => unknown;
11
+ factory: (...middleware: import("../types").Middleware[]) => <T>(request: T) => unknown;
12
+ match: (router: import("../router").Router, spa?: boolean) => (request: {
13
+ data: {
14
+ parameters?: Record<PropertyKey, unknown> | undefined;
15
+ route?: import("../router").Route | undefined;
16
+ };
17
+ hostname: string;
18
+ method: string;
19
+ path: string;
20
+ subdomain?: string | undefined;
21
+ }, next: import("../types").Next) => unknown;
22
+ };
23
+ export default _default;
24
+ export { dispatch, factory, match };
@@ -1,4 +1,5 @@
1
- import common from './common';
2
- import factory from './factory';
3
- export default { common, factory };
4
- export { common, factory };
1
+ import dispatch from './dispatch';
2
+ import factory from './factory';
3
+ import match from './match';
4
+ export default { dispatch, factory, match };
5
+ export { dispatch, factory, match };
@@ -0,0 +1,10 @@
1
+ import { Next, Router } from '../types';
2
+ type Request = {
3
+ data: ReturnType<Router['match']>;
4
+ hostname: string;
5
+ method: string;
6
+ path: string;
7
+ subdomain?: string;
8
+ };
9
+ declare const _default: (router: Router, spa?: boolean) => (request: Request, next: Next) => unknown;
10
+ export default _default;
@@ -0,0 +1,23 @@
1
+ export default (router, spa = false) => {
2
+ let subdomain = null;
3
+ return (request, next) => {
4
+ if ((typeof request.subdomain !== 'string' && !spa) || subdomain === null) {
5
+ if (router.subdomains) {
6
+ for (let i = 0, n = router.subdomains.length; i < n; i++) {
7
+ if (!request.hostname.startsWith(router.subdomains[i])) {
8
+ continue;
9
+ }
10
+ subdomain = router.subdomains[i];
11
+ break;
12
+ }
13
+ }
14
+ if (subdomain === null) {
15
+ subdomain = '';
16
+ }
17
+ }
18
+ let { parameters, route } = router.match(request.method, request.path, request.subdomain || subdomain);
19
+ request.data.parameters = parameters;
20
+ request.data.route = route;
21
+ return next(request);
22
+ };
23
+ };
@@ -0,0 +1,36 @@
1
+ import { Middleware, Responder, Options } from '../types';
2
+ import { Node } from './node';
3
+ import factory from '../middleware/factory';
4
+ declare class Route {
5
+ dispatch: ReturnType<typeof factory> | null;
6
+ name: string | null;
7
+ path: string | null;
8
+ responder: Responder;
9
+ stack: Middleware[] | null;
10
+ subdomain: string | null;
11
+ constructor(responder: Responder);
12
+ get dispatcher(): <T>(request: T) => unknown;
13
+ }
14
+ declare class Router {
15
+ groups: Omit<Options, 'responder'>[];
16
+ root: Node;
17
+ routes: Record<string, Route>;
18
+ static: Record<string, Route>;
19
+ subdomains: string[] | null;
20
+ constructor();
21
+ private add;
22
+ private route;
23
+ delete(options: Options): this;
24
+ get(options: Options): this;
25
+ group(options: Router['groups'][0]): {
26
+ routes: (fn: (router: Router) => void) => void;
27
+ };
28
+ match(method: string, path: string, subdomain?: string | null): ReturnType<Node['find']>;
29
+ on(methods: string[], options: Options): void;
30
+ post(options: Options): this;
31
+ put(options: Options): this;
32
+ uri(name: string, values?: unknown[]): string;
33
+ }
34
+ declare const _default: () => Router;
35
+ export default _default;
36
+ export { Router, Route };
@@ -0,0 +1,182 @@
1
+ import { STATIC } from "../symbols";
2
+ import { Node } from './node';
3
+ import { normalize, radixkey } from './path';
4
+ import factory from '../middleware/factory';
5
+ let { isArray } = Array;
6
+ function set(route, key, value) {
7
+ if (!value) {
8
+ return;
9
+ }
10
+ if (!route[key]) {
11
+ route[key] = value;
12
+ }
13
+ else if (typeof value === 'string') {
14
+ if (typeof route[key] === 'string') {
15
+ route[key] += value;
16
+ }
17
+ }
18
+ else if (isArray(value)) {
19
+ if (isArray(route[key])) {
20
+ route[key].push(...value);
21
+ }
22
+ }
23
+ }
24
+ class Route {
25
+ dispatch = null;
26
+ name = null;
27
+ path = null;
28
+ responder;
29
+ stack = null;
30
+ subdomain = null;
31
+ constructor(responder) {
32
+ this.responder = responder;
33
+ }
34
+ get dispatcher() {
35
+ if (this.dispatch === null) {
36
+ if (!this.stack?.length) {
37
+ this.dispatch = (request) => this.responder(request);
38
+ }
39
+ else {
40
+ this.dispatch = factory(...this.stack, (request => this.responder(request)));
41
+ }
42
+ }
43
+ return this.dispatch;
44
+ }
45
+ }
46
+ class Router {
47
+ groups = [];
48
+ root;
49
+ routes = {};
50
+ static = {};
51
+ subdomains = null;
52
+ constructor() {
53
+ this.root = new Node();
54
+ }
55
+ add(radixkey, route) {
56
+ let node = this.root.add(radixkey, route);
57
+ if (node.type === STATIC) {
58
+ if (this.static[radixkey]) {
59
+ throw new Error(`Routing: static path '${radixkey}' is already in use`);
60
+ }
61
+ this.static[radixkey] = route;
62
+ }
63
+ }
64
+ route({ middleware, name, path, responder, subdomain }) {
65
+ let route = new Route(responder);
66
+ for (let i = 0, n = this.groups.length; i < n; i++) {
67
+ let { middleware, name, path, subdomain } = this.groups[i];
68
+ set(route, 'name', name);
69
+ set(route, 'path', path);
70
+ set(route, 'stack', middleware);
71
+ set(route, 'subdomain', subdomain);
72
+ }
73
+ set(route, 'name', name);
74
+ set(route, 'path', path);
75
+ set(route, 'stack', middleware);
76
+ set(route, 'subdomain', subdomain);
77
+ if (route.path) {
78
+ route.path = normalize(route.path);
79
+ }
80
+ if (route.subdomain === 'www') {
81
+ route.subdomain = '';
82
+ }
83
+ return route;
84
+ }
85
+ delete(options) {
86
+ this.on(['DELETE'], options);
87
+ return this;
88
+ }
89
+ get(options) {
90
+ this.on(['GET'], options);
91
+ return this;
92
+ }
93
+ group(options) {
94
+ return {
95
+ routes: (fn) => {
96
+ this.groups.push(options);
97
+ fn(this);
98
+ this.groups.pop();
99
+ }
100
+ };
101
+ }
102
+ match(method, path, subdomain) {
103
+ let key = radixkey(path, { method, subdomain });
104
+ if (this.static[key]) {
105
+ return {
106
+ route: this.static[key]
107
+ };
108
+ }
109
+ return this.root.find(key);
110
+ }
111
+ on(methods, options) {
112
+ let route = this.route(options);
113
+ if (route.name) {
114
+ if (this.routes[route.name]) {
115
+ throw new Error(`Routing: '${route.name}' is already in use`);
116
+ }
117
+ this.routes[route.name] = route;
118
+ }
119
+ if (route.path) {
120
+ for (let i = 0, n = methods.length; i < n; i++) {
121
+ let key = radixkey(route.path, {
122
+ method: methods[i],
123
+ subdomain: route.subdomain
124
+ });
125
+ if (key.indexOf('?:') !== -1) {
126
+ let segments = key.split('?:'), url = '';
127
+ for (let i = 0, n = segments.length; i < n; i++) {
128
+ this.add((url += (i > 0 ? '/:' : '/') + segments[i]), route);
129
+ }
130
+ }
131
+ else {
132
+ this.add(key, route);
133
+ }
134
+ }
135
+ }
136
+ if (route.subdomain) {
137
+ if (!this.subdomains) {
138
+ this.subdomains = [route.subdomain];
139
+ }
140
+ else {
141
+ this.subdomains.push(route.subdomain);
142
+ }
143
+ }
144
+ }
145
+ post(options) {
146
+ this.on(['POST'], options);
147
+ return this;
148
+ }
149
+ put(options) {
150
+ this.on(['PUT'], options);
151
+ return this;
152
+ }
153
+ uri(name, values = []) {
154
+ let path = this.routes?.[name]?.path;
155
+ if (!path) {
156
+ throw new Error(`Routing: route name '${name}' does not exist or it does not provide a path`);
157
+ }
158
+ let resolved = [], segments = path.split('/');
159
+ for (let i = 0, n = segments.length; i < n; i++) {
160
+ let segment = segments[i], symbol = segment[0];
161
+ if (symbol === ':') {
162
+ resolved.push(values[i]);
163
+ }
164
+ else if (symbol === '?') {
165
+ if (values[i] === undefined) {
166
+ break;
167
+ }
168
+ resolved.push(values[i]);
169
+ }
170
+ else if (symbol === '*') {
171
+ resolved.push(...values.slice(i));
172
+ break;
173
+ }
174
+ else {
175
+ resolved.push(segment);
176
+ }
177
+ }
178
+ return resolved.join('/');
179
+ }
180
+ }
181
+ export default (...args) => new Router(...args);
182
+ export { Router, Route };
@@ -0,0 +1,17 @@
1
+ import { Route } from './index';
2
+ declare class Node {
3
+ children: Map<string | number, Node> | null;
4
+ parent: Node | null;
5
+ path: string | null;
6
+ property: string | null;
7
+ route: Route | null;
8
+ type: number | null;
9
+ constructor(parent?: Node['parent']);
10
+ add(path: string, route: Route): Node;
11
+ find(path: string): {
12
+ parameters?: Record<PropertyKey, unknown>;
13
+ route?: Route;
14
+ };
15
+ remove(path: string): Node | undefined;
16
+ }
17
+ export { Node };