@dhis2/app-service-data 3.7.0 → 3.9.0
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/build/cjs/__tests__/integration.test.js +16 -10
- package/build/cjs/__tests__/mutations.test.js +8 -5
- package/build/cjs/engine/DataEngine.js +14 -12
- package/build/cjs/engine/helpers/resolveDynamicQuery.js +14 -11
- package/build/cjs/engine/helpers/resolveDynamicQuery.test.js +23 -14
- package/build/cjs/engine/helpers/validate.js +6 -4
- package/build/cjs/engine/helpers/validate.test.js +74 -15
- package/build/cjs/engine/types/FetchError.js +6 -5
- package/build/cjs/engine/types/InvalidQueryError.js +1 -1
- package/build/cjs/index.js +10 -10
- package/build/cjs/links/CustomDataLink.js +8 -6
- package/build/cjs/links/CustomDataLink.test.js +2 -2
- package/build/cjs/links/RestAPILink/fetchData.js +3 -2
- package/build/cjs/links/RestAPILink/fetchData.test.js +1 -1
- package/build/cjs/links/RestAPILink/metadataResources.js +1 -1
- package/build/cjs/links/RestAPILink/path.js +5 -1
- package/build/cjs/links/RestAPILink/queryToRequestOptions/multipartFormDataMatchers.js +29 -16
- package/build/cjs/links/RestAPILink/queryToRequestOptions/requestContentType.js +9 -6
- package/build/cjs/links/RestAPILink/queryToRequestOptions/requestContentType.test.js +2 -2
- package/build/cjs/links/RestAPILink/queryToRequestOptions/textPlainMatchers.js +51 -33
- package/build/cjs/links/RestAPILink/queryToRequestOptions/xWwwFormUrlencodedMatchers.js +6 -3
- package/build/cjs/links/RestAPILink/queryToRequestOptions.js +1 -1
- package/build/cjs/links/RestAPILink/queryToRequestOptions.test.js +56 -6
- package/build/cjs/links/RestAPILink/queryToResourcePath.js +14 -6
- package/build/cjs/links/RestAPILink/queryToResourcePath.test.js +16 -16
- package/build/cjs/links/RestAPILink/validateQuery.test.js +12 -12
- package/build/cjs/links/RestAPILink.js +4 -3
- package/build/cjs/react/components/CustomDataProvider.js +7 -6
- package/build/cjs/react/components/DataMutation.js +8 -7
- package/build/cjs/react/components/DataProvider.js +1 -1
- package/build/cjs/react/components/DataQuery.js +9 -8
- package/build/cjs/react/context/defaultContext.test.js +10 -2
- package/build/cjs/react/hooks/stableVariablesHash.js +1 -2
- package/build/cjs/react/hooks/stableVariablesHash.test.js +6 -6
- package/build/cjs/react/hooks/useDataMutation.js +7 -6
- package/build/cjs/react/hooks/useDataMutation.test.js +70 -43
- package/build/cjs/react/hooks/useDataQuery.js +13 -9
- package/build/cjs/react/hooks/useDataQuery.test.js +259 -162
- package/build/cjs/react/hooks/useQueryExecutor.js +11 -9
- package/build/cjs/react/hooks/useQueryExecutor.test.js +16 -12
- package/build/cjs/react/hooks/useStaticInput.js +7 -6
- package/build/cjs/react/hooks/useStaticInput.test.js +44 -25
- package/build/cjs/react/index.js +6 -6
- package/build/es/__tests__/integration.test.js +16 -10
- package/build/es/__tests__/mutations.test.js +8 -5
- package/build/es/engine/DataEngine.js +14 -12
- package/build/es/engine/helpers/resolveDynamicQuery.js +14 -11
- package/build/es/engine/helpers/resolveDynamicQuery.test.js +23 -14
- package/build/es/engine/helpers/validate.js +6 -4
- package/build/es/engine/helpers/validate.test.js +74 -15
- package/build/es/engine/types/FetchError.js +6 -5
- package/build/es/engine/types/InvalidQueryError.js +1 -1
- package/build/es/links/CustomDataLink.js +8 -6
- package/build/es/links/CustomDataLink.test.js +2 -2
- package/build/es/links/RestAPILink/fetchData.js +3 -2
- package/build/es/links/RestAPILink/fetchData.test.js +1 -1
- package/build/es/links/RestAPILink/path.js +5 -1
- package/build/es/links/RestAPILink/queryToRequestOptions/multipartFormDataMatchers.js +28 -15
- package/build/es/links/RestAPILink/queryToRequestOptions/requestContentType.js +8 -5
- package/build/es/links/RestAPILink/queryToRequestOptions/requestContentType.test.js +2 -2
- package/build/es/links/RestAPILink/queryToRequestOptions/textPlainMatchers.js +50 -32
- package/build/es/links/RestAPILink/queryToRequestOptions/xWwwFormUrlencodedMatchers.js +6 -3
- package/build/es/links/RestAPILink/queryToRequestOptions.js +1 -1
- package/build/es/links/RestAPILink/queryToRequestOptions.test.js +56 -6
- package/build/es/links/RestAPILink/queryToResourcePath.js +14 -6
- package/build/es/links/RestAPILink/queryToResourcePath.test.js +16 -16
- package/build/es/links/RestAPILink/validateQuery.test.js +12 -12
- package/build/es/links/RestAPILink.js +4 -3
- package/build/es/react/components/CustomDataProvider.js +7 -6
- package/build/es/react/components/DataMutation.js +8 -7
- package/build/es/react/components/DataQuery.js +9 -8
- package/build/es/react/context/defaultContext.test.js +10 -2
- package/build/es/react/hooks/stableVariablesHash.js +1 -2
- package/build/es/react/hooks/stableVariablesHash.test.js +6 -6
- package/build/es/react/hooks/useDataMutation.js +7 -6
- package/build/es/react/hooks/useDataMutation.test.js +70 -43
- package/build/es/react/hooks/useDataQuery.js +13 -9
- package/build/es/react/hooks/useDataQuery.test.js +259 -162
- package/build/es/react/hooks/useQueryExecutor.js +11 -9
- package/build/es/react/hooks/useQueryExecutor.test.js +16 -12
- package/build/es/react/hooks/useStaticInput.js +7 -6
- package/build/es/react/hooks/useStaticInput.test.js +44 -25
- package/package.json +2 -2
|
@@ -6,9 +6,10 @@ var _useQueryExecutor = require("./useQueryExecutor");
|
|
|
6
6
|
|
|
7
7
|
const testError = new Error('TEST ERROR');
|
|
8
8
|
let theSignal;
|
|
9
|
-
const execute = jest.fn(async ({
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
const execute = jest.fn(async (_ref) => {
|
|
10
|
+
let {
|
|
11
|
+
signal
|
|
12
|
+
} = _ref;
|
|
12
13
|
theSignal = signal;
|
|
13
14
|
return 42;
|
|
14
15
|
});
|
|
@@ -116,15 +117,18 @@ describe('useQueryExecutor', () => {
|
|
|
116
117
|
result,
|
|
117
118
|
waitForNextUpdate,
|
|
118
119
|
rerender
|
|
119
|
-
} = (0, _reactHooks.renderHook)(({
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
120
|
+
} = (0, _reactHooks.renderHook)((_ref2) => {
|
|
121
|
+
let {
|
|
122
|
+
onComplete
|
|
123
|
+
} = _ref2;
|
|
124
|
+
return (0, _useQueryExecutor.useQueryExecutor)({
|
|
125
|
+
execute,
|
|
126
|
+
immediate: true,
|
|
127
|
+
singular: true,
|
|
128
|
+
variables: {},
|
|
129
|
+
onComplete
|
|
130
|
+
});
|
|
131
|
+
}, {
|
|
128
132
|
initialProps: {
|
|
129
133
|
onComplete: () => null
|
|
130
134
|
}
|
|
@@ -7,16 +7,17 @@ exports.useStaticInput = void 0;
|
|
|
7
7
|
|
|
8
8
|
var _react = require("react");
|
|
9
9
|
|
|
10
|
-
const useStaticInput = (staticValue
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
const useStaticInput = function (staticValue) {
|
|
11
|
+
let {
|
|
12
|
+
warn = false,
|
|
13
|
+
name = 'input'
|
|
14
|
+
} = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
14
15
|
const originalValue = (0, _react.useRef)(staticValue);
|
|
15
16
|
const [value, setValue] = (0, _react.useState)(() => originalValue.current);
|
|
16
|
-
(0, _react.useDebugValue)(value, debugValue =>
|
|
17
|
+
(0, _react.useDebugValue)(value, debugValue => `${name}: ${JSON.stringify(debugValue)}`);
|
|
17
18
|
(0, _react.useEffect)(() => {
|
|
18
19
|
if (warn && originalValue.current !== staticValue) {
|
|
19
|
-
console.warn(
|
|
20
|
+
console.warn(`The ${name} should be static, don't create it within the render loop!`);
|
|
20
21
|
}
|
|
21
22
|
}, [warn, staticValue, originalValue, name]);
|
|
22
23
|
return [value, setValue];
|
|
@@ -23,9 +23,12 @@ describe('useStaticInput', () => {
|
|
|
23
23
|
const {
|
|
24
24
|
result,
|
|
25
25
|
rerender
|
|
26
|
-
} = (0, _reactHooks.renderHook)(({
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
} = (0, _reactHooks.renderHook)((_ref) => {
|
|
27
|
+
let {
|
|
28
|
+
value
|
|
29
|
+
} = _ref;
|
|
30
|
+
return (0, _useStaticInput.useStaticInput)(value);
|
|
31
|
+
}, {
|
|
29
32
|
initialProps: {
|
|
30
33
|
value: 42
|
|
31
34
|
}
|
|
@@ -41,11 +44,14 @@ describe('useStaticInput', () => {
|
|
|
41
44
|
const {
|
|
42
45
|
result,
|
|
43
46
|
rerender
|
|
44
|
-
} = (0, _reactHooks.renderHook)(({
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
} = (0, _reactHooks.renderHook)((_ref2) => {
|
|
48
|
+
let {
|
|
49
|
+
value
|
|
50
|
+
} = _ref2;
|
|
51
|
+
return (0, _useStaticInput.useStaticInput)(value, {
|
|
52
|
+
warn: true
|
|
53
|
+
});
|
|
54
|
+
}, {
|
|
49
55
|
initialProps: {
|
|
50
56
|
value: 42
|
|
51
57
|
}
|
|
@@ -55,19 +61,26 @@ describe('useStaticInput', () => {
|
|
|
55
61
|
value: 54
|
|
56
62
|
});
|
|
57
63
|
expect(mockWarn).toHaveBeenCalled();
|
|
58
|
-
expect(mockWarn.mock.calls.pop()).toMatchInlineSnapshot(
|
|
64
|
+
expect(mockWarn.mock.calls.pop()).toMatchInlineSnapshot(`
|
|
65
|
+
Array [
|
|
66
|
+
"The input should be static, don't create it within the render loop!",
|
|
67
|
+
]
|
|
68
|
+
`);
|
|
59
69
|
expect(result.current[0]).toBe(42);
|
|
60
70
|
});
|
|
61
71
|
it('Should show custom name in warning if supplied', () => {
|
|
62
72
|
const {
|
|
63
73
|
result,
|
|
64
74
|
rerender
|
|
65
|
-
} = (0, _reactHooks.renderHook)(({
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
75
|
+
} = (0, _reactHooks.renderHook)((_ref3) => {
|
|
76
|
+
let {
|
|
77
|
+
value
|
|
78
|
+
} = _ref3;
|
|
79
|
+
return (0, _useStaticInput.useStaticInput)(value, {
|
|
80
|
+
warn: true,
|
|
81
|
+
name: 'TESTING THING'
|
|
82
|
+
});
|
|
83
|
+
}, {
|
|
71
84
|
initialProps: {
|
|
72
85
|
value: 42
|
|
73
86
|
}
|
|
@@ -84,11 +97,14 @@ describe('useStaticInput', () => {
|
|
|
84
97
|
const {
|
|
85
98
|
result,
|
|
86
99
|
rerender
|
|
87
|
-
} = (0, _reactHooks.renderHook)(({
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
100
|
+
} = (0, _reactHooks.renderHook)((_ref4) => {
|
|
101
|
+
let {
|
|
102
|
+
value
|
|
103
|
+
} = _ref4;
|
|
104
|
+
return (0, _useStaticInput.useStaticInput)(value, {
|
|
105
|
+
warn: true
|
|
106
|
+
});
|
|
107
|
+
}, {
|
|
92
108
|
initialProps: {
|
|
93
109
|
value: 42
|
|
94
110
|
}
|
|
@@ -117,11 +133,14 @@ describe('useStaticInput', () => {
|
|
|
117
133
|
const {
|
|
118
134
|
result,
|
|
119
135
|
rerender
|
|
120
|
-
} = (0, _reactHooks.renderHook)(({
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
136
|
+
} = (0, _reactHooks.renderHook)((_ref5) => {
|
|
137
|
+
let {
|
|
138
|
+
value
|
|
139
|
+
} = _ref5;
|
|
140
|
+
return (0, _useStaticInput.useStaticInput)(value, {
|
|
141
|
+
warn: true
|
|
142
|
+
});
|
|
143
|
+
}, {
|
|
125
144
|
initialProps: {
|
|
126
145
|
value: fn
|
|
127
146
|
}
|
package/build/cjs/react/index.js
CHANGED
|
@@ -9,6 +9,12 @@ Object.defineProperty(exports, "CustomDataProvider", {
|
|
|
9
9
|
return _CustomDataProvider.CustomDataProvider;
|
|
10
10
|
}
|
|
11
11
|
});
|
|
12
|
+
Object.defineProperty(exports, "DataContext", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () {
|
|
15
|
+
return _DataContext.DataContext;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
12
18
|
Object.defineProperty(exports, "DataMutation", {
|
|
13
19
|
enumerable: true,
|
|
14
20
|
get: function () {
|
|
@@ -27,12 +33,6 @@ Object.defineProperty(exports, "DataQuery", {
|
|
|
27
33
|
return _DataQuery.DataQuery;
|
|
28
34
|
}
|
|
29
35
|
});
|
|
30
|
-
Object.defineProperty(exports, "DataContext", {
|
|
31
|
-
enumerable: true,
|
|
32
|
-
get: function () {
|
|
33
|
-
return _DataContext.DataContext;
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
36
|
Object.defineProperty(exports, "defaultContext", {
|
|
37
37
|
enumerable: true,
|
|
38
38
|
get: function () {
|
|
@@ -7,11 +7,14 @@ describe('<DataQuery />', () => {
|
|
|
7
7
|
answer: 42
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
-
const wrapper = ({
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
const wrapper = (_ref) => {
|
|
11
|
+
let {
|
|
12
|
+
children
|
|
13
|
+
} = _ref;
|
|
14
|
+
return /*#__PURE__*/React.createElement(CustomDataProvider, {
|
|
15
|
+
data: data
|
|
16
|
+
}, children);
|
|
17
|
+
};
|
|
15
18
|
|
|
16
19
|
const renderFunction = jest.fn(() => null);
|
|
17
20
|
render( /*#__PURE__*/React.createElement(DataQuery, {
|
|
@@ -45,11 +48,14 @@ describe('<DataQuery />', () => {
|
|
|
45
48
|
}
|
|
46
49
|
};
|
|
47
50
|
|
|
48
|
-
const wrapper = ({
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
const wrapper = (_ref2) => {
|
|
52
|
+
let {
|
|
53
|
+
children
|
|
54
|
+
} = _ref2;
|
|
55
|
+
return /*#__PURE__*/React.createElement(CustomDataProvider, {
|
|
56
|
+
data: data
|
|
57
|
+
}, children);
|
|
58
|
+
};
|
|
53
59
|
|
|
54
60
|
const renderFunction = jest.fn(() => null);
|
|
55
61
|
render( /*#__PURE__*/React.createElement(DataQuery, {
|
|
@@ -15,11 +15,14 @@ describe('<DataMutation />', () => {
|
|
|
15
15
|
answer: endpointSpy
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
const wrapper = ({
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
const wrapper = (_ref) => {
|
|
19
|
+
let {
|
|
20
|
+
children
|
|
21
|
+
} = _ref;
|
|
22
|
+
return /*#__PURE__*/React.createElement(CustomDataProvider, {
|
|
23
|
+
data: data
|
|
24
|
+
}, children);
|
|
25
|
+
};
|
|
23
26
|
|
|
24
27
|
const renderSpy = jest.fn(() => null);
|
|
25
28
|
render( /*#__PURE__*/React.createElement(DataMutation, {
|
|
@@ -16,12 +16,13 @@ export class DataEngine {
|
|
|
16
16
|
this.link = link;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
query(query
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
query(query) {
|
|
20
|
+
let {
|
|
21
|
+
variables = {},
|
|
22
|
+
signal,
|
|
23
|
+
onComplete,
|
|
24
|
+
onError
|
|
25
|
+
} = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
25
26
|
const names = Object.keys(query);
|
|
26
27
|
const queries = names.map(name => query[name]).map(q => resolveDynamicQuery(q, variables));
|
|
27
28
|
validateResourceQueries(queries, names);
|
|
@@ -39,12 +40,13 @@ export class DataEngine {
|
|
|
39
40
|
});
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
mutate(mutation
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
mutate(mutation) {
|
|
44
|
+
let {
|
|
45
|
+
variables = {},
|
|
46
|
+
signal,
|
|
47
|
+
onComplete,
|
|
48
|
+
onError
|
|
49
|
+
} = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
48
50
|
const query = resolveDynamicQuery(mutation, variables);
|
|
49
51
|
const type = getMutationFetchType(mutation);
|
|
50
52
|
validateResourceQuery(type, query);
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
export const resolveDynamicQuery = ({
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
export const resolveDynamicQuery = (_ref, variables) => {
|
|
2
|
+
let {
|
|
3
|
+
resource,
|
|
4
|
+
id,
|
|
5
|
+
data,
|
|
6
|
+
params
|
|
7
|
+
} = _ref;
|
|
8
|
+
return {
|
|
9
|
+
resource,
|
|
10
|
+
id: typeof id === 'function' ? id(variables) : id,
|
|
11
|
+
data: typeof data === 'function' ? data(variables) : data,
|
|
12
|
+
params: typeof params === 'function' ? params(variables) : params
|
|
13
|
+
};
|
|
14
|
+
};
|
|
@@ -17,20 +17,29 @@ describe('resolveDynamicQuery', () => {
|
|
|
17
17
|
it('Should replace variables in all dynamic properties', () => {
|
|
18
18
|
const query = {
|
|
19
19
|
resource: 'test',
|
|
20
|
-
id: ({
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
20
|
+
id: (_ref) => {
|
|
21
|
+
let {
|
|
22
|
+
id
|
|
23
|
+
} = _ref;
|
|
24
|
+
return id;
|
|
25
|
+
},
|
|
26
|
+
params: (_ref2) => {
|
|
27
|
+
let {
|
|
28
|
+
page
|
|
29
|
+
} = _ref2;
|
|
30
|
+
return {
|
|
31
|
+
page,
|
|
32
|
+
foo: 'bar'
|
|
33
|
+
};
|
|
34
|
+
},
|
|
35
|
+
data: (_ref3) => {
|
|
36
|
+
let {
|
|
37
|
+
bar
|
|
38
|
+
} = _ref3;
|
|
39
|
+
return {
|
|
40
|
+
bar
|
|
41
|
+
};
|
|
42
|
+
}
|
|
34
43
|
};
|
|
35
44
|
const vars = {
|
|
36
45
|
id: '42',
|
|
@@ -3,7 +3,7 @@ const validQueryKeys = ['resource', 'id', 'params', 'data'];
|
|
|
3
3
|
const validTypes = ['read', 'create', 'update', 'replace', 'delete', 'json-patch'];
|
|
4
4
|
export const getResourceQueryErrors = (type, query) => {
|
|
5
5
|
if (!validTypes.includes(type)) {
|
|
6
|
-
return [
|
|
6
|
+
return [`Unknown query or mutation type ${type}`];
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
if (typeof query !== 'object') {
|
|
@@ -38,18 +38,20 @@ export const getResourceQueryErrors = (type, query) => {
|
|
|
38
38
|
|
|
39
39
|
const invalidKeys = Object.keys(query).filter(k => !validQueryKeys.includes(k));
|
|
40
40
|
invalidKeys.forEach(k => {
|
|
41
|
-
errors.push(
|
|
41
|
+
errors.push(`Property ${k} is not supported`);
|
|
42
42
|
});
|
|
43
43
|
return errors;
|
|
44
44
|
};
|
|
45
|
-
export const validateResourceQueries = (queries
|
|
45
|
+
export const validateResourceQueries = function (queries) {
|
|
46
|
+
let names = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
47
|
+
|
|
46
48
|
if (names.length !== queries.length) {
|
|
47
49
|
for (let i = names.length; i < queries.length; ++i) {
|
|
48
50
|
names.push('query#' + i);
|
|
49
51
|
}
|
|
50
52
|
}
|
|
51
53
|
|
|
52
|
-
const errors = queries.reduce((errors, query, i) => errors.concat(getResourceQueryErrors('read', query).map(e =>
|
|
54
|
+
const errors = queries.reduce((errors, query, i) => errors.concat(getResourceQueryErrors('read', query).map(e => `[${names[i]}] ${e}`)), []);
|
|
53
55
|
|
|
54
56
|
if (errors.length) {
|
|
55
57
|
throw new InvalidQueryError(errors);
|
|
@@ -19,25 +19,45 @@ describe('query validation', () => {
|
|
|
19
19
|
resource: 'me'
|
|
20
20
|
});
|
|
21
21
|
expect(errors).toHaveLength(1);
|
|
22
|
-
expect(errors).toMatchInlineSnapshot(
|
|
22
|
+
expect(errors).toMatchInlineSnapshot(`
|
|
23
|
+
Array [
|
|
24
|
+
"Unknown query or mutation type rainbow",
|
|
25
|
+
]
|
|
26
|
+
`);
|
|
23
27
|
});
|
|
24
28
|
it('should fail if query is not an object', () => {
|
|
25
29
|
let errors = getResourceQueryErrors('read', 'query');
|
|
26
30
|
expect(errors).toHaveLength(1);
|
|
27
|
-
expect(errors).toMatchInlineSnapshot(
|
|
31
|
+
expect(errors).toMatchInlineSnapshot(`
|
|
32
|
+
Array [
|
|
33
|
+
"A query or mutation must be a javascript object",
|
|
34
|
+
]
|
|
35
|
+
`);
|
|
28
36
|
errors = getResourceQueryErrors('read', 42);
|
|
29
37
|
expect(errors).toHaveLength(1);
|
|
30
|
-
expect(errors).toMatchInlineSnapshot(
|
|
38
|
+
expect(errors).toMatchInlineSnapshot(`
|
|
39
|
+
Array [
|
|
40
|
+
"A query or mutation must be a javascript object",
|
|
41
|
+
]
|
|
42
|
+
`);
|
|
31
43
|
});
|
|
32
44
|
it('should fail if query is missing resource property', () => {
|
|
33
45
|
const errors = getResourceQueryErrors('read', {});
|
|
34
46
|
expect(errors).toHaveLength(1);
|
|
35
|
-
expect(errors).toMatchInlineSnapshot(
|
|
47
|
+
expect(errors).toMatchInlineSnapshot(`
|
|
48
|
+
Array [
|
|
49
|
+
"Property resource must be a string",
|
|
50
|
+
]
|
|
51
|
+
`);
|
|
36
52
|
});
|
|
37
53
|
it('should fail if query is missing resource property', () => {
|
|
38
54
|
const errors = getResourceQueryErrors('read', {});
|
|
39
55
|
expect(errors).toHaveLength(1);
|
|
40
|
-
expect(errors).toMatchInlineSnapshot(
|
|
56
|
+
expect(errors).toMatchInlineSnapshot(`
|
|
57
|
+
Array [
|
|
58
|
+
"Property resource must be a string",
|
|
59
|
+
]
|
|
60
|
+
`);
|
|
41
61
|
});
|
|
42
62
|
it('should fail if query is create mutation with id prop', () => {
|
|
43
63
|
const errors = getResourceQueryErrors('create', {
|
|
@@ -45,7 +65,11 @@ describe('query validation', () => {
|
|
|
45
65
|
id: 'something'
|
|
46
66
|
});
|
|
47
67
|
expect(errors).toHaveLength(1);
|
|
48
|
-
expect(errors).toMatchInlineSnapshot(
|
|
68
|
+
expect(errors).toMatchInlineSnapshot(`
|
|
69
|
+
Array [
|
|
70
|
+
"Mutation type 'create' does not support property 'id'",
|
|
71
|
+
]
|
|
72
|
+
`);
|
|
49
73
|
});
|
|
50
74
|
it('should fail if id prop is not a string', () => {
|
|
51
75
|
const errors = getResourceQueryErrors('update', {
|
|
@@ -53,7 +77,11 @@ describe('query validation', () => {
|
|
|
53
77
|
id: 42
|
|
54
78
|
});
|
|
55
79
|
expect(errors).toHaveLength(1);
|
|
56
|
-
expect(errors).toMatchInlineSnapshot(
|
|
80
|
+
expect(errors).toMatchInlineSnapshot(`
|
|
81
|
+
Array [
|
|
82
|
+
"Property id must be a string",
|
|
83
|
+
]
|
|
84
|
+
`);
|
|
57
85
|
});
|
|
58
86
|
it('should fail if params prop is not an object', () => {
|
|
59
87
|
const errors = getResourceQueryErrors('update', {
|
|
@@ -62,7 +90,11 @@ describe('query validation', () => {
|
|
|
62
90
|
params: 'querystring=42'
|
|
63
91
|
});
|
|
64
92
|
expect(errors).toHaveLength(1);
|
|
65
|
-
expect(errors).toMatchInlineSnapshot(
|
|
93
|
+
expect(errors).toMatchInlineSnapshot(`
|
|
94
|
+
Array [
|
|
95
|
+
"Property params must be an object",
|
|
96
|
+
]
|
|
97
|
+
`);
|
|
66
98
|
});
|
|
67
99
|
it('should fail if query is delete mutation with data prop', () => {
|
|
68
100
|
const errors = getResourceQueryErrors('delete', {
|
|
@@ -71,7 +103,11 @@ describe('query validation', () => {
|
|
|
71
103
|
data: 'querystring=42'
|
|
72
104
|
});
|
|
73
105
|
expect(errors).toHaveLength(1);
|
|
74
|
-
expect(errors).toMatchInlineSnapshot(
|
|
106
|
+
expect(errors).toMatchInlineSnapshot(`
|
|
107
|
+
Array [
|
|
108
|
+
"Mutation type 'delete' does not support property 'data'",
|
|
109
|
+
]
|
|
110
|
+
`);
|
|
75
111
|
});
|
|
76
112
|
it('should fail if query is json-patch mutation with non-array data prop', () => {
|
|
77
113
|
const errors = getResourceQueryErrors('json-patch', {
|
|
@@ -79,7 +115,11 @@ describe('query validation', () => {
|
|
|
79
115
|
data: {}
|
|
80
116
|
});
|
|
81
117
|
expect(errors).toHaveLength(1);
|
|
82
|
-
expect(errors).toMatchInlineSnapshot(
|
|
118
|
+
expect(errors).toMatchInlineSnapshot(`
|
|
119
|
+
Array [
|
|
120
|
+
"Mutation type 'json-patch' requires property 'data' to be of type Array",
|
|
121
|
+
]
|
|
122
|
+
`);
|
|
83
123
|
});
|
|
84
124
|
it('should fail if unrecognized keys are passed to query', () => {
|
|
85
125
|
const errors = getResourceQueryErrors('update', {
|
|
@@ -89,7 +129,12 @@ describe('query validation', () => {
|
|
|
89
129
|
foo: 'bar'
|
|
90
130
|
});
|
|
91
131
|
expect(errors).toHaveLength(2);
|
|
92
|
-
expect(errors).toMatchInlineSnapshot(
|
|
132
|
+
expect(errors).toMatchInlineSnapshot(`
|
|
133
|
+
Array [
|
|
134
|
+
"Property query is not supported",
|
|
135
|
+
"Property foo is not supported",
|
|
136
|
+
]
|
|
137
|
+
`);
|
|
93
138
|
});
|
|
94
139
|
});
|
|
95
140
|
describe('validateResourceQuery', () => {
|
|
@@ -102,13 +147,19 @@ describe('query validation', () => {
|
|
|
102
147
|
expect(() => validateResourceQuery('create', {
|
|
103
148
|
resource: 'me',
|
|
104
149
|
id: '42'
|
|
105
|
-
})).toThrowErrorMatchingInlineSnapshot(
|
|
150
|
+
})).toThrowErrorMatchingInlineSnapshot(`
|
|
151
|
+
"Invalid query
|
|
152
|
+
- Mutation type 'create' does not support property 'id'"
|
|
153
|
+
`);
|
|
106
154
|
});
|
|
107
155
|
it('should throw an error with an invalid query', () => {
|
|
108
156
|
expect(() => validateResourceQuery('create', {
|
|
109
157
|
resource: 'me',
|
|
110
158
|
answer: 42
|
|
111
|
-
})).toThrowErrorMatchingInlineSnapshot(
|
|
159
|
+
})).toThrowErrorMatchingInlineSnapshot(`
|
|
160
|
+
"Invalid query
|
|
161
|
+
- Property answer is not supported"
|
|
162
|
+
`);
|
|
112
163
|
});
|
|
113
164
|
});
|
|
114
165
|
describe('validateResourceQueries', () => {
|
|
@@ -128,7 +179,11 @@ describe('query validation', () => {
|
|
|
128
179
|
}, {
|
|
129
180
|
resource: 'me',
|
|
130
181
|
id: 42
|
|
131
|
-
}])).toThrowErrorMatchingInlineSnapshot(
|
|
182
|
+
}])).toThrowErrorMatchingInlineSnapshot(`
|
|
183
|
+
"Invalid query
|
|
184
|
+
- [query#1] Property params must be an object
|
|
185
|
+
- [query#2] Property id must be a string"
|
|
186
|
+
`);
|
|
132
187
|
});
|
|
133
188
|
it('should throw if any query is invalid, prefixing with relevant name', () => {
|
|
134
189
|
expect(() => validateResourceQueries([{
|
|
@@ -139,7 +194,11 @@ describe('query validation', () => {
|
|
|
139
194
|
}, {
|
|
140
195
|
resource: 'me',
|
|
141
196
|
id: 42
|
|
142
|
-
}], ['me', 'inds'])).toThrowErrorMatchingInlineSnapshot(
|
|
197
|
+
}], ['me', 'inds'])).toThrowErrorMatchingInlineSnapshot(`
|
|
198
|
+
"Invalid query
|
|
199
|
+
- [inds] Property params must be an object
|
|
200
|
+
- [query#2] Property id must be a string"
|
|
201
|
+
`);
|
|
143
202
|
});
|
|
144
203
|
});
|
|
145
204
|
});
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
2
2
|
|
|
3
3
|
export class FetchError extends Error {
|
|
4
|
-
constructor({
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
constructor(_ref) {
|
|
5
|
+
let {
|
|
6
|
+
message,
|
|
7
|
+
type,
|
|
8
|
+
details = {}
|
|
9
|
+
} = _ref;
|
|
9
10
|
super(message);
|
|
10
11
|
|
|
11
12
|
_defineProperty(this, "type", void 0);
|
|
@@ -2,7 +2,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
|
|
|
2
2
|
|
|
3
3
|
export class InvalidQueryError extends Error {
|
|
4
4
|
constructor(errors) {
|
|
5
|
-
super(
|
|
5
|
+
super(`Invalid query\n${errors.map(e => ' - ' + e).join('\n')}`);
|
|
6
6
|
|
|
7
7
|
_defineProperty(this, "type", 'invalid-query');
|
|
8
8
|
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
2
2
|
|
|
3
3
|
export class CustomDataLink {
|
|
4
|
-
constructor(customData
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
constructor(customData) {
|
|
5
|
+
let {
|
|
6
|
+
failOnMiss = true,
|
|
7
|
+
loadForever = false
|
|
8
|
+
} = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
9
|
+
|
|
8
10
|
_defineProperty(this, "failOnMiss", void 0);
|
|
9
11
|
|
|
10
12
|
_defineProperty(this, "loadForever", void 0);
|
|
@@ -25,7 +27,7 @@ export class CustomDataLink {
|
|
|
25
27
|
|
|
26
28
|
if (customResource === undefined) {
|
|
27
29
|
if (this.failOnMiss) {
|
|
28
|
-
throw new Error(
|
|
30
|
+
throw new Error(`No data provided for resource type ${query.resource}!`);
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
return Promise.resolve(null);
|
|
@@ -43,7 +45,7 @@ export class CustomDataLink {
|
|
|
43
45
|
const result = await customResource(type, query, options);
|
|
44
46
|
|
|
45
47
|
if (typeof result === 'undefined' && this.failOnMiss) {
|
|
46
|
-
throw new Error(
|
|
48
|
+
throw new Error(`The custom function for resource ${query.resource} must always return a value but returned ${result}`);
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
return result || null;
|
|
@@ -14,7 +14,7 @@ describe('CustomDataLink', () => {
|
|
|
14
14
|
});
|
|
15
15
|
expect(link.executeResourceQuery('read', {
|
|
16
16
|
resource: 'something'
|
|
17
|
-
}, {})).rejects.toMatchInlineSnapshot(
|
|
17
|
+
}, {})).rejects.toMatchInlineSnapshot(`[Error: No data provided for resource type something!]`);
|
|
18
18
|
});
|
|
19
19
|
it('Should swallow miss error with failOnMiss=false', async () => {
|
|
20
20
|
const link = new CustomDataLink({
|
|
@@ -40,7 +40,7 @@ describe('CustomDataLink', () => {
|
|
|
40
40
|
});
|
|
41
41
|
expect(link.executeResourceQuery('read', {
|
|
42
42
|
resource: 'foo'
|
|
43
|
-
}, {})).rejects.toMatchInlineSnapshot(
|
|
43
|
+
}, {})).rejects.toMatchInlineSnapshot(`[Error: The custom function for resource foo must always return a value but returned undefined]`);
|
|
44
44
|
});
|
|
45
45
|
it('Should swallow functional miss if failOnMiss=false', async () => {
|
|
46
46
|
const link = new CustomDataLink({
|