@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 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": "error",
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
- i18n.scanObject({
6
- da: {
7
- activerecord: {
8
- models: {
9
- user: {
10
- one: "Bruger",
11
- other: "Brugere"
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
- i18n.setLocale("da")
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
- currentLocale = "da"
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
- currentLocale = "en"
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
- currentLocale = "en"
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
- currentLocale = "en"
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
- currentLocale = "en"
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
- currentLocale = "en"
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
- currentLocale = "en"
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.122",
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": "^7.26.0",
51
- "eslint-find-rules": "^3.6.1",
52
- "eslint-plugin-jest": "^24.3.6",
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",
@@ -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: className,
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.primaryKey()
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
- }
@@ -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
- }