@kaspernj/api-maker 1.0.335 → 1.0.337
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/api.mjs +9 -9
- package/src/commands-pool.mjs +3 -0
- package/src/devise.mjs +1 -6
- package/src/event-listener.jsx +18 -29
- package/src/events.mjs +7 -0
- package/src/inputs/input-wrapper.jsx +1 -3
- package/src/use-current-user.mjs +9 -2
- package/src/use-event-emitter.mjs +1 -9
- package/src/use-event-listener.mjs +17 -0
- package/src/use-validation-errors.mjs +32 -0
- package/src/validation-error.mjs +4 -3
- package/src/validation-errors.mjs +5 -17
package/package.json
CHANGED
package/src/api.mjs
CHANGED
|
@@ -4,23 +4,23 @@ import FormDataObjectizer from "form-data-objectizer"
|
|
|
4
4
|
import qs from "qs"
|
|
5
5
|
|
|
6
6
|
export default class Api {
|
|
7
|
-
static get
|
|
7
|
+
static get(path, pathParams = null) {
|
|
8
8
|
return Api.requestLocal({path, pathParams, method: "GET"})
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
static delete
|
|
11
|
+
static delete(path, pathParams = null) {
|
|
12
12
|
return Api.requestLocal({path, pathParams, method: "DELETE"})
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
static patch
|
|
15
|
+
static patch(path, data = {}) {
|
|
16
16
|
return Api.requestLocal({path, data, method: "PATCH"})
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
static post
|
|
19
|
+
static post(path, data = {}) {
|
|
20
20
|
return Api.requestLocal({path, data, method: "POST"})
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
static request
|
|
23
|
+
static request({data, headers, method, path, pathParams}) {
|
|
24
24
|
let requestPath = ""
|
|
25
25
|
if (config.getHost()) requestPath += config.getHost()
|
|
26
26
|
requestPath += path
|
|
@@ -62,7 +62,7 @@ export default class Api {
|
|
|
62
62
|
})
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
static requestLocal
|
|
65
|
+
static requestLocal(args) {
|
|
66
66
|
if (!args.headers) {
|
|
67
67
|
args.headers = {}
|
|
68
68
|
}
|
|
@@ -85,18 +85,18 @@ export default class Api {
|
|
|
85
85
|
return this.request(args)
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
static put
|
|
88
|
+
static put(path, data = {}) {
|
|
89
89
|
return this.requestLocal({path, data, method: "PUT"})
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
static _token
|
|
92
|
+
static _token() {
|
|
93
93
|
const tokenElement = document.querySelector("meta[name='csrf-token']")
|
|
94
94
|
|
|
95
95
|
if (tokenElement)
|
|
96
96
|
return tokenElement.getAttribute("content")
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
static _parseResponse
|
|
99
|
+
static _parseResponse(xhr) {
|
|
100
100
|
const responseType = xhr.getResponseHeader("content-type")
|
|
101
101
|
|
|
102
102
|
if (responseType && responseType.startsWith("application/json")) {
|
package/src/commands-pool.mjs
CHANGED
|
@@ -4,6 +4,7 @@ import CustomError from "./custom-error.mjs"
|
|
|
4
4
|
import DestroyError from "./destroy-error.mjs"
|
|
5
5
|
import Deserializer from "./deserializer.mjs"
|
|
6
6
|
import {dig, digg} from "diggerize"
|
|
7
|
+
import events from "./events.mjs"
|
|
7
8
|
import FormDataObjectizer from "form-data-objectizer"
|
|
8
9
|
import Serializer from "./serializer.mjs"
|
|
9
10
|
import SessionStatusUpdater from "./session-status-updater.mjs"
|
|
@@ -176,6 +177,8 @@ export default class ApiMakerCommandsPool {
|
|
|
176
177
|
validationErrors: digg(commandResponseData, "validation_errors")
|
|
177
178
|
})
|
|
178
179
|
error = new ValidationError(validationErrors, {response: commandResponseData})
|
|
180
|
+
|
|
181
|
+
events.emit("onValidationErrors", validationErrors)
|
|
179
182
|
} else {
|
|
180
183
|
let errorMessage
|
|
181
184
|
|
package/src/devise.mjs
CHANGED
|
@@ -1,18 +1,13 @@
|
|
|
1
1
|
import CanCan from "./can-can.mjs"
|
|
2
2
|
import Deserializer from "./deserializer.mjs"
|
|
3
3
|
import {digg} from "diggerize"
|
|
4
|
-
import
|
|
4
|
+
import events from "./events.mjs"
|
|
5
5
|
import * as inflection from "inflection"
|
|
6
6
|
import modelClassRequire from "./model-class-require.mjs"
|
|
7
7
|
import Services from "./services.mjs"
|
|
8
8
|
|
|
9
|
-
const events = new EventEmitter()
|
|
10
9
|
const shared = {}
|
|
11
10
|
|
|
12
|
-
events.setMaxListeners(1000)
|
|
13
|
-
|
|
14
|
-
export {events}
|
|
15
|
-
|
|
16
11
|
export default class ApiMakerDevise {
|
|
17
12
|
static callSignOutEvent (args) {
|
|
18
13
|
events.emit("onDeviseSignOut", {args})
|
package/src/event-listener.jsx
CHANGED
|
@@ -1,36 +1,25 @@
|
|
|
1
1
|
import PropTypes from "prop-types"
|
|
2
2
|
import propTypesExact from "prop-types-exact"
|
|
3
|
-
import
|
|
3
|
+
import {memo} from "react"
|
|
4
|
+
import useEventListener from "./use-event-listener.mjs"
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
static propTypes = propTypesExact({
|
|
13
|
-
event: PropTypes.string.isRequired,
|
|
14
|
-
onCalled: PropTypes.func.isRequired,
|
|
15
|
-
target: PropTypes.object.isRequired
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
constructor (props) {
|
|
19
|
-
super(props)
|
|
20
|
-
this.onCalled = this.onCalled.bind(this)
|
|
21
|
-
}
|
|
6
|
+
const callEvent = (target, eventName, args = []) => {
|
|
7
|
+
let event = document.createEvent("Event")
|
|
8
|
+
event.initEvent(eventName, false, true)
|
|
9
|
+
target.dispatchEvent(event, args)
|
|
10
|
+
}
|
|
22
11
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
12
|
+
const ApiMakerEventListener = ({event, onCalled, target}) => {
|
|
13
|
+
useEventListener(target, event, onCalled)
|
|
26
14
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
15
|
+
return null
|
|
16
|
+
}
|
|
30
17
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
18
|
+
ApiMakerEventListener.propTypes = propTypesExact({
|
|
19
|
+
event: PropTypes.string.isRequired,
|
|
20
|
+
onCalled: PropTypes.func.isRequired,
|
|
21
|
+
target: PropTypes.object.isRequired
|
|
22
|
+
})
|
|
34
23
|
|
|
35
|
-
|
|
36
|
-
|
|
24
|
+
export {callEvent}
|
|
25
|
+
export default memo(ApiMakerEventListener)
|
package/src/events.mjs
ADDED
|
@@ -140,9 +140,7 @@ const inputWrapper = (WrapperComponentClass, wrapperOptions = {}) => {
|
|
|
140
140
|
return this._inputRefBackup
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
inputRef()
|
|
144
|
-
return this.props.inputRef || this.inputRefBackup()
|
|
145
|
-
}
|
|
143
|
+
inputRef = () => this.props.inputRef || this.inputRefBackup()
|
|
146
144
|
|
|
147
145
|
inputType() {
|
|
148
146
|
if ("type" in this.props) {
|
package/src/use-current-user.mjs
CHANGED
|
@@ -33,16 +33,23 @@ const useCurrentUser = (args) => {
|
|
|
33
33
|
|
|
34
34
|
if (!(scopeName in s.setStates)) throw new Error(`'${scopeName}' not found in setStates`)
|
|
35
35
|
|
|
36
|
+
Devise.updateSession(current)
|
|
36
37
|
s.setStates[scopeName](current)
|
|
38
|
+
|
|
39
|
+
if (s.props.onCurrentUserLoaded) setTimeout(() => s.props.onCurrentUserLoaded(current), 0)
|
|
37
40
|
}, [])
|
|
38
41
|
|
|
39
42
|
const defaultCurrentUser = useCallback(() => {
|
|
40
43
|
const {scope, scopeName} = s.m
|
|
41
44
|
|
|
42
45
|
if (Devise.current().hasCurrentScope(scope)) {
|
|
43
|
-
|
|
46
|
+
const current = Devise[scopeName]()
|
|
47
|
+
|
|
48
|
+
debugs(() => `Setting ${scope} from current scope: ${current?.id()}`)
|
|
49
|
+
|
|
50
|
+
if (s.props.onCurrentUserLoaded) setTimeout(() => s.props.onCurrentUserLoaded(current), 0)
|
|
44
51
|
|
|
45
|
-
return
|
|
52
|
+
return current
|
|
46
53
|
}
|
|
47
54
|
}, [])
|
|
48
55
|
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import EventEmitter from "events"
|
|
2
|
-
import PropTypes from "prop-types"
|
|
3
1
|
import {useCallback, useEffect} from "react"
|
|
4
2
|
|
|
5
3
|
const ApiMakerUseEventEmitter = (events, event, onCalled) => {
|
|
6
4
|
const onCalledCallback = useCallback((...args) => {
|
|
7
|
-
onCalled.apply(null,
|
|
5
|
+
onCalled.apply(null, args)
|
|
8
6
|
}, [events, event, onCalled])
|
|
9
7
|
|
|
10
8
|
useEffect(() => {
|
|
@@ -16,10 +14,4 @@ const ApiMakerUseEventEmitter = (events, event, onCalled) => {
|
|
|
16
14
|
}, [events, event, onCalled])
|
|
17
15
|
}
|
|
18
16
|
|
|
19
|
-
ApiMakerUseEventEmitter.propTypes = {
|
|
20
|
-
event: PropTypes.string.isRequired,
|
|
21
|
-
events: PropTypes.instanceOf(EventEmitter).isRequired,
|
|
22
|
-
onCalled: PropTypes.func.isRequired
|
|
23
|
-
}
|
|
24
|
-
|
|
25
17
|
export default ApiMakerUseEventEmitter
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {useCallback, useEffect} from "react"
|
|
2
|
+
|
|
3
|
+
const ApiMakerUseEventListener = (target, event, onCalled) => {
|
|
4
|
+
const onCalledCallback = useCallback((...args) => {
|
|
5
|
+
onCalled.apply(null, args)
|
|
6
|
+
}, [target, event, onCalled])
|
|
7
|
+
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
target.addEventListener(event, onCalledCallback)
|
|
10
|
+
|
|
11
|
+
return () => {
|
|
12
|
+
target.removeEventListener(event, onCalledCallback)
|
|
13
|
+
}
|
|
14
|
+
}, [target, event, onCalled])
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export default ApiMakerUseEventListener
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import events from "./events.mjs"
|
|
2
|
+
import useEventEmitter from "./use-event-emitter.mjs"
|
|
3
|
+
import useShape from "set-state-compare/src/use-shape.js"
|
|
4
|
+
|
|
5
|
+
const useValidationErrors = (callback) => {
|
|
6
|
+
const s = useShape({callback})
|
|
7
|
+
|
|
8
|
+
s.useStates({validationErrors: []})
|
|
9
|
+
|
|
10
|
+
const onValidationErrors = useCallback((validationErrors) => {
|
|
11
|
+
const matchedValidationErrors = []
|
|
12
|
+
|
|
13
|
+
for (const validationError of validationErrors.getValidationErrors()) {
|
|
14
|
+
if (s.p.callback(validationError)) {
|
|
15
|
+
validationError.setHandled()
|
|
16
|
+
matchedValidationErrors.push(validationError)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
s.set({
|
|
21
|
+
validationErrors: matchedValidationErrors
|
|
22
|
+
})
|
|
23
|
+
}, [])
|
|
24
|
+
|
|
25
|
+
useEventEmitter(events, "onValidationErrors", onValidationErrors)
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
validationErrors: s.s.validationErrors
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default useValidationErrors
|
package/src/validation-error.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import BaseError from "./base-error.mjs"
|
|
|
2
2
|
import * as inflection from "inflection"
|
|
3
3
|
|
|
4
4
|
class ValidationError extends BaseError {
|
|
5
|
-
constructor
|
|
5
|
+
constructor(validationErrors, args) {
|
|
6
6
|
const errorMessage = validationErrors.getUnhandledErrorMessage() || validationErrors.getErrorMessage()
|
|
7
7
|
const forwardedArgs = {addResponseErrorsToErrorMessage: false}
|
|
8
8
|
const newArgs = Object.assign({}, args, forwardedArgs)
|
|
@@ -11,12 +11,13 @@ class ValidationError extends BaseError {
|
|
|
11
11
|
this.validationErrors = validationErrors
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
hasUnhandledErrors
|
|
14
|
+
hasUnhandledErrors() {
|
|
15
15
|
const unhandledError = this.validationErrors.getValidationErrors().find((validationError) => !validationError.getHandled())
|
|
16
|
+
|
|
16
17
|
return Boolean(unhandledError)
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
hasValidationErrorForAttribute
|
|
20
|
+
hasValidationErrorForAttribute(attributeName) {
|
|
20
21
|
const underscoredAttributeName = inflection.underscore(attributeName)
|
|
21
22
|
const foundAttribute = this.validationErrors.getValidationErrors().find((validationError) => validationError.getAttributeName() == underscoredAttributeName)
|
|
22
23
|
|
|
@@ -30,13 +30,8 @@ class ValidationError {
|
|
|
30
30
|
return false
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
getAttributeName()
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
getErrorMessages() {
|
|
38
|
-
return digg(this, "errorMessages")
|
|
39
|
-
}
|
|
33
|
+
getAttributeName = () => digg(this, "attributeName")
|
|
34
|
+
getErrorMessages = () => digg(this, "errorMessages")
|
|
40
35
|
|
|
41
36
|
getFullErrorMessages() {
|
|
42
37
|
const {attributeType} = digs(this, "attributeType")
|
|
@@ -55,13 +50,8 @@ class ValidationError {
|
|
|
55
50
|
}
|
|
56
51
|
}
|
|
57
52
|
|
|
58
|
-
getHandled()
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
getInputName() {
|
|
63
|
-
return digg(this, "inputName")
|
|
64
|
-
}
|
|
53
|
+
getHandled = () => digg(this, "handled")
|
|
54
|
+
getInputName = () => digg(this, "inputName")
|
|
65
55
|
|
|
66
56
|
getModelClass() {
|
|
67
57
|
const modelName = inflection.classify(digg(this, "modelName"))
|
|
@@ -92,9 +82,7 @@ class ValidationErrors {
|
|
|
92
82
|
return fullErrorMessages.join(". ")
|
|
93
83
|
}
|
|
94
84
|
|
|
95
|
-
getValidationErrors()
|
|
96
|
-
return this.validationErrors
|
|
97
|
-
}
|
|
85
|
+
getValidationErrors = () => this.validationErrors
|
|
98
86
|
|
|
99
87
|
getValidationErrorsForInput ({attribute, inputName, onMatchValidationError}) {
|
|
100
88
|
const validationErrors = this.validationErrors.filter((validationError) => {
|