@kaspernj/api-maker 1.0.122 → 1.0.126
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/.eslintrc.js +7 -4
- package/__tests__/model-name.test.js +16 -10
- package/__tests__/routes-native.test.js +15 -33
- package/index.js +0 -4
- package/package.json +4 -4
- package/src/base-model.cjs +4 -0
- package/src/model-recipes-model-loader.cjs +9 -3
- package/src/event-location-changed.jsx +0 -21
- package/src/history-listener.jsx +0 -20
package/.eslintrc.js
CHANGED
|
@@ -64,23 +64,22 @@ module.exports = {
|
|
|
64
64
|
"implicit-arrow-linebreak": "error",
|
|
65
65
|
"indent": ["error", 2, {"MemberExpression": "off"}],
|
|
66
66
|
"init-declarations": "error",
|
|
67
|
-
"jest/lowercase-name": ["error", {ignore: ["describe"]}],
|
|
68
67
|
"jest/max-nested-describe": "error",
|
|
69
68
|
"jest/no-alias-methods": "error",
|
|
70
69
|
"jest/no-duplicate-hooks": "error",
|
|
71
|
-
"jest/no-hooks": "
|
|
70
|
+
"jest/no-hooks": "off",
|
|
72
71
|
"jest/no-if": "error",
|
|
73
72
|
"jest/no-large-snapshots": "error",
|
|
74
73
|
"jest/no-restricted-matchers": "error",
|
|
75
74
|
"jest/no-test-return-statement": "error",
|
|
76
75
|
"jest/prefer-expect-resolves": "off", // Needs configuration and no documentation could be found?
|
|
77
76
|
"jest/prefer-hooks-on-top": "error",
|
|
77
|
+
"jest/prefer-lowercase-title": "off",
|
|
78
78
|
"jest/prefer-to-be": "off", // Needs configuration and no documentation could be found?
|
|
79
79
|
"jest/prefer-spy-on": "error",
|
|
80
|
-
"jest/prefer-to-be-null": "error",
|
|
81
|
-
"jest/prefer-to-be-undefined": "error",
|
|
82
80
|
"jest/prefer-to-contain": "error",
|
|
83
81
|
"jest/prefer-todo": "error",
|
|
82
|
+
"jest/require-hook": "error",
|
|
84
83
|
"jest/require-to-throw-message": "error",
|
|
85
84
|
"jest/require-top-level-describe": "error",
|
|
86
85
|
"jest/unbound-method": "error",
|
|
@@ -165,6 +164,7 @@ module.exports = {
|
|
|
165
164
|
"no-unmodified-loop-condition": "error",
|
|
166
165
|
"no-unneeded-ternary": "error",
|
|
167
166
|
"no-unreachable-loop": "error",
|
|
167
|
+
"no-unused-private-class-members": "error",
|
|
168
168
|
"no-unsafe-optional-chaining": "error",
|
|
169
169
|
"no-unused-expressions": "error",
|
|
170
170
|
"no-use-before-define": "error",
|
|
@@ -242,9 +242,11 @@ module.exports = {
|
|
|
242
242
|
"react/no-access-state-in-setstate": "error",
|
|
243
243
|
"react/no-adjacent-inline-elements": "error",
|
|
244
244
|
"react/no-array-index-key": "error",
|
|
245
|
+
"react/no-arrow-function-lifecycle": "error",
|
|
245
246
|
"react/no-danger": "error",
|
|
246
247
|
"react/no-did-mount-set-state": "error",
|
|
247
248
|
"react/no-did-update-set-state": "error",
|
|
249
|
+
"react/no-invalid-html-attribute": "error",
|
|
248
250
|
"react/no-multi-comp": "error",
|
|
249
251
|
"react/no-namespace": "error",
|
|
250
252
|
"react/no-redundant-should-component-update": "error",
|
|
@@ -252,6 +254,7 @@ module.exports = {
|
|
|
252
254
|
"react/no-this-in-sfc": "error",
|
|
253
255
|
"react/no-typos": "error",
|
|
254
256
|
"react/no-unstable-nested-components": "error",
|
|
257
|
+
"react/no-unused-class-component-methods": "error",
|
|
255
258
|
"react/no-unused-prop-types": "error",
|
|
256
259
|
"react/no-unused-state": "error",
|
|
257
260
|
"react/no-will-update-set-state": "error",
|
|
@@ -2,21 +2,27 @@ const I18nOnSteroids = require("i18n-on-steroids")
|
|
|
2
2
|
const i18n = new I18nOnSteroids()
|
|
3
3
|
const ModelName = require("../src/model-name.cjs")
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
5
|
+
const initializeI18n = () => {
|
|
6
|
+
i18n.scanObject({
|
|
7
|
+
da: {
|
|
8
|
+
activerecord: {
|
|
9
|
+
models: {
|
|
10
|
+
user: {
|
|
11
|
+
one: "Bruger",
|
|
12
|
+
other: "Brugere"
|
|
13
|
+
}
|
|
12
14
|
}
|
|
13
15
|
}
|
|
14
16
|
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
})
|
|
18
|
+
i18n.setLocale("da")
|
|
19
|
+
}
|
|
18
20
|
|
|
19
21
|
describe("ModelName", () => {
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
initializeI18n()
|
|
24
|
+
})
|
|
25
|
+
|
|
20
26
|
test("human", () => {
|
|
21
27
|
const modelClassData = {i18nKey: "user"}
|
|
22
28
|
const modelName = new ModelName({i18n, modelClassData})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const RoutesNative = require("../src/routes-native.cjs")
|
|
2
|
-
const testRoutes = {
|
|
2
|
+
const testRoutes = () => ({
|
|
3
3
|
routes: [
|
|
4
4
|
{"name": "blank", "path": "/blank", "component": "blank"},
|
|
5
5
|
|
|
@@ -10,8 +10,8 @@ const testRoutes = {
|
|
|
10
10
|
{"name": "drink", "path": "/drinks/:id", "component": "drinks/show"},
|
|
11
11
|
{"name": "drinks", "path": "/drinks", "component": "drinks/index"}
|
|
12
12
|
]
|
|
13
|
-
}
|
|
14
|
-
const testTranslations = {
|
|
13
|
+
})
|
|
14
|
+
const testTranslations = () => ({
|
|
15
15
|
locales: {
|
|
16
16
|
da: {
|
|
17
17
|
routes: {
|
|
@@ -26,94 +26,76 @@ const testTranslations = {
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
let currentLocale = "en"
|
|
29
|
+
})
|
|
32
30
|
|
|
33
|
-
const routesNative = ({args}) => {
|
|
31
|
+
const routesNative = ({args, currentLocale}) => {
|
|
34
32
|
const test = new RoutesNative({
|
|
35
33
|
getLocale: () => currentLocale
|
|
36
34
|
})
|
|
37
35
|
|
|
38
|
-
test.loadRouteTranslations(testTranslations)
|
|
39
|
-
test.loadRouteDefinitions(testRoutes, args)
|
|
36
|
+
test.loadRouteTranslations(testTranslations())
|
|
37
|
+
test.loadRouteDefinitions(testRoutes(), args)
|
|
40
38
|
|
|
41
39
|
return test
|
|
42
40
|
}
|
|
43
41
|
|
|
44
42
|
describe("RoutesNative", () => {
|
|
45
43
|
it("translates routes from the current locale", () => {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const test = routesNative({args: {localized: true}})
|
|
44
|
+
const test = routesNative({args: {localized: true}, currentLocale: "da"})
|
|
49
45
|
const daRoute = test.editDrinkPath(5)
|
|
50
46
|
|
|
51
47
|
expect(daRoute).toEqual("/da/drinks/5/rediger")
|
|
52
48
|
})
|
|
53
49
|
|
|
54
50
|
it("translates routes from the locale-param", () => {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const test = routesNative({args: {localized: true}})
|
|
51
|
+
const test = routesNative({args: {localized: true}, currentLocale: "en"})
|
|
58
52
|
const daRoute = test.editDrinkPath(5, {locale: "da"})
|
|
59
53
|
|
|
60
54
|
expect(daRoute).toEqual("/da/drinks/5/rediger")
|
|
61
55
|
})
|
|
62
56
|
|
|
63
57
|
it("defaults to the locale given by the getLocale callback", () => {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const test = routesNative({args: {localized: true}})
|
|
58
|
+
const test = routesNative({args: {localized: true}, currentLocale: "en"})
|
|
67
59
|
const daRoute = test.editDrinkPath(5)
|
|
68
60
|
|
|
69
61
|
expect(daRoute).toEqual("/en/drinks/5/edit")
|
|
70
62
|
})
|
|
71
63
|
|
|
72
64
|
it("uses the rest of the params as a query string", () => {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const test = routesNative({args: {localized: true}})
|
|
65
|
+
const test = routesNative({args: {localized: true}, currentLocale: "en"})
|
|
76
66
|
const daRoute = test.editDrinkPath(5, {drink: {name: "Pina Colada"}, locale: "da"})
|
|
77
67
|
|
|
78
68
|
expect(daRoute).toEqual("/da/drinks/5/rediger?drink%5Bname%5D=Pina%20Colada")
|
|
79
69
|
})
|
|
80
70
|
|
|
81
71
|
it("translates a route without localization", () => {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const test = routesNative({})
|
|
72
|
+
const test = routesNative({currentLocale: "en"})
|
|
85
73
|
const daRoute = test.editDrinkPath(5, {drink: {name: "Pina Colada"}})
|
|
86
74
|
|
|
87
75
|
expect(daRoute).toEqual("/drinks/5/edit?drink%5Bname%5D=Pina%20Colada")
|
|
88
76
|
})
|
|
89
77
|
|
|
90
78
|
it("generates urls", () => {
|
|
91
|
-
currentLocale = "en"
|
|
92
|
-
|
|
93
79
|
if (!global.location) global.location = {} // eslint-disable-line jest/no-if
|
|
94
80
|
|
|
95
81
|
global.location.host = "localhost"
|
|
96
82
|
global.location.protocol = "http:"
|
|
97
83
|
|
|
98
|
-
const test = routesNative({args: {localized: true}})
|
|
84
|
+
const test = routesNative({args: {localized: true}, currentLocale: "en"})
|
|
99
85
|
const daRoute = test.editDrinkUrl(5, {drink: {name: "Pina Colada"}, locale: "da"})
|
|
100
86
|
|
|
101
87
|
expect(daRoute).toEqual("http://localhost/da/drinks/5/rediger?drink%5Bname%5D=Pina%20Colada")
|
|
102
88
|
})
|
|
103
89
|
|
|
104
90
|
it("generates urls with custom options", () => {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const test = routesNative({args: {localized: true}})
|
|
91
|
+
const test = routesNative({args: {localized: true}, currentLocale: "en"})
|
|
108
92
|
const daRoute = test.editDrinkUrl(5, {drink: {name: "Pina Colada"}, locale: "da", host: "google.com", port: 123, protocol: "https"})
|
|
109
93
|
|
|
110
94
|
expect(daRoute).toEqual("https://google.com:123/da/drinks/5/rediger?drink%5Bname%5D=Pina%20Colada")
|
|
111
95
|
})
|
|
112
96
|
|
|
113
97
|
it("generates urls without locales", () => {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
const test = routesNative({})
|
|
98
|
+
const test = routesNative({currentLocale: "en"})
|
|
117
99
|
const daRoute = test.editDrinkUrl(5, {drink: {name: "Pina Colada"}, locale: "da", host: "google.com", port: 123, protocol: "https"})
|
|
118
100
|
|
|
119
101
|
expect(daRoute).toEqual("https://google.com:123/drinks/5/edit?drink%5Bname%5D=Pina%20Colada")
|
package/index.js
CHANGED
|
@@ -16,10 +16,8 @@ const EventCreated = require("./src/event-created").default
|
|
|
16
16
|
const EventDestroyed = require("./src/event-destroyed").default
|
|
17
17
|
const EventEmitterListener = require("./src/event-emitter-listener").default
|
|
18
18
|
const EventListener = require("./src/event-listener").default
|
|
19
|
-
const EventLocationChanged = require("./src/event-location-changed").default
|
|
20
19
|
const EventModelClass = require("./src/event-model-class").default
|
|
21
20
|
const EventUpdated = require("./src/event-updated").default
|
|
22
|
-
const HistoryListener = require("./src/history-listener").default
|
|
23
21
|
const instanceOfClassName = require("./src/instance-of-class-name.cjs")
|
|
24
22
|
const KeyValueStore = require("./src/key-value-store.cjs")
|
|
25
23
|
const Logger = require("./src/logger.cjs")
|
|
@@ -62,10 +60,8 @@ export {
|
|
|
62
60
|
EventDestroyed,
|
|
63
61
|
EventEmitterListener,
|
|
64
62
|
EventListener,
|
|
65
|
-
EventLocationChanged,
|
|
66
63
|
EventModelClass,
|
|
67
64
|
EventUpdated,
|
|
68
|
-
HistoryListener,
|
|
69
65
|
instanceOfClassName,
|
|
70
66
|
KeyValueStore,
|
|
71
67
|
Logger,
|
package/package.json
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
]
|
|
17
17
|
},
|
|
18
18
|
"name": "@kaspernj/api-maker",
|
|
19
|
-
"version": "1.0.
|
|
19
|
+
"version": "1.0.126",
|
|
20
20
|
"description": "",
|
|
21
21
|
"main": "index.js",
|
|
22
22
|
"repository": {
|
|
@@ -47,9 +47,9 @@
|
|
|
47
47
|
"@babel/preset-env": "^7.12.11",
|
|
48
48
|
"@babel/preset-react": "^7.12.10",
|
|
49
49
|
"babel-jest": "^27.0.6",
|
|
50
|
-
"eslint": "^
|
|
51
|
-
"eslint-find-rules": "^
|
|
52
|
-
"eslint-plugin-jest": "^
|
|
50
|
+
"eslint": "^8.2.0",
|
|
51
|
+
"eslint-find-rules": "^4.0.0",
|
|
52
|
+
"eslint-plugin-jest": "^25.2.4",
|
|
53
53
|
"eslint-plugin-react": "^7.23.2",
|
|
54
54
|
"i18n-on-steroids": "^1.0.2",
|
|
55
55
|
"jest": "^27.0.6",
|
package/src/base-model.cjs
CHANGED
|
@@ -152,6 +152,10 @@ module.exports = class BaseModel {
|
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
+
static all() {
|
|
156
|
+
return this.ransack()
|
|
157
|
+
}
|
|
158
|
+
|
|
155
159
|
async create(attributes, options) {
|
|
156
160
|
if (attributes) this.assignAttributes(attributes)
|
|
157
161
|
const paramKey = this.modelClassData().paramKey
|
|
@@ -138,12 +138,14 @@ module.exports = class ApiMakerModelRecipesModelLoader {
|
|
|
138
138
|
})
|
|
139
139
|
} else if (type == "has_many") {
|
|
140
140
|
this.defineHasManyGetMethod({
|
|
141
|
+
activeRecordName,
|
|
141
142
|
className,
|
|
142
143
|
foreignKey,
|
|
143
144
|
ModelClass,
|
|
144
145
|
modelMethodName,
|
|
145
146
|
modelRecipesLoader,
|
|
146
147
|
optionsAs,
|
|
148
|
+
optionsPrimaryKey,
|
|
147
149
|
optionsThrough,
|
|
148
150
|
relationshipName,
|
|
149
151
|
resourceName
|
|
@@ -194,7 +196,7 @@ module.exports = class ApiMakerModelRecipesModelLoader {
|
|
|
194
196
|
}
|
|
195
197
|
}
|
|
196
198
|
|
|
197
|
-
defineHasManyGetMethod({className, foreignKey, ModelClass, modelMethodName, modelRecipesLoader, optionsAs, optionsThrough, relationshipName, resourceName}) {
|
|
199
|
+
defineHasManyGetMethod({activeRecordName, className, foreignKey, ModelClass, modelMethodName, modelRecipesLoader, optionsAs, optionsPrimaryKey, optionsThrough, relationshipName, resourceName}) {
|
|
198
200
|
ModelClass.prototype[modelMethodName] = function () {
|
|
199
201
|
const id = this.primaryKey()
|
|
200
202
|
const modelClass = modelRecipesLoader.getModelClass(resourceName)
|
|
@@ -215,7 +217,7 @@ module.exports = class ApiMakerModelRecipesModelLoader {
|
|
|
215
217
|
queryParameters = {
|
|
216
218
|
params: {
|
|
217
219
|
through: {
|
|
218
|
-
model:
|
|
220
|
+
model: activeRecordName,
|
|
219
221
|
id: this.primaryKey(),
|
|
220
222
|
reflection: relationshipName
|
|
221
223
|
}
|
|
@@ -223,8 +225,12 @@ module.exports = class ApiMakerModelRecipesModelLoader {
|
|
|
223
225
|
}
|
|
224
226
|
} else {
|
|
225
227
|
const ransack = {}
|
|
228
|
+
const primaryKeyColumnName = optionsPrimaryKey || digg(ModelClass.modelClassData(), "primaryKey")
|
|
229
|
+
const primaryKeyMethodName = inflection.camelize(primaryKeyColumnName, true)
|
|
230
|
+
|
|
231
|
+
if (!(primaryKeyMethodName in this)) throw new Error(`No such primary key method: ${primaryKeyMethodName}`)
|
|
226
232
|
|
|
227
|
-
ransack[`${foreignKey}_eq`] = this
|
|
233
|
+
ransack[`${foreignKey}_eq`] = this[primaryKeyMethodName]()
|
|
228
234
|
|
|
229
235
|
if (optionsAs) {
|
|
230
236
|
ransack[`${optionsAs}_type_eq`] = activeRecordName
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import PropTypes from "prop-types"
|
|
2
|
-
import React from "react"
|
|
3
|
-
|
|
4
|
-
export default class EventLocationChanged extends React.PureComponent {
|
|
5
|
-
static propTypes = {
|
|
6
|
-
history: PropTypes.object.isRequired,
|
|
7
|
-
onChanged: PropTypes.func.isRequired
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
componentDidMount() {
|
|
11
|
-
this.appHistoryUnlisten = this.props.history.listen(this.props.onChanged)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
componentWillUnmount() {
|
|
15
|
-
this.appHistoryUnlisten()
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
render() {
|
|
19
|
-
return null
|
|
20
|
-
}
|
|
21
|
-
}
|
package/src/history-listener.jsx
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
const PropTypes = require("prop-types")
|
|
2
|
-
const PropTypesExact = require("prop-types-exact")
|
|
3
|
-
|
|
4
|
-
export default class ApiMakerHistoryListener extends React.PureComponent {
|
|
5
|
-
static propTypes = PropTypesExact({
|
|
6
|
-
onChanged: PropTypes.func.isRequired
|
|
7
|
-
})
|
|
8
|
-
|
|
9
|
-
componentDidMount() {
|
|
10
|
-
this.unlisten = AppHistory.listen((location, action) => this.props.onChanged({location, action}))
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
componentWillUnmount() {
|
|
14
|
-
this.unlisten()
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
render() {
|
|
18
|
-
return null
|
|
19
|
-
}
|
|
20
|
-
}
|