@ossy/router 0.0.1-beta.0

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/README.md ADDED
File without changes
@@ -0,0 +1,22 @@
1
+ import { MultiLanguagePage, SingleLanguagePage } from './router';
2
+ export interface ExtendedSingleLangaugePage extends SingleLanguagePage {
3
+ matchingUrls: string[];
4
+ }
5
+ export interface ExtendedMultiLanguagePage extends MultiLanguagePage {
6
+ matchingUrls: string[];
7
+ }
8
+ export declare class MockData {
9
+ static getPagesForSingleLanguageRouter(): {
10
+ id: string;
11
+ path: string;
12
+ matchingUrls: string[];
13
+ }[];
14
+ static getPagesForMultiLanguageRouter(): {
15
+ id: string;
16
+ path: {
17
+ en: string;
18
+ es: string;
19
+ };
20
+ matchingUrls: string[];
21
+ }[];
22
+ }
@@ -0,0 +1 @@
1
+ export * from './router';
@@ -0,0 +1 @@
1
+ export { Router } from './router.js';
@@ -0,0 +1,39 @@
1
+ export interface SingleLanguagePage {
2
+ id: string;
3
+ path: string;
4
+ }
5
+ export interface MultiLanguagePage {
6
+ id: string;
7
+ path: {
8
+ [language: string]: string;
9
+ };
10
+ }
11
+ export type Page = SingleLanguagePage | MultiLanguagePage;
12
+ export interface RouterOptions<T extends Page = Page> {
13
+ pages: T[];
14
+ /** Required for multi language router */
15
+ defaultLanguage?: string;
16
+ /** Required for multi language router */
17
+ supportedLanguages?: string[];
18
+ }
19
+ /** Router
20
+ *
21
+ * Handles
22
+ * - build href from route id
23
+ *
24
+ * */
25
+ export declare class Router<T extends Page = Page> {
26
+ static of<T extends Page = Page>(options: RouterOptions<T>): Router<T>;
27
+ pages: T[];
28
+ defaultLanguage?: string;
29
+ supportedLanguages?: string[];
30
+ constructor({ pages, defaultLanguage, supportedLanguages }: RouterOptions<T>);
31
+ getPageById(id: string): T | undefined;
32
+ getPageByUrl(_url: string): T | undefined;
33
+ getParamsFromUrl(_url: string): Record<string, string>;
34
+ getPathname({ id, params, language }: {
35
+ id: string;
36
+ params?: Record<string, string>;
37
+ language?: string;
38
+ }): string | undefined;
39
+ }
@@ -0,0 +1,144 @@
1
+ import { padWithSlash } from './utli.js';
2
+
3
+ /** Router
4
+ *
5
+ * Handles
6
+ * - build href from route id
7
+ *
8
+ * */
9
+ class Router {
10
+ static of(options) {
11
+ return new Router(options);
12
+ }
13
+ constructor({ pages, defaultLanguage, supportedLanguages }) {
14
+ this.pages = pages || [];
15
+ this.defaultLanguage = defaultLanguage;
16
+ this.supportedLanguages = supportedLanguages || [];
17
+ }
18
+ getPageById(id) {
19
+ var _a;
20
+ return (_a = this.pages.find(page => page.id === id)) !== null && _a !== void 0 ? _a : this.pages.find(page => page.id === '404');
21
+ }
22
+ getPageByUrl(_url) {
23
+ var _a, _b;
24
+ console.log('[Router][getPageByUrl()] _url', _url);
25
+ console.log('[Router][getPageByUrl()] this.pages?.length', (_a = this.pages) === null || _a === void 0 ? void 0 : _a.length);
26
+ if (typeof _url !== 'string' || ((_b = this.pages) === null || _b === void 0 ? void 0 : _b.length) === 0)
27
+ return;
28
+ let url;
29
+ try {
30
+ url = new URL(_url);
31
+ }
32
+ catch (_c) {
33
+ // If url is not valid, try to parse it with localhost.com fince URL needs domain, but it wont be used
34
+ url = new URL(_url, 'http://localhost.com');
35
+ }
36
+ console.log('[Router][getPageByUrl()] url', url);
37
+ const pathname = padWithSlash(url.pathname);
38
+ const pathnameParts = pathname.split('/').filter(x => !!x);
39
+ console.log('[Router][getPageByUrl()] pathname', pathname);
40
+ console.log('[Router][getPageByUrl()] pathnameParts', pathnameParts);
41
+ const exactMatch = this.pages.find(page => {
42
+ const paths = typeof page.path === 'string'
43
+ ? [page.path]
44
+ : Object.entries(page.path).map(([language, path]) => `/${language}${path}`);
45
+ return paths.map(padWithSlash).includes(pathname);
46
+ });
47
+ console.log('[Router][getPageByUrl()] exactMatch', exactMatch);
48
+ if (exactMatch)
49
+ return exactMatch;
50
+ const dynamicMatch = this.pages.find(page => {
51
+ // take path from page and find positions of params
52
+ // then take params from url and insert them into url
53
+ // then see if url matches
54
+ const paths = typeof page.path === 'string'
55
+ ? [page.path]
56
+ : Object.entries(page.path).map(([language, path]) => `/${language}${path}`);
57
+ const matchContenders = paths.map(path => path
58
+ .split('/')
59
+ .filter(x => !!x)
60
+ .reduce((contender, part, index) => {
61
+ return part.startsWith(':')
62
+ ? contender + pathnameParts[index] + '/'
63
+ : contender + part + '/';
64
+ }, '/'));
65
+ return matchContenders.includes(pathname);
66
+ });
67
+ console.log('[Router][getPageByUrl()] dynamicMatch', dynamicMatch);
68
+ return dynamicMatch;
69
+ }
70
+ getParamsFromUrl(_url) {
71
+ var _a;
72
+ if (typeof _url !== 'string' || ((_a = this.pages) === null || _a === void 0 ? void 0 : _a.length) === 0)
73
+ return {};
74
+ let url;
75
+ try {
76
+ url = new URL(_url);
77
+ }
78
+ catch (_b) {
79
+ // If url is not valid, try to parse it with localhost.com fince URL needs domain, but it wont be used
80
+ url = new URL(_url, 'http://localhost.com');
81
+ }
82
+ const pathname = padWithSlash(url.pathname);
83
+ const pathnameParts = pathname.split('/').filter(x => !!x);
84
+ const page = this.getPageByUrl(_url);
85
+ let params = {};
86
+ if (typeof (page === null || page === void 0 ? void 0 : page.path) === 'string') {
87
+ const pageParts = page.path.split('/').filter(x => !!x);
88
+ pageParts.forEach((part, index) => {
89
+ if (part.startsWith(':')) {
90
+ params[part.slice(1)] = pathnameParts[index];
91
+ }
92
+ });
93
+ }
94
+ if (typeof (page === null || page === void 0 ? void 0 : page.path) === 'object') {
95
+ const language = pathname.split('/')[1];
96
+ const pageParts = page.path[language].split('/').filter(x => !!x);
97
+ pageParts.forEach((part, index) => {
98
+ if (part.startsWith(':')) {
99
+ params[part.slice(1)] = pathnameParts[index + 1];
100
+ }
101
+ });
102
+ }
103
+ return params;
104
+ }
105
+ getPathname({ id, params, language }) {
106
+ const page = this.getPageById(id);
107
+ if (!page)
108
+ return undefined;
109
+ let pathnameTemplate = page.path;
110
+ if (typeof pathnameTemplate === 'object') {
111
+ if (!language)
112
+ throw new Error('[Router][getPathname()] Language is required for multi language router');
113
+ if (!params)
114
+ return '/' + language + pathnameTemplate[language];
115
+ return pathnameTemplate[language]
116
+ .split('/')
117
+ .filter(x => !!x)
118
+ .reduce((pathanme, part) => {
119
+ if (part.startsWith(':')) {
120
+ const key = part.replace(':', '');
121
+ return pathanme + '/' + params[key];
122
+ }
123
+ return pathanme + '/' + part;
124
+ }, `/${language}`);
125
+ }
126
+ if (typeof pathnameTemplate === 'string') {
127
+ if (!params)
128
+ return pathnameTemplate;
129
+ return pathnameTemplate
130
+ .split('/')
131
+ .filter(x => !!x)
132
+ .reduce((pathanme, part) => {
133
+ if (part.startsWith(':')) {
134
+ const key = part.replace(':', '');
135
+ return pathanme + '/' + params[key];
136
+ }
137
+ return pathanme + '/' + part;
138
+ }, '');
139
+ }
140
+ return undefined;
141
+ }
142
+ }
143
+
144
+ export { Router };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export declare const padWithSlash: (string?: string) => string;
@@ -0,0 +1,7 @@
1
+ const appendSlash = (string) => string[string.length - 1] === '/'
2
+ ? string : `${string}/`;
3
+ const prependSlash = (string) => string[0] === '/'
4
+ ? string : `/${string}`;
5
+ const padWithSlash = (string = '') => appendSlash(prependSlash(string));
6
+
7
+ export { padWithSlash };
@@ -0,0 +1,41 @@
1
+ interface SingleLanguagePage {
2
+ id: string;
3
+ path: string;
4
+ }
5
+ interface MultiLanguagePage {
6
+ id: string;
7
+ path: {
8
+ [language: string]: string;
9
+ };
10
+ }
11
+ type Page = SingleLanguagePage | MultiLanguagePage;
12
+ interface RouterOptions<T extends Page = Page> {
13
+ pages: T[];
14
+ /** Required for multi language router */
15
+ defaultLanguage?: string;
16
+ /** Required for multi language router */
17
+ supportedLanguages?: string[];
18
+ }
19
+ /** Router
20
+ *
21
+ * Handles
22
+ * - build href from route id
23
+ *
24
+ * */
25
+ declare class Router<T extends Page = Page> {
26
+ static of<T extends Page = Page>(options: RouterOptions<T>): Router<T>;
27
+ pages: T[];
28
+ defaultLanguage?: string;
29
+ supportedLanguages?: string[];
30
+ constructor({ pages, defaultLanguage, supportedLanguages }: RouterOptions<T>);
31
+ getPageById(id: string): T | undefined;
32
+ getPageByUrl(_url: string): T | undefined;
33
+ getParamsFromUrl(_url: string): Record<string, string>;
34
+ getPathname({ id, params, language }: {
35
+ id: string;
36
+ params?: Record<string, string>;
37
+ language?: string;
38
+ }): string | undefined;
39
+ }
40
+
41
+ export { type MultiLanguagePage, type Page, Router, type RouterOptions, type SingleLanguagePage };
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@ossy/router",
3
+ "version": "0.0.1-beta.0",
4
+ "description": "",
5
+ "type": "module",
6
+ "source": "src/public.index.ts",
7
+ "module": "build/esm/public.index.js",
8
+ "main": "build/cjs/public.index.js",
9
+ "types": "build/public.index.d.ts",
10
+ "files": [
11
+ "/build",
12
+ "README.md"
13
+ ],
14
+ "scripts": {
15
+ "start": "storybook dev -p 6006",
16
+ "build": "rollup -c rollup.config.js",
17
+ "test": "jest --verbose",
18
+ "test:watch": "jest --watch"
19
+ },
20
+ "keywords": [],
21
+ "author": "",
22
+ "license": "ISC",
23
+ "devDependencies": {
24
+ "@jest/globals": "^29.7.0",
25
+ "@rollup/plugin-commonjs": "^25.0.5",
26
+ "@rollup/plugin-node-resolve": "^15.2.3",
27
+ "@rollup/plugin-typescript": "^11.1.5",
28
+ "@types/react": "18.2.79",
29
+ "@types/react-dom": "18.2.18",
30
+ "autoprefixer": "^10.4.16",
31
+ "casual": "^1.6.2",
32
+ "jest": "^29.7.0",
33
+ "rollup": "^4.6.0",
34
+ "rollup-plugin-dts": "^6.1.0",
35
+ "rollup-plugin-peer-deps-external": "^2.2.4",
36
+ "rollup-plugin-postcss-modules": "^2.1.1",
37
+ "rollup-plugin-preserve-directives": "^0.4.0",
38
+ "ts-jest": "^29.1.1",
39
+ "tslib": "^2.6.2"
40
+ },
41
+ "peerDependencies": {
42
+ "typescript": "4 - 5"
43
+ }
44
+ }