UNPKG

3.21 kBJavaScriptView Raw
1/**
2 * @copyright Copyright (c) 2019 Maxim Khorin <maksimovichu@gmail.com>
3 */
4'use strict';
5
6const Base = require('../base/Base');
7
8module.exports = class Url extends Base {
9
10 constructor (config) {
11 super(config);
12
13 const sources = pathToRegexp.parse(this.source);
14 const targets = pathToRegexp.parse(this.target);
15
16 this.sourceParamNames = this.getParamNames(sources);
17 this.targetParamNames = this.getParamNames(targets);
18
19 this.sourceRegExp = pathToRegexp.tokensToRegExp(sources);
20 this.targetRegExp = pathToRegexp.tokensToRegExp(targets);
21 this.createSource = pathToRegexp.tokensToFunction(sources);
22 this.createTarget = pathToRegexp.tokensToFunction(targets);
23
24 // target params must be a subset of the source's params
25 const names = ArrayHelper.intersect(this.sourceParamNames, this.targetParamNames);
26 if (names.length !== this.targetParamNames.length) {
27 throw new Error(`Invalid params: Source: ${this.source}: Target: ${this.target}`);
28 }
29 if (this.methods && !Array.isArray(this.methods)) {
30 throw new Error(`Invalid methods: ${this.methods}`);
31 }
32 }
33
34 resolve (url, method) {
35 if (this.methods && !this.methods.includes(method)) {
36 return null;
37 }
38 const result = this.sourceRegExp.exec(url);
39 if (!result) {
40 return null;
41 }
42 let params = this.getParams(result, this.sourceParamNames);
43 if (this.defaults) {
44 params = {...this.defaults, ...params};
45 }
46 return {path: this.createTarget(params), params};
47 }
48
49 createSourceUrl (data) {
50 const result = this.targetRegExp.exec(data.path);
51 if (!result) {
52 return null;
53 }
54 let params = this.getParams(result, this.targetParamNames);
55 try {
56 // data.params = { id: 123, test: '456'};
57 // data.anchor = 'anchor';
58 let url = this.createSource(Object.assign(params, data.params));
59 ObjectHelper.deleteProperties(this.sourceParamNames, params);
60 params = UrlHelper.serialize(params);
61 if (params) {
62 url = `${url}?${params}`;
63 }
64 if (data.anchor !== undefined) {
65 url = `${url}#${data.anchor}`;
66 }
67 return url;
68 } catch {
69 return null;
70 }
71 }
72
73 getParams (result, names) {
74 const params = {};
75 for (let i = 0; i < names.length; ++i) {
76 params[names[i]] = result[i + 1];
77 }
78 return params;
79 }
80
81 getParamNames (tokens) {
82 const names = [];
83 for (const token of tokens) {
84 if (token.name && !names.includes(token.name)) {
85 names.push(token.name);
86 }
87 }
88 return names;
89 }
90};
91
92const pathToRegexp = require('path-to-regexp');
93const ArrayHelper = require('../helper/ArrayHelper');
94const ObjectHelper = require('../helper/ObjectHelper');
95const UrlHelper = require('../helper/UrlHelper');
\No newline at end of file