@dhis2/app-service-data 3.16.0 → 3.17.0-beta.2
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 +10 -16
- package/build/cjs/__tests__/mutations.test.js +5 -8
- package/build/cjs/index.js +16 -44
- package/build/cjs/react/components/CustomDataProvider.js +9 -11
- package/build/cjs/react/components/DataMutation.js +7 -8
- package/build/cjs/react/components/DataProvider.js +3 -4
- package/build/cjs/react/components/DataProvider.test.js +3 -4
- package/build/cjs/react/components/DataQuery.js +8 -9
- package/build/cjs/react/components/index.js +33 -0
- package/build/cjs/react/context/DataContext.js +2 -2
- package/build/cjs/react/context/defaultDataContext.js +13 -0
- package/build/cjs/react/context/{defaultContext.test.js → defaultDataContext.test.js} +3 -3
- package/build/cjs/react/hooks/index.js +26 -0
- package/build/cjs/react/hooks/useDataMutation.js +6 -7
- package/build/cjs/react/hooks/useDataMutation.test.js +44 -71
- package/build/cjs/react/hooks/useDataQuery.js +10 -14
- package/build/cjs/react/hooks/useDataQuery.test.js +172 -265
- package/build/cjs/react/hooks/useQueryExecutor.js +11 -13
- package/build/cjs/react/hooks/useQueryExecutor.test.js +12 -16
- package/build/cjs/react/hooks/useStaticInput.js +4 -5
- package/build/cjs/react/hooks/useStaticInput.test.js +24 -39
- package/build/cjs/react/index.js +22 -77
- package/build/es/__tests__/integration.test.js +10 -16
- package/build/es/__tests__/mutations.test.js +5 -8
- package/build/es/index.js +2 -3
- package/build/es/react/components/CustomDataProvider.js +7 -9
- package/build/es/react/components/DataMutation.js +7 -8
- package/build/es/react/components/DataProvider.js +1 -2
- package/build/es/react/components/DataProvider.test.js +1 -2
- package/build/es/react/components/DataQuery.js +8 -9
- package/build/es/react/components/index.js +4 -0
- package/build/es/react/context/DataContext.js +2 -2
- package/build/es/react/context/{defaultContext.js → defaultDataContext.js} +2 -3
- package/build/es/react/context/{defaultContext.test.js → defaultDataContext.test.js} +3 -3
- package/build/es/react/hooks/index.js +3 -0
- package/build/es/react/hooks/useDataMutation.js +6 -7
- package/build/es/react/hooks/useDataMutation.test.js +44 -71
- package/build/es/react/hooks/useDataQuery.js +10 -14
- package/build/es/react/hooks/useDataQuery.test.js +172 -265
- package/build/es/react/hooks/useQueryExecutor.js +10 -12
- package/build/es/react/hooks/useQueryExecutor.test.js +12 -16
- package/build/es/react/hooks/useStaticInput.js +4 -5
- package/build/es/react/hooks/useStaticInput.test.js +24 -39
- package/build/es/react/index.js +3 -11
- package/build/types/index.d.ts +2 -3
- package/build/types/react/components/CustomDataProvider.d.ts +1 -1
- package/build/types/react/components/DataMutation.d.ts +1 -1
- package/build/types/react/components/DataQuery.d.ts +1 -1
- package/build/types/react/components/index.d.ts +4 -0
- package/build/types/react/context/defaultDataContext.d.ts +4 -0
- package/build/types/react/hooks/index.d.ts +3 -0
- package/build/types/react/hooks/mergeAndCompareVariables.d.ts +1 -1
- package/build/types/react/hooks/useDataEngine.d.ts +1 -1
- package/build/types/react/hooks/useDataMutation.d.ts +1 -1
- package/build/types/react/hooks/useDataQuery.d.ts +1 -1
- package/build/types/react/index.d.ts +2 -11
- package/build/types/types.d.ts +2 -7
- package/package.json +4 -3
- package/build/cjs/engine/DataEngine.js +0 -73
- package/build/cjs/engine/DataEngine.test.js +0 -156
- package/build/cjs/engine/helpers/getMutationFetchType.js +0 -8
- package/build/cjs/engine/helpers/getMutationFetchType.test.js +0 -39
- package/build/cjs/engine/helpers/resolveDynamicQuery.js +0 -21
- package/build/cjs/engine/helpers/resolveDynamicQuery.test.js +0 -63
- package/build/cjs/engine/helpers/validate.js +0 -62
- package/build/cjs/engine/helpers/validate.test.js +0 -206
- package/build/cjs/engine/index.js +0 -104
- package/build/cjs/engine/types/DataEngineLink.js +0 -1
- package/build/cjs/engine/types/ExecuteOptions.js +0 -1
- package/build/cjs/engine/types/FetchError.js +0 -24
- package/build/cjs/engine/types/FetchError.test.js +0 -14
- package/build/cjs/engine/types/InvalidQueryError.js +0 -18
- package/build/cjs/engine/types/JsonValue.js +0 -1
- package/build/cjs/engine/types/Mutation.js +0 -1
- package/build/cjs/engine/types/PossiblyDynamic.js +0 -1
- package/build/cjs/engine/types/Query.js +0 -1
- package/build/cjs/engine/types/QueryParameters.js +0 -1
- package/build/cjs/links/CustomDataLink.js +0 -51
- package/build/cjs/links/CustomDataLink.test.js +0 -73
- package/build/cjs/links/ErrorLink.js +0 -20
- package/build/cjs/links/RestAPILink/fetchData.js +0 -80
- package/build/cjs/links/RestAPILink/fetchData.test.js +0 -132
- package/build/cjs/links/RestAPILink/metadataResources.js +0 -22
- package/build/cjs/links/RestAPILink/path.js +0 -14
- package/build/cjs/links/RestAPILink/path.test.js +0 -16
- package/build/cjs/links/RestAPILink/queryToRequestOptions/multipartFormDataMatchers.js +0 -58
- package/build/cjs/links/RestAPILink/queryToRequestOptions/multipartFormDataMatchers.test.js +0 -73
- package/build/cjs/links/RestAPILink/queryToRequestOptions/requestContentType.js +0 -80
- package/build/cjs/links/RestAPILink/queryToRequestOptions/requestContentType.test.js +0 -120
- package/build/cjs/links/RestAPILink/queryToRequestOptions/textPlainMatchers.js +0 -170
- package/build/cjs/links/RestAPILink/queryToRequestOptions/textPlainMatchers.test.js +0 -246
- package/build/cjs/links/RestAPILink/queryToRequestOptions/xWwwFormUrlencodedMatchers.js +0 -14
- package/build/cjs/links/RestAPILink/queryToRequestOptions/xWwwFormUrlencodedMatchers.test.js +0 -20
- package/build/cjs/links/RestAPILink/queryToRequestOptions.js +0 -34
- package/build/cjs/links/RestAPILink/queryToRequestOptions.test.js +0 -107
- package/build/cjs/links/RestAPILink/queryToResourcePath.js +0 -82
- package/build/cjs/links/RestAPILink/queryToResourcePath.test.js +0 -173
- package/build/cjs/links/RestAPILink/validateQuery.js +0 -59
- package/build/cjs/links/RestAPILink/validateQuery.test.js +0 -209
- package/build/cjs/links/RestAPILink.js +0 -33
- package/build/cjs/links/RestAPILink.test.js +0 -21
- package/build/cjs/links/index.js +0 -38
- package/build/cjs/locales/en/translations.json +0 -3
- package/build/cjs/locales/index.js +0 -21
- package/build/cjs/react/context/defaultContext.js +0 -14
- package/build/es/engine/DataEngine.js +0 -66
- package/build/es/engine/DataEngine.test.js +0 -154
- package/build/es/engine/helpers/getMutationFetchType.js +0 -1
- package/build/es/engine/helpers/getMutationFetchType.test.js +0 -37
- package/build/es/engine/helpers/resolveDynamicQuery.js +0 -14
- package/build/es/engine/helpers/resolveDynamicQuery.test.js +0 -61
- package/build/es/engine/helpers/validate.js +0 -53
- package/build/es/engine/helpers/validate.test.js +0 -204
- package/build/es/engine/index.js +0 -10
- package/build/es/engine/types/DataEngineLink.js +0 -1
- package/build/es/engine/types/ExecuteOptions.js +0 -1
- package/build/es/engine/types/FetchError.js +0 -17
- package/build/es/engine/types/FetchError.test.js +0 -12
- package/build/es/engine/types/InvalidQueryError.js +0 -11
- package/build/es/engine/types/JsonValue.js +0 -1
- package/build/es/engine/types/Mutation.js +0 -1
- package/build/es/engine/types/PossiblyDynamic.js +0 -1
- package/build/es/engine/types/Query.js +0 -1
- package/build/es/engine/types/QueryParameters.js +0 -1
- package/build/es/links/CustomDataLink.js +0 -44
- package/build/es/links/CustomDataLink.test.js +0 -71
- package/build/es/links/ErrorLink.js +0 -13
- package/build/es/links/RestAPILink/fetchData.js +0 -71
- package/build/es/links/RestAPILink/fetchData.test.js +0 -130
- package/build/es/links/RestAPILink/metadataResources.js +0 -16
- package/build/es/links/RestAPILink/path.js +0 -7
- package/build/es/links/RestAPILink/path.test.js +0 -14
- package/build/es/links/RestAPILink/queryToRequestOptions/multipartFormDataMatchers.js +0 -47
- package/build/es/links/RestAPILink/queryToRequestOptions/multipartFormDataMatchers.test.js +0 -71
- package/build/es/links/RestAPILink/queryToRequestOptions/requestContentType.js +0 -70
- package/build/es/links/RestAPILink/queryToRequestOptions/requestContentType.test.js +0 -118
- package/build/es/links/RestAPILink/queryToRequestOptions/textPlainMatchers.js +0 -151
- package/build/es/links/RestAPILink/queryToRequestOptions/textPlainMatchers.test.js +0 -244
- package/build/es/links/RestAPILink/queryToRequestOptions/xWwwFormUrlencodedMatchers.js +0 -7
- package/build/es/links/RestAPILink/queryToRequestOptions/xWwwFormUrlencodedMatchers.test.js +0 -18
- package/build/es/links/RestAPILink/queryToRequestOptions.js +0 -27
- package/build/es/links/RestAPILink/queryToRequestOptions.test.js +0 -105
- package/build/es/links/RestAPILink/queryToResourcePath.js +0 -75
- package/build/es/links/RestAPILink/queryToResourcePath.test.js +0 -171
- package/build/es/links/RestAPILink/validateQuery.js +0 -52
- package/build/es/links/RestAPILink/validateQuery.test.js +0 -207
- package/build/es/links/RestAPILink.js +0 -26
- package/build/es/links/RestAPILink.test.js +0 -19
- package/build/es/links/index.js +0 -4
- package/build/es/locales/en/translations.json +0 -3
- package/build/es/locales/index.js +0 -13
- package/build/types/engine/DataEngine.d.ts +0 -13
- package/build/types/engine/helpers/getMutationFetchType.d.ts +0 -3
- package/build/types/engine/helpers/resolveDynamicQuery.d.ts +0 -2
- package/build/types/engine/helpers/validate.d.ts +0 -4
- package/build/types/engine/index.d.ts +0 -9
- package/build/types/engine/types/DataEngineLink.d.ts +0 -9
- package/build/types/engine/types/ExecuteOptions.d.ts +0 -9
- package/build/types/engine/types/FetchError.d.ts +0 -19
- package/build/types/engine/types/InvalidQueryError.d.ts +0 -5
- package/build/types/engine/types/JsonValue.d.ts +0 -6
- package/build/types/engine/types/Mutation.d.ts +0 -29
- package/build/types/engine/types/PossiblyDynamic.d.ts +0 -1
- package/build/types/engine/types/Query.d.ts +0 -24
- package/build/types/engine/types/QueryParameters.d.ts +0 -12
- package/build/types/links/CustomDataLink.d.ts +0 -17
- package/build/types/links/ErrorLink.d.ts +0 -6
- package/build/types/links/RestAPILink/fetchData.d.ts +0 -4
- package/build/types/links/RestAPILink/metadataResources.d.ts +0 -2
- package/build/types/links/RestAPILink/path.d.ts +0 -1
- package/build/types/links/RestAPILink/queryToRequestOptions/multipartFormDataMatchers.d.ts +0 -6
- package/build/types/links/RestAPILink/queryToRequestOptions/requestContentType.d.ts +0 -6
- package/build/types/links/RestAPILink/queryToRequestOptions/textPlainMatchers.d.ts +0 -14
- package/build/types/links/RestAPILink/queryToRequestOptions/xWwwFormUrlencodedMatchers.d.ts +0 -2
- package/build/types/links/RestAPILink/queryToRequestOptions.d.ts +0 -2
- package/build/types/links/RestAPILink/queryToResourcePath.d.ts +0 -3
- package/build/types/links/RestAPILink/validateQuery.d.ts +0 -2
- package/build/types/links/RestAPILink.d.ts +0 -10
- package/build/types/links/index.d.ts +0 -3
- package/build/types/react/context/defaultContext.d.ts +0 -4
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
import { DataEngine } from './DataEngine';
|
|
2
|
-
const mockQuery = {
|
|
3
|
-
test: {
|
|
4
|
-
resource: 'test'
|
|
5
|
-
}
|
|
6
|
-
};
|
|
7
|
-
const mockMutation = {
|
|
8
|
-
resource: 'test',
|
|
9
|
-
type: 'create',
|
|
10
|
-
data: {}
|
|
11
|
-
};
|
|
12
|
-
const mockLink = {
|
|
13
|
-
executeResourceQuery: jest.fn(async (type, query) => {
|
|
14
|
-
if (query.resource === 'ERROR') {
|
|
15
|
-
throw new Error('MOCK ERROR');
|
|
16
|
-
}
|
|
17
|
-
return {
|
|
18
|
-
type,
|
|
19
|
-
resource: query.resource,
|
|
20
|
-
answer: 42
|
|
21
|
-
};
|
|
22
|
-
})
|
|
23
|
-
};
|
|
24
|
-
describe('DataEngine', () => {
|
|
25
|
-
beforeEach(() => {
|
|
26
|
-
jest.clearAllMocks();
|
|
27
|
-
});
|
|
28
|
-
it('Should construct successfully with a mock Link', () => {
|
|
29
|
-
expect(() => {
|
|
30
|
-
new DataEngine(mockLink);
|
|
31
|
-
}).not.toThrow();
|
|
32
|
-
});
|
|
33
|
-
it('Should call the mock link with the passed query and options', () => {
|
|
34
|
-
const controller = new AbortController();
|
|
35
|
-
const engine = new DataEngine(mockLink);
|
|
36
|
-
engine.query(mockQuery, {
|
|
37
|
-
signal: controller.signal
|
|
38
|
-
});
|
|
39
|
-
expect(mockLink.executeResourceQuery).toHaveBeenCalledWith('read', mockQuery.test, {
|
|
40
|
-
signal: controller.signal
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
it('Should call the mock link with the passed mutation and options', async () => {
|
|
44
|
-
const controller = new AbortController();
|
|
45
|
-
const engine = new DataEngine(mockLink);
|
|
46
|
-
const result = await engine.mutate(mockMutation, {
|
|
47
|
-
signal: controller.signal
|
|
48
|
-
});
|
|
49
|
-
expect(mockLink.executeResourceQuery).toHaveBeenCalledWith(mockMutation.type, {
|
|
50
|
-
resource: mockMutation.resource,
|
|
51
|
-
data: {}
|
|
52
|
-
}, {
|
|
53
|
-
signal: controller.signal
|
|
54
|
-
});
|
|
55
|
-
expect(result).toMatchObject({
|
|
56
|
-
type: mockMutation.type,
|
|
57
|
-
resource: mockMutation.resource,
|
|
58
|
-
answer: 42
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
it('Should call multilple queries in parallel', async () => {
|
|
62
|
-
const engine = new DataEngine(mockLink);
|
|
63
|
-
const result = await engine.query({
|
|
64
|
-
test: {
|
|
65
|
-
resource: 'test'
|
|
66
|
-
},
|
|
67
|
-
test2: {
|
|
68
|
-
resource: 'test2'
|
|
69
|
-
},
|
|
70
|
-
test3: {
|
|
71
|
-
resource: 'test3'
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
expect(mockLink.executeResourceQuery).toHaveBeenCalledTimes(3);
|
|
75
|
-
expect(result).toMatchObject({
|
|
76
|
-
test: {
|
|
77
|
-
type: 'read',
|
|
78
|
-
resource: 'test',
|
|
79
|
-
answer: 42
|
|
80
|
-
},
|
|
81
|
-
test2: {
|
|
82
|
-
type: 'read',
|
|
83
|
-
resource: 'test2',
|
|
84
|
-
answer: 42
|
|
85
|
-
},
|
|
86
|
-
test3: {
|
|
87
|
-
type: 'read',
|
|
88
|
-
resource: 'test3',
|
|
89
|
-
answer: 42
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
it('Should call onComplete callback only once for multiple-query method', async () => {
|
|
94
|
-
const options = {
|
|
95
|
-
onComplete: jest.fn()
|
|
96
|
-
};
|
|
97
|
-
const engine = new DataEngine(mockLink);
|
|
98
|
-
await engine.query({
|
|
99
|
-
test: {
|
|
100
|
-
resource: 'test'
|
|
101
|
-
},
|
|
102
|
-
test2: {
|
|
103
|
-
resource: 'test2'
|
|
104
|
-
},
|
|
105
|
-
test3: {
|
|
106
|
-
resource: 'test3'
|
|
107
|
-
}
|
|
108
|
-
}, options);
|
|
109
|
-
expect(mockLink.executeResourceQuery).toHaveBeenCalledTimes(3);
|
|
110
|
-
expect(options.onComplete).toHaveBeenCalledTimes(1);
|
|
111
|
-
});
|
|
112
|
-
it('Should call onComplete callback only once for multiple-query method', async () => {
|
|
113
|
-
const options = {
|
|
114
|
-
onComplete: jest.fn(),
|
|
115
|
-
onError: jest.fn()
|
|
116
|
-
};
|
|
117
|
-
const engine = new DataEngine(mockLink);
|
|
118
|
-
await expect(engine.query({
|
|
119
|
-
test: {
|
|
120
|
-
resource: 'test'
|
|
121
|
-
},
|
|
122
|
-
test2: {
|
|
123
|
-
resource: 'ERROR'
|
|
124
|
-
},
|
|
125
|
-
test3: {
|
|
126
|
-
resource: 'test3'
|
|
127
|
-
}
|
|
128
|
-
}, options)).rejects.toBeTruthy();
|
|
129
|
-
expect(options.onComplete).toHaveBeenCalledTimes(0);
|
|
130
|
-
expect(options.onError).toHaveBeenCalledTimes(1);
|
|
131
|
-
});
|
|
132
|
-
it('Should call onComplete callback after mutation', async () => {
|
|
133
|
-
const options = {
|
|
134
|
-
onComplete: jest.fn()
|
|
135
|
-
};
|
|
136
|
-
const engine = new DataEngine(mockLink);
|
|
137
|
-
await engine.mutate(mockMutation, options);
|
|
138
|
-
expect(options.onComplete).toHaveBeenCalledTimes(1);
|
|
139
|
-
});
|
|
140
|
-
it('Should call onError callback after failed mutation', async () => {
|
|
141
|
-
const options = {
|
|
142
|
-
onComplete: jest.fn(),
|
|
143
|
-
onError: jest.fn()
|
|
144
|
-
};
|
|
145
|
-
const engine = new DataEngine(mockLink);
|
|
146
|
-
await expect(engine.mutate({
|
|
147
|
-
resource: 'ERROR',
|
|
148
|
-
type: 'delete',
|
|
149
|
-
id: '2'
|
|
150
|
-
}, options)).rejects.toBeTruthy();
|
|
151
|
-
expect(options.onComplete).toHaveBeenCalledTimes(0);
|
|
152
|
-
expect(options.onError).toHaveBeenCalledTimes(1);
|
|
153
|
-
});
|
|
154
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const getMutationFetchType = mutation => mutation.type === 'update' ? mutation.partial ? 'update' : 'replace' : mutation.type;
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { getMutationFetchType } from './getMutationFetchType';
|
|
2
|
-
describe('getMutationFetchType', () => {
|
|
3
|
-
it('should return the passed fetch type if not `update`', () => {
|
|
4
|
-
expect(getMutationFetchType({
|
|
5
|
-
type: 'create',
|
|
6
|
-
resource: 'test',
|
|
7
|
-
data: {}
|
|
8
|
-
})).toBe('create');
|
|
9
|
-
expect(getMutationFetchType({
|
|
10
|
-
type: 'delete',
|
|
11
|
-
resource: 'test',
|
|
12
|
-
id: 'id'
|
|
13
|
-
})).toBe('delete');
|
|
14
|
-
expect(getMutationFetchType({
|
|
15
|
-
type: 'json-patch',
|
|
16
|
-
resource: 'test',
|
|
17
|
-
data: {}
|
|
18
|
-
})).toBe('json-patch');
|
|
19
|
-
});
|
|
20
|
-
it('should return `replace` for non-partial `update`', () => {
|
|
21
|
-
expect(getMutationFetchType({
|
|
22
|
-
type: 'update',
|
|
23
|
-
resource: 'test',
|
|
24
|
-
id: 'id',
|
|
25
|
-
data: {}
|
|
26
|
-
})).toBe('replace');
|
|
27
|
-
});
|
|
28
|
-
it('should return `update` for partial `update`', () => {
|
|
29
|
-
expect(getMutationFetchType({
|
|
30
|
-
type: 'update',
|
|
31
|
-
partial: true,
|
|
32
|
-
resource: 'test',
|
|
33
|
-
id: 'id',
|
|
34
|
-
data: {}
|
|
35
|
-
})).toBe('update');
|
|
36
|
-
});
|
|
37
|
-
});
|
|
@@ -1,14 +0,0 @@
|
|
|
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
|
-
};
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { resolveDynamicQuery } from './resolveDynamicQuery';
|
|
2
|
-
describe('resolveDynamicQuery', () => {
|
|
3
|
-
it('Should return an unmodified query if no dynamic properties exist', () => {
|
|
4
|
-
const query = {
|
|
5
|
-
resource: 'test',
|
|
6
|
-
id: '42',
|
|
7
|
-
params: {
|
|
8
|
-
page: 3,
|
|
9
|
-
foo: 'bar'
|
|
10
|
-
},
|
|
11
|
-
data: {
|
|
12
|
-
bar: 'baz'
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
expect(resolveDynamicQuery(query, {})).toStrictEqual(query);
|
|
16
|
-
});
|
|
17
|
-
it('Should replace variables in all dynamic properties', () => {
|
|
18
|
-
const query = {
|
|
19
|
-
resource: 'test',
|
|
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
|
-
}
|
|
43
|
-
};
|
|
44
|
-
const vars = {
|
|
45
|
-
id: '42',
|
|
46
|
-
page: 3,
|
|
47
|
-
bar: 'baz'
|
|
48
|
-
};
|
|
49
|
-
expect(resolveDynamicQuery(query, vars)).toStrictEqual({
|
|
50
|
-
resource: 'test',
|
|
51
|
-
id: '42',
|
|
52
|
-
params: {
|
|
53
|
-
page: 3,
|
|
54
|
-
foo: 'bar'
|
|
55
|
-
},
|
|
56
|
-
data: {
|
|
57
|
-
bar: 'baz'
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
});
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { InvalidQueryError } from '../types/InvalidQueryError';
|
|
2
|
-
const validQueryKeys = ['resource', 'id', 'params', 'data'];
|
|
3
|
-
const validTypes = ['read', 'create', 'update', 'replace', 'delete', 'json-patch'];
|
|
4
|
-
export const getResourceQueryErrors = (type, query) => {
|
|
5
|
-
if (!validTypes.includes(type)) {
|
|
6
|
-
return [`Unknown query or mutation type ${type}`];
|
|
7
|
-
}
|
|
8
|
-
if (typeof query !== 'object') {
|
|
9
|
-
return ['A query or mutation must be a javascript object'];
|
|
10
|
-
}
|
|
11
|
-
const errors = [];
|
|
12
|
-
if (!query.resource || typeof query.resource !== 'string') {
|
|
13
|
-
errors.push('Property resource must be a string');
|
|
14
|
-
}
|
|
15
|
-
if (type === 'create' && query.id) {
|
|
16
|
-
errors.push("Mutation type 'create' does not support property 'id'");
|
|
17
|
-
}
|
|
18
|
-
if (query.id && typeof query.id !== 'string') {
|
|
19
|
-
errors.push('Property id must be a string');
|
|
20
|
-
}
|
|
21
|
-
if (query.params && typeof query.params !== 'object') {
|
|
22
|
-
errors.push('Property params must be an object');
|
|
23
|
-
}
|
|
24
|
-
if (type === 'delete' && query.data) {
|
|
25
|
-
errors.push("Mutation type 'delete' does not support property 'data'");
|
|
26
|
-
}
|
|
27
|
-
if (type === 'json-patch' && !Array.isArray(query.data)) {
|
|
28
|
-
errors.push("Mutation type 'json-patch' requires property 'data' to be of type Array");
|
|
29
|
-
}
|
|
30
|
-
const invalidKeys = Object.keys(query).filter(k => !validQueryKeys.includes(k));
|
|
31
|
-
invalidKeys.forEach(k => {
|
|
32
|
-
errors.push(`Property ${k} is not supported`);
|
|
33
|
-
});
|
|
34
|
-
return errors;
|
|
35
|
-
};
|
|
36
|
-
export const validateResourceQueries = function (queries) {
|
|
37
|
-
let names = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
38
|
-
if (names.length !== queries.length) {
|
|
39
|
-
for (let i = names.length; i < queries.length; ++i) {
|
|
40
|
-
names.push('query#' + i);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
const errors = queries.reduce((errors, query, i) => errors.concat(getResourceQueryErrors('read', query).map(e => `[${names[i]}] ${e}`)), []);
|
|
44
|
-
if (errors.length) {
|
|
45
|
-
throw new InvalidQueryError(errors);
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
export const validateResourceQuery = (type, query) => {
|
|
49
|
-
const errors = getResourceQueryErrors(type, query);
|
|
50
|
-
if (errors.length) {
|
|
51
|
-
throw new InvalidQueryError(errors);
|
|
52
|
-
}
|
|
53
|
-
};
|
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
import { getResourceQueryErrors, validateResourceQuery, validateResourceQueries } from './validate';
|
|
2
|
-
describe('query validation', () => {
|
|
3
|
-
describe('getResourceQueryErrors', () => {
|
|
4
|
-
it('should pass with a simple valid query', () => {
|
|
5
|
-
expect(getResourceQueryErrors('read', {
|
|
6
|
-
resource: 'me'
|
|
7
|
-
})).toHaveLength(0);
|
|
8
|
-
});
|
|
9
|
-
it('should pass with a simple valid mutation', () => {
|
|
10
|
-
expect(getResourceQueryErrors('create', {
|
|
11
|
-
resource: 'indicators',
|
|
12
|
-
data: {
|
|
13
|
-
this: 'is a test'
|
|
14
|
-
}
|
|
15
|
-
})).toHaveLength(0);
|
|
16
|
-
});
|
|
17
|
-
it('should fail if an unknown type is specified', () => {
|
|
18
|
-
const errors = getResourceQueryErrors('rainbow', {
|
|
19
|
-
resource: 'me'
|
|
20
|
-
});
|
|
21
|
-
expect(errors).toHaveLength(1);
|
|
22
|
-
expect(errors).toMatchInlineSnapshot(`
|
|
23
|
-
Array [
|
|
24
|
-
"Unknown query or mutation type rainbow",
|
|
25
|
-
]
|
|
26
|
-
`);
|
|
27
|
-
});
|
|
28
|
-
it('should fail if query is not an object', () => {
|
|
29
|
-
let errors = getResourceQueryErrors('read', 'query');
|
|
30
|
-
expect(errors).toHaveLength(1);
|
|
31
|
-
expect(errors).toMatchInlineSnapshot(`
|
|
32
|
-
Array [
|
|
33
|
-
"A query or mutation must be a javascript object",
|
|
34
|
-
]
|
|
35
|
-
`);
|
|
36
|
-
errors = getResourceQueryErrors('read', 42);
|
|
37
|
-
expect(errors).toHaveLength(1);
|
|
38
|
-
expect(errors).toMatchInlineSnapshot(`
|
|
39
|
-
Array [
|
|
40
|
-
"A query or mutation must be a javascript object",
|
|
41
|
-
]
|
|
42
|
-
`);
|
|
43
|
-
});
|
|
44
|
-
it('should fail if query is missing resource property', () => {
|
|
45
|
-
const errors = getResourceQueryErrors('read', {});
|
|
46
|
-
expect(errors).toHaveLength(1);
|
|
47
|
-
expect(errors).toMatchInlineSnapshot(`
|
|
48
|
-
Array [
|
|
49
|
-
"Property resource must be a string",
|
|
50
|
-
]
|
|
51
|
-
`);
|
|
52
|
-
});
|
|
53
|
-
it('should fail if query is missing resource property', () => {
|
|
54
|
-
const errors = getResourceQueryErrors('read', {});
|
|
55
|
-
expect(errors).toHaveLength(1);
|
|
56
|
-
expect(errors).toMatchInlineSnapshot(`
|
|
57
|
-
Array [
|
|
58
|
-
"Property resource must be a string",
|
|
59
|
-
]
|
|
60
|
-
`);
|
|
61
|
-
});
|
|
62
|
-
it('should fail if query is create mutation with id prop', () => {
|
|
63
|
-
const errors = getResourceQueryErrors('create', {
|
|
64
|
-
resource: 'indicators',
|
|
65
|
-
id: 'something'
|
|
66
|
-
});
|
|
67
|
-
expect(errors).toHaveLength(1);
|
|
68
|
-
expect(errors).toMatchInlineSnapshot(`
|
|
69
|
-
Array [
|
|
70
|
-
"Mutation type 'create' does not support property 'id'",
|
|
71
|
-
]
|
|
72
|
-
`);
|
|
73
|
-
});
|
|
74
|
-
it('should fail if id prop is not a string', () => {
|
|
75
|
-
const errors = getResourceQueryErrors('update', {
|
|
76
|
-
resource: 'indicators',
|
|
77
|
-
id: 42
|
|
78
|
-
});
|
|
79
|
-
expect(errors).toHaveLength(1);
|
|
80
|
-
expect(errors).toMatchInlineSnapshot(`
|
|
81
|
-
Array [
|
|
82
|
-
"Property id must be a string",
|
|
83
|
-
]
|
|
84
|
-
`);
|
|
85
|
-
});
|
|
86
|
-
it('should fail if params prop is not an object', () => {
|
|
87
|
-
const errors = getResourceQueryErrors('update', {
|
|
88
|
-
resource: 'indicators',
|
|
89
|
-
id: '42',
|
|
90
|
-
params: 'querystring=42'
|
|
91
|
-
});
|
|
92
|
-
expect(errors).toHaveLength(1);
|
|
93
|
-
expect(errors).toMatchInlineSnapshot(`
|
|
94
|
-
Array [
|
|
95
|
-
"Property params must be an object",
|
|
96
|
-
]
|
|
97
|
-
`);
|
|
98
|
-
});
|
|
99
|
-
it('should fail if query is delete mutation with data prop', () => {
|
|
100
|
-
const errors = getResourceQueryErrors('delete', {
|
|
101
|
-
resource: 'indicators',
|
|
102
|
-
id: '42',
|
|
103
|
-
data: 'querystring=42'
|
|
104
|
-
});
|
|
105
|
-
expect(errors).toHaveLength(1);
|
|
106
|
-
expect(errors).toMatchInlineSnapshot(`
|
|
107
|
-
Array [
|
|
108
|
-
"Mutation type 'delete' does not support property 'data'",
|
|
109
|
-
]
|
|
110
|
-
`);
|
|
111
|
-
});
|
|
112
|
-
it('should fail if query is json-patch mutation with non-array data prop', () => {
|
|
113
|
-
const errors = getResourceQueryErrors('json-patch', {
|
|
114
|
-
resource: 'metadata',
|
|
115
|
-
data: {}
|
|
116
|
-
});
|
|
117
|
-
expect(errors).toHaveLength(1);
|
|
118
|
-
expect(errors).toMatchInlineSnapshot(`
|
|
119
|
-
Array [
|
|
120
|
-
"Mutation type 'json-patch' requires property 'data' to be of type Array",
|
|
121
|
-
]
|
|
122
|
-
`);
|
|
123
|
-
});
|
|
124
|
-
it('should fail if unrecognized keys are passed to query', () => {
|
|
125
|
-
const errors = getResourceQueryErrors('update', {
|
|
126
|
-
resource: 'indicators',
|
|
127
|
-
id: '42',
|
|
128
|
-
query: 'something',
|
|
129
|
-
foo: 'bar'
|
|
130
|
-
});
|
|
131
|
-
expect(errors).toHaveLength(2);
|
|
132
|
-
expect(errors).toMatchInlineSnapshot(`
|
|
133
|
-
Array [
|
|
134
|
-
"Property query is not supported",
|
|
135
|
-
"Property foo is not supported",
|
|
136
|
-
]
|
|
137
|
-
`);
|
|
138
|
-
});
|
|
139
|
-
});
|
|
140
|
-
describe('validateResourceQuery', () => {
|
|
141
|
-
it('should pass with a valid query', () => {
|
|
142
|
-
expect(() => validateResourceQuery('read', {
|
|
143
|
-
resource: 'me'
|
|
144
|
-
})).not.toThrowError();
|
|
145
|
-
});
|
|
146
|
-
it('should throw an error with an invalid query', () => {
|
|
147
|
-
expect(() => validateResourceQuery('create', {
|
|
148
|
-
resource: 'me',
|
|
149
|
-
id: '42'
|
|
150
|
-
})).toThrowErrorMatchingInlineSnapshot(`
|
|
151
|
-
"Invalid query
|
|
152
|
-
- Mutation type 'create' does not support property 'id'"
|
|
153
|
-
`);
|
|
154
|
-
});
|
|
155
|
-
it('should throw an error with an invalid query', () => {
|
|
156
|
-
expect(() => validateResourceQuery('create', {
|
|
157
|
-
resource: 'me',
|
|
158
|
-
answer: 42
|
|
159
|
-
})).toThrowErrorMatchingInlineSnapshot(`
|
|
160
|
-
"Invalid query
|
|
161
|
-
- Property answer is not supported"
|
|
162
|
-
`);
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
describe('validateResourceQueries', () => {
|
|
166
|
-
it('should pass with valid queries', () => {
|
|
167
|
-
expect(() => validateResourceQueries([{
|
|
168
|
-
resource: 'me'
|
|
169
|
-
}, {
|
|
170
|
-
resource: 'indicators'
|
|
171
|
-
}], ['me', 'ind'])).not.toThrowError();
|
|
172
|
-
});
|
|
173
|
-
it('should throw if any query is invalid', () => {
|
|
174
|
-
expect(() => validateResourceQueries([{
|
|
175
|
-
resource: 'me'
|
|
176
|
-
}, {
|
|
177
|
-
resource: 'indicators',
|
|
178
|
-
params: 'parameters'
|
|
179
|
-
}, {
|
|
180
|
-
resource: 'me',
|
|
181
|
-
id: 42
|
|
182
|
-
}])).toThrowErrorMatchingInlineSnapshot(`
|
|
183
|
-
"Invalid query
|
|
184
|
-
- [query#1] Property params must be an object
|
|
185
|
-
- [query#2] Property id must be a string"
|
|
186
|
-
`);
|
|
187
|
-
});
|
|
188
|
-
it('should throw if any query is invalid, prefixing with relevant name', () => {
|
|
189
|
-
expect(() => validateResourceQueries([{
|
|
190
|
-
resource: 'me'
|
|
191
|
-
}, {
|
|
192
|
-
resource: 'indicators',
|
|
193
|
-
params: 'parameters'
|
|
194
|
-
}, {
|
|
195
|
-
resource: 'me',
|
|
196
|
-
id: 42
|
|
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
|
-
`);
|
|
202
|
-
});
|
|
203
|
-
});
|
|
204
|
-
});
|
package/build/es/engine/index.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export * from './DataEngine';
|
|
2
|
-
export * from './types/DataEngineLink';
|
|
3
|
-
export * from './types/ExecuteOptions';
|
|
4
|
-
export * from './types/FetchError';
|
|
5
|
-
export * from './types/JsonValue';
|
|
6
|
-
export * from './types/Mutation';
|
|
7
|
-
export * from './types/PossiblyDynamic';
|
|
8
|
-
export * from './types/Query';
|
|
9
|
-
export * from './types/QueryParameters';
|
|
10
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
2
|
-
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
3
|
-
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
4
|
-
export class FetchError extends Error {
|
|
5
|
-
constructor(_ref) {
|
|
6
|
-
let {
|
|
7
|
-
message,
|
|
8
|
-
type,
|
|
9
|
-
details = {}
|
|
10
|
-
} = _ref;
|
|
11
|
-
super(message);
|
|
12
|
-
_defineProperty(this, "type", void 0);
|
|
13
|
-
_defineProperty(this, "details", void 0);
|
|
14
|
-
this.type = type;
|
|
15
|
-
this.details = details;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { FetchError } from './FetchError';
|
|
2
|
-
describe('FetchError', () => {
|
|
3
|
-
it('should construct successfully', () => {
|
|
4
|
-
const message = 'this is a test';
|
|
5
|
-
const error = new FetchError({
|
|
6
|
-
message,
|
|
7
|
-
type: 'network'
|
|
8
|
-
});
|
|
9
|
-
expect(error.type).toBe('network');
|
|
10
|
-
expect(error.message).toBe(message);
|
|
11
|
-
});
|
|
12
|
-
});
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
2
|
-
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
3
|
-
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
4
|
-
export class InvalidQueryError extends Error {
|
|
5
|
-
constructor(errors) {
|
|
6
|
-
super(`Invalid query\n${errors.map(e => ' - ' + e).join('\n')}`);
|
|
7
|
-
_defineProperty(this, "type", 'invalid-query');
|
|
8
|
-
_defineProperty(this, "details", void 0);
|
|
9
|
-
this.details = errors;
|
|
10
|
-
}
|
|
11
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
2
|
-
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
3
|
-
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
4
|
-
export class CustomDataLink {
|
|
5
|
-
constructor(customData) {
|
|
6
|
-
let {
|
|
7
|
-
failOnMiss = true,
|
|
8
|
-
loadForever = false
|
|
9
|
-
} = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
10
|
-
_defineProperty(this, "failOnMiss", void 0);
|
|
11
|
-
_defineProperty(this, "loadForever", void 0);
|
|
12
|
-
_defineProperty(this, "data", void 0);
|
|
13
|
-
this.data = customData;
|
|
14
|
-
this.failOnMiss = failOnMiss;
|
|
15
|
-
this.loadForever = loadForever;
|
|
16
|
-
}
|
|
17
|
-
async executeResourceQuery(type, query, options) {
|
|
18
|
-
if (this.loadForever) {
|
|
19
|
-
return new Promise(() => undefined);
|
|
20
|
-
}
|
|
21
|
-
const customResource = this.data[query.resource];
|
|
22
|
-
if (customResource === undefined) {
|
|
23
|
-
if (this.failOnMiss) {
|
|
24
|
-
throw new Error(`No data provided for resource type ${query.resource}!`);
|
|
25
|
-
}
|
|
26
|
-
return Promise.resolve(null);
|
|
27
|
-
}
|
|
28
|
-
switch (typeof customResource) {
|
|
29
|
-
case 'string':
|
|
30
|
-
case 'number':
|
|
31
|
-
case 'boolean':
|
|
32
|
-
case 'object':
|
|
33
|
-
return customResource;
|
|
34
|
-
case 'function':
|
|
35
|
-
{
|
|
36
|
-
const result = await customResource(type, query, options);
|
|
37
|
-
if (typeof result === 'undefined' && this.failOnMiss) {
|
|
38
|
-
throw new Error(`The custom function for resource ${query.resource} must always return a value but returned ${result}`);
|
|
39
|
-
}
|
|
40
|
-
return result || null;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|