@kaspernj/api-maker 1.0.150 → 1.0.151
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/package.json +1 -1
- package/src/config.js +16 -0
- package/src/router.jsx +9 -95
- package/src/with-router.jsx +128 -0
package/package.json
CHANGED
package/src/config.js
CHANGED
|
@@ -11,6 +11,14 @@ class ApiMakerConfig {
|
|
|
11
11
|
return this.global.currenciesCollection
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
getRouteDefinitions() {
|
|
15
|
+
return this.global.routeDefinitions
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
getRoutes() {
|
|
19
|
+
return this.global.routes
|
|
20
|
+
}
|
|
21
|
+
|
|
14
22
|
setCurrenciesCollection(newCurrenciesCollection) {
|
|
15
23
|
this.global.currenciesCollection = newCurrenciesCollection
|
|
16
24
|
}
|
|
@@ -18,6 +26,14 @@ class ApiMakerConfig {
|
|
|
18
26
|
setHistory(history) {
|
|
19
27
|
this.global.history = history
|
|
20
28
|
}
|
|
29
|
+
|
|
30
|
+
setRouteDefinitions(routeDefinitions) {
|
|
31
|
+
this.global.routeDefinitions = routeDefinitions
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
setRoutes(routes) {
|
|
35
|
+
this.global.routes = routes
|
|
36
|
+
}
|
|
21
37
|
}
|
|
22
38
|
|
|
23
39
|
const apiMakerConfig = new ApiMakerConfig()
|
package/src/router.jsx
CHANGED
|
@@ -1,110 +1,22 @@
|
|
|
1
|
-
import escapeStringRegexp from "escape-string-regexp"
|
|
2
|
-
import inflection from "inflection"
|
|
3
1
|
import PropTypes from "prop-types"
|
|
4
2
|
import React from "react"
|
|
5
|
-
import
|
|
3
|
+
import shouldComponentUpdate from "set-state-compare/src/should-component-update"
|
|
6
4
|
import {Suspense} from "react"
|
|
5
|
+
import withRouter from "./with-router"
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
class ApiMakerRouter extends React.Component {
|
|
9
8
|
static propTypes = {
|
|
10
9
|
notFoundComponent: PropTypes.elementType,
|
|
11
|
-
|
|
12
|
-
requireComponent: PropTypes.func.isRequired,
|
|
13
|
-
routes: PropTypes.object,
|
|
14
|
-
routeDefinitions: PropTypes.object
|
|
10
|
+
requireComponent: PropTypes.func.isRequired
|
|
15
11
|
}
|
|
16
12
|
|
|
17
|
-
parsedRouteDefinitions = this.parseRouteDefinitions()
|
|
18
|
-
|
|
19
13
|
shouldComponentUpdate(nextProps, nextState) {
|
|
20
14
|
return shouldComponentUpdate(this, nextProps, nextState)
|
|
21
15
|
}
|
|
22
16
|
|
|
23
|
-
findRouteParams (routeDefinition) {
|
|
24
|
-
const result = []
|
|
25
|
-
const parts = routeDefinition.path.split("/")
|
|
26
|
-
|
|
27
|
-
for (const part of parts) {
|
|
28
|
-
if (part.match(/^:([a-z_]+)$/))
|
|
29
|
-
result.push(part)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return result
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
parseRouteDefinitions() {
|
|
36
|
-
const Locales = require("shared/locales").default
|
|
37
|
-
const {routeDefinitions, routes} = this.props
|
|
38
|
-
const regex = /:([A-z\d_]+)/
|
|
39
|
-
const parsedRouteDefinitions = []
|
|
40
|
-
|
|
41
|
-
for (const locale of Locales.availableLocales()) {
|
|
42
|
-
for (const routeDefinition of routeDefinitions.routes) {
|
|
43
|
-
const routePathName = `${inflection.camelize(routeDefinition.name, true)}Path`
|
|
44
|
-
const params = this.findRouteParams(routeDefinition)
|
|
45
|
-
|
|
46
|
-
params.push({locale})
|
|
47
|
-
|
|
48
|
-
if (!(routePathName in routes))
|
|
49
|
-
throw new Error(`${routePathName} not found in routes: ${Object.keys(routes, ", ")}`)
|
|
50
|
-
|
|
51
|
-
const routePath = routes[routePathName](...params).replace(/[\/]+$/, "")
|
|
52
|
-
const groups = []
|
|
53
|
-
|
|
54
|
-
let pathRegexString = '^'
|
|
55
|
-
|
|
56
|
-
pathRegexString += escapeStringRegexp(routePath)
|
|
57
|
-
|
|
58
|
-
while (true) {
|
|
59
|
-
const match = pathRegexString.match(regex)
|
|
60
|
-
|
|
61
|
-
if (!match) break
|
|
62
|
-
|
|
63
|
-
const variableName = match[1]
|
|
64
|
-
|
|
65
|
-
groups.push(variableName)
|
|
66
|
-
|
|
67
|
-
pathRegexString = pathRegexString.replace(match[0], `([^\/]+)`)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
pathRegexString += '$'
|
|
71
|
-
|
|
72
|
-
const pathRegex = new RegExp(pathRegexString)
|
|
73
|
-
|
|
74
|
-
parsedRouteDefinitions.push({groups, pathRegex, routeDefinition})
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return parsedRouteDefinitions
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
findMatchingRoute() {
|
|
82
|
-
const path = this.props.path.replace(/[\/]+$/, "")
|
|
83
|
-
|
|
84
|
-
for (const parsedRouteDefinition of this.parsedRouteDefinitions) {
|
|
85
|
-
const match = path.match(parsedRouteDefinition.pathRegex)
|
|
86
|
-
let matched, params
|
|
87
|
-
|
|
88
|
-
if (match) {
|
|
89
|
-
matched = true
|
|
90
|
-
params = {}
|
|
91
|
-
|
|
92
|
-
for (const groupKey in parsedRouteDefinition.groups) {
|
|
93
|
-
const groupName = parsedRouteDefinition.groups[groupKey]
|
|
94
|
-
|
|
95
|
-
params[groupName] = match[Number(groupKey) + 1]
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (path == "" && parsedRouteDefinition.routeDefinition.path == "/") matched = true
|
|
100
|
-
if (matched) {
|
|
101
|
-
return {params, parsedRouteDefinition}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
17
|
render() {
|
|
107
|
-
const
|
|
18
|
+
const {match, ...restProps} = this.props
|
|
19
|
+
const {matchingRoute} = match
|
|
108
20
|
|
|
109
21
|
if (!matchingRoute) {
|
|
110
22
|
if (this.props.notFoundComponent) {
|
|
@@ -124,8 +36,10 @@ export default class ApiMakerRouter extends React.Component {
|
|
|
124
36
|
|
|
125
37
|
return (
|
|
126
38
|
<Suspense fallback={<div />}>
|
|
127
|
-
<Component match={{
|
|
39
|
+
<Component match={match} {...restProps} />
|
|
128
40
|
</Suspense>
|
|
129
41
|
)
|
|
130
42
|
}
|
|
131
43
|
}
|
|
44
|
+
|
|
45
|
+
export default withRouter(ApiMakerRouter)
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import config from "./config"
|
|
2
|
+
import escapeStringRegexp from "escape-string-regexp"
|
|
3
|
+
import inflection from "inflection"
|
|
4
|
+
import PropTypes from "prop-types"
|
|
5
|
+
import React from "react"
|
|
6
|
+
import shouldComponentUpdate from "set-state-compare/src/should-component-update"
|
|
7
|
+
|
|
8
|
+
export default (WrapperComponent) => class WithRouter extends React.Component {
|
|
9
|
+
static propTypes = {
|
|
10
|
+
path: PropTypes.string,
|
|
11
|
+
routes: PropTypes.object,
|
|
12
|
+
routeDefinitions: PropTypes.object
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
parsedRouteDefinitions = this.parseRouteDefinitions()
|
|
16
|
+
|
|
17
|
+
shouldComponentUpdate(nextProps, nextState) {
|
|
18
|
+
return shouldComponentUpdate(this, nextProps, nextState)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
findRouteParams (routeDefinition) {
|
|
22
|
+
const result = []
|
|
23
|
+
const parts = routeDefinition.path.split("/")
|
|
24
|
+
|
|
25
|
+
for (const part of parts) {
|
|
26
|
+
if (part.match(/^:([a-z_]+)$/))
|
|
27
|
+
result.push(part)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return result
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
path() {
|
|
34
|
+
let path = this.props.path || window.location.pathname
|
|
35
|
+
|
|
36
|
+
path = path.replace(/[\/]+$/, "")
|
|
37
|
+
|
|
38
|
+
return path
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
routeDefinitions() { return this.props.routeDefinitions || config.getRouteDefinitions() }
|
|
42
|
+
routes() { return this.props.routes || config.getRoutes() }
|
|
43
|
+
|
|
44
|
+
parseRouteDefinitions() {
|
|
45
|
+
const Locales = require("shared/locales").default
|
|
46
|
+
const routeDefinitions = this.routeDefinitions()
|
|
47
|
+
const routes = this.routes()
|
|
48
|
+
const regex = /:([A-z\d_]+)/
|
|
49
|
+
const parsedRouteDefinitions = []
|
|
50
|
+
|
|
51
|
+
for (const locale of Locales.availableLocales()) {
|
|
52
|
+
for (const routeDefinition of routeDefinitions.routes) {
|
|
53
|
+
const routePathName = `${inflection.camelize(routeDefinition.name, true)}Path`
|
|
54
|
+
const params = this.findRouteParams(routeDefinition)
|
|
55
|
+
|
|
56
|
+
params.push({locale})
|
|
57
|
+
|
|
58
|
+
if (!(routePathName in routes))
|
|
59
|
+
throw new Error(`${routePathName} not found in routes: ${Object.keys(routes, ", ")}`)
|
|
60
|
+
|
|
61
|
+
const routePath = routes[routePathName](...params).replace(/[\/]+$/, "")
|
|
62
|
+
const groups = []
|
|
63
|
+
|
|
64
|
+
let pathRegexString = '^'
|
|
65
|
+
|
|
66
|
+
pathRegexString += escapeStringRegexp(routePath)
|
|
67
|
+
|
|
68
|
+
while (true) {
|
|
69
|
+
const match = pathRegexString.match(regex)
|
|
70
|
+
|
|
71
|
+
if (!match) break
|
|
72
|
+
|
|
73
|
+
const variableName = match[1]
|
|
74
|
+
|
|
75
|
+
groups.push(variableName)
|
|
76
|
+
|
|
77
|
+
pathRegexString = pathRegexString.replace(match[0], `([^\/]+)`)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
pathRegexString += '$'
|
|
81
|
+
|
|
82
|
+
const pathRegex = new RegExp(pathRegexString)
|
|
83
|
+
|
|
84
|
+
parsedRouteDefinitions.push({groups, pathRegex, routeDefinition})
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return parsedRouteDefinitions
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
findMatchingRoute() {
|
|
92
|
+
const path = this.path()
|
|
93
|
+
|
|
94
|
+
for (const parsedRouteDefinition of this.parsedRouteDefinitions) {
|
|
95
|
+
const match = path.match(parsedRouteDefinition.pathRegex)
|
|
96
|
+
let matched, params
|
|
97
|
+
|
|
98
|
+
if (match) {
|
|
99
|
+
matched = true
|
|
100
|
+
params = {}
|
|
101
|
+
|
|
102
|
+
for (const groupKey in parsedRouteDefinition.groups) {
|
|
103
|
+
const groupName = parsedRouteDefinition.groups[groupKey]
|
|
104
|
+
|
|
105
|
+
params[groupName] = match[Number(groupKey) + 1]
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (path == "" && parsedRouteDefinition.routeDefinition.path == "/") matched = true
|
|
110
|
+
if (matched) {
|
|
111
|
+
return {params, parsedRouteDefinition}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
render() {
|
|
117
|
+
const {path, routes, routeDefinitions, ...restProps} = this.props
|
|
118
|
+
const matchingRoute = this.findMatchingRoute()
|
|
119
|
+
const match = {
|
|
120
|
+
matchingRoute,
|
|
121
|
+
params: matchingRoute.params
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return (
|
|
125
|
+
<WrapperComponent match={match} {...restProps} />
|
|
126
|
+
)
|
|
127
|
+
}
|
|
128
|
+
}
|